How I can create a camel globalObject? - apache-camel

I need a global Object for all routes, processes and Components. In this global Object I would save configuration parameters. But I don't know how and where I can set a global Object, and how I can read it in my own process and my own components.
I create the camel Context in Spring and have a RouteBuilder to build my routes.
Thank you

If you want to setup your route, then you may use PropertyPlaceholderConfigurer, see here:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<camelContext xmlns="http://activemq.apache.org/camel/schema/spring">
<route>
<from uri="activemq:${someQueueName}"/>
<to uri="mock:results"/>
</route>
</camelContext>
Alternatively, you may use ApplicationContextRegistry that allows you to look up beans in the Spring ApplicationContext. This implementation is automatically used when you’re using Camel in a Spring environment, see here. E.g., access the registry as follows:
String myValue = exchange.getContext().getRegistry().lookupByNameAndType("myKey", String.class);

Related

Camel activemq component - TTL

I want old messages to be automatically removed from topic so I'm using the option timeToLive which is described in the Camel ActiveMQ component documentation. However, it only works with queue and not with topic. Any idea why?
For testing purposes I made this simple route:
<route>
<from uri="timer://foo?repeatCount=1"/>
<to uri="activemq:topic:test?timeToLive=10000"/>
</route>
Route sends message to my test topic with TTL=10seconds. I would expect that after 10 seconds message would disappear.
When I use queue instead everything works as expected ( <to uri="activemq:queue:test?timeToLive=10000"/> )

Encapsulate backend specifics with custom Camel component that wraps existing component

We have different backends (mostly SOAP so I will focus on this) each with its own specifics (security, default timeout, error handling etc).
On the other hand we have a lot of integration services that orchestrate calls to these backends. For example "service A" first calls "backend 1" and then "backend 2" with SOAP requests. Finally it uses the responses of both backends to create a response.
There are a lot of services like "service A", each of them has an individual orchestration. Each of them is an individual project with its own repository and is deployed as a small Spring-Boot unit.
Let's say that 4 out of 10 services call "backend 1". They do not necessarily call the same service of "backend 1", but they all need to implement the specifics of this same backend. For example send special headers, a specific security token, use a retry strategy for this backend etc.
To avoid that every integration service repeats the specifics for "backend 1" or "backend 2", I would like to somehow encapsulate these specifics.
Because we use Apache Camel, I assume that I could do this with a custom Camel component. But because components typically integrate a new type of backend, I don't know if I should do this or if it is a bad idea. My backend types (for example SOAP) already exist as components, I would just wrap them with specifics.
For example to "encapsulate" a SOAP backend I could create a custom component that delegates to the CXF component to create concrete service endpoints with the common specifics of this backend (headers, security, etc).
In the Camel route the endpoints would perhaps look somehow like this
MyBackend://serviceUri?option1=value1
and under the hood it would create
cxf://serviceUri?backendSpecific1=valueA&backendSpecific2=valueB&option1=value1
Or are there other, better suited extension points to use for this use case?
There is a way to achieve this to some level. Its called endpoint reuse. Let me take you on how I typically tackle a problem like this.
I normally declare all my SOAP and JMS enpoints in my camel-context.xml. I then create xml files for each route and reference the endpoints defined in my camel-context.xml from there.
Here is a short example of my camel-context.xml note the routeContextRef element:
<bp:blueprint
xmlns="http://camel.apache.org/schema/blueprint"
xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd
http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0 http://aries.apache.org/schemas/blueprint-ext/blueprint-ext-1.2.xsd">
<camelContext id="foo-bar" trace="{{camel.context.trace}}" autoStartup="true" useMDCLogging="true" useBreadcrumb="true" depends-on="jms" threadNamePattern="#camelId#-thread-#counter#" managementNamePattern="#camelId#-#version#" allowUseOriginalMessage="false" streamCache="false">
<routeContextRef ref="foo-bar-routes"/>
<endpoint id="jms-gateway-v1" uri="jms:queue:Foo.Bar.System.Evt.1.0.T" />
<endpoint id="rs-gateway-v1" uri="cxfrs://bean://rs-gateway-impl-v1" />
</camelContext>
I then create a foo-bar-routes.xml and I reference the endpoint from there like so:
<bp:blueprint xmlns="http://camel.apache.org/schema/blueprint"
xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ers="http://www.fooxml.com/events/resourceitem/service/v1"
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<routeContext id="foo-bar-routes">
<!--
This route receives an event from the JMS queue
-->
<route id="jms-gateway-route-v1">
<from ref="jms-gateway-v1" />
<to ref="rs-gateway-v1" />
</route>
</bp:blueprint>
So in short I wrap my SOAP and JMS components in endpoint definitions and then reuse these in routes that are defined in the own xml document. I could add a second route in another XML file and reuse the endpoint in that route just add, rinse and repeat.
I know the JavaDSL has similar functionality so it is achievable as well using the JavaDSL as well.

