Missing routeId in direct-vm routes - apache-camel

We have found that when we have 2 routes connected via direct-vm in a transaction, with MDC logging enabled, at the point when the second route returns to the first route after the direct-vm call, the routeId in the MDC is missing (everything else in the MDC is intact).
We are on version 2.24.3 and the routes are defined in JAVA DSL bootstrapped within a springboot application.
Debugging with Camel source code takes us to
this class
https://github.com/apache/camel/blob/camel-2.24.3/camel-core/src/main/java/org/apache/camel/impl/MDCUnitOfWork.java
and we can see that on line 112, that is where the routeId is removed
// not running in route, so clear (should ideally not happen)
MDC.remove(MDC_ROUTE_ID);
But I don't fully understand how route context fits into the picture, how a route context is being created in the first place.
There isn't much documentation I can find about route context except that it can be used as a way to group routes in separate XML files and imported into a camel context, which is irrelevant in our case.
Anyone can shed some lights would be much appreciated!
Thanks in advance.

As the UOW on the direct-vm call is done, the CamelInternalProcessor .UnitOfWorkProcessorAdvice.after(Exchange exchange, UnitOfWork uow) is called;
On line
https://github.com/apache/camel/blob/camel-2.24.x/camel-core/src/main/java/org/apache/camel/processor/CamelInternalProcessor.java#L685
the routeContextStack in the UOW object is cleared at
https://github.com/apache/camel/blob/camel-2.24.x/camel-core/src/main/java/org/apache/camel/impl/DefaultUnitOfWork.java#L179
then on line
https://github.com/apache/camel/blob/camel-2.24.x/camel-core/src/main/java/org/apache/camel/processor/CamelInternalProcessor.java#L690
it's trying to get the route context object again from the stack
https://github.com/apache/camel/blob/camel-2.24.x/camel-core/src/main/java/org/apache/camel/impl/MDCUnitOfWork.java#L106
which would be always null as the stack has been cleared;
hence the routeId is removed from MDC as
https://github.com/apache/camel/blob/camel-2.24.x/camel-core/src/main/java/org/apache/camel/impl/MDCUnitOfWork.java#L112
We are on Camel 2.24.3 but the latest Camel master branch at this point seems to behave the same.

Related

How to capture error at compile level in Apache Camel

I have route like
.bean(OrderService.class, "doSomething")
Now my question is if for any reason any developer misspell method name in route, we would not be able to identify at compile level or we may realize after going to production.
How to handle these scenario?
At a minimum I would recommend a test which ensures that your Camel components are registered with the Camel context, and if they're not, one would expect an exception to be thrown at application startup time.
In essence, you would want a Spring test suite (since Camel will leverage Spring's context for its own context) to ensure that your bean is wired in correctly here.
This cannot be a compile-time error or check since this is specific to how the application context is built, which is done dynamically at runtime.

Sharing state in camel?

It appears I am running into issues sharing information between routes.
What is the camel pattern for passing around information ?
I looked at exchange properties but that does not stick around between routes I think...
eg:
one file has one has some configutations
i have a route to read this file
and several other routes that will act on based on the configs,
how do I accomplish this ?
I thought of puttin the values in a singleton bean, but that seems kind of ugly...
Exchange properties are preserved across routes inside camel (but there are some limitations and special cases when using splitter/aggregator etc.)
Assign ID's to all sub routes which will act on based on the config. Then get the suitable Route or RouteDefinition from camel context and check whether you can advice or share information to the route according.
ModelCamelContext modelContext;
modelContext.getRouteDefinition(String routeId) or modelContext.getRoute(String routeId)

stop certain routes instead of completely stopping the whole camel context

I am wondering how can we stop certain routes instead of completely stopping the whole camel context and also is there any other alternative for Thread.sleep(); method for processing.
I would like to run a route once and stop the context when the route is completed. Currently I do the usual Thread.sleep(3000) in the main Java class to leave some time for the route to finish.
I saw some documentation saying camel route supports graceful shutdown but if i don't use Thread.sleep() route shut downs immediately without processing.
the CamelContext has APIs to stop individual routes (startRoute(routeId), stopRoute(routeId), etc) or you can use route policies for more advanced route control
also, to keep your context running, you don't need to use Thread.sleep, just bootstrap the context with Spring or using a Main class...

Transacted camel route with auto-startup set to false

I am in the process of developing a message router which has a bunch of routes that are started and stopped at runtime based some certain conditions.
By default all these routes are configured with auto-starup=false
Now I am trying to add transactional support to these routes and it seems that you cannot define a transacted route and control the its startup behavior at the same time. This is because RouteDefinition.transacted() returns a TransactedDefinition instance which does not have an autoStartup(boolean autoStartup) method.
I am sure I am not the only one to need this kind of functionality and just wondering what is the camel way of addressing such requirements.
Thank you in advance for your inputs
Maybe just set autoStartup first, eg
from("direct:start").autoStartup(false)
.transacted()
.to("mock:result");

Start Camel route in suspended state

Is there a way to build Camel routes that starts in suspended mode?
I'm looking so to say "declutch" at start up, then at some stage quickly start processing messages by just calling resumeRoute(routeId)
I could perhaps just create the route and then quickly call suspendRoute(routeId), after the route has been created, but at that stage, it would probably have consumed some messages (for instance in the case of JMS routes or polling consumer routes).
generally, you'd just disable the route by using autostartup(false)...
I assume you are asking though because you need the route started (warmed), but not active. In that case, then you should be able to use a custom route policy and some external variable to get this behavior

Resources