Camel HazelCast component throwing HazelcastSerializationException - apache-camel

I have the following route in Camel:
<route>
<from uri="servlet:///user?matchOnUriPrefix=true"/>
<setHeader headerName="cachename">
<simple>${header.CamelHttpPath.split("/")[1]}</simple>
</setHeader>
<setHeader headerName="key1">
<simple>${header.CamelHttpPath.split("/")[2]}</simple>
</setHeader>
<to uri="direct:put"/>
</route>
<route>
<from uri="direct:put" />
<!-- If using version 2.8 and above set headerName to "CamelHazelcastOperationType" -->
<setHeader headerName="CamelHazelcastOperationType">
<constant>put</constant>
</setHeader>
<setHeader headerName="CamelHazelcastObjectId">
<simple>${header.key1}</simple>
</setHeader>
<process ref="requestTimeProc"/>
<to uri="hazelcast:map:default" />
</route>
And i am trying to put a string as value into the cache.
My HazelCast Configuration is :
<map name="default">
<in-memory-format>OBJECT</in-memory-format>
<backup-count>1</backup-count>
<async-backup-count>0</async-backup-count>
<time-to-live-seconds>0</time-to-live-seconds>
<max-idle-seconds>0</max-idle-seconds>
<eviction-policy>NONE</eviction-policy>
<max-size policy="PER_NODE">0</max-size>
<eviction-percentage>25</eviction-percentage>
<merge-policy>com.hazelcast.map.merge.PassThroughMergePolicy</merge-policy>
</map>
<serialization>
<portable-version>0</portable-version>
</serialization>
And i Am gettign the following exception:
2013-12-10 22:47:08,288 [tp-1763826860-0] ERROR DefaultErrorHandler - Failed delivery for (MessageId: ID-DJD7W4R1-54721-1386740808850-0-1 on ExchangeId: ID-DJD7W4R1-54721-1386740808850-0-2). Exhausted after delivery attempt: 1 caught: com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable serializer for class org.apache.camel.converter.stream.InputStreamCache
com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable serializer for class org.apache.camel.converter.stream.InputStreamCache
at com.hazelcast.nio.serialization.SerializationServiceImpl.toData(SerializationServiceImpl.java:172)[hazelcast-3.1.2.jar:3.1.2]
at com.hazelcast.nio.serialization.SerializationServiceImpl.toData(SerializationServiceImpl.java:157)[hazelcast-3.1.2.jar:3.1.2]
at com.hazelcast.map.MapService.toData(MapService.java:666)[hazelcast-3.1.2.jar:3.1.2]
at com.hazelcast.map.proxy.MapProxyImpl.put(MapProxyImpl.java:72)[hazelcast-3.1.2.jar:3.1.2]
at com.hazelcast.map.proxy.MapProxyImpl.put(MapProxyImpl.java:60)[hazelcast-3.1.2.jar:3.1.2]
at org.apache.camel.component.hazelcast.map.HazelcastMapProducer.put(HazelcastMapProducer.java:136)[camel-hazelcast-2.11.2.jar:2.11.2]
at org.apache.camel.component.hazelcast.map.HazelcastMapProducer.process(HazelcastMapProducer.java:71)[camel-hazelcast-2.11.2.jar:2.11.2]
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)[camel-core-2.11.2.jar:2.11.2]
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73)[camel-core-2.11.2.jar:2.11.2]
at org.apache.camel.processor.SendProcessor$2.doInAsyncProducer(SendProcessor.java:122)[camel-core-2.11.2.jar:2.11.2]
Please let me know if i am missing anythign inthe configuration . I am using the default Hazelcast configuration provided int he Hazelcast jar. Any help will be highly appreciated

A few comments:
I would not change the 'default' map. This means that any map in the system, which doesn't have an explicit configuration, will now use this configuration. So figure out which map is used and configure explicitly for that map.
<map name="explicitName">
<in-memory-format>OBJECT</in-memory-format>
....
</map>
About the exception:
com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable serializer for class org.apache.camel.converter.stream.InputStreamCache
It means that the InputStreamCache is put in the map, but Hazelcast doesn't know how to conver it to a stream of bytes. You can plug in a serializer for this class, see the following blogpost how to do so:
http://blog.hazelcast.com/blog/2013/10/16/kryo-serializer/
The big question for me is: why are you trynig to put an InputStreamCache in a map? My gut feeling says that this class is not something you want to put in a distribured Hazelcast map at all.

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

Camel blueprint <setHeader headerName="CamelHttpPath" id="_setHeader1"><el>${header.uriPattern}</el></setHeader> waiting for dependencies

