Monday, September 12, 2016

Apache camel routing to return the Exact HTTP error code

Let's say we need an apache camel routing configuration which acts as a HTTP proxy. It does only hand over the message to an external system which is given to the ESB by another external system. No any message modification happens in the ESB.

System A >>>>> ESB >>>>> System B

Let's take an example.

System A sends a request to the ESB without required Authorization header. ESB just forewards that message to the System B. So, System B returns a 401(Unauthorized) status code to the ESB. According to the default behavior ESB returns HTTP 500 back to the System A which we don't like to expect from a proxy setup. We need exactly what System B has sent to ESB. To achieve that behavior from ESB, we can apply following routing configuration.

<route>
            <from
                uri="jetty:http://{{xxx.esb.host}}:{{xxx.esb.port}}/?matchOnUriPrefix=true" />
            <setHeader headerName="CamelHttpMethod">
                <simple>${headers.CamelHttpMethod}</simple>
            </setHeader>
            <setHeader headerName="RestEndpointURL">
                <simple>
                    http://{{xxx.rest.endpoint.host}}:{{cgx.rest.endpoint.port}}${headers.CamelHttpUri}?bridgeEndpoint=true
                </simple>
            </setHeader>
            <setHeader headerName="Exchange.HTTP_PATH">
                <constant></constant>
            </setHeader>
            <recipientList>
                <simple>${headers.RestEndpointURL}</simple>
            </recipientList>

            <onException>
                <exception>java.lang.Exception</exception>
                <handled>
                    <simple> true </simple>
                </handled>
                <setHeader headerName="Exchange.HTTP_RESPONSE_CODE">
                    <simple>${exception.statusCode}</simple>
                </setHeader>
            </onException>


        </route> 

Thursday, August 25, 2016

