Using Apache Camel and Spring, can I build uri using properties? - java

I have created my own component and I want to do something similar to this:
<camel:camelContext id="camel1">
<camel:route>
<camel:from uri="mysch://realthing?network=${network}" id="testEndpoint"/>
I want ${network} to come from a properties file (using Spring properties placeholder):
<context:property-placeholder location="classpath:test.properties"/>
How can I do that?

See this FAQ
http://camel.apache.org/how-do-i-use-spring-property-placeholder-with-camel-xml.html

Related

BridgePropertyPlaceholderConfigurer camel bean

I use the following bean to manage properties in camel as below :
<bean id="ilePropertiesConfigurer"
class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="properties" ref="allProperties" />
</bean>
allproperties is a java class. it works very well when starting the application.
But now, I want to update properties without restarting my application. I update allproperties but it still takes the old values.
Can you help me?
This is not supported in Apache Camel with that Spring property placeholder bridge. You need to restart your application.
OSGi Blueprint has a concept of allowing to reload/restart your application when properties are changed, but it does a full bundle restart command.

Apache Camel file component with dynamic path

I am trying to set dynamic path in camel file component to avoid platform specific paths. But camel is not allowing this as it doesn't expect $ in directory path.
What I am trying to do is to set a VM param say file.home and then use this into my file component like
file:\${file.home}\type1
This will allow me to eliminate the platform specific path directly.
I tried externalizing this into property file but then Spring doesn't understand the camel specific dynamic language for e.g. ${in.header.abc}
Can someone help me out in achieving this.
Those answers are not correct. If you use a BridgePropertyPlaceholderConfigurer and a PropertiesComponent, you can use dynamic values everywhere.
<bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="properties">
<value>
...normal property syntax name=value - use this in test definitions
</value>
</property>
</bean>
Or use something like this in real application
<bean id="dummyPropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="location" value="classpath:/dummy.properties" />
</bean>
e.g.
<route id="DummyRoute">
<from uri="file:{{dummy.int.dir}}?delay={{poll.delay}}&initialDelay={{initial.delay}}&{{readlockChanged}}&move={{root}}/{{dummy.arch.dir}}/{{archive.dir}}&moveFailed={{error.dir}}&scheduledExecutorService=#scheduledExecutorService" />
<to uri="file:{{root}}/{{dummy.int.destination.dir}}" />
</route>
There is a trick with later versions of Camel: use $simple{file.path} instead of ${file.path} so Spring won't strip your ${} and pass the bare file.path to Camel. E.g. a move on an input 'from' uri might be like this:
move=archive/$simple{date:now:yyyyMMdd}/$simple{file:name}
http://camel.apache.org/how-do-i-use-spring-property-placeholder-with-camel-xml.html
http://camel.apache.org/using-propertyplaceholder.html
You can use dynamic uri but only in to endpoints (using specific components). You can't use it as from.
There you can find explanation how to use toD (from Camel 2.16) or recipientList: How to use dynamic URI in to
But as I said - there is only possibility to use it in to. It's not possible to use it in from. As a workaround, you have to write a route for each location you are expecting to be in use. You can also use autoCreate=false option to not creating other directories automatically, because for example Linux path without autoCreate=false option: /home/user/test will create directory structure in Windows c:\home\user\test
Since Camel 2.16
We can use
.from("file://folder")
.toD("file://folder/${file:onlyname}")
Here are some details about using properties within camel and/or spring xml: http://camel.apache.org/using-propertyplaceholder.html
According to Camel File Component:
Camel supports only endpoints configured with a starting directory. So
the directoryName must be a directory. If you want to consume a single
file only, you can use the fileName option e.g., by setting
fileName=thefilename. Also, the starting directory must not contain
dynamic expressions with ${} placeholders. Again use the fileName
option to specify the dynamic part of the filename.
So, you could do somethings like:
from(...).to("file://?fileName=${somePathAndSomeFile}").to(...)
Some of the comments/answers in this thread are misleading, as it's possible to set the value of "from" endpoint URI to have a value of a directory taken from a properties file as asked.
Place propertyPlaceholder element under camelContext, and ensure that the properties file could be found in the classpath
<propertyPlaceholder location="dir.properties" />
<from id="_fromInputFolder" uri="file:{{fromDir}}?"/>

Spring file configuration with conditions

