Insert external data into persistence.xml - java

I want my persistence.xml to set some of its properties dynamically, to be specific:
<property name="hibernate.connection.password" value="password"/>
<property name="hibernate.connection.username" value="username"/>
I can build a class that could provide me the data I need, but I don't know how to set the class up in a way that it works like this:
<property name="hibernate.connection.password" value="${my.clazz.pass}"/>
<property name="hibernate.connection.username" value="${my.clazz.user}"/>
I have tried to set the class up like this
public class clazz{
String pass;
String user;
public clazz(){
//do stuff to set pass and user
}
//getter/setter
}
But that does not work. I haven't found a way here or in google, but I have seen the ${my.clazz.smth}-way several times.
So, how can I set that up? :)
Thanks in advance!

So, resolved this a while ago, but I still didn't answer:
Anthony Accioly pointed me to the right direction:
I added this to my applicationContext.xml's entityManagerFactory
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitPostProcessors">
<bean class="my.package.SetupDatabase">
</bean>
</property>
//the other stuff
</bean>
The corresponding class, in this case I use hibernate:
package my.package;
public class SetupDatabase implements PersistenceUnitPostProcessor {
private String username;
private String password;
private String dbserver;
public void SetupDatabase(){
//do stuff to obtain needed information
}
public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
pui.getProperties().setProperty("hibernate.connection.username", username );
pui.getProperties().setProperty("hibernate.connection.password", password);
pui.getProperties().setProperty("hibernate.connection.url", dbserver );
}
}
This way the setup is done just once when starting the whole thing up, but the required data may be 'outsourced'.
Thanks again for pointing me to the right direction!

The value placeholder ${my.clazz.smth} that you refer to is usually read from a properties file as opposed to a class directly.
This is done using Spring's PropertyPlaceholderConfigurer.
Here is an example of a project which combined the Hibernate & Spring.

If you really need to delay the configuration until runtime (e.g., to obtain the database credentials from an external source such as a Web service) you can do it with Hibernate API Programatic Configuration, particularly Ejb3Configuration for legacy versions of Hibernate or ServiceRegistryBuilder (v 4.X)...
But be warned that, to the best of my knowledge, there is no way to dynamically update the username and password of a PersintenceUnit. You will have to build another EntityManagerFactory from a new Configuration instance (a quite expensive operation) every time that you need to change it's properties.
Anyway, unless you have a really good reason to, do not manage database credentials from your application, delegate it to a JNDI-Bound DataSource instead.
Ejb3Configuration cfg = new Ejb3Configuration()
// Add classes, other properties, etc
.setProperty("hibernate.connection.password", "xxxx")
.setProperty("hibernate.connection.username", "yyyy");
EntityManagerFactory emf= cfg.buildEntityManagerFactory();

Related

Connection Reset using Spring + Hibernate