Excetion: waiting for namespace handlers [http://camel.apache.org/schema/cxf

2016-08-26 09:19:06,451 | INFO  | -7.0.0.M2/deploy | BlueprintContainerImpl           | 28 - org.apache.aries.blueprint.core - 1.6.1 | Bundle com.xxxx.yyyyyyy.esb/0.0.1.SNAPSHOT is waiting for namespace handlers [http://camel.apache.org/schema/cxf]

When I was developing an Apache Camel REST project using CXFRS with the blueprint schema in XML DSL, above INFO log was appeared and bundle went to a Grace period. When the issue occurred my xml namespace configurations as below.

<?xml version="1.0" encoding="UTF-8"?>

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util xmlns:cxf="http://camel.apache.org/schema/cxf"     

xsi:schemaLocation=" 
http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd 
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd"> 

I verified several times for the existence of the camel-cxf.xsd in the schemas of the camel-cxf dependency.

And also verified servicemix container contains the camel-cxf feature installed.

Finally I understood name-spaces and XSD locations should be as follows since I am using the blueprint schema.

xmlns:cxf="http://camel.apache.org/schema/bluprint/cxf" 

http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd

Then issue resolved.

Monday, August 22, 2016

Available XML tags in Apache Camel

onException when onCompletion
intercept interceptFrom interceptSendToEndpoint
to toD route
aop aggregate bean
doCatch choice otherwise
convertBodyTo delay dynamicRouter
enrich filter doFinally
idempotentConsumer inOnly inOut
loadBalance log loop
marshal multicast pipeline
policy pollEnrich process
recipientList removeHeader removeHeaders
removeProperties removeProperty resequence
rollback routingSlip sample
script setBody setExchangePattern
setFaultBody setHeader setOutHeader
setProperty sort split
stop threads throttle
throwException transacted transform
doTry unmarshal validate
whenSkipSendToEndpoint wireTap restBinding

Friday, August 5, 2016

How to set message headers for a apache camel restlet request

It is simple to set message headers for camel restlet request (Here we follow XML method to add those headers to a camel routing).

Following route will send a GET request to  http://192.168.1.20:8081/abcsys/services/esbInboundAdaptorServiceRest/V1.0/receiveMessage including Basic Authentication headers with username admin and password admin. A query param also get appended to the URI as http://192.168.1.20:8081/abcsys/services/esbInboundAdaptorServiceRest/V1.0/receiveMessage?message=new message

<route>

                    <!-- Set the query parameters to URI -->
                    <setHeader headerName="CamelHttpQuery">
                        <simple>message=new message</simple>
                    </setHeader>

                    <!-- Set the authentication header username for endpoint authorization -->
                    <setHeader headerName="CamelRestletLogin">
                        <simple>admin</simple>
                    </setHeader>

                    <!-- Set the authorization header password for endpoint authorization -->
                    <setHeader headerName="CamelRestletPassword">
                        <simple>admin</simple>
                    </setHeader>

                    <to
                        uri="restlet:http://192.168.1.20:8081/abcsys/services/esbInboundAdaptorServiceRest/V1.0/receiveMessage" />


</route>

Refer this for possible lists of headers that can be set to restlet requests.

Friday, July 22, 2016

Camel installing dependencies

[Note : Following content is related to a Apache-servicemix-7.0.0.M2 test setup]


When we are creating routing with Camel, we may need to install dependencies to Camel.
As an example if we have created a mail sending route and deploy it in a fresh camel installation, you may get a error like following:

2016-07-22 14:50:35,439 | ERROR | rint Extender: 2 | BlueprintContainerImpl           | 28 - org.apache.aries.blueprint.core - 1.6.1 | Unable to start blueprint container for bundle blueprint.jms/0.0.1.SNAPSHOT due to unresolved dependencies [(&(component=smtps)(objectClass=org.apache.camel.spi.ComponentResolver))]
java.util.concurrent.TimeoutException
    at org.apache.aries.blueprint.container.BlueprintContainerImpl$1.run(BlueprintContainerImpl.java:371)[28:org.apache.aries.blueprint.core:1.6.1]
    at org.apache.aries.blueprint.utils.threading.impl.DiscardableRunnable.run(DiscardableRunnable.java:48)[28:org.apache.aries.blueprint.core:1.6.1]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)[:1.7.0_79]
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)[:1.7.0_79]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)[:1.7.0_79]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)[:1.7.0_79]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)[:1.7.0_79]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)[:1.7.0_79]
    at java.lang.Thread.run(Thread.java:745)[:1.7.0_79]
 


It is because we have not installed a feature called "mail" as a dependency for Camel. There are several dependencies available. We can display them by typing karaf@root>feature:install camel-  and tab.

We can install those dependencies with following command.
karaf@root>feature:install camel-mail  

Now issue should be resolved.

Wednesday, July 20, 2016

Activemq REST API adapter for external systems

Following content is tested only with Apache ActiveMQ 5.13.3

If we need to implement a communication between a ActiveMQ JMS server and any REST support external system that is implemented with a technology which has no JMS API support, ActiveMQ REST API comes as a solution. So, this REST API can be introduced as an adapter for any External system to be connected with a ActiveMQ JMS server.

ActiveMQ REST API provides following services.
1. Publish a message.
2. Consume a message.
3. Get list of queues.
4. Get list of messages in a particular queue or topic.
5. Get the content of a particular message.

Publish a message

Method : POST
URI format :
http://localhost:8161/api/message/queue_or_topic_name?type=either_queue_or_topic&requestTimeout=time_in_miliseconds&body=message to send&clientId=any_unique_id_for_client
Example URI:
http://localhost:8161/api/message/FOO?type=queue&requestTimeout=1000&body=This is test 34&clientId=soapui

Consume a message

Method :GET
URI format :
http://localhost:8161/api/message/queue_or_topic_name?type=either_queue_or_topic&clientId=any_unique_id_for_client&requestTimeout=time_in_miliseconds
Example URI:
http://localhost:8161/api/message/FOO?type=queue&clientId=soapui&requestTimeout=1000

Get list of queues or topics

