Reading Camel Constant From Property file - apache-camel

I am trying to read time delay from property file .
have defined in my property file :
time_inMilis=15000
I have configured my camel context xml to be :
<bean id="property" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>file:/D:/Develop/resources/my.properties
</value>
</property>
</bean>
<camel:camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties" location="file:/D:/Develop/resources/my.properties"/>
<camel:route id="delayQueue">
<camel:from uri="seda:queue1" />
<delay asyncDelayed="true">
<constant>${time_inMilis}</constant>
</delay>
<camel:to uri="seda:queue2" />
</camel:route>
</camel:camelContext>
camel do not throw any error but it seems that it ignores ${time_inMilis} and set 0 for my delay time.
What is the right way to read the delay constant from my property file ?

First, it would be enough just to use camel:propertyPlaceholder instead of declaring bean property.
Second mistake is that you are using Constant instead of Simple expression when trying to read your time_inMilis property value.
Third, when trying to get value of you property, you should specifically tell Camel that your are looking at properties.
If your context defines propertiesPlaceholder like this:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="props" location="classpath:/org/smp/eip/sample.properties"/>
<package>org.apache.camel.example.spring</package>
</camelContext>
them with java DSL you'll be able to read the textProeprty value like this
from("file:src/data?noop=true")
.transform().simple("Text read from properties: ${properties:textProperty}")
.bean(new SomeBean());
Using Spring DSL from your original post, the correct way of reading property would be:
<camel:route id="delayQueue">
<camel:from uri="seda:queue1" />
<delay asyncDelayed="true">
<simple>${properties:time_inMilis}</simple>
</delay>
<camel:to uri="seda:queue2" />
</camel:route>

Related

How to use properties with the SimpleRegistry in Apache Camel (Spring XML)

I want to use a SimpleRegistry to store properties (as global variables). The property is changed with setProperty in a route with a jms endpoint. The camel documentation changed last week and has many dead links, also the Registry page. I did not found any samples that describe the use of the simpleRegistry.
I used the camel-example-servlet-tomcat as base. I do not use Fuse or the patched camel wildfly, because is to huge for our simple module.
<beans .... >
.
.
.
<bean id="simpleRegistry" class="org.apache.camel.support.SimpleRegistry" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties" location="ref:simpleRegistry" />
<route id="storeConfig">
<from id="myTopic" uri="jms:topic:myTopic?selector=Configuration %3D 'xyz'" />
<log id="printHeader2" message="Received header: ${headers}" />
<log id="logToken" message="Received token: ${headers[myToken]}" />
<setProperty id="setMyToken" name="myProperty">
<simple>${headers[myToken]}</simple>
</setProperty>
</route>
<route id="externalIncomingDataRoute">
<from uri="servlet:hello" />
<transform>
<simple>The Token is: {{myProperty}}</simple>
</transform>
</route>
</camelContext>
</beans>
With the camel context deined like above, I got a java.io.FileNotFoundException Properties simpleRegistry not found in registry.
When I use <propertyPlaceholder id="properties" location="classpath:test.properties" /> and create a test.properties file, everything works fine but I cannot change the property. The operation in the setProperty tag is ignored.
The reason why I need a global variable is, I send a dynamic configuration (the myToken) via a jms topic to the camel context. A single route should store this configuration globaly. If an other route is called via an rest component, this route need the token to make a choice.
Alternatively you can achieve the same result following the below approach which uses the PropertiesComponent
<bean id="applicationProperties" class="java.util.Properties"/>
<bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent">
<property name="location" value="classpath:application.properties"/>
<property name="overrideProperties" ref="applicationProperties" />
</bean>
Define the property place holder in the camel context:
<propertyPlaceholder id="propertiesRef" location="ref:applicationProperties" />
Set a property as shown below :
<bean ref="applicationProperties" method="setProperty(token, 'Test'})" />
And to fetch the property : ${properties:token}
OK, there are multiple subjects in your question.
You write you want to use Camel SimpleRegistry, but you obviously have a Spring application.
If you got Spring available, the Camel Registry automatically uses the Spring bean registry. The Camel Registry is just a thin wrapper or provider interface that uses whenever possible an available registry of another framework.
The Camel SimpleRegistry is only used when nothing else is available. This is basically an in-memory registry based on a Map.
You want to set an application property with <setProperty>.
<setProperty> sets an Exchange property, NOT an application property. With this you can save values in the Exchange of a message.
You want to use "global variables".
You could perhaps use a Spring singleton bean that is a Map. You could then autowire it where you need it, it would be like an application wide available map.
However, think twice why you need this kind of variable. This could also be a symptom of a design problem.

