I am trying to sign the payload of a JMS text message with a private key. The message is then sent to a queue and routed accordingly. The signature will be place in the message header along with the public key.
I am using the following code to set the header with the public key.
TextMessage textMessage = session.createTextMessage(message);
String publicKey = new String(pubk.getEncoded());
textMessage.setStringProperty("CamelSignaturePublicKeyOrCert", publicKey);
However when the message is begin routed I get the following error
11:13:20,027 WARN [org.apache.camel.component.jms.EndpointMessageListener] Execution of JMS message listener failed. Caused by: [org.apache.camel.RuntimeCamelException - java.lang.IllegalStateException: Cannot verify signature as no Public Key or Certificate has been supplied. Either supply one in the route definition or via the message header 'CamelSignaturePublicKeyOrCert']: org.apache.camel.RuntimeCamelException: java.lang.IllegalStateException: Cannot verify signature as no Public Key or Certificate has been supplied. Either supply one in the route definition or via the message header 'CamelSignaturePublicKeyOrCert
the routes are defined as follows
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<!-- Dependencies: ojdbc.jar and aqjms.jar must be in the activemq lib directory -->
<route>
<from uri="activemq:queue:queue.outbound"/>
<log message="The expected queue is :: ${headers.queue}" />
<to uri="crypto:verify://slpy" />
<choice>
<when>
<simple>${headers.queue} == 'ora'</simple>
<to uri="oracleQueue:queue:SLEEPY_LION_QUEUE"/>
</when>
<when>
<simple>${headers.queue} == 'proc'</simple>
<to uri="activemq:queue:queue.proc"/>
</when>
<otherwise>
<log message="Invalid queue"/>
</otherwise>
</choice>
</route>
In order to fix this issue I updated the broker-config.xml as follows
<route>
<!-- <package>com.rs2.sleepylion.routes</package> -->
<from uri="activemq:queue:queue.outbound"/>
<to uri="log:in?showHeaders=true" />
<log message="The expected queue is :: ${headers.queue}" />
<to uri="log:out?showHeaders=true" />
<choice>
<when>
<simple>${headers.queue} == 'ora'</simple>
<to uri="oracleQueue:queue:SLEEPY_LION_QUEUE"/>
</when>
<when>
<simple>${headers.queue} == 'proc'</simple>
<to uri="crypto:verify://headers?publicKey=#myPublicKey&clearHeaders=false" />
<to uri="activemq:queue:queue.proc"/>
</when>
<otherwise>
<log message="Invalid queue"/>
</otherwise>
</choice>
</route>
<bean id="myPublicKey" class="com.rs2.sleepylion.routes.Keys" factory-method="publicKey"/>
Related
I have a Camel route that looks something like the one below. If all records parse successfully, then I get an email from the onCompletion step. If one record gets an exception then the rest of the records will process, which is fine, but the onCompletion step does not fire.
What I'd like is for the onCompletion step to run even if there are errors and to be able to send a message saying "route completed with errors". How can I do this?
<route id="route1">
<from uri="file://C:/TEMP/load?noop=true&idempotentRepository=#sysoutStore&sorter=#externalDataFilesSorter"/>
<choice>
<when>
<simple>${file:name} regex '*file.*.(txt)'</simple>
<to uri="direct:RouteFile" />
</when>
</choice>
</route>
<route id="testRouteDirect">
<from uri="direct:RouteFile" />
<onException>
<exception>java.lang.IllegalArgumentException</exception>
<redeliveryPolicy maximumRedeliveries="1" />
<handled>
<constant>true</constant>
</handled>
<to uri="log:java.lang.IllegalArgumentException"></to>
</onException>
<onException>
<exception>java.text.ParseException</exception>
<redeliveryPolicy maximumRedeliveries="1" />
<handled>
<constant>true</constant>
</handled>
<to uri="log:java.text.ParseException"></to>
</onException>
<split parallelProcessing="false" strategyRef="exchangePropertiesAggregatorStrategy" >
<tokenize token="\r\n"/>
<to uri="log:Record"></to>
</split>
<onCompletion>
<to uri="log:completion"></to>
<to uri="smtp://mail.com?contentType=text/html&to=done#test.com&from=route#test.com&subject=we're done" />
</onCompletion>
</route>
The best part of your route is, you have onException inside your route with handled=true. So move your onCompletion to the parent route(route1), It should work !
There are a bunch of tickets related to oncompletion on the camel site: Camel Jira URL. I upgraded to a newer version of camel & I don't get this issue any more.
Help needed on setting headers based on the method call from bean integration.
within my application I am using a custom POJO and there are before I actually send the message over the wire I want to do set the headers on the exchange, but don't want to do it within my bean and rather do it where my spring DSL is written for the route.
I know that usually the value returned from method is sent as body for the message to the next the endpoint but i want to send values returned as header.
I have attached a sample of my route needs to be, and want:
<route id="someRoute">
<from ref="InboundAsyncEndpoint" />
<to uri="bean:validatorBean?method=validateMessageInternals(MyCostomMessagePojo obj)" />
<choice>
<when>
<simple>
${body.getMetaData().getFinalDestinationName()} == 'AMQEndpoint'
</simple>
<to uri="bean:payloadAndHeaderExtractor?extractHeader(MyCostomMessagePojo obj)" />
<to uri="bean:payloadAndHeaderExtractor?extractPayload(MyCostomMessagePojo obj)" /> <!-- i want the headers being set on the exchange from the map that is returnd from the previous bean and method -->
<to uri="activemq:someQueue"
</when>
<otherwise>
...
...
</otherwise>
</choice>
You can do that in the following way:
<setHeader headerName="YOUR_HEADER">
<simple>bean:payloadAndHeaderExtractor?extractHeader(MyCostomMessagePojo obj)</simple>
</setHeader>
Hope this helps.
R.
I am able to called Web Service, now what ever response came from web service, i need to fetch same response in java code so that i am able to further processing.
<camelContext xmlns="http://camel.apache.org/schema/spring" trace="false">
<route id="my_Sample_Camel_Route_with_CXF">
<from uri="file:src/data?noop=true"/>
<log loggingLevel="INFO" message=">>> ${body}"/>
<to uri="cxf://http://www.webservicex.net/stockquote.asmx?wsdlURL=src/main/resources/META-INF/stockquote.wsdl&serviceName={http://www.webserviceX.NET/}StockQuote&portName={http://www.webserviceX.NET/}StockQuoteSoap&dataFormat=MESSAGE"/>
<log loggingLevel="INFO" message=">>> ${body}"/>
</route>
Instead of logging using
I have a situation where I want to pass data into an Aggregator, but I don't want the aggregator to do anything until it has received messages from 3 distinct routes:
<route id="route-1">
<from uri="direct:fizz" />
<to uri="bean:bean1?method=process" />
<setHeader headerName="id">
<constant>1</constant>
</setHeader>
<to uri="direct:aggregator" />
</route>
<route id="route-2">
<from uri="direct:buzz" />
<to uri="bean:bean2?method=process" />
<setHeader headerName="id">
<constant>2</constant>
</setHeader>
<to uri="direct:aggregator" />
</route>
<route id="route-3">
<from uri="direct:foo" />
<to uri="bean:bean3?method=process" />
<setHeader headerName="id">
<constant>3</constant>
</setHeader>
<to uri="direct:aggregator" />
</route>
<route id="aggregator-route">
<from uri="direct:aggregator" />
<aggregate strategyRef="myAggregationStrategy" completionSize="1">
<correlationExpression>
<simple>header.id</simple>
</correlationExpression>
<to uri="bean:lastBean?method=process" />
</aggregate>
</route>
The way this is configured, when the aggregator's completionSize is set to 1 or 2, the aggregated Exchange is routed on to my lastBean. However, if I set completionSize to 3, for some reason, lastBean#process never gets invoked.
I'm sure that I'm using header.id and the aggregator incorrectly here. In the correlationExpression, I just need to make sure that we have 1 Message from each of the 3 routes.
So my question: what do I need to do to make my aggregator "wait" until it has received 1 message from route-1, 1 message from route-2 and 1 message from route-3?
If you are correlating messages from three routes, there needs to be a way for them all to have a matching header.id value by the time they reach the aggregating route.
In your example, each route sets a different id value so there would be no match. If you set the id value to "1" in each route, I think it would start to work as expected.
I have a service which has two operations.
RegisterUser
UpdateUser
I have a camel rout:
<camel:route id="myRoute">
<camel:from uri="cxf:bean:myListenerEndpoint?dataFormat=POJO&synchronous=true" />
<camel:bean ref="processor" method="processMessage"/>
<camel:to uri="xslt:file:resources/service/2.0.0/UserRegistration.xsl"/>
<camel:to uri="cxf:bean:myTargetEndpoint"/>
</camel:route>
In my processor bean, when I specify:
RegisterUser registerUser = exchange.getIn().getBody(RegisterUser.class);
I get the register user object. Everything works fine.
The problem is that I want camel to route my request conditionally, for e.g:
If the service operation is RegisterUser I want to route the message to my specific bean and if the service operation is UpdateUser I want to route the message to the other bean.
I have tried to use camel xPath, but it not seems to be working.
<camel:route id="myRoute">
<camel:from uri="cxf:bean:myListenerEndpoint?dataFormat=POJO&synchronous=true" />
<camel:choice>
<camel:when>
<camel:xpath>
//RegisterUser
</camel:xpath>
<camel:bean ref="processor" method="processMessage"/>
<camel:to uri="xslt:file:resources/service/2.0.0/UserRegistration.xsl"/>
</camel:when>
</camel:choice>
<camel:to uri="cxf:bean:myTargetEndpoint"/>
</camel:route>
I was searching how to set up camel to route to the different targets but did not find anything. Maybe somebody knows where might be the problem?
The information of the operation required will be in the header of the message.
The header you are looking for is called 'operationName'
So here is an example :
<camelContext xmlns="http://camel.apache.org/schema/blueprint">
<route id="example">
<from uri="cxf:bean:myListenerEndpoint?dataFormat=POJO&synchronous=true" />
<log message="The expected operation is :: ${headers.operationName}" />
<choice>
<when>
<simple>${headers.operationName} == 'RegisterUser'</simple>
<bean ref="processor" method="processMessage"/>
<to uri="xslt:file:resources/service/2.0.0/UserRegistration.xsl"/>
</when>
<when>
<simple>${headers.operationName} == 'UpdateUser'</simple>
<!-- Do the update user logic here -->
<bean ref="processor" method="updateUser" />
</when>
</choice>
<to uri="cxf:bean:myTargetEndpoint"/>
</route>
</camelContext>
(Note the example is using apache aries blueprint - but it will be identical for spring, other than the namespace)
try using camel-simple expressions instead of xpath for this...
<when><simple>${body} is 'com.RegisterUser'</simple><to uri="..."/></when>
Spring XML route
In my case I use inbound Jetty EP.
I check parametr in request.
Invole URL http://localhost:8080/srv?alg=1
<choice id="_choice1">
<when id="_when1">
<simple>${in.header.alg} == '1'</simple>
<log id="_log10" message="LOG ALG 1"/>
</when>
...
<otherwise id="_otherwise1">
<setFaultBody id="_setFaultBody1">
<constant>Return message about ERROR</constant>
</setFaultBody>
</otherwise>
</choice>
final CamelContext context = exchange.getContext();
if (isAlive) {
context.startRoute("table-reader-route");
log.info("starting dailycase route= " + response);
} else {
context.stopRoute("table-reader-route");
log.info("stoping dailycase route= " + response);
}