Kaha DB message store to persist Files in camel

This is my Camel Route:
<route>
<from uri="file:///c:/"/>
<to uri="file:///D:/"/>
</route>
In case of any failure in this route I want to persistently store files in Kaha DB so that files won't be lost. But am not aware of blueprint.xml configuration of Kaha DB persistence for storing files. And my Activemq.xml file is as follows
<broker brokerName="kahaDB_Persistence" persistent="true" useShutdownHook="false">
<persistenceAdapter>
<kahaDB directory="${data}/kahadb/"
journalMaxFileLength="100mb"
concurrentStoreAndDispatchQueues="false"
concurrentStoreAndDispatchTopics="false"/>
</persistenceAdapter>
</broker>
Please advise me how to connect to this KahaDB from blueprint.xml by considering above mentioned route.
Camel's file component has a built in archive feature that saves files that have been processed. It copies them into a folder called ".camel", but it can be changed with a configuration option.
I would not recommend using KahaDB, as it doesn't fit the "right tool for the job" mantra.
Camel File component docs

Difference between CamelContext and Registry in Camel

I'm new to Camel and bit confused between CamelContext and Registry.
As far as I know that CamelContext is the base object like ApplicationContext in Spring that is used for add routes and maintains the camel life cycle.
Also we got the Registry object from CamelContext but not sure what is the main purpose of this registry.
My intention is to add the component in the context/registry so that JNDIBind can look up the components.
CamelContext: Kind of Camel Runtime that keeps everything in Camel together, e.g.: Endpoints, TypeConverter, Routes, Components and Registry(!).
Registry: allows you to lookup beans, which by default will be JNDI beans. If you use the spring integration it will be Spring's ApplicationContext.
Generally camel when used with spring makes use of the ApplicationContextRegistry to lookup components, endpoints etc with the name of the bean defined in spring-bean.xml file. In places where we need to use JNDIRegistry we would have to add that registry when creating the CamelContext. This is used in places where JNDI objects are shared accross multiple JVMs where JNDI is the best solution.
Please see different types of registry implementation for camel: camel registries

JBoss Fuse Camel Route Editor: How to write multicast doing request-response fanout calls, and aggregating all responses into one message sent on?

I'm using "Fuse Tooling Routes Editor" (aka "Fuse Integration Editor", aka "JBoss Fuse Tooling Apache Camel Editor"), described for example here. The version is "Nightly build version 8.0.0.v20150805-1820-H573-MASTER".
I'd like to create a Camel route having a multicast which aggregates the responses it receives from the components it sends a message to, and then forwards the aggregate to a single final receiver. This is certainly doable in Camel, as one of the parameters of a multicast, strategyRef, has the description:
Refers to an AggregationStrategy to be used to assemble the replies from the multicasts, into a single outgoing message from the Multicast. By default Camel will use the last reply as the outgoing message.
However, when I write the following set of routes in my camel-context.xml (which compiles and runs fine):
<route>
<from uri="direct:a"/>
<setExchangePattern pattern="InOut"/>
<multicast strategyRef="x">
<to uri="direct:b"/>
<to uri="direct:c"/>
</multicast>
<log message="This flow works!"/>
<to uri="mock:p"/>
</route>
<route>
<from uri="direct:b"/>
<to uri="mock:q"/>
</route>
<route>
<from uri="direct:c"/>
<to uri="mock:r"/>
</route>
and then click to go to the visual editor, it produces the following (incorrect) picture:
When I switch back to the XML editing, my routes are automatically changed to:
<route>
<from uri="direct:a"/>
<setExchangePattern pattern="InOut"/>
<log message="This flow works!"/>
<to uri="mock:p"/>
</route>
<route>
<from uri="direct:b"/>
<to uri="mock:q"/>
</route>
<route>
<from uri="direct:c"/>
<to uri="mock:r"/>
</route>
And on switching to the editor once again, I get the picture:
This seems like a bug in the editor, but perhaps I'm doing something wrong here?
Many thanks!
Edit:
We found that indeed this used to be an issue logged with the Fuse Camel editor, which however should have been fixed in version 7.1 of the tooling.
that seems to be a bug in the editor. Thank you for reporting it.
I reopened the original issue in Jira. You can track the progress there.
Lars

Resources