rabbitMQ message forwarding from one queue to another - apache-camel

Could you please help me to resolve the problem I am facing?
When forwarding message from one queue to another ( no message seems to be published ) ,
steps:
timer publish current date to queue 'inbox'- this part working
from 'inbox' to 'outbox' - this is not working
from 'outbox' to print console
Follows the spring xml.
<route>
<camel:from
uri="rabbitmq://localhost:5672/outBox?sername=guest&password=guest" />
<camel:to uri="stream:out" />
</route>
<route>
<camel:from
uri="rabbitmq://localhost:5672/inbox?username=guest&password=guest" />
<camel:to
uri="rabbitmq://localhost:5672/outBox?username=guest&password=guest" />
</route>
<route>
<camel:from uri="timer:foo?period=10" />
<setBody>
<simple>${body}Message at ${date:now:yyyy-MM-dd HH:mm:ss}</simple>
</setBody>
<to
uri="rabbitmq://localhost:5672/inbox?username=guest&password=guest" />
</route>

According to http://camel.apache.org/rabbitmq.html the URI format is
rabbitmq://hostname[:port]/exchangeName?[options]
Thus inbox in your code is not queue name but exchange.
Use queue= option to specify the queue

Related

Camel exchange failed without an exception

After upgrading from Camel 2.1 to 2.17 and some code modification we are having some problems with the exception handling in Camel. We send message from app A to app B. The happy flow works fine, but the unhappy flow doesn't.
We send the message to cause an exception but it is not correctly handled in the onexception block.
Actually, we see the following tracelog: ProcessTaskEx - message received, but I don't see: ProcessTaskEx - exception
The exception we get from Camel is:
camel exchange failed without an exception: <SOAP-ENV:Fault xmlns:SOAP-ENV>
Our route looks like this, any idea what the problem could be? Thank you very much for your time community! :)
<?xml version="1.0" encoding="ASCII"?>
<routes xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="switchyard://ProcessTaskEx"/>
<log message="ProcessTaskEx - message received: ${body}" loggingLevel="DEBUG" logName="WebServiceQueues" />
<to uri="switchyard://RequestCapacity"/>
<onException>
<exception>java.lang.Exception</exception>
<exception>webservicequeues.utilities.WebServiceQueueException</exception>
<log message="ProcessTaskEx - exception" loggingLevel="DEBUG" logName="WebServiceQueues" />
<redeliveryPolicy maximumRedeliveries="2" redeliveryDelay="60000" maximumRedeliveryDelay="900000" retriesExhaustedLogLevel="INFO" retryAttemptedLogLevel="INFO"/>
<handled>
<constant>true</constant>
</handled>
<log message="Failed after Retry.Sending ProcessTask Request to Error Queue" loggingLevel="ERROR" logName="WebServiceQueues" />
<to uri="switchyard://ErrorProcessTaskExQueue"/>
</onException>
</route>
</routes>
As fas as I remember, faults are not handled by default. In order to enable this a property must be set: handleFault="true". It can be set for the whole Camel context or for individual routes.
Example for a route in XML:
<route handleFault="true">
...
</route

How to add scheduler and custome checks around camel file processing

Before explaining my problem I would state here that I am completely new to camel file processing. I have a requirement to read the file from a directory do some processing and delete them. This was a very high level requirement and I am able to achieve this using camel. But now I've got some new requirements as stated below. Need help on that.
Create this application as a job and trigger it by reading another directory where some specific files would be dropped other wise it should kicked of by its own every 15-20 minutes.
Before triggering the actual application make sure that the directory has some specific number of files present (say 25 files)
If all files are present - execute a method to create a unique tracking ID for all these 25 files. If I have a unique ID how can I make it available through multiple routes?
As of now I have tried implementing routepolicy but since I have never used it earlier I need some guidance so that I can go ahead with this.
1. Separe your route logic from route triggering
<route id="TriggerFromFile">
<from uri="file:triggerFolder" />
<log message="Triggered from file" />
<to uri="direct:startLogic" />
<route>
<route id="TriggerFromTimer">
<from uri="timer:triggerTimer?period=15m" />
<log message="Triggered from timer" />
<to uri="direct:startLogic" />
</route>
<route id="Logic>
<from uri="direct:startLogic" />
<to uri="..." />
</route>
2. Count the number of files and use that as a filter
Define a bean that counts the number of files in the dir, set that number
as body and validate using a filter.
<route id="TriggerFromFile">
<from uri="file:triggerFolder" />
<log message="Triggered from file" />
<to uri="direct:countFile" />
<route>
<route id="TriggerFromTimer">
<from uri="timer:triggerTimer?period=15m" />
<log message="Triggered from timer" />
<to uri="direct:countFile" />
</route>
<route id="FileCount">
<from uri="direct:countFile" />
<to uri="bean:countFilesInDir" />
<log message="There are ${body} files the directory" />
<filter>
<simple>${body} >= 25</simple>
<to uri="direct:startLogic" />
</filter>
</route>
<route id="Logic">
<from uri="direct:startLogic" />
<to uri="..." />
</route>
3. Set a Header to your Exchange's message before sending it to other routes
When Camel sends an Exchange between routes, headers and properties are copied.
Calculate a unique id in some way (concatenate file names, md5 of content, file modification timestamp....) and set it in a Header.
An header can hold any java object.

