Get Rest Response from Camel Route - apache-camel

I'm using camel to route from SOAP web service to Rest Service. My route is like following.
SOAP Service --> Processor A --> Rest --> Processor B .
I'm using Exchange pattern and Rest is hosted in Jboss Server. My problem is how to get Rest Response ( json string ). When i get in message in Processor B it contains the output message or processor A.
<camelContext xmlns="http://camel.apache.org/schema/spring" trace="true">
<route>
<from uri="cxf:bean:serviceA"/>
<process ref="processorA" />
<to uri="cxfrs:bean:serviceRest"/>
<process ref="processorB"/>
</route>
</camelContxt>
I'm new to camel. any help would be appreciated.

You should be able to the REST response in the proxessorB by referencing the exchange in message.

Finally found the answer with the help of friends. It was error in fasterxml jason provider. I changed the json provider to codehaus
<cxf:rsClient id="serviceRest" address="http://localhost:8080/rest-test/rest"
serviceClass="org.apache.cxf.jaxrs.client.WebClient" loggingFeatureEnabled="true" >
<cxf:providers>
<ref bean="jasonProvider"/>
</cxf:providers>
</cxf:rsClient>
<bean id="jasonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
Now i have the json response in exchange.

Related

Expose an OSGi Service as Camel Endpoint

I don't even know if I formulated the question the right way around ;-)
What I basically want to achieve is something like this:
<route >
<from uri="osgi:serviceName"/>
<!-- do some processing ->
<to uri="activemq:queue:inbox"/>
</route>
So I'd like to have an OSGi Service as starting point of my route. This service can be referenced by some other bundles and fed with input data, that will be later on processed by the Route.
How would I do this?
Simply create an OSGi service outside of camel and a route that starts with direct:anyname. Then you can inject a ProducerTemplate into your service an call the route from there.
If you have really simple method signature, or typeConverter for the parameters you want to pass, you can use CamelProxy to link the service to your route in a simple XML configuration file.
To extends the example of the doc, you would have something like :
<osgi:service id="service" ref="myProxySender" (4)
interface="org.apache.camel.spring.config.MyProxySender" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<!-- create a proxy that will route to the direct:start endpoint when invoked -->
<proxy id="myProxySender"
serviceInterface="org.apache.camel.spring.config.MyProxySender"
serviceUrl="direct:start"/>
<!-- this is the route that our proxy will routed when invoked
and the output from this route is returned as reply on the proxy -->
<route>
<from uri="direct:start"/>
<transform>
<simple>Bye ${body}</simple>
</transform>
</route>
</camelContext>
To use "osgi" as the URI scheme in a Camel route, you would need to create a custom Camel component to handle invoking the relevant OSGi commands. For more information, please see http://camel.apache.org/creating-a-new-camel-component.html
A simpler alternative would be to write custom OSGi commands that used a ProducerTemplate to send messages to a Camel route. An example for Karaf can be found here: https://github.com/apache/karaf/tree/master/demos/command
Injecting a ProducerTemplate can be done via standard Spring configuration.

Clarification about Camel direct component

I can see that many Camel route examples are initiated with a "direct" component. For example:
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route id="myroute">
<from uri="direct:start"/>
<setBody>
<simple>Hello World!</simple>
</setBody>
<log message="${body}"/>
<to uri="mock:result"/>
</route>
</camelContext>
However, by running a route like this (mvn camel:run) the route is not started and Camel keeps hanging forever. Is it not meant to be used directly this kind the direct component?
Thanks
Its not hanging. You need to send a message to the direct endpoint before its routed. eg like in java code to do a direct method invocation from a client by calling a java method.
Instead of direct you can use a timer if you want to route a message automatic every X time etc.
To send a message to the direct endpoint (or any other Camel endpoint) then read about the producer template. For example from the getting started guide: http://camel.apache.org/walk-through-an-example.html

How to get camel-mqtt endpoint to locate (resolving) my ActiveMQ on openshift/fuse

