I have an endpoint in the route that cannot be instatiated locally - due to some missing properties that are unavailable and cannot be accessed in the local environment.
So when I start the application in local environment I get the error org.apache.camel.FailedToCreateRouteException. However in server environment it works fine.
How to prevent camel from initializing endpoint on the local environment (I have a property that allows to find out whether the environent is local or not)? Something like this
<choice>
<when>
<simple>{{is.local}} == true</simple>
<to uri="direct:local.route"/>
</when>
<otherwise>
<to uri="direct:server.route"/>
</otherwise>
</choice>
But for from clause
Thanks to the idea of MickaƫlB to use profiles, I did like this.
I created camel-route-local.xml and camel-route.xml. First file contains routes that should work in the local environment. Second - routes that operates with endpoints that are not for local environment. File camel-context.xml contains camelContext definition definition.
In my main application-context.xml I added these line at the end of the file
<beans profile="default">
<import resource="classpath:camel-route.xml"/>
<import resource="classpath:camel-context.xml"/>
</beans>
<beans profile="LOCAL">
<import resource="classpath:camel-route-local.xml"/>
<import resource="classpath:camel-context.xml"/>
</beans>
Now, if I run local environment - aka set spring profile as LOCAL - it will load camel-route-local.xml with routes that works for local environment (also I got of rid the check for is.local) and if the environment is not LOCAL - aka any other profile - it will load main routes.
You can use Java DSL for this part only (create simple RouteBuilder) and initialize required "from" part depending on anything you want.
There is "better" alternative solution. Why don't you inject your parameters as environment variables. Then inject those as properties and you can use use Camel's property resolver to inject the properties in your from() or to().
See here under "propertyinject"
http://camel.apache.org/properties.html
Related
I have project A which has below simple route logrouteTest.xml
<routeContext id="CommonLogRoutes" xmlns="http://camel.apache.org/schema/spring">
<route id="logRoute">
<from id="_NSDL_PAN" uri="seda:MyLogRoute"/>
<convertBodyTo id="_convertBodyTo1" type="java.lang.String"/>
<log message="my received body : ${body}"/>
</route>
</routeContext>
I composed this project into JAR.
In my project B I have imported the above jar and trying to refer the Project A route like this
<import resource="classpath:com/tcl/Testjar/logrouteTest.xml"/>
Error
I am getting the below error
java.io.FileNotFoundException: class path resource [com/tcl/Testjar/logrouteTest.xml] cannot be opened because it does not exist
Is there any way to refer the external project camel route from current project route without deploying project A.
Note : I am looking for option to use Project A as ESB library
Update: It took a little time to realize for some reason but I see that configuration files are bundle PID specific and by trying to load the same cfg file in blueprint within two different bundles, I was creating a race condition. Make sure you use the cfg files in their target bundles only.
Note: The above applies only to blueprint bundles. If you do not depend on OSGI ConfigAdmin service to keep the bundles dynamically and want to use the cfg files from something like a Camel context, that should be fine.
I have 2 blueprints deployed through karaf 4.0.8 'deploy' folder. Both have the following common section:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.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 https://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
<cm:property-placeholder id="common" persistent-id="common" update-strategy="reload" placeholder-prefix="$(" placeholder-suffix=")"/>
<cm:property-placeholder id="sqlcfg" persistent-id="12345" update-strategy="reload" placeholder-prefix="$[" placeholder-suffix="]">
</cm:property-placeholder>
I would like to load configuration common to both from 'common'. However, when they share the same persistentId and properties file from the 'etc' folder, the blueprint to be deployed second keeps loading and unloading.
If I get them to load from different files - it all works.
Any ideas from the community why I have this behaviour?
Thanks in advance.
In my experience, you either set a different persistent-id or set update-strategy="none". This will stop the second module from going into that loading/unloading loop.
The downside is that you lose the auto refresh of the config file.
i have jsut upgraded my camel version and some functionality that was working before version 2.16.0 is now broken, I used to be able to get the URI for a toDefinition that replaced a placeholder, having just upgraded, this now doesnt replace the placeholder.
Code example is as follows:
<propertyPlaceholder id="properties" location="config.properties" />
<route>
<from uri="direct:input" />
<to uri="mq:queue:{{MY_PLACEHOLDER}}" />
</route>
config.properties
MY_PLACEHOLDER=FOO
Camel version 2.15.5
toDefinition.getUri() // equals mq:queue:FOO
Camel version 2.16.0
toDefinition.getUri() // equals mq:queue:{{MY_PLACEHOLDER}}
Any ideas?
Yes that is how its intended to be. The model is the model as it was designed (in this case with placeholder value).
The resolved uri is when Camel startup and runs the routes. So you can take that uri, and ask Camel to resolve, there is an API on CamelContext for that resolvePropertyPlaceholders
http://static.javadoc.io/org.apache.camel/camel-core/2.18.2/org/apache/camel/CamelContext.html#resolvePropertyPlaceholders-java.lang.String-
I understand that if you deploy your Camel project to an OSGI environment like Karaf you can simply write:
<cm:property-placeholder id="INT001_********_Properties" persistent-id="INT001_SelfServiceMachine" />
<camelContext xmlns="http://camel.apache.org/schema/blueprint"
id="INT001_SelfServiceMachine" useMDCLogging="true">
<propertyPlaceholder id="properties" location="blueprint:INT001_*********_Properties"/>
And this works when the project is deployed to Karaf and the property file is located there in the etc folder.
But how can you configure it when Karaf is not available?
I used this bean before:
<bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent">
<property name="location" value="classpath:some.properties"
/> </bean>
But is there a single way to refer to property files regardless of when you are in Karaf or when you are in your e.g. Eclipse environment and your property file is in your /src/resources folder and the bean above works? For instance, when you use Jenkins and and want to run tests and build the bundle, you may not have Karaf available.
Thanks for any input on this.
You can maybe implement your own PropertiesResolver which know how to resolve your properties according to the runtime environment. If OSGi is detected, then it can use ConfigurationAdmin, else it can use a static properties file.
Personally, I use something more simple thanks to Spring DM: my beans/configurations are dispatched in multiples files, and all the configuration related to OSGi is regrouped in one file. In Karaf, Spring DM load all XML in META-INF/spring. Outside of Karaf, I filter the XML to exclude the OSGi configuration.
There is a blueprint noosgi bundle around, that one can be used to have the blueprint capabilities outside of the osgi container. With this you're able to stick to your blueprint xml, though you need to change from configuration admin service for property lookup to native blueprint property replacement.
This is the example that is bundled with apache camel binaries
<route>
<!-- incoming requests from the servlet is routed -->
<from uri="servlet:///hello"/>
<choice>
<when>
<!-- is there a header with the key name? -->
<header>name</header>
<!-- yes so return back a message to the user -->
<transform>
<simple>Hello ${header.name} how are you?</simple>
</transform>
</when>
<otherwise>
<!-- if no name parameter then output a syntax to the user -->
<transform>
<constant>Add a name parameter to uri, eg ?name=foo</constant>
</transform>
</otherwise>
</choice>
</route>
How to translate this to Java
Am a beginner in camel, and some how came up to this
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder(){
public void configure(){
from("servlet://hello").transform().....
}
});
But dont know how to proceed further...
If you want to port it over to java without any XML (spring that is) you can't (easily) use the servlet component.
Just porting the route will be like:
from("servlet:///hello")
.choice()
.when()
.header("name")
.transform(simple("Hello ${header.name} how are you?"))
.otherwise()
.transform(constant("Add a name parameter to uri, eg ?name=foo"));
It should work in the spring example (or any spring web app), just replacing the <route> in the <CamelContext> with <routeBuilder ref="demoRoute"> given you have defined your route as a spring bean (<bean id="demoRoute" class="org.example.demo.DemoRoute">).
However, I guess you want to do this in plain java (no spring, no xml, no webapp). You could go with the Jetty component. The difference being that Camel then will start the servlet container, instead of the servlet container starting Camel. No difference for this simple example though.
I suggest you start out with a Maven archetype to get the skeleton up
e.g. mvn archetype:generate then choose org.apache.camel.archetypes:camel-archetype-java (Creates a new Camel project using Java DSL.)
Well, you don't need the maven archetype if you have your own java application and have the thread keep running. Then you should do fine with your approach. The maven archetype is however very good for training purposes.
You then need to add a dependency to Jetty (camel-jetty.jar) (read more here).
The actual route would be exactly the same except the first row: from("jetty:http://localhost:8080/camel/hello")
Nice and easy.
Try this one:
from("servlet://hello")
.choice()
.when(header("name").isNotNull()).transform(simple("Hello ${header.name} how are you?"))
.otherwise().transform(constant("Add a name parameter to uri, eg ?name=foo"));