Spring MVC with several configurations - java

for my spring-mvc application I created several types of configuration (unittest, integration, qa, production). All the configs are in one war-file, so there is only one type of application I create. Which configuration to take should be decided by the server, where the application is running.
To decide what kind of configuration should be used, I have to look into a file. After that I can decide which configuration should be used by spring mvc.
For now by convention there is always the -servlet.xml used. Is there a way how to decide dynamically which config to take?
Regards,
Michael

Here is a solution that I use. It works very well:
Put the configuration differences in property files.
Keep a single Spring xml with placeholders.
Use PropertyPlaceholderConfigurer to set the properties.
PropertyPlaceholderConfigurer can use system properties to resolve the name of the property file to load.
Set a system property with the name of your environment before initilizing the PropertyPlaceholderConfigurer (you can do this in a bean that reads the value out of your file).
And there you go! The environment will be cleanly detected, and the relevant properties will be loaded!
No need to wait for Spring 3.1, you can use this solution today with 3.0.

I have the same setup, but I use maven to build the WARs differently. I use a PropertyPlaceholderConfigurer in the context:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:datasource.properties" ignore-unresolvable="true" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="${jdbc.driver}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}" />
<!--other beans-->
</beans>
then I setup an environments folder:
src
--main
----environments
------dev
--------datasource.properties
------cert
--------datasource.properties
------prod
--------datasource.properties
Then in my Maven pom, I use a build profile to copy anything in the environment folder based on a parameter flag in the maven command:
<profiles>
<profile>
<id>environment</id>
<activation>
<property>
<name>environment</name>
</property>
</activation>
<build>
<resources>
<resource>
<directory>
src/main/environments/${environment}
</directory>
</resource>
</resources>
<!-- other build config and plugins -->
so the following command:
mvn clean -Denvironment=dev install
would copy the dev datasource.properties to the war

After all I'm using PropertyPlaceholderConfigurer but slightly differnt than Axel mentioned: I load just one property from my configuration and use it to determine which import to use. Because of https://jira.springframework.org/browse/SPR-1332 I cant use a file to store the instance-type, but have to use environment-variables.
<bean id="propertyConfigurerOne" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<import resource="classpath:/web${vabse.Environment}.xml"/>

Related

Spring Hibernate configuration with maven multi module project