camel when/otherwise for activemq and seda

I have a route where I'd like to compute if "from" is activemq or something else. I found replaceFromWith, but it seems to be used for testing only. I tried using camel's choice when/otherwise to switch between "from activemq" and "from seda", but that errors out as invalid syntax. I'm looking for something that would do the following:
<route id="doPost">
<choice>
<when>
<groovy>exchange.getIn().getHeader("sometest") != null</groovy>
<from uri="activemq:doPost?..."/>
</when>
<otherwise>
<from uri="seda:doPost?....."/>
</otherwise>
</choice>
Thanks in advance, appreciate the help.
You cannot dynamically select a consumer based on the exchange, the exchange wont exist before consuming it using the <from .../> tag.
Instead, you can construct a route for each consumer, normalize the exchange you receive from different types of consumers, and forward them to a common route for processing.
<route id="activemqConsumerRoute">
<from uri="activemq:doPost?..."/>
<!-- normalize the exchange to be understandable by the next route -->
<to uri="direct:commonProcessingRoute" />
</route>
<route id="sedaConsumerRoute">
<from uri="seda:doPost?....."/>
<!-- normalize the exchange to be understandable by the next route -->
<to uri="direct:commonProcessingRoute" />
</route>
<route id="commonProccessingRoute">
<from uri="direct:commonProcessingRoute" />
<!-- whatever business logic you have -->
</route>

Request only messaging with direct-vm in camel routes

How can we process direct-vm asynchronously?
I have the following Camel routes definition:
<route id="routeA">
<from uri="activemq:queue:queueA" />
<to uri="direct-vm:someProcessing" />
<to uri="direct-vm:processAsync" />
</route>
<route id="routeB">
<from uri="direct-vm:processAsync">
<threads executorServiceRef="someRef">
<inOnly uri="direct-vm:timeTakingRoute" />
<threads>
<route>
When queue consumer consumes message and sends to routeB and calls direct-vm:timeTakingRoute using threads DSL, caller thread which is queueA still waits until thread created using thread DSL completes.
How can we process this asynchronously (Caller thread should not wait until thread created using thread DSL completes)?
Direct component is designed to be synchronous http://camel.apache.org/direct-vm.html
Please try to use seda instead:
<route id="routeA">
<from uri="activemq:queue:queueA" />
<to uri="direct-vm:someProcessing" />
<inOnly uri="seda:processAsync" />
</route>
<route id="routeB">
<from uri="seda:processAsync" />
<to uri="direct-vm:timeTakingRoute" />
</route>
You can either choose seda or vm component.
When using seda, note that queues are only visible within a it's CamelContext.
If you want inter-communication between CamelContext, use vm component, which is an extension to seda component.
Read more: seda vm

Camel + sql + error handling

I have a task to handle all incoming messages within the route and save them to database.
My route starts with webservice (camel-cxf), and then process to ejb and return soap response.
I've decided to use camel-sql component. As far as I don't have any problems with logging incoming message:
<camelContext id="InstitutionContext" xmlns="http://camel.apache.org/schema/spring">
<onException>
<exception>org.example.MyException</exception>
<continued><constant>true</constant></continued>
<to uri="bean:myExceptionHandler?method=handle" />
</onException>
<route id="InstitutionRoute" >
<from uri="direct:start" />
<to uri="sql:insert into translog(id,type,data) values(2,'IN',#)" />
<split>
<tokenize token="\n" />
<unmarshal>
<csv delimiter=";" />
</unmarshal>
<process ref="InstitutionProcessorTest" />
</split>
<to uri="bean:myExceptionHandler?method=checkErrors" />
</route>
</camelContext>
but I don't have idea how to handle exceptions and save them in the form of SOAP message.
<onCompletion onFailureOnly="true">
<to uri="sql:insert into translog(id,type,data) values(2,'ERROR',#)" />
</onCompletion>
but it saves original message in data column. Is there any body who can help?
I might be misunderstanding the question but it looks you are trying to save the SOAP message in XML format if there is a exception.
By default the dataFormat for CXF is POJO meaning it sends a POJO around the camel route i.e. the SOAP XML is converted to a POJO.
Two options come to mind:
Set the dataformat to message or payload. This will send the XML message across the camel route instead of a POJO
Marshall the POJO into a XML message and save it.

Resources