Apache Camel Environment Property file - java

I am implementing application for job scheduling in apache camel. I am able to read property config data inside camel context xml using spring propertyplaceholder.
How can I pass commandline argument like sit, dev, uat, prod to read config file of specific environment. like app.dev.properties to the camel xml file.
Currently I hardcoded dev in below configuration.
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>Application.dev.properties</value>
</property>
</bean>
and accessing properties in Apache camel as below
<route id="GET-XML-DATA">
<from uri="direct:getxmldata"></from>
<to uri="http://{{appIPAddress}}:{{AppPort}}/getData" />
</route>
I am trying to implement completely xml and less java code

You can use spring beans profile where you can define same bean for different environment. This way you would be able to pick environment specific beans

Related

Using custom registries within apache camel

Apache Camel does not seem to support any bean that is to be used within its registry. I am currently trying to add an AWS S3 Client object/bean to the spring configuration without any luck. The bean itself is added to the registry, but when camel goes to use the client object it throws an error similar to this:
Caused by: java.lang.IllegalArgumentException: Could not find a
suitable setter for property: amazonS3Client as there isn't a setter method
with same type: java.lang.String nor type conversion possible: No type
converter available to convert from type: java.lang.String to the
required type: com.amazonaws.services.s3.AmazonS3 with value
#amazonClient
The amazonClient is the aforementioned bean that is added appropriately the spring config which has led me to believe the camel config is indeed finding the bean. Here is the related xml configuration:
<!-- set up default amazon s3 client from amazon aws sdk -->
<bean id="amazonClient" class="com.amazonaws.services.s3.AmazonS3Client">
<constructor-arg>
<bean class="com.amazonaws.auth.BasicAWSCredentials">
<constructor-arg name="accessKey" value=""/>
<constructor-arg name="secretKey" value=""/>
</bean>
</constructor-arg>
</bean>
Within the camel context section (you can see the bean is mentioned):
<camel:route id="importFilesFromS3">
<camel:from uri="aws-s3://intuit-commerce-imports?amazonS3Client=#amazonClient&region=us-west-2&deleteAfterRead=true"/>
<camel:to uri="ref:importProcessingEndpoint"/>
</camel:route>
Apache camel claims to have this feature in their documentation, but I have found a few sources that come across the same issue. The answer in the link does not provide much explanation.
I've never worked with AWS S3, but I also ran into a similar problem with Camel seemingly not able to find the bean within the Spring registry.
By stepping through IntrospectionSupport.setProperty, I noticed that CamelContextHelper.lookup was using JndiRegistry instead of the ApplicationContextRegistry.
My solution was to add camel-spring as a project dependency, as well as to initialize my camel context with ApplicationContextRegistry:
camelContext = new DefaultCamelContext(new ApplicationContextRegistry(applicationContext));

System property used in camel for velocity template uses default value, not environment-level setting

I'm using Spring and Camel for a small service. Both are drawing on several locations for properties files, including environment-specific settings file specified on the server launch config.
Spring:
<context:property-placeholder
location="classpath*:config/*.properties,classpath:config/*.properties, file:${application.properties.file}"/>
Camel context:
<propertyPlaceholder id="properties" location="classpath:config/camel-constant.properties,
config/application.properties, file:${application.properties.file}"/>
this seems to be fine for eg endpoint configuration:
<endpoint id="supplierEmail" uri="smtp:${mailsender.host}?contentType=text/html"/>
But I want to access a property in my velocity template. If I try eg
<setHeader headerName="environment_id">
<simple>${properties:environment.id}</simple>
</setHeader>
$headers.environment_id in velocity template picks up a value, but it's the default value, not the value from the environment-level properties file.
What have I missed?
Sorry, ignore. Config was pointing at the wrong flipping file.

How spring load configuration file by environment?

I use spring framework in my application,and i use some configuration files,but in different environment,i need to use different properties like db config properties.Now i put different files in different path,then i use maven profile method to package different WAR.
Now,i want to package only one WAR in all environment,and want by transfer different parameters to use different configuration files.In addition i don't want to put the configuration file out of the project.
You can use spring bean profiles or conditional beans.You can use following configuration to define propertyplaceholder beans for each environment.
<beans profile="environment1">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database_env1.properties</value>
</property>
</bean>
</beans>
<beans profile="environment2">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database_env2.properties</value>
</property>
</bean>
</beans>
For database configuration, a possible approach is to define the JDBC DataSource as a JNDI resource directly in your application server that you then use (see how) - this way your WAR file doesn't contain the connection information, the runtime environment does hold this info instead.
One advantage of this approach is that the connection information then can be managed by a server administrator instead of the application developer.
Not sure it meets your "no configuration outside project" requirement though.

Is there a way to pass the file location by jndi in a <util:properties /> tag?

I have the following properties declared in my spring-config.xml
<util:properties id="ldap" location="classpath:com/company/project/resources/some_configuration.properties"/>
Then I inject the values contained in the properties into some member variables using the spring #Value annotation in a service implementation (this approach is by far the cleanest/most elegant I have used in the implementation of the service and if possible I wouldn't want to change it).
The problem with this layout is that I have to modify the properties file and regenerate the application war for every deployment environment (quality, production, etc) and the server admins want to configure the some_configuration.properties path by JNDI (the application server is JBoss)
How can I pass the file location by jndi in the <util:properties /> tag?
Any help and suggestions would be appreciated
edit:
It would be nice if somebody comes out with a solution where I could do something like:
<util:properties id="ldap" location="jndi:url/some_configuration.properties"/>
Or similar
Old post, but this may be useful for others:
<jee:jndi-lookup id="ldapProps" jndi-name="your/jndi" resource-ref="true"/>
<util:properties id="ldap" location="file://#{ldapProps}/some_configuration.properties" />
I was looking something similar, this answer will help you using PropertyPlaceholderConfigurer: https://stackoverflow.com/a/3486315/439427.
HTH
In your case you will need to configure the PropertyPlaceholderConfigurer in your beans then you will just need to do the following change:
<util:properties id="ldap"
location="classpath:x/y/z/resources/${environment}.properties"/>
Where ${environment} will be set by an environment variable like this: -Denvironment=dev

Spring lazy initialization in development environment

In order to reduce the server startup time in development envrionment, I would like to change the default behaviour of Spring to lazily initialize the beans.
I know this can be done by specifying default-lazy-init="true" at the beans level. However I would not want to change this property everytime I get the latest config files from SCM and change it back before checking it back in.
Is there any other way out to externalize this property? Like specifying a System property?
I also tried to define a property in an environment specific property file and refer to the property in beans element, but it did not work.
default-lazy-init="${default-lazy-init-value}"
Any other way this can be achieved easily?
How about taking default-lazy-init in an external properties file and passing it to the bean definition
XML
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:system-env.properties</value>
</list>
</property>
</bean>
<bean id="bean1" class="com.Foo" lazy="${default-lazy-init}"/>
Properties File (system-env.properties)
#set true in dev (if needed)
default-lazy-init=true
You could use the following:
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>
...as described on http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-lazy-init

Categories