read value from property file for from URI in apache camel

Below is my camel context, but reading vlaue from property file doesnt work, it is not listening to Queue which is mentioned in queueName. Is using poll
enrich A good Idea, because it uses direct component?
<bean id="bridgePropertyPlaceholder"
class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="location" value="classpath:/config/queue.properties"/>
</bean>
<Route>
<from uri="activemq:queue:{{queueName}}/>
.......
</Route>

Camel Component: setting a Property dynamically from a Bean

I have defined a Camel Route in a Jboss Fuse BluePrint. I'd need to set one variable at runtime from a Bean. See this example:
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route id="wsClient">
<from uri="timer:foo?repeatCount=1" />
<setBody>
<simple>Message</simple>
</setBody>
<transform>
<method bean="myBean" method="transform" />
</transform>
<to uri="cxf:bean:MyWebService?defaultOperationName={{operation}}" />
<to uri="mock:result" />
</route>
</camelContext>
In this example, I'd like to set the property named "operation" within the bean "myBean". Is it possible to do it?
Thanks!
Yes, it is possible.
First, set a header from the bean and later use http://camel.apache.org/recipient-list.html
I am not familiar with Spring DSL, but in Java DSL it would look like this:
.recipientList(simple("cxf:bean:MyWebService?defaultOperationName=${header.operation}"))
Yes you can do that inside the bean. No need to pass any specific parameter. Camel can bind the exchange, body...etc as a method parameter automatically. Ref: http://camel.apache.org/bean-binding.html
using below code you can set the header or property
exchange.getIn().setHeader("HeaderName", "Value");
exchange.setProperty("Key", "Value");

Is There a way to treat a large file?

I m using apache Camel to treat files.
However, i m asking if i can split a file depending on the number of byte.
For exemple , if i have a file with a size like 1 GO, is that possible to read it by block of 10 MO. (with a parameter that defines the size of a block)
Is there a component Camel EIP able to do this ?
I have tried with stream-caching but nothing happened.
<camelContext xmlns="http://camel.apache.org/schema/spring" trace="true">
<properties>
<property key="CamelCachedOutputStreamBufferSize" value="1024"/>
</properties>
<route id="READ-FILE-STREAM-CACHE" streamCache="true">
<from uri="file:src/data?noop=true"/>
<bean ref="readBean" method="readFileStream"/>
<to uri="file:src/out"/>
</route>
</camelContext>
Thanks

How do I process a zip file with Camel using the Spring DSL?

I want to monitor a directory for zip files and then individually process the files in the zip file using Camel and the Spring DSL. Is something like the following possible?
<camel:route>
<camel:from uri="file:/src/Path/"/>
<camel:split streaming="true">
<zipSplit/>
<camel:to uri="bean:fileProcessor?method=processStream"/>
</camel:split>
</camel:route>
Ok so I found that the following works for a zip file containing one file but the question is how can a zip file containing more than one file be processed?
<bean id="zipFileDataFormat" class="org.apache.camel.dataformat.zipfile.ZipFileDataFormat"/>
<camel:camelContext>
<camel:contextScan/>
<camel:route>
<camel:from uri="file:///C:/testSrc/?delay=6000&noop=true&idempotent=false"/>
<camel:unmarshal ref="zipFileDataFormat"/>
<camel:to uri="file:///C:/testDst"/>
</camel:route>
</camel:camelContext>
Note that the file is not being sent to a bean for processing just unzipped into another directory.
This works. Note the log element will give you the details.
<bean id="zipFileDataFormat" class="org.apache.camel.dataformat.zipfile.ZipFileDataFormat">
<property name="usingIterator" value="true"/>
</bean>
<camel:camelContext>
<camel:contextScan/>
<camel:route id="unzipMultipleFiles">
<camel:from uri="file:///C:/testSrc/?delay=30000&noop=true&idempotent=false"/>
<camel:unmarshal ref="zipFileDataFormat"/>
<camel:split streaming="true">
<camel:simple>${body}</camel:simple>
<camel:to uri="log:org.apache.camel?level=INFO&showAll=true&multiline=true"/>
<camel:to uri="file:///C:/testDst"/>
</camel:split>
</camel:route>
</camel:camelContext>

Resources