Camel type conversion fails in Fuse - apache-camel

I have a camel route with a cxf producer (Camel v2.10):
<to uri="cxf:bean:myCxfEndpoint?dataFormat=PAYLOAD"/>
I know that camel does a conversion to CxfPayload, so I added the following imports to OSGi header:
org.apache.camel.component.cxf,
org.apache.camel.component.cxf.converter,
org.apache.camel.converter.jaxb
So when the producer is triggered the following exception occurs:
org.apache.camel.NoTypeConversionAvailableException - No type converter available to convert from type: my.package.Foo to the required type: org.apache.camel.component.cxf.CxfPayload
I can get rid of this exception by restarting the camel-jaxb bundle, but getting rid of it is not enough: I need to prevent it, because it happens every time I restart Fuse.
Any idea is highly appreciated :)
EDIT
It turned out that the issue doesn't always come up. Sometimes it works after restart, sometimes it doesn't. I tried to play with bundle-levels but it remained unpredictable. I have a feeling that it might be Camel who doesn't load the converters correctly, but based on the trace log it looks like the CxfPayloadConverter is always loaded into the ConverterRegistry.

After 10 hours of tracing and debugging I figured out the solution: I added a manual marshalling before the CXF Producer, like this:
<marshal ref="myDataFormat"/>
<to uri="cxf:bean:myCxfEndpoint?dataFormat=PAYLOAD"/>
Why: My assumption was that it's OK to send any POJO to the Camel CXF Endpoint and it'll be able to handle the Conversion. The only thing I can think of is it matters that in what order Camel loads the Converters. Every second time when it worked in fuse it could make a POJO -> String -> CxfPayload conversion so it could transitively resolve the conversion. I decided not to rely on this transitive conversion logic and checked all the loaded converters. I found that there are certain direct converters registered in the registry between XML Node/Element -> CxfPayload classes. So I decided to trick Camel's logic with marshalling my POJO.

Related

pollEnrich from FTP

I'm trying enrich using dynamically selected remote files on an FTP server using pollEnrich. The remote files must remain in place and can be selected again and again so the endpoint has noop=true and idempotent=false. Everything seems to work fine until multiple requests start coming in that use the same remote file for enrichment, and this results in all but a few of the requests receiving a null body for the new exchange argument in the aggregation strategy. Here is the relevant part of the route, which has been modified slightly to post here:
.pollEnrich()
.simple("ftp://username:password#ftp.example.com/path/files?fileName=${header.sourceFilename}&passiveMode=true&noop=true&idempotent=false")
.timeout(0)
.cacheSize(-1)
.aggregationStrategy(myEnrichmentAggregationStrategy)
I switched to using file:// instead of ftp:// as a test and still experienced the same problems. I also tried different modes for timeout, cacheSize, and also enabling streamCaching since the body is an InputStream. I'm now thinking about implementing a custom read-lock mechanism (processStrategy) but it feels like a long shot workaround. Has anyone else come across this problem and can shed some light on what's wrong?
I believe I've found a solution and it is using the inProgressRepository property on the polling consumer to set a dummy implementation of IdempotentRepository, allowing me to disable the check for in progress files.

In Apache Camel, for which component will create endpoints if it's not exist?