I have the following Camel Context.
<camelContext id="_camuatomicservicecontext" xmlns="http://camel.apache.org/schema/blueprint">
<route id="_camuatomicserviceroute1">
<from id="_from1" uri="direct-vm:camuatomicservice">
<description>accepts vm messages directly </description>
</from>
<log id="_log1" message="Camu Atomic Service body = ${body}, header= ${header.uriPattern}"/>
<!-- <to id="_to1" uri="restlet:protocol:localhost:8189/"/> -->
<setHeader headerName="api.key" id="_setHeader1">
<constant>replace later with properties api.key Does not matter for this poc</constant>
</setHeader>
<setHeader headerName="CamelHttpPath" id="_setOutHeader1">
<el>${header.uriPattern}</el>
</setHeader>
<to id="_to1" pattern="InOut" uri="netty4-http:http:localhost:8189/path"/>
<log id="_log2" message="CamuAtomicService Response body ${body}"/>
</route>
</camelContext>
From the documentation I expect the CamelHttpPath header to override the endpoint configuration "/path" such that calling Facade Services can pass the header.uriPattern in and dynamically change the resource they want to access. The bundle worked fine until I added the setHeader for CamelHttpPath and now getting "Waiting for dependencies." I assume I need to install a feature, but Simple EL in other bundles on that server work already so not sure what feature I need to install.
Instead of I used and it worked fine. The choice was farther down in the options.

Apache Camel: Send empty body ws

How can i call a SOAP web service with an empty message body using Apache Camel?
For example, the final endpoint on a route would be the invocation of a method on my proxy that takes 0 arguments.
EDIT:
example xml configuration:
<route id="someRoute">
<from uri="ref:activemq-queue"/>
<setHeader headerName="operationName">
<constant>invoke</constant>
</setHeader>
<to uri="cxf:bean:someWS"/>
</route>
...
<cxf:cxfEndpoint id="someWS" address="${ws.address}"
serviceClass="com.example.ws.SomeWS"
The problem is that the method 'invoke' on the WS takes 0 arguments, and an exception is thrown stating that 1 argument is being received. Is there a way for me to specify to ignore this received input?
You can set the message body to be null, if the invocation just take 0 argument. null simple expression is added since camel 2.12.3.
<route id="someRoute">
<from uri="ref:activemq-queue"/>
<setBody>
<simple>null</simple>
</setBody>
<setHeader headerName="operationName">
<constant>invoke</constant>
</setHeader>
<to uri="cxf:bean:someWS"/>
</route>
I also needed to set an empty body to Apache Camel xml and the solution below worked for me.
<setBody id="set-empty-body">
<constant/>
</setBody>
Hope this helps to whoever need it.
The xml configuration will fail if the content of the body is not with the correct type of the class required by the method of your bean. By default, it could be an Object and not a String. When the method recieves the body in an incorrect format, it would process a null value, instead of the body of the route. To solve this problem, you will need to convert the body into the expected class of the method of your bean. For example, if the method's argument of the bean is a String, then you could do something like:
<route id="someRoute">
<from uri="ref:activemq-queue"/>
<setHeader headerName="operationName">
<constant>invoke</constant>
</setHeader>
<convertBodyTo type="String"/>
<to uri="cxf:bean:someWS"/>
</route>
For more information about body conversion, you can check the docs: https://camel.apache.org/components/3.14.x/eips/convertBodyTo-eip.html

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

How to configure a Servlet to HazelCast route using Camel

I want to build a route something like
<route>
<from uri="servlet:///user?matchOnUriPrefix=true"/>
<to uri="direct:put"/>
</route>
<route>
<from uri="direct:put"/>
<setHeader headerName="CamelHazelcastOperationType">
<constant>put</constant>
</setHeader>
<to uri="hazelcast:map:foo"/>
</route>
ie everything that matches POST:/user/{cachename}/{key1} should take the key1 as key and place the payload under key:key1 to map:{cachename}.
Same thing for
GET:/user/{cachename}/{key1} should take the {key1} as key and retrieve the payload under key1 from map:{cachename}.
Any Help will be highly appreciated.
Thanks,
You should have a number of Camel headers available from the incoming servlet, such as:
CamelHttpMethod = GET
CamelHttpPath = /user/{cachename}/{key1}
You could use code or an expression language to extract the information from there, a very basic example would be:
<setHeader headerName="cachename">
<simple>${header.CamelHttpPath.split("/")[2]}</simple>
</setHeader>
<setHeader headerName="key1">
<simple>${header.CamelHttpPath.split("/")[3]}</simple>
</setHeader>

Resources