Currently I am creating Maven multi-module project with Spring and Hibernate. I am confused where should I have to put spring-dispature.xml to access bean configuration. Currently there are [core-web][core-service(request mapping)][core-bal(bal layer)][core-dal(implementation layer)] and [core-model(data access layer)].
I have put applicationContextBalUserProfile.xml in core-bal layer.
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!--Scan Merchandising Rest Services for Beans Defined In this Context -->
<context:component-scan base-package="com.hrcs.bal.userProfile.impl">
</context:component-scan>
<bean id="loginDal" class="com.hrcs.dal.userProfile.impl.LoginDalImpl" />
Now where should I have to put View Resolver?
You have an example of an Spring multimodule project here https://github.com/DISID/disid-proofs/tree/master/spring-boot-multimodule
(Don't worry if you are not using Spring Boot... is the same idea but without the provided auto-configuration)
Remember that you will have an "application"/"web" module with war packaging. All the other modules should be .jar packages.
That module will be the deployable one that have dependency with the rest of the modules with .jar packaging. (service-api, service-impl, etc.)
All #Configuration classes, .xml configuration files, spring boot starters (if needed), application.properties, etc. must be included on the .war module.
Regards,

ActiveMQ configuration with Spring Boot

I use ActiveMQ as Embedded with Spring Boot.
It seems the Broker is created trough an ActiveMQConnectionFactory.
I understand that the way to configure the broker is to set parameters in the query with broker. as described here : http://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection.html
I would like to setup some features about the DLQ, so it's in the destinationPolicy attribute, but the attribute type is not a simple type but a complex type, how can I write the query parameter to disable DLQ, please ?
Complementing #Petter and #April answers, below the same solutions but with more complete samples:
1. Petter solution, import activemq.xml at connnection factory url
build.gradle
ext {
springBootVersion = "1.5.3.RELEASE"
activeMQVersion = "5.14.5"
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-activemq:${springBootVersion}")
compile("org.apache.activemq:activemq-broker:${activeMQVersion}")
testCompile("org.springframework.boot:spring-boot-starter-test:${springBootVersion}")
testCompile group: 'org.apache.activemq', name: 'activemq-spring', version: "${activeMQVersion}"
testCompile("junit:junit:4.12")
}
src/main/resources/activemq.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.4.0.xsd
">
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="broker1" persistent="false" >
<transportConnectors>
<transportConnector name="vm" uri="vm://broker1"/>
</transportConnectors>
</broker>
</beans>
Config.java
#EnableJms
#SpringBootApplication
#EnableAutoConfiguration
#Configuration
public class Config {}
application.properties
spring.activemq.broker-url=vm://broker1?brokerConfig=xbean:activemq.xml
2. April solution, import activemq.xml at Spring Configuration
Just remove application.properties then add #ImportResource("classpath:activemq.xml") entry to Config.java
Config.java
#EnableJms
#SpringBootApplication
#EnableAutoConfiguration
#Configuration
#ImportResource("classpath:activemq.xml")
public class Config {}
Good question. The properties on the vm-transport for auto-broker creation are great, but only up to a point which I think you have hit.
My suggestion is that you define the broker configuration as you normally would have done in XML and then just refer to this xml in the URI. Destination policies are indeed a complex structure and I don't see how it would be a good idea to define them with simple query params even if it was possible.
vm://localhost?brokerConfig=xbean:activemq.xml
I had this problem and solved it by using a spring configuration file. In my case, I wanted to configure my broker to persist.
I added the needed libs in my pom: including activemq-broker, activemq-spring, spring-jms (and in my case, activemq-leveldb-store).
My spring xml file looked like this:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="xyz">
<persistenceAdapter>
<levelDB directory="activemq-data"/>
</persistenceAdapter>
<transportConnectors>
<transportConnector uri="vm:localhost?persistent=true" />
</transportConnectors>
</broker>
</beans>
And I registered the spring file in one of my configuration classes:
#ImportResource("activemq-spring.xml")
That did the job.
I tried the xbeans solution first, but I got stuck because I was missing some xbeans classes, and I didn't know if it was a version thing or what. I'm using activemq 5.12.1

Maven Project: Spring cannot find property file inside src/main/resources using PropertyPlaceholderConfigurer

Spring cant find my property file (MyPropFile.properties) inside src/main/resources and throws an exception like below
java.io.FileNotFoundException: class path resource [file*:/src/main/resources/MyPropFile.properties] cannot be opened because it does not exist
But if I place MyPropFile.properties at the root of my project (MyProject/MyPropFile.properties) spring can find it and the programs executes properly.
How do I configure this so that I can place my .properties file inside src/main/resources
this is my namespace
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
this is my bean
<context:property-placeholder location="classpath:MyPropFile.properties" />
Java:
#Value("${message.fromfile}")
private String message;
Thanks in advance guys.
Try this. Make this entry in your application config file:
<beans xmlns:context="http://www.springframework.org/schema/context"
.....
xsi:schemaLocation="...
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
....>
<context:property-placeholder location="classpath:MyPropFile.properties" />
....
</beans>
and access the message property:
#Value("${messageFromfile}")
private String message;
I'd expect Maven to copy this to the target directory and for the classpath to be set appropriately. I wouldn't expect Maven to search the source directory other than at compile time.
You should use
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:/MyPropFile.properties</value>
</property>
</bean>
Without the classpath: prefix, the PropertyPlaceholderConfigurer is attempting to resolve the resource as a file resource, so is looking for it in your current working directory.
As an addendum to #ryanp solution which is the correct and sanitized way to deal with files resources, which should be under the classpath location.
Maven will automagically collect the configured file resources and append them to your runtime classpath holder so that resources prefixed with classpath: can be resolved.
Otherwise, if you find your self stack with Maven not being able to stream file resources, you may hook into Maven's resources configuration and map your files location as follows:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>*.properties</include>
</includes>
</resource>
</resources>
</build>

Mule not finding properties file using Spring

I have a Mule flow that I wish to configure via a Spring .properties file. I have read the Mule documentation on how to do this and I'm pretty sure I have it correct, but I get:
Could not load properties; nested exception is java.io.FileNotFoundException:
class path resource [agt-commission.properties] cannot be opened because
it does not exist
My Mule flow XML file begins with:
<mule xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:file="http://www.mulesoft.org/schema/mule/file"
xmlns:jdbc-ee="http://www.mulesoft.org/schema/mule/ee/jdbc"
xmlns:data-mapper="http://www.mulesoft.org/schema/mule/ee/data-mapper"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:core="http://www.mulesoft.org/schema/mule/core"
xmlns:context="http://www.springframework.org/schema/context"
version="EE-3.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/xml
http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
http://www.mulesoft.org/schema/mule/http
http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/file
http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/ee/jdbc
http://www.mulesoft.org/schema/mule/ee/jdbc/current/mule-jdbc-ee.xsd
http://www.mulesoft.org/schema/mule/ee/data-mapper
http://www.mulesoft.org/schema/mule/ee/data-mapper/current/mule-data-mapper.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core
http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/tracking
http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<spring:beans>
<context:property-placeholder location="classpath:agt-commission.properties"/>
</spring:beans>
My properties file is located in the src/main/app folder as specified by the documentation and I have copied and pasted the file name, so I know that is the same.
I am running the project from Mule Studio (3.5.0) as a Mule application.
Why can't Spring find the properties file?
Store your agt-commission.properties file in src/main/resources instead of src/main/app.
By default files under app doesn't get copied to classes which is causing FileNotFoundException
For Property placeholder files the better location is src/main/resources.
As properties file to be provided in the app folder, is the mule-deploy properties which has the details of the application deployment.
Move your resource file to src/main/resources and it should work with your config file.
Note: This will work when the build in the POM has got the src/main/resources declared as resource
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
Hope this helps.

How to instruct Maven to ignore my main/resources/persistence.xml in favor of test/...?

I have two persistence.xml files, for the sake of testing:
src/main/resources/META-INF/persistence.xml
src/test/resources/META-INF/persistence.xml
How to instruct Maven to ignore the first file during testing? Now it is not ignored since OpenEJB says:
ERROR - FAIL ... Finder: #PersistenceContext unitName has multiple matches:
unitName "abc" has 2 possible matches.
Check out the alternate descriptors functionality which is aimed at what you're trying to do.
Try this setup:
src/main/resources/META-INF/persistence.xml
src/main/resources/META-INF/test.persistence.xml
Then you can construct OpenEJB to prefer the test.persistence.xml file by setting the openejb.altdd.prefix System or InitialContext property to test
A different possible solution could be to override the persistence unit properties in the test. With that approach you could avoid the need for a second persistence.xml which can be nice as maintaining two can be a pain.
You can use the Maven approach, but be aware that per spec the persistence provider will only look (aka scan) for #Entity beans in the exact jar or directory where the persistence.xml is found. So be keenly aware that in Maven these are two different locations:
target/classes
target/test-classes
EDIT More details on the overriding capabilities
You can override any property in your test setup via either system properties or the initial context properties (this includes jndi.properties files). The format is:
<unit-name>.<property>=<value>
So for example with the following persistence.xml:
<persistence>
<persistence-unit name="movie-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>movieDatabase</jta-data-source>
<non-jta-data-source>movieDatabaseUnmanaged</non-jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.max_fetch_depth" value="3"/>
</properties>
</persistence-unit>
</persistence>
You can override and add persistence unit properties in your test case. There are currently no facilities for removing them (if you have a need for that let us know – it hasn't really come up so far).
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,"org.apache.openejb.client.LocalInitialContextFactory");
p.put("movie-unit.hibernate.hbm2ddl.auto", "update");
p.put("movie-unit.hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
context = new InitialContext(p);
Or alternatively via a jndi.properties file
java.naming.factory.initial=org.apache.openejb.client.LocalInitialContextFactory
movie-unit.hibernate.hbm2ddl.auto = update
movie-unit.hibernate.dialect = org.hibernate.dialect.HSQLDialect
I think you can create two profiles in your pom.xml:
<properties>
<environment>dev</environment>
</properties>
<profiles>
<profile>
<id>prod</id>
<properties>
<environment>test</environment>
</properties>
</profile>
</profiles>
After that, in your src folder, create two folders named dev/resoruces and test/resources and copy your different resources there. After that, add something like this:
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>false</filtering>
</resource>
<resource>
<directory>${basedir}/src/main/${environment}/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
The ${basedir} depends on the command line parameter, it can be test or dev.
You run the maven command like this: mvn clean package -P test.
I have been testing these and other similar solutions without involving the pom.xml... In my opinion, the best way to solve this issue is to have two application-context.xml (one only to be used in test classes) and to add a custom persistence unit manager bean in the test's application-context.xml. Like this example:
<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocation">
<value>classpath*:META-INF/test.persistence.xml</value>
</property>
<property name="defaultDataSource" ref="dataSource"/>
</bean>
This solution runs.
:)
Better add both files - in general, making test/production or debug/profile/production distinction in build makes only trouble.
Better try to use different perasistence unit name for production (say abc-production) and for tests (abc-tests).

Categories