I'm new to Camel, and have some basic questions which can't found the answers online. Please help and I'm appreciate it.
I have read many example online, and saw bunch example like this:
from(direct:A).to(jms:queue:B)
But didn't see any configuration for them. My question is what will happen if the direct doesn't exist? How about from(jms:queue:A).to(direct:A)? and what about the other components?
For this example, what's the execution order? does it pass the original message to B first, then process and pass to C?
from(direct:A)
.to(jms:B)
.process(something)
.to(jms:C)
Direct is an in memory queue, provided by Camel. Prior it Camel 3, it was bundled with the camel-core module and you would not need any configuration at all in order to use the direct component. However, due to sake of modularity, since Camel 3, direct has been made its own component and in order to use it camel-direct needs to be imported.
Jms on the other hand is a generic component, using which you can implement connectivity to different Jms providers such as ActiveMq(though in Camel activemq has it's own component), IBM MQ, Weblogic JMS server, and others.
For your 1st question, if direct doesn't not exist, you need to import the direct component into your build. If the uri provided to the component is not present, Camel will create its own. This is true for most of the Camel components. One of the most common is the file component, which is used to pick up files from a given directory. If the given directory is not present, Camel is smart enough to create the directory. Obviously, these are default behaviours and you have a lot of control to pick and choose how you want your route to behave.
For your second question, the route will be processed entirely in order, which is, the message will be picked up from the direct:A, then will be sent to jms:B. After that it will be processed using the something processor and will finally be sent to jms:c.
The thing to note here is that the direct:A is just an example to show the syntax of a route. You can use any component which can act as a consumer.

How can I send a notification to an endpoint when a Throttler starts/stops throttling?

As the title says, I would like to send a notification to an endpoint if messages to it start getting throttled, and another message when the throttling stops.
I currently have the following (very basic) route configuration:
from("test-jms:queue:test.queue")
.throttle(2)
.to("file://test");
This configuration throttles messages just fine, but I need a way to let the consumer know that the messages are being throttled.
When the Throttler starts throttling, I would like to send a notification to the 'to' endpoint so those reading the messages know that they are being throttled. I would also like to be able to send another message when the Throttler is no longer throttling, so the consumer knows the messages are up to date.
This doesn't appear to be something the Throttler does. The only way I see of getting a notification when it starts throttling is setting rejectExecution to true, at which point it will throw an exception. The problem is that execution stops at that point, and no more messages are passed through (since an exception was thrown).
My current thoughts are that I will need to create a custom bean/processor/something that performs essentially the same function as the Throttler, but also injects a message when the throttling starts or stops. I don't want to do that unless I really need to, though. Any help is appreciated. Thanks!
No the throttler eip does not support such information (however you may be able to grab some statistics via JMX). A different thought would be to reverse the direction so the consumers signals upstream when they want new messages (this is what reactive systems does).
I assume the above to write to a file is just some example, what consumers are you using in real life, and do they really need to know that some messages are backed up within a short-time period of 1 second because they are throttled? Also since your source is JMS, you can also look at the route throttling policy, where you can suspend/resume the JMS consumer instead of using the throttler EIP.

Camel executing flow after exception is thrown

I have two different routing classes(RouteBuilder). In first RouteBuilder, it picks the files and does some process and send to another route flow which is defined in the second routeBuilder.
Here the trick, I defined all exception strategies in the first RouteBuilder and expecting the second RouteBuilder to inherit it. I don't know whether camel supports this or not. Please let me know if any problem with this
Now the problem what i am facing is, when the exception is throwing inside Second routeBuilder. It is executing the main route flow as well as the exception strategy.
Yes this is correct behaviour, it depends what and how you want to handle in the expection block.
Here it is explained in details http://camel.apache.org/exception-clause.html

How to route custom Java Listener onEvent using Camel

I haven't been able to find any examples that help me understand what I need to do here, so I'll explain my problem:
I have a Java Bean that implements a custom listener for Pivotal's Gemfire product. It implements an interface known as CqListener, which defines a method as follows:
public void onEvent(CQEvent evt){
...
}
Basically, when we execute a Continuous Query (CQ) on the Gemfire grid, we register this Bean as a Listener that will receive any change in the grid that matches our query.
For example, executing a CQ like
SELECT * FROM /table_name
will give us a CQEvent in the onEvent method whenever anything in the 'table_name' table (in Gemfire it's called a region though) changes (CRUD)
What I am now trying to do is wire up Camel to route anything from this underlying CQ stuff to a custom route. Is there anyway I can tell Camel to say "Hey, anytime a call is made to onEvent, take that and route it somewhere else" ?
The somewhere else I am trying to route to is an Akka Actor. There already is a project that wraps akka and camel (http://doc.akka.io/docs/akka/snapshot/scala/camel.html) but I can't figure out this Endpoint URI business to get the inbound CQ events.
I know I am missing a conceptual key regarding Camel, so any help is greatly appreciated. I have managed to implement this using a jms endpoint, so I get how it works for the well known protocols, but I'm just trying to figure out how to do this for custom protocols where the implementation is abstracted away from me (As is the case of CQListener)
I added the "spring-integration" label to your post. Someone from the Spring Integration team may have more experience, or ideas with regard to this sort of problem.
Also, Spring Integration's GemFire Suppor documentation specifically, and surrounding documentation in general, may give you additional ideas, or options.

Resources