Method :GET
URI format :
http://localhost:8161/admin/xml/queues.jsp

Get list of messages in a particular queue or topic

Method :GET
URI format :
http://localhost:8161/admin/queueBrowse/queue_or_topic_name
Example URI:
http://localhost:8161/admin/queueBrowse/FOO 

Get the content of a particular message

Method :GET
URI format :
http://localhost:8161/admin/queueBrowse/queue_or_topic_name?msgId=ID_value_of_a_particular_message_in_mentioned_queue_or_topic
Example URI:
http://localhost:8161/admin/queueBrowse/FOO?msgId=ID:dhcppc1-54766-1469009393902-5:1:1:1:4


NOTE:

If the authentication is enabled in the ActiveMQ admin as example in jetty.xml

 <bean id="securityConstraint" class="org.eclipse.jetty.util.security.Constraint">
        <property name="name" value="BASIC" />
        <property name="roles" value="user,admin" />
        <!-- set authenticate=false to disable login -->
        <property name="authenticate" value="true" />
    </bean>



we have to set security headers. If not 401 response will be received. So, following header should be set in the REST request

Authorization: Basic YWRtaW46YWRtaW4= 

YWRtaW46YWRtaW4= equivalent to the base 64 encoded version of the provided_username:provided_password
(Username and password is one of set which you use to access to the ActiveMq webconsole.)




Activemq REST API adapter for external systems

Following content is tested only with Apache ActiveMQ 5.13.3

If we need to implement a communication between a ActiveMQ JMS server and any REST support external system that is implemented with a technology which has no JMS API support, ActiveMQ REST API comes as a solution. So, this REST API can be introduced as an adapter for any External system to be connected with a ActiveMQ JMS server.

ActiveMQ REST API provides following services.
1. Publish a message.
2. Consume a message.
3. Get list of queues.
4. Get list of messages in a particular queue or topic.
5. Get the content of a particular message.

Publish a message

Method : POST
URI format :
http://localhost:8161/api/message/queue_or_topic_name?type=either_queue_or_topic&requestTimeout=time_in_miliseconds&body=message to send&clientId=any_unique_id_for_client
Example URI:
http://localhost:8161/api/message/FOO?type=queue&requestTimeout=1000&body=This is test 34&clientId=soapui

Consume a message

Method :GET
URI format :
http://localhost:8161/api/message/queue_or_topic_name?type=either_queue_or_topic&clientId=any_unique_id_for_client&requestTimeout=time_in_miliseconds
Example URI:
http://localhost:8161/api/message/FOO?type=queue&clientId=soapui&requestTimeout=1000

Get list of queues or topics

Method :GET
URI format :
http://localhost:8161/admin/xml/queues.jsp

Get list of messages in a particular queue or topic

Method :GET
URI format :
http://localhost:8161/admin/queueBrowse/queue_or_topic_name
Example URI:
http://localhost:8161/admin/queueBrowse/FOO 

Get the content of a particular message

Method :GET
URI format :
http://localhost:8161/admin/queueBrowse/queue_or_topic_name?msgId=ID_value_of_a_particular_message_in_mentioned_queue_or_topic
Example URI:
http://localhost:8161/admin/queueBrowse/FOO?msgId=ID:dhcppc1-54766-1469009393902-5:1:1:1:4


NOTE:

If the authentication is enabled in the ActiveMQ admin as example in jetty.xml

 <bean id="securityConstraint" class="org.eclipse.jetty.util.security.Constraint">
        <property name="name" value="BASIC" />
        <property name="roles" value="user,admin" />
        <!-- set authenticate=false to disable login -->
        <property name="authenticate" value="true" />
    </bean>



we have to set security headers. If not 401 response will be received. So, following header should be set in the REST request

Authorization: Basic YWRtaW46YWRtaW4= 

YWRtaW46YWRtaW4= equivalent to the base 64 encoded version of the provided_username:provided_password
(Username and password is one of set which you use to access to the ActiveMq webconsole.)