Load different jndi.properties file in spring application context depending on profile - spring

I have a jms connection settings that is defined in jndi.properties file on my classpath which I used to connect to ActiveMQ in my local development environment. I would like to rename this file to "activemq.jndi.properties" as I am planning to have another jms connection settings to WebsphereMQ ( say webshperemq.jndi.properties ). However I have no success so far in telling spring in my applicationContext.xml to look at activemq.jndi.properties.
Here is a snippet of my applicationContext.xml which works for jndi.properties
<!-- Define how to connect to the Message Queueing system -->
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${jms.connectionFactory}" />
<property name="resourceRef" value="true" />
</bean>
<bean id="defaultDestination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="${jms.topic}" />
<property name="resourceRef" value="true" />
</bean>
<!-- Define a connection template that links to the factory -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="defaultDestination" ref="defaultDestination" />
<property name="receiveTimeout" value="6000" />
</bean>
Both ${jms.connectionFactory} and ${jms.topic} are being filtered from maven. Any input on what needs to be changed in my applicationContext.xml to make it load from activemq.jndi.properties would be much appreciated.
Thanks!

Well, Ithink you should configure maven resources so use one of another configuration file depending of the profile instead change anything in your Spring configuration file.
For example:
<profiles>
<profile>
<id>local</id>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>jndi.properties</exclude>
</excludes>
</resource>
</resources>
</build>
</profile>
<profile>
<id>webshpere</id>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>webshperemq.jndi.properties</exclude>
</excludes>
</resource>
</resources>
</build>
</profile>
</profiles>

Related

How to passing Maven Profiles value to Spring Bean XML

I'm new in Spring & Maven, I think my question is simple. But I cannot to figure and setup it. I have Maven POM like below:
<profiles>
<profile>
<id>qa</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<db.driverClassName>oracle.jdbc.driver.OracleDriver</db.driverClassName>
<db.url>jdbc:oracle:thin:#10.148.36.89:1521:mmki</db.url>
<db.username>APW</db.username>
<db.password>apw</db.password>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<db.driverClassName>oracle.jdbc.driver.OracleDriver</db.driverClassName>
<db.url>jdbc:oracle:thin:#10.148.36.88:1521:mmki</db.url>
<db.username>APW</db.username>
<db.password>apw</db.password>
</properties>
</profile>
</profiles>
My question is how I can passing the value from Maven profile to Spring bean property like below:
<!-- QA ENVIRONMENT -->
<!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#10.148.36.89:1521:mmki" />
<property name="username" value="APW" />
<property name="password" value="apw" />
</bean> -->
<!-- PRD ENVIRONMENT -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#10.148.36.88:1521:mmki" />
<property name="username" value="APW" />
<property name="password" value="apw" />
</bean>
I'm so dumb for this question, but please everyone to answer and explain with the simple method.
Many thanks.
First:
Do not write user and pass at pom.xml file
Second:
You can have one applicationContext for each environment like applicationContext-prod.xml and applicationContext-qa.xml
On your pom.xml you can have one property for each profile like:
pom.xml
<profile>
<id>qa</id>
<properties>
<appContext>classpath:applicationContext-qa.xml</appContext>
...
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<appContext>classpath:applicationContext-prod.xml</appContext>
...
</properties>
</profile>
In web.xml you can write you context param like:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>${appContext}</param-value>
</context-param>
If you write your passwords in the applicationContext files you do not need anything else. But, for security reasons I recommend you as best practice write your sensible environment values at external properties file:
You can have multiple *.properties on /etc/app
(production.properties and qa.properties)
And finally, on your applicationContext-prod.xml you can have your propertyConfigurer like:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>file:/etc/app/production.properties</value>
</property>
</bean>
....
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
....
<property name="password">
<value>${db.password}</value>
And on your applicationContext-qa.xml you can have your propertyConfigurer like:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>file:/etc/app/qa.properties</value>
</property>
</bean>
...
Obviously on your /etc/app/production.properties you have to write:
db.password=prodpass
Finally, on your /etc/app/qa.properties you have to write:
db.password=qapass

Reading properties from a file to a spring context in a Confluence plugin

I'm trying to read in a property file to a spring context in a confluence plugin. I've added to META-INF/spring the following context file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:atlassian-spring="http://www.atlassian.com/schema/atlassian-spring"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.atlassian.com/schema/atlassian-spring http://www.atlassian.com/schema/atlassian-spring/atlassian.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="db.properties"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="url" value="${db.url}" />
<property name="driverClassName" value="${db.driver}" />
<property name="username" value="${db.user}" />
<property name="password" value="${db.password}" />
</bean></beans>
Also to the pom.xml I've added the following dependency:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>2.5.6.SEC02</version>
<scope>provided</scope>
</dependency>
Unfortunately I keep getting the ClassNotFoundException for PropertyPlaceholderConfigurer.
As far as I can tell this is an OSGi problem - because the class isn't referenced from code it is not added by OSGi.
Here: https://developer.atlassian.com/display/DOCS/ClassNotFoundException I have found that I should add Import-Package to the spring beans package in the atlassian-plugin.xml but adding this:
<bundle-instructions>
<Import-Package>org.springframework.beans*</Import-Package>
</bundle-instructions>
Does not help.
Any suggestions?
The spring version which mentioned above has OSGI bundles? Can you confirm? Because for some spring versions does not have OSGI bundles. In that case, you need convert to bundles yourself. If its not a OSGI bundle. then package wont be exposed and class wont be able to find , hence your getting above error.
Some details about spring OSGI bundles.
http://ebr.springsource.com/repository/app/
http://www.srikanthugar.in/2014/04/sspring-framework-is-no-longer.html
http://www.srikanthugar.in/2014/04/how-to-convert-spring-beans-artifact-to.html
I found the answer to my question. In order to configure OSGI in confluence one should configure the maven plugin:
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-***-plugin</artifactId> <!-- *** is the name of the application (product) you're using -->
<version>3.2.3</version>
<extensions>true</extensions>
<configuration>
<productVersion>${product.version}</productVersion>
<instructions>
<!-- OSGi instructions go here -->
</instructions>
</configuration>
</plugin>
and put the Import-Package declarations there.