I am using Spring + Hibernate on my JavaEE project.
In this project the user can upload an XLS file which I should import to my database. Before importing I have to validate this file checking its integrity with the other entities on my database. So I have more or less the following:
// The importer
#Component("importer")
public class Importer {
#Autowired
FirstDAO firstDao;
#Autowired
SecondDAO secondDao;
// Read the file and open it (65.000 lines for example)
public void validate() {
foreach line in the file {
firstDAO.has(line[col1]);
secondDao.has(line[col2]);
}
// It stores the valid objects in a List and persist them at the end
}
}
// The DAO
#Repository
public class FirstDao {
#PersistenceContext
protected EntityManager entityManager;
#Transactional(propagation = Propagation.NOT_SUPPORTED)
public boolean has(String name) {
List<Object> result = entityManager.createQuery( from FIRST_TABLE where name = :name)
.setParameter("name", name)
.getResultList();
if (result.size > 0) return true;
else return false;
}
}
// The PersistenceContext/Hibernate configuration
<!-- Data Source -->
<jee:jndi-lookup id="myDS" jndi-name="jdbc/my-DS" cache="true" proxy-interface="javax.sql.DataSource" />
<!-- Entity Manager -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property value="classpath:META-INF/my_persistence.xml" name="persistenceXmlLocation"/>
<property name="dataSource" ref="myDS"/>
<property name="persistenceUnitName" value="myPersistenceUnit" />
<!--
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
-->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="ORACLE" />
<property name="showSql" value="false" />
</bean>
</property>
</bean>
After logging the application I have noticed:
For each query (has method on my DAO) a connection is opened and closed with my Database.
The memory on the server is being flooded (probably memory leak).
After a lot of opening and closing connections I have a connection reset from the Database. Don't know why. And if I still keep requesting coonections, the Datasource is suspended.
I have read somethings about entityManager but I still don't know if I am doing it right, so:
Is it right to execute the validation in a for loop that way? (One connection for each item, meaning 130.000 connections open and closed in a 65000 lines file)
I have read about Stateless Persistence Context for the entityManager. I suspect the memory leak may be there. Maybe Hibernate is kepting a lot of objects in the PersistenceContext. How do I tell Entity Manager to not cache those guys when validating?
Thanks in advance.
First of all, you really shouldn't do that line by line unless you have a very very good reason. Even if the data size is bigger than your memory you should do that 1000 lines at a time or something like that but definitely not one by one.
Because one of the most important optimization for database usage is reducing number of database hit.
Secondly you should not retrieve the data just to check if it is exist.
You should use a basic "select count" query. By that way you will get rid of all stuff like consuming IO to read data and retrieving that data through network to your server and spending memory to just get the number of object in that list.
If you will use my first advice and check the existing of records not one at a time but 1000s at a time you can select just the names instead of all rows.
Btw as far as I can see you are using a datasource if that is properly configured like number of max connection etc. you shouldn't worry about number of database connection.

howto change cache removal strategy in hdiv

I am using the HDIV Web Application Security Framework for a java web application. Every new web-page-request generates hdiv-internal security information that is cached and used for security checks.
I have the following szenario:
I have one order page that pops up a confirmation-page for 2 seconds when something was added to or removed from the cart.
after 50 popups the the underlaying order page is removed from the cache and therefor an error occurs in the app.
does anybody know how to influence the hdiv cache-removal strategy to keep the basepage alive?
One way around is to increase org.hdiv.session.StateCache.maxSize from 50 to 500.
but this would only cure the symptoms not the underlying cause.
Update:
using #rbelasko solution
I succeded to use the original org.hdiv.session.StateCache to change the maxSize to 20 and verified in the debug-log that the cachentries are dismissed after 20 entries.
When I changed it to use my own implementation it didn-t work
Bean definition
<bean id="cache" class="com.mycompany.session.StateCacheTest" singleton="false"
init-method="init">
<property name="maxSize">
<value>20</value>
</property>
</bean>
My own class
public class StateCacheTest extends StateCache
{
private static final Log log = LogFactory.getLog(StateCacheTest.class);
public StateCacheTest()
{
log.debug("StateCache()");
}
#Override
public void setMaxSize(final int maxSize)
{
super.setMaxSize(maxSize);
if (log.isDebugEnabled())
{
log.debug("setMaxSize to " + maxSize);
}
}
}
In the debug-log were no entries from StateCacheTest
Any ideas?
Update 2:
While i was not able to load a different IStateCache implementation via spring i was able to make this error less likely using
<hdiv:config ... maxPagesPerSession="200" ... />
the bean-settings definition
<property name="maxSize">
<value>20</value>
</property>
had no effect on the cachesize in my system.
You could create a custom IStateCache interface implementation.
Using the HDIV explicit configuration (not using HDIV's new custom schema) this is the default configuration for "cache" bean:
<bean id="cache" class="org.hdiv.session.StateCache" singleton="false"
init-method="init">
<property name="maxSize">
<value>200</value>
</property>
</bean>
You could create your own implementation and implement the strategy that fits your requirements.
Regards,
Roberto

how can get the datasource configuration for spring from persistence.xml?

I need a spring datasource like:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="<driver>"/>
<property name="url" value="<url>" />
<property name="username" value="<user>" />
<property name="password" value="<pass>" />
</bean>
I need to obtain driver, url, user, pass from persistence.xml.
Tanks a lot!
Here is my snippet for doign the same, you will obviously have to use your BasicDataSource instead of the ComboPooledDataSource I use. But they are pretty much the same, replace getDriverClass() with driverClassName, apparently.
#Autowired
private ComboPooledDataSource dataSource;
public String myMethod() {
return dataSource.getDriverClass());
}
Do you want to print it, or use it in your application for connecting to the dB?
If later one is the case, then, create a bean for sessionFactory, set hibernateProperties for the same where you can inject datasource as well.
In java code, autowire sessionFactory object (or set it using a setter method) and call getCurrentSession method for the same.
For getting various attributes, use chained getter methods to return datasource and extract all the details.
Let me know if you face any issue or need more details for the same.

