From ActiveMQ to Java Bean - apache-camel

I'm trying to learn Camel on Fuse- within this example an ActiveMQ message is converted in a Java object named CustInfo using the Dozer component:
<camelContext id="context-43faded0-825e-454b-8037-c72122aa0418" xmlns="http://camel.apache.org/schema/blueprint">
<propertyPlaceholder location="classpath:sql.properties" id="properties"/>
<endpoint uri="dozer:toCustInfo?sourceModel=homeloancust.CustInfo&targetModel=org.blogdemo.homeloan.model.CustInfo&unmarshalId=homeloancust&mappingFile=toCustInfo.xml" id="toCustInfo"/>
<dataFormats>
<jaxb contextPath="homeloancust" id="homeloancust"/>
</dataFormats>
<route id="CustomerEvaluation">
<from uri="activemq:queue:customer"/>
<to ref="CustInfo" id="to3"/>
. . . .
</route>
</camelContext>
My question is, in case I don't need transformations in the Java object, can I convert the message into the Java class directly (without Dozer).
Tried with:
<bean id="CustInfo" class="homeloancust.CustInfo"/>
. . .
<to ref="CustInfo" id="to3"/>
Without success! Any help ?

Assuming that the incoming message has a contract (which it should if it follows a good contract-first approach), then you can simply unmarshall the payload into a Java object using JAXB. If it doesn't have a contract, you can still annotate your Java class with JAXB annotations and unmarshall to it:
<unmarshal>
<jaxb prettyPrint="true" contextPath="org.apache.camel.example"/>
</unmarshal>
http://camel.apache.org/jaxb.html

Related