maven, xml files for different profiles

I have maven pom with 2 profiles: dev and production
I have some xml files in my project. For example persistence.xml . Settings for dev and production environments are different
I need a way to have right files in dev and production assemblies
Maybe possible to have 2 copies of each xml file and put into assemblies right one? Or maybe possible to use settings from pom file inside xml file ?
Any other ideas or best practices?
What you are looking for was already answered here: Maven: include resource file based on profile
Instead of having two files, another solution would be to use properties directly inside the properties.xml:
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.username" value="${db.username}"/>
<property name="hibernate.connection.password" value="${db.password}"/>
<property name="hibernate.connection.url" value="${db.connectionURL}/database"/>
In your pom.xml, define a value for each property for each environment:
<profile>
<id>development</id>
<properties>
<db.username>dev</db.username>
<db.password>dev_password</db.password>
<db.connectionURL>http://dev:3306/</db.connectionURL>
</properties>
</profile>
<profile>
<id>production</id>
<properties>
<db.username>prod</db.username>
<db.password>prod_password</db.password>
<db.connectionURL>http://prod:3306/</db.connectionURL>
</properties>
</profile>
You could then use filtering to enable token replacement by the right value in each environement:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
For mode details on this solution look at this page.
If you really need to have two copy of the same file, you could also use the

How can I use maven profile Id value in spring bean files?

mvn -P dev
If I build my project using profile dev, then I want to use dev.properties in my spring bean like below. Is it possible ? If so , how could I get profile name ?
<bean id="xyz" class="abc.xyz">
<property name="propertyFile" value="${maven_profile_id}.properties" />
</bean>
Thanks in advance.
You can use Maven profiles to add a 'profile' property to the build:
<profiles>
<profile>
<id>dev</id>
<properties>
<profile>dev</profile>
</properties>
</profile>
</profiles>
Then pass the value into your application using a system property, here's an example with surefire:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<profile>${profile}</profile>
</systemPropertyVariables>
</configuration>
</plugin>
Finally this can be referenced in you application:
<bean id="xyz" class="abc.xyz">
<property name="propertyFile" value="${profile}.properties" />
</bean>
Alternatively, if you are using Spring 3.1 or later you might find the XML profile feature meets your needs (although it may be overkill).
Create a properties file that will be populated using Maven's resource filtering that specifies the profile you are using at build time.
build.properties
activatedProfile=${profileId}
pom.xml (You don't need to filter the complete directory, customise as required)
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resources>
</build>
Add a profileId (or whatever you want to call it) property under each different profile:
<profile>
<id>dev</id>
<properties>
<profileId>dev</profileId>
</properties>
</profile>
<profile>
<id>qa</id>
<properties>
<profileId>qa</profileId>
</properties>
</profile>
You can then use ${activatedProfile}.properties as value for a bean
<bean id="xyz" class="abc.xyz">
<property name="propertyFile" value="${activatedProfile}.properties" />
</bean>

Maven Exposing properties files appassembler

To load environment specific values, in my src/main/resources folder, I have some properties files in different subfolders i.e.
com/app/ws/webservices-dev.properties
com/app/ws/webservices-test.properties
com/app/jms/jms-dev.properties
com/app/jms/jms-test.properties
I am loading these properties through spring
<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/com/app/jms/jms-${ENVIRONMENT:dev}.properties</value>
<value>classpath:/com/app/ws/webservices-${ENVIRONMENT:dev}.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="order" value="0" />
</bean>
ENVIRONMENT is environment variable.
I am using appassembler-maven-plugin to generate the executable .sh file.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<binFileExtensions>
<unix>.sh</unix>
</binFileExtensions>
<programs>
<program>
<mainClass>com.app.MainApp</mainClass>
<name>MainApp</name>
</program>
</programs>
</configuration>
</plugin>
As a result of this all my properties files become part of my generated jar file. I want to expose some of the properties to set their values at deployment time. I have tried following configuration
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<configurationSourceDirectory>src/main/resources/com/app/bootstrap</configurationSourceDirectory>
<configurationDirectory>conf</configurationDirectory>
<copyConfigurationDirectory>true</copyConfigurationDirectory>
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
<binFileExtensions>
<unix>.sh</unix>
</binFileExtensions>
<programs>
<program>
<mainClass>com.app.MainApp</mainClass>
<name>MainApp</name>
</program>
</programs>
</configuration>
</plugin>
But Spring does not load the properties; maybe due to the given path in spring config (see above).
What maven configuration should I use to move my properties files in appassembler\conf folder during package time and have spring load them from the classpath. I am after the configuration that works for both development(in eclipse, unit tests as maven builds) and in deployment.

Resources