I'm kind of new to this so I might have missed the obvious.
I have an openshift gear with jboss fuse. I have started an ActiveMQ broker with an mqtt connector and created a camel route (using OSGi blueprint) consuming from the ActiveMQ mqtt connector on the same openshift gear. Everything works perfectly when I use the ip-address:port to the mqtt connector but that is not what I want to do. I would like to have some other solution (resolver) that doesn't make me have to point out a specific ip-address in the mqtt endpoint so I can move around the camel-route without reconfiguring it.
ActiveMQ connector config:
<transportConnectors>
<transportConnector name="openwire" publishedAddressPolicy="#addressPolicy" uri="tcp://${OPENSHIFT_FUSE_IP}:${OPENSHIFT_FUSE_AMQ_PORT}"/>
<transportConnector name="mqtt" publishedAddressPolicy="#addressPolicy" uri="mqtt://${OPENSHIFT_FUSE_IP}:1883"/>
</transportConnectors>
Camel-Route when it works:
<camelContext trace="false" id="blueprintContext" xmlns="http://camel.apache.org/schema/blueprint">
<route id="mqttToLog">
<from uri="mqtt:iot?host=tcp://127.4.22.139:1883&subscribeTopicName=mytesttopic&userName=admin&password=xxxxxxx" id="iot_endpoint">
<description>The MQTT endpoint for consuming data sent from the devices.</description>
</from>
<log message="The message contains ${body}" loggingLevel="INFO" id="iot_log">
<description>Logs all the incoming MQTT messages. This is just for verification purpouses.</description>
</log>
<to uri="mock:result" id="iot_mock">
<description>Final sink for the MQTT message flow. Kept for verification.</description>
</to>
</route>
</camelContext>
My camel-routes profile has feature-camel as parent and features camel and camel-mqtt.
So how do I get rid of actually having to specify the host in the endpoint, using for instance the mq group, or some other registry (fabric) or similar?
Thanks,
Tomas
If you are running a fabric then the ActiveMQ clustering feature works like this: The broker is part of a so called "broker group". The default broker is part of the group "default" which means there is a profile called mq-client-default. This profile will register a pre-configured ActiveMQ ConnectionFactory in the OSGi services registry. Its configured to connect to where-ever your broker is located, and will failover automatically to other brokers in the same group.
To make use of the above in Fuse 6.1 do the following:
Create a new child container
Add the mq-client-default profile to it
Add the feature "mq-fabric-camel" to the mq-client-default profile. This will install a camel component called "amq" that automatically uses the connectionFactory from the mq-client-default profile.
Deploy a camel route like the following and witness the awesomeness of JBoss Fuse :)
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<route id="myRoute">
<from uri="timer://foo?fixedRate=true&period=5000"/>
<setBody>
<simple>Hello from Camel route to ActiveMQ</simple>
</setBody>
<to uri="amq:queue:timermessages"/>
</route>
</camelContext>
The messages generated by this route will end up on the broker, no matter where the broker is, or where the camel route is.
Good luck!
P.S. The amq component uses openwire to communicate to the broker, but any other client can use whatever protocol you've enabled to consume or produce messages to your queues.

Apache Camel VM queue between servlets

I'm trying to setup simple VM queue test between two servlets without success. The problem is that the request always timeouts as there is no response, OUT message, within expected timeframe.
"org.apache.camel.ExchangeTimedOutException: The OUT message was not received within: 30000 millis."
The servlets are running in Tomcat and are both deploying Apache Camel. Both apps are defining camel context and simple routes. The basic setup should be fine as simple routes like following are working:
<route>
<from uri="servlet:///hello?servletName=app1" />
<transform>
<simple>Hello world</simple>
</transform>
</route>
<route>
<from uri="servlet:///hello?servletName=app2" />
<transform>
<simple>Hello world</simple>
</transform>
</route>
First of all I'm not sure if the message ever reaches the app2 as the same timout happens even if the requested route wouldn't be even defined (the app2 would be missing the VM route). So the problem could be in how to define the route between two servlets using VM queue.
If the route between the servlets is fine then the problem should be in the missing/incorrect reply. I do understand that the receiving end should return the reply as the incoming requst from web server is inOut type, but I don't know how to achieve that.
The route in app1 receiving the web request:
<route>
<from uri="servlet:///test?servletName=app1" />
<to uri="vm:test">
</route>
and the other end in servlet app2:
<route>
<from uri="vm:test" />
// Tested here: output with <simple>, 'To', 'inOut'... the result is always timeout
</route>
As I'm new with Apache Camel the root cause is most likely very simple. Any help would be highly appreciated.
The question is simply, how to setup VM queue between two servlet apps?
The vm component works in the same classloader, eg kinda what we say on the vm documentation page: http://camel.apache.org/vm.html
This component differs from the SEDA component in that VM supports
communication across CamelContext instances - so you can use this
mechanism to communicate across web applications (provided that
camel-core.jar is on the system/boot classpath).
So if you use Apache Tomcat, you need to have camel-core JAR as shared JAR. Such as in the boot classpath somewhere.

How do I set up a Camel route between two CXF endpoints where the SOAP faults are transferred correctly?

I set up a route between two CXF endpoints up like this:
<cxf:cxfEndpoint id="monitoringService"
address="${esb.monitoring-service.ep.address}" serviceName="s:monitoring-service"
endpointName="s:portSOAP" wsdlURL="classpath:/webservices/monitoring-service.wsdl"
xmlns:s="http://xyz/monitoring/"
/>
<endpoint
id="originMonitoringService"
uri="${origin.monitoring-service.ep.address}" />
<route>
<from uri="cxf:bean:monitoringService?dataFormat=MESSAGE" />
<to ref="originMonitoringService" />
</route>
However when there are SOAP faults happening at the 'originMonitoringService' then they seem not to be forwarded to the endpoint published by Camel and as such do not reach the client that is connecting to it.
How am I supposed to declare this connection?
(Just FYI: ${xx}-style variable are properly replaced with values like http://somehost/someservice at runtime.)
This issue should be fixed by CAMEL-4570

Resources