In my spring configuration I am loading a file with all the cxf services when I start a test. Sometimes, I don't want load these services on my tests because aren't necessary and I want work quickly.
I have all my cxf services loaded in this way:
<import resource="classpath:services-app-ib-es-test.xml" />
Can I change this line to read it only on conditional way? Something like this:
<if javavm param loadcxf = true>
<import resource="classpath:services-app-ib-es-test.xml" />
</if>
Edit: I am using spring-core-2.55
Thanks
With Spring 3.1 you could use the Profile feature, giving the profile as JM argument or in a property file.
I don't know about spring 2.x.
http://docs.spring.io/spring/docs/3.2.0.RELEASE/spring-framework-reference/html/new-in-3.1.html
http://spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile/
http://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/

Get Spring Environment as Properties

I wonder if there is a way to extract properties from Spring Environment (e.g. obtained from ApplicationContext) in the form of Properties instance? Or, at least, is there a way to enumerate the properties in Spring Environment, or get them all as a map, or any other way I can turn a [initially unknown] set of properties into a Properties object?
I need this in order to create a jclouds Context by calling org.jclouds.ContextBuilder.newBuilder() and .overrides(Properties). The idea is to configure the actual cloud provider solely by means of .properties file, and I don't want to couple application logic with provider-specific properties.
[UPDATE]
The .properties files to be used are configured using <context:property-placeholder>, and it actually specifies a list of paths, like this:
< context:property-placeholder location=
"classpath:/jdbc.properties,
file:${jboss.server.config.dir}/jdbc.properties,
file:${catalina.home}/conf/jdbc.properties"
ignore-resource-not-found="true"/>
which suggests that the .properties file is searched in the mentioned list of locations in order. I would like to achieve the following:
keep the list of .properties files and their possible locations in this XML definition file only;
allow to place jclouds related properties in any of the .properties files mentioned in the XML;
access the properties, resolved and loaded by Spring, in the form of Properties object so I am able to feed that to jclouds ContextBuilder.
Please let me know if all of this is feasible. Thank you in advance!
-Vlad
If you wan't to use properties in your Spring configuration then you can simply use:
<context:property-placeholder location="classpath:foo.properties" />
To get the properties in your code later you can simply read this file from the classpath into a Properties object:
props.load(MyClass.class.getClassLoader().getResourceAsStream("foo.properties"));
Alternatively you can have a look at PropertyPlaceholderConfigurer.
UPDATE
Updated after Deinum's remark but only if you are getting the properties from a Spring managed bean:
<util:properties id="myProps"
location="classpath:foo.properties"/>
<context:property-placeholder properties-ref="myProps" />
Now you can inject myProps into Spring managed beans (no need to load them again from the classpath).
You could use PropertiesFactoryBean and do something like this:
<bean id="jcloudsProps"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>your/props/file.properties</value>
</property>
</bean>
You can then use jcloudsProps as you would any other Spring bean.

Apache CXF Logging

I have some problems with my server-client communication via web services with Apache CXF framework. I want to log the server errors to an external file instead of terminal. Piece of code for server;
server= new JaxwsNotificationBroker("Hello",..);
server.setAddress("http://localhost:" + brokerPort + "/wsn/NotificationBroker");
And I tried this for logging;
server.getInInterceptors().add(new LoggingInInterceptor());
server.getOutInterceptors().add(new LoggingOutInterceptor());
But it gives the error The method getInInterceptors() is undefined for the type JaxwsNotificationBroker.
Is there any method to log the errors for JaxwsNotificationBroker?
Thank you
You can add loggingInInterceptor & logOutInterceptor inside cxf:bus
<cxf:bus>
<cxf:ininterceptors>
<ref bean="loggingInInterceptor" />
</cxf:ininterceptors>
<cxf:outinterceptors>
<ref bean="logOutInterceptor" />
</cxf:outinterceptors>
</cxf:bus>
add this to your spring config file, if you are using spring:
<cxf:bus>
<cxf:features>
<cxf:logging />
</cxf:features>
</cxf:bus>
don't forget to add cxf namespace as
xmlns:cxf="http://cxf.apache.org/core"
If you use log4j for logging you must put a META-INF/cxf/org.apache.cxf.Logger file onto the classpath with the 'org.apache.cxf.common.logging.Log4jLogger' class name in it as a single line, otherwise cxf will use the JavaTM 2 platform's core logging facilities.
For some reason, gnodet wanted to keep all the WS-N stuff as independent from CXF as possible and only rely on pure JAX-WS stuff. Thus, nice methods for things like the CXF interceptors aren't possible. :-(
Looking at the code, the only option right now would be to write a subclass of JaxwsEndpointManager that would call the super.register method, then cast it to the CXF EndpointImpl, and set the interceptors on there. Not really ideal. :-(

Categories

Resources