Failed to create route route-t: >>> OnException[[com.sample] ->

I am migrating from camle 2 to camel 3 as below configuration
<onException>
<exception>com.sample</exception>
<redeliveryPolicy disableRedelivery="true"/>
<handled>
<constant>true</constant>
</handled>
<log message="got here, before predict, ${exchangeProperty.firstCall}" loggingLevel="INFO"/>
<choice>
<when>
<method>operation</method>
<bean ref="Procs" method="SampleCommentRequestForError"/>
<setProperty propertyName="firstCall">
<constant>false</constant>
</setProperty>
<log message="got here, after predict, ${exchangeProperty.firstCallOf}" loggingLevel="INFO"/>
<to uri="direct:sample-comment"/>
</when>
</choice>
<bean ref="abc_errorhandler" method="abcException"/>
</onException>
and getting below exception :
Failed to create route route-nsm-client-call at: >>> OnException[[com.sample] -> [Log[got here, before predict, ${exchangeProperty.firstCall], Choice[[When[bean{abc} [From[direct:bbc-call ->... because of Bean language requires bean, beanType, or ref argument
Caused by: java.lang.IllegalArgumentException: Bean language requires bean, beanType, or ref argument
Any idea on this?
This will work camel 2.x operation but if you try to upgrade camel 3.x for existing code. So, in that case you need to change this code to like below sample . but rather than myBean provide whole class package path.
Try below sample code..
for more details, please check below official website..
https://camel.apache.org/components/3.17.x/languages/bean-language.html

How to use properties with the SimpleRegistry in Apache Camel (Spring XML)

I want to use a SimpleRegistry to store properties (as global variables). The property is changed with setProperty in a route with a jms endpoint. The camel documentation changed last week and has many dead links, also the Registry page. I did not found any samples that describe the use of the simpleRegistry.
I used the camel-example-servlet-tomcat as base. I do not use Fuse or the patched camel wildfly, because is to huge for our simple module.
<beans .... >
.
.
.
<bean id="simpleRegistry" class="org.apache.camel.support.SimpleRegistry" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties" location="ref:simpleRegistry" />
<route id="storeConfig">
<from id="myTopic" uri="jms:topic:myTopic?selector=Configuration %3D 'xyz'" />
<log id="printHeader2" message="Received header: ${headers}" />
<log id="logToken" message="Received token: ${headers[myToken]}" />
<setProperty id="setMyToken" name="myProperty">
<simple>${headers[myToken]}</simple>
</setProperty>
</route>
<route id="externalIncomingDataRoute">
<from uri="servlet:hello" />
<transform>
<simple>The Token is: {{myProperty}}</simple>
</transform>
</route>
</camelContext>
</beans>
With the camel context deined like above, I got a java.io.FileNotFoundException Properties simpleRegistry not found in registry.
When I use <propertyPlaceholder id="properties" location="classpath:test.properties" /> and create a test.properties file, everything works fine but I cannot change the property. The operation in the setProperty tag is ignored.
The reason why I need a global variable is, I send a dynamic configuration (the myToken) via a jms topic to the camel context. A single route should store this configuration globaly. If an other route is called via an rest component, this route need the token to make a choice.
Alternatively you can achieve the same result following the below approach which uses the PropertiesComponent
<bean id="applicationProperties" class="java.util.Properties"/>
<bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent">
<property name="location" value="classpath:application.properties"/>
<property name="overrideProperties" ref="applicationProperties" />
</bean>
Define the property place holder in the camel context:
<propertyPlaceholder id="propertiesRef" location="ref:applicationProperties" />
Set a property as shown below :
<bean ref="applicationProperties" method="setProperty(token, 'Test'})" />
And to fetch the property : ${properties:token}
OK, there are multiple subjects in your question.
You write you want to use Camel SimpleRegistry, but you obviously have a Spring application.
If you got Spring available, the Camel Registry automatically uses the Spring bean registry. The Camel Registry is just a thin wrapper or provider interface that uses whenever possible an available registry of another framework.
The Camel SimpleRegistry is only used when nothing else is available. This is basically an in-memory registry based on a Map.
You want to set an application property with <setProperty>.
<setProperty> sets an Exchange property, NOT an application property. With this you can save values in the Exchange of a message.
You want to use "global variables".
You could perhaps use a Spring singleton bean that is a Map. You could then autowire it where you need it, it would be like an application wide available map.
However, think twice why you need this kind of variable. This could also be a symptom of a design problem.

Camel Component: setting a Property dynamically from a Bean

I have defined a Camel Route in a Jboss Fuse BluePrint. I'd need to set one variable at runtime from a Bean. See this example:
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route id="wsClient">
<from uri="timer:foo?repeatCount=1" />
<setBody>
<simple>Message</simple>
</setBody>
<transform>
<method bean="myBean" method="transform" />
</transform>
<to uri="cxf:bean:MyWebService?defaultOperationName={{operation}}" />
<to uri="mock:result" />
</route>
</camelContext>
In this example, I'd like to set the property named "operation" within the bean "myBean". Is it possible to do it?
Thanks!
Yes, it is possible.
First, set a header from the bean and later use http://camel.apache.org/recipient-list.html
I am not familiar with Spring DSL, but in Java DSL it would look like this:
.recipientList(simple("cxf:bean:MyWebService?defaultOperationName=${header.operation}"))
Yes you can do that inside the bean. No need to pass any specific parameter. Camel can bind the exchange, body...etc as a method parameter automatically. Ref: http://camel.apache.org/bean-binding.html
using below code you can set the header or property
exchange.getIn().setHeader("HeaderName", "Value");
exchange.setProperty("Key", "Value");

How to extract value from Exchange object in camel esb

I have created a simple cxf web service. following is the body of soap message
<soapenv:Body>
<bean:getRTOEmployeeSalary>
<!--Optional:-->
<bean:arg0>sdf</bean:arg0>
</bean:getRTOEmployeeSalary>
</soapenv:Body>
My requirement is to extract the value of arg0 in my camel context file. i.e. i want to log the value of arg0. Please help me on this
<route routePolicyRef="loggingInInterceptor">
<from uri="cxf:bean:rtoemplyeeService"/>
<setHeader headerName="exchange">
<spel>${exchange}</spel>
</setHeader>
<log message="value of arg0======== "/>
<convertBodyTo type="java.lang.String" id="stringInput"/>
<bean ref="rtoEmpBean" method="getRTOEmployeeSalary" beanType="rtoEmpBean" id="govtRTOEmp"/>
</route>
I need to use the value of arg0 here.
We can use camel provided spring expression language to extract the value from exchange object. Since exchange object also resides in spring container.
below will be code src to extract the value of arg0 in camel context-
<setHeader headerName="arg0">
<spel>#{exchange.in.body.get(0)}</spel>
</setHeader>
This will set the value of arg0 of soap message in a header named arg0.
http://camel.apache.org/spel.html

Want to build a route which will check contents of Soap request and pass the request to appropriate URI

I am Ashish from Mumbai and very new to Apache Camel.
Currently I am building a route in XML which will scan the SOAP request and will redirect the request to appropriate URI.
My Soap request isn as follows:
<service xmlns="http://ws.madcomum.comprova.com">
<request>
<keysValues>
<item>
<bytesValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<dateValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<doubleValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<key>validatesOriginIntegrity</key>
<longValue
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<stringValue>z4x/FOOR+EPQ0vD9+itPSCBeNR4=</stringValue>
</item>
</keysValues>
<actionId>1</actionId>
<clientId>ARGO</clientId>
</request>
</service>
From this SOAP envelope, I want to parse out value of actionId tag using Camel Route.
If actionId has value of 1 then route must be redirected to callService else to another service.
I developed logic of route as folows:
<route>
<from uri="cxf:bean:comprovaWS?dataFormat=MESSAGE" />
<when>
<xpath>//actionId=1</xpath>
<to uri="log:input" />
<to ref="callService" />
<to uri="log:output" />
</when>
<otherwise>
<to uri="log:input" />
<to ref="otherService"/>
<to uri="log:output" />
</otherwise>
</choice>
</route>
But this logic is not working.
Is there any error in my route?
Though I am Java guy, I don't want to use Java here. I want to rely on Camel itself.
Please help me ASAP.
Regards,
Ashish
When you use xpath then 95% of the times when people have trouble its often due to namespaces. Your SOAP message is defined using a namespace - "http://ws.madcomum.comprova.com". The xpath expression must use this namespace to make it work.
See more details at: http://camel.apache.org/xpath, there is an example at the section Using XML configuration
Also as you use CXF in MESSAGE mode, then read about stream caching as the message is stream based: http://camel.apache.org/stream-caching.html

Resources