How to setup Hibernate to read/write to different datasources?

Using Spring and Hibernate, I want to write to one MySQL master database, and read from one more more replicated slaves in cloud-based Java webapp.
I can't find a solution that is transparent to the application code. I don't really want to have to change my DAOs to manage different SessionFactories, as that seems really messy and couples the code with a specific server architecture.
Is there any way of telling Hibernate to automatically route CREATE/UPDATE queries to one datasource, and SELECT to another? I don't want to do any sharding or anything based on object type - just route different types of queries to different datasources.
An example can be found here: https://github.com/afedulov/routing-data-source.
Spring provides a variation of DataSource, called AbstractRoutingDatasource. It can be used in place of standard DataSource implementations and enables a mechanism to determine which concrete DataSource to use for each operation at runtime. All you need to do is to extend it and to provide an implementation of an abstract determineCurrentLookupKey method. This is the place to implement your custom logic to determine the concrete DataSource. Returned Object serves as a lookup key. It is typically a String or en Enum, used as a qualifier in Spring configuration (details will follow).
package website.fedulov.routing.RoutingDataSource
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class RoutingDataSource extends AbstractRoutingDataSource {
#Override
protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}
}
You might be wondering what is that DbContextHolder object and how does it know which DataSource identifier to return? Keep in mind that determineCurrentLookupKey method will be called whenever TransactionsManager requests a connection. It is important to remember that each transaction is "associated" with a separate thread. More precisely, TransactionsManager binds Connection to the current thread. Therefore in order to dispatch different transactions to different target DataSources we have to make sure that every thread can reliably identify which DataSource is destined for it to be used. This makes it natural to utilize ThreadLocal variables for binding specific DataSource to a Thread and hence to a Transaction. This is how it is done:
public enum DbType {
MASTER,
REPLICA1,
}
public class DbContextHolder {
private static final ThreadLocal<DbType> contextHolder = new ThreadLocal<DbType>();
public static void setDbType(DbType dbType) {
if(dbType == null){
throw new NullPointerException();
}
contextHolder.set(dbType);
}
public static DbType getDbType() {
return (DbType) contextHolder.get();
}
public static void clearDbType() {
contextHolder.remove();
}
}
As you see, you can also use an enum as the key and Spring will take care of resolving it correctly based on the name. Associated DataSource configuration and keys might look like this:
....
<bean id="dataSource" class="website.fedulov.routing.RoutingDataSource">
<property name="targetDataSources">
<map key-type="com.sabienzia.routing.DbType">
<entry key="MASTER" value-ref="dataSourceMaster"/>
<entry key="REPLICA1" value-ref="dataSourceReplica"/>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSourceMaster"/>
</bean>
<bean id="dataSourceMaster" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${db.master.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<bean id="dataSourceReplica" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="${db.replica.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
At this point you might find yourself doing something like this:
#Service
public class BookService {
private final BookRepository bookRepository;
private final Mapper mapper;
#Inject
public BookService(BookRepository bookRepository, Mapper mapper) {
this.bookRepository = bookRepository;
this.mapper = mapper;
}
#Transactional(readOnly = true)
public Page<BookDTO> getBooks(Pageable p) {
DbContextHolder.setDbType(DbType.REPLICA1); // <----- set ThreadLocal DataSource lookup key
// all connection from here will go to REPLICA1
Page<Book> booksPage = callActionRepo.findAll(p);
List<BookDTO> pContent = CollectionMapper.map(mapper, callActionsPage.getContent(), BookDTO.class);
DbContextHolder.clearDbType(); // <----- clear ThreadLocal setting
return new PageImpl<BookDTO>(pContent, p, callActionsPage.getTotalElements());
}
...//other methods
Now we can control which DataSource will be used and forward requests as we please. Looks good!
...Or does it? First of all, those static method calls to a magical DbContextHolder really stick out. They look like they do not belong the business logic. And they don't. Not only do they not communicate the purpose, but they seem fragile and error-prone (how about forgetting to clean the dbType). And what if an exception is thrown between the setDbType and cleanDbType? We cannot just ignore it. We need to be absolutely sure that we reset the dbType, otherwise Thread returned to the ThreadPool might be in a "broken" state, trying to write to a replica in the next call. So we need this:
#Transactional(readOnly = true)
public Page<BookDTO> getBooks(Pageable p) {
try{
DbContextHolder.setDbType(DbType.REPLICA1); // <----- set ThreadLocal DataSource lookup key
// all connection from here will go to REPLICA1
Page<Book> booksPage = callActionRepo.findAll(p);
List<BookDTO> pContent = CollectionMapper.map(mapper, callActionsPage.getContent(), BookDTO.class);
DbContextHolder.clearDbType(); // <----- clear ThreadLocal setting
} catch (Exception e){
throw new RuntimeException(e);
} finally {
DbContextHolder.clearDbType(); // <----- make sure ThreadLocal setting is cleared
}
return new PageImpl<BookDTO>(pContent, p, callActionsPage.getTotalElements());
}
Yikes >_< ! This definitely does not look like something I would like to put into every read only method. Can we do better? Of course! This pattern of "do something at the beginning of a method, then do something at the end" should ring a bell. Aspects to the rescue!
Unfortunately this post has already gotten too long to cover the topic of custom aspects. You can follow up on the details of using aspects using this link.
I don't think that deciding that SELECTs should go to one DB (one slave) and CREATE/UPDATES should go to a different one (master) is a very good decision. The reasons are:
replication is not instantaneous, so you could CREATE something in the master DB and, as part of the same operation, SELECT it from the slave and notice that the data hasn't yet reached the slave.
if one of the slaves is down, you shouldn't be prevented from writing data in the master, because as soon as the slave is back up, its state will be synchronized with master. In your case though, your write operations are dependent on both master and slave.
How would you then define transactionality if you're in fact using 2 dbs?
I would advise using the master DB for all the WRITE flows, with all the instructions they might require (whether they are SELECTs, UPDATE or INSERTS). Then, the application dealing with the read-only flows can read from the slave DB.
I'd also advise having separate DAOs, each with its own methods, so that you'll have a clear distinction between read-only flows and write/update flows.
You could create 2 session factories and hava a BaseDao wrapping the 2 factories(or the 2 hibernateTemplates if you use them) and use the get methods with on factory and the saveOrUpdate methods with the other
Try this way : https://github.com/kwon37xi/replication-datasource
It works nicely and very easy to implement without any extra annotation or code. It requires only #Transactional(readOnly=true|false).
I have been using this solution with Hibernate(JPA),Spring JDBC Template, iBatis.
You can use DDAL to implement writting master database and reading slave database in a DefaultDDRDataSource without modifying your Daos, and what's more, DDAL provided loading balance for mulit-slave databases. It doesn't rely on spring or hibernate. There is a demo project to show how to use it: https://github.com/hellojavaer/ddal-demos and the demo1 is just what you described scene.

Load environment-specific properties for use with PropertyPlaceholderConfigurer?

This seems like a pretty common problem, but I haven't found any sort of consensus on the best method, so I'm posing the question here.
I'm working on a command-line Java application using Spring Batch and Spring. I'm using a properties file along with a PropertyPlaceholderConfigurer, but I'm a little unsure of the best way of handling the properties files for multiple environments (dev, test, etc.). My Googling is only turning up programmatic ways of loading the properties (i.e., in the Java code itself), which doesn't work for what I'm doing.
One approach I've considered is simply placing each environment's properties file on the server and adding the file's directory to the classpath via a command-line argument, but I've been having trouble loading the file using that method.
The other method I'm considering is to just include all the properties files in the jar and use a system property or command line argument to fill in the name of the properties file at runtime, like this:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:job.properties.${env}</value>
</list>
</property>
</bean>
I lean towards the latter solution, but I'm also looking to see if there's a better method I'm overlooking.
I should also mention that I have to make the substitution at runtime rather than in the build. The process I'm constrained to use requires a single build which will be promoted through the environments to production, so I'm unable to use substitution ala Maven or Ant.
Essentially you have a finished JAR which you want to drop into another environment, and without any modification have it pick up the appropriate properties at runtime. If that is correct, then the following approaches are valid:
1) Rely on the presence of a properties file in the user home directory.
Configure the PropertyPlaceholderConfigurer to reference a properties file external to the JAR like this:
<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="false"/>
<property name="order" value="1"/>
<property name="locations">
<list>
<!-- User home holds secured information -->
<value>file:${user.home}/MyApp/application.properties</value>
</list>
</property>
</bean>
The operating system will secure the contents of the application.properties file so that only the right people can have access to it. Since this file does not exist when you first run up the application, create a simple script that will interrogate the user for the critical values (e.g. username, password, Hibernate dialect etc) at start up. Provide extensive help and sensible default values for the command line interface.
2) If your application is in a controlled environment so that a database can be seen then the problem can be reduced to one of creating the basic credentials using technique 1) above to connect to the database during context startup and then performing substitution using values read via JDBC. You will need a 2-phase approach to application start up: phase 1 invokes a parent context with the application.properties file populating a JdbcTemplate and associated DataSource; phase 2 invokes the main context which references the parent so that the JdbcTemplate can be used as configured in the JdbcPropertyPlaceholderConfigurer.
An example of this kind of code would be this:
public class JdbcPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private Logger log = Logger.getLogger(JdbcPropertyPlaceholderConfigurer.class);
private JdbcTemplate jdbcTemplate;
private String nameColumn;
private String valueColumn;
private String propertiesTable;
/**
* Provide a different prefix
*/
public JdbcPropertyPlaceholderConfigurer() {
super();
setPlaceholderPrefix("#{");
}
#Override
protected void loadProperties(final Properties props) throws IOException {
if (null == props) {
throw new IOException("No properties passed by Spring framework - cannot proceed");
}
String sql = String.format("select %s, %s from %s", nameColumn, valueColumn, propertiesTable);
log.info("Reading configuration properties from database");
try {
jdbcTemplate.query(sql, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
String name = rs.getString(nameColumn);
String value = rs.getString(valueColumn);
if (null == name || null == value) {
throw new SQLException("Configuration database contains empty data. Name='" + name + "' Value='" + value + "'");
}
props.setProperty(name, value);
}
});
} catch (Exception e) {
log.fatal("There is an error in either 'application.properties' or the configuration database.");
throw new IOException(e);
}
if (props.size() == 0) {
log.fatal("The configuration database could not be reached or does not contain any properties in '" + propertiesTable + "'");
}
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void setNameColumn(String nameColumn) {
this.nameColumn = nameColumn;
}
public void setValueColumn(String valueColumn) {
this.valueColumn = valueColumn;
}
public void setPropertiesTable(String propertiesTable) {
this.propertiesTable = propertiesTable;
}
}
The above would then be configured in Spring like this (note the order property comes after the usual $ prefixed placeholders):
<!-- Enable configuration through the JDBC configuration with fall-through to framework.properties -->
<bean id="jdbcProperties" class="org.example.JdbcPropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="false"/>
<property name="order" value="2"/>
<property name="nameColumn" value="name"/>
<property name="valueColumn" value="value"/>
<property name="propertiesTable" value="my_properties_table"/>
<property name="jdbcTemplate" ref="configurationJdbcTemplate"/> <!-- Supplied in a parent context -->
</bean>
This would allow the follow to occur in the Spring configuration
<!-- Read from application.properties -->
<property name="username">${username}</property>
...
<!-- Read in from JDBC as part of second pass after all $'s have been fulfilled -->
<property name="central-thing">#{name.key.in.db}</property>
3) Of course, if you're in a web application container then you just use JNDI. But you're not so you can't.
Hope this helps!
You could use <context:property-placeholder location="classpath:${target_env}configuration.properties" />
in your Spring XML and configure ${target_env} using a command-line argument (-Dtarget_env=test.).
Starting in Spring 3.1 you could use <context:property-placeholder location="classpath:${target_env:prod.}configuration.properties" /> and specify a default value, thereby eliminating the need to set the value on the command-line.
In case Maven IS an option, the Spring variable could be set during plugin execution, e.g. during test or integration test execution.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<systemPropertyVariables>
<target_env>test.</target_env>
</systemPropertyVariables>
</configuration>
</plugin>
I assume different Maven profiles would also work.
Spring Property Placeholder Configurer – A few not so obvious options
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:db.properties"></property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${db.url.${mode}}" />
<property name="username" value="${db.username.${mode}}" />
<property name="password" value="${db.password.${mode}}" />
</bean>
${db.username.${mode}}: Here "mode" defines the project mode (environment) - dev / prod
Properties file looks like:
#Database properties
#mode dev/prod
mode=dev
#dev db properties
db.url.dev=jdbc:mysql://localhost:3306/dbname
db.username.dev=root
db.password.dev=root
#prod db properties
db.url.prod=jdbc:mysql://localhost:3306/dbname
db.username.prod=root
db.password.prod=root
I agree - it should not be a build time configuration as you want to deploy the exact same payload to the various contexts.
The Locations property of PropertyPlaceHolderConfigurer can take various types of resources. Can also be a filesystem resouce or a url? Thus you could set the location of the config file to a file on the local server and then whenever it runs it would run in the mode specified by the config file on that server. If you have particular servers for particular modes of running this would work fine.
Reading between the lines though it seems you want to run the same application in different modes on the same server. What I would suggest in this case is to pass the location of the config file via a command line parameter. It would be a little tricky to pass this value into the PropertyPlaceHolderConfigurer but would not be impossible.
The way I've normally done this in the past is to perform a substitution of the environment (dev/test/prod) in some sort of way at package/deployment time.
That can either copy the correct config file to the right location on the server or just bundle the correct config file in the deployment package. If you use Ant/Maven this should be fairly straightforward to achieve. Which build tool are you using? Ant/Maven, that should provide you with the ability to substitute a value.
Another alternative, which use PropertyPlaceholderConfigurer is that of the SYSTEM_PROPERTIES_MODE_OVERRIDE property. You can use this to set the location of the properties file you wish to load through a system property, see:
http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.html#SYSTEM_PROPERTIES_MODE_OVERRIDE
Hope that helps.
For build time substitution I use Maven build properties for variable substitution. You can determine what properties to load in your Maven settings.xml file and the file could be specific to the environment. For production properties using PPC see this blog
Hi after reading Spring in Action found a solution provided by Spring.
Profile Or Conditional : you can create multiple profile eg. test, dev, prod etc.
Spring honors two separate properties when determining which profiles are active:
spring.profiles.active and spring.profiles.default . If spring.profiles.active
is set, then its value determines which profiles are active. But if spring
.profiles.active isn’t set, then Spring looks to spring.profiles.default . If neither
spring.profiles.active nor spring.profiles.default is set, then there are no
active profiles, and only those beans that aren’t defined as being in a profile are created.
There are several ways to set these properties:
1 As initialization parameters on DispatcherServlet
2 As context parameters of a web application
3 As JNDI entries
4 As environment variables
5 As JVM system properties
6 Using the #ActiveProfiles annotation on an integration test class
I use the classpath option and adjust the classpath per environment in Jetty. In the jetty-maven-plugin you can set a directory for testclasses and have your testresources located there.
For non-local environments (test / production) I use an environment flag and send the appropriate files to the $JETTY_HOME/resources folder (which is built into Jetty's classpath)

Categories

Resources