What is difference between PropertyOverrideConfigurer and PropertyPlaceholderConfigurer? - java

What are the differences between using PropertyOverrideConfigurer and PropertyPlaceholderConfigurer in the Spring framework? I'm unable to find any solid difference between these 2 classes.

PropertyOverrideConfigurer :
"Property resource configurer that overrides bean property values in
an application context definition. It pushes values from a properties
file into bean definitions."
it allows you to override some values that beans take, means you can override some values of spring beans from properties defined in property file
declare:
<bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
<property name="location" value="classpath:myproperties.properties" />
</bean>
<bean id="person" class="com.sample.Employee" >
<property name="name" value="Dugan"/>
<property name="age" value="50"/>
</bean>
myproperties.properties:
person.age=40
person.name=Stanis
so when you load the bean
Employee e = (Employee)context.getBean(Employee.class);
e.getAge() => 40
e.getName() => "Stanis"
PropertyPlaceholderConfigurer :
resolves ${...} placeholders against local properties and/or system
properties and environment variables.
it allows you to resolve ${..} placeholders in bean definitions, it also checks for System properties for values. This behavior can be controlled with systemPropertiesMode
never (0): Never check system properties
fallback (1): Check system properties if not resolvable in the
specified properties files. This is the default.
override (2): Check system properties first, before trying the
specified properties files. This allows system properties to override
any other property source.
to configure
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mydb" />
<property name="username" value="root" />
<property name="password" value="password" />
<property name="systemPropertiesMode" value="0" />
</bean>
move the 'dataSource' properties to property files
database.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
jdbc.username=root
jdbc.password=password
then refer them with place holders =>
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>database.properties</value>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>

Related

Configuring Spring to useMultiple Data Sources

I am trying to connect 2 different schemas within my spring boot application.
To do this I have got 2 different data sources. How should I configure this within my properties files?
I seen this answer which gave me an idea of how to do so. I currently have the following 3 property files in my application:
1. application.properties
2. hibernate.properties
3. multiple-db.properties
application.properties is currently empty. Below are the other 2 files:
hibernate.properties:
# Connection configuration
hibernate.connection.username= my_uname1
hibernate.connection.password= my_pword1
multiple-db.properties:
# Schema 1-Data source configuration
oracle.db.username1= my_uname1
oracle.db.password1= my_pword1
oracle.db.url1= my_url1
# Schema 2-Data source configuration
oracle.db.username2= my_uname2
oracle.db.password1= my_pword2
oracle.db.url2= my_url2
# JPA configuration
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
# Hibernate configuration
hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver
hibernate.connection.url=my_url
hibernate.connection.provider_class=org.hibernate.connection.C3P0ConnectionProvider
Is this the correct approach? Do I need 3 properties files, or could I do this all in one?
The Spring documentation suggests a way to create primary and secondary data sources:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-two-datasources
Each data source can be configured as described here:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-configure-a-datasource
You can access them by using #Autowire from other beans. You can associate a prefix to each data source so you can configure it in your application.properties or application.yml file.
You can also set one as primary.
With Spring you can do this easily.
It would be something like this:
<bean id="dataSource_1" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/northwind" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="dataSource_2" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/northwind_dup" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
You could also use your properties files and do something like this:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="jdbc.properties"/>
And you could use only one file, or three. It is really up to you.

Apache Camel - Read JDBC dataSource properties from file

i'm using Apache Camel and i try to load datasource properties from this file
config.properties:
url = my_url
user = user_name
password = user_pass
this is dataSource (blueprint.xml):
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
<property name="URL" value="my_url"/>
<property name="user" value="user_name"/>
<property name="password" value="user_pass"/>
</bean>
How can i read values from config.properties and insert them into dataSource properties ?
You talk about blueprint.xml, and camel, so I assume you are in an osgi container like Karaf/ServiceMix, and you are using Aries Blueprint.
Then you can use the cm namespace and a property-placeholder. If you use camel and want your properties to be dynamically reloaded, then you can use too an update strategy reload, which start/stop the blueprint container when the configuration change. This will load the configuration with pid "datasource" (ie, in karaf, the file etc/datasource.cfg) :
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0">
<cm:cm-properties id="myProps" persistent-id="datasource" update-strategy="reload"/>
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
<property name="URL" value="${url}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
</bean>
</blueprint>
If you want to use your configuration file without using ConfigurationAdmin or dynamically reload your bundle, then you can use the ext namespace :
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0">
<ext:property-placeholder>
<ext:location>file:config.properties</ext:location>
</ext:property-placeholder>
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
<property name="URL" value="${url}"/>
<property name="user" value="${user}"/>
<property name="password" value="${password}"/>
</bean>
</blueprint>
According to code I assume you use probably spring as container. General solution in spring is to use PropertyPlaceHolder, your configuration will look like this:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>config.properties</value>
</property>
</bean>
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource">
<property name="URL" value="${jdbc.myUrl}"/>
<property name="user" value="${jdbc.user_name}"/>
<property name="password" value="${jdbc.user_pass}"/>
</bean>
Please check the example for details.

Converted JNDI name [java:comp/env/***] not found before reading the properties file

Good Mornig.
I have an application in tomcat 8, java 1.7, Spring 3.2.2 and primefaces 5.0. When the application starts, it shows the next debug message in console:
Looking up JNDI object with name [java:comp/env/etl.csv.token]
localhost-startStop-1: org.springframework.jndi.JndiLocatorDelegate
Converted JNDI name [java:comp/env/etl.csv.token] not found
But the key isn't in the JNDI context. It is in a properties file. The application works fine and takes the property from the properties file, but i can't understand why spring is trying to find the property in the JNDI context
The properties file is like this:
database.driverClassName=org.postgresql.Driver
database.initialSize=3
database.maxActive=15
database.maxIdle=10
database.minIdle=3
database.maxWait=10000
etl.csv.token=,
And its properties are used like this:
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<property name="initialSize" value="${database.initialSize}" />
<property name="maxActive" value="${database.maxActive}" />
<property name="maxIdle" value="${database.maxIdle}" />
<property name="maxWait" value="${database.maxWait}" />
<property name="minIdle" value="${database.minIdle}" />
<property name="testOnBorrow" value="true" />
<property name="validationQuery" value="SELECT CURRENT_TIMESTAMP" />
<property name="removeAbandoned" value="true" />
</bean>
For all properties, the behaviour is the same. I would like that message does not appear
Sorry for the english, is not my native language
Any help will be apreciated.

How to do arithmetic in Spring properties, with values from a properties file?

Example use-case: properties file passes in a numeric value in millis, and you want to use it in seconds.
Your .properties file:
jdbc.timeout= 2000
Your applicationContext.xml currently
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"value="jdbc:mysql://myserver/mydb" />
<property name="username" value="user" />
<property name="password" value="changeme" />
<property name="validationQuery" value="SELECT 1;"/>
<property name="validationQueryTimeout" value="${jdbc.timeout}" />
</bean>
You want the validationQueryTimeout value to be in seconds, how do you convert it?
If you're using Spring 3.0 or later, you can use the property inside the SpEL expression like this:
<property name="validationQueryTimeout" value="#{${jdbc.timeout}/1000}" />

Why does Spring 3.x ignore certain placeholderPrefixes for PropertyPlaceholderConfigurer?

I have the bean definitions below. If I change the placeholderPrefix for the "exposeSystemProperties" bean to "${" and use that in the properties path of the second bean, it works. If I change it to anything but "%{" it doesn't work. I can't use any other string (e.g. "$sys{", "#[", etc.). I'm currently on 3.0.5.RELEASE.
Any thoughts as to why this is? To compound it all, I have a 3rd PropertyPlaceHolderConfigure, so only having two prefixes does not work.
<bean id="exposeSystemProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="placeholderPrefix"><value>$sys{</value></property>
<property name="order" value="10" />
</bean>
<bean id="localFileProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_NEVER" />
<property name="placeholderPrefix" value="%{" />
<property name="placeholderSuffix" value="}" />
<property name="order" value="20" />
<property name="locations">
<array>
<bean class="java.lang.String">
<constructor-arg><value>classpath:properties/$sys{deploy.env}/client.properties</value></constructor-arg>
</bean>
</array>
</property>
</bean>
Since what you need the prefix for is to control environment specific properties, this can be done by using system variables ( instead of a deploy.env property in your example ):
<value>classpath:properties/${ENV_SYSTEM:dev}/client.properties</value>
In this case it will always look under:
<value>classpath:properties/dev/client.properties</value>
by default, unless a ENV_SYSTEM system variable is set. If it is set to "qa", for example, it will automatically look under:
<value>classpath:properties/qa/client.properties</value>
Another approach, in case you are open to "look into the future" a bit, is to use Spring 3.1's PROFILE feature, where beans can be profile specific. For example:
<beans profile="dev">
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
<jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
</jdbc:embedded-database>
</beans>
This dataSource will only be loaded in case a profile is set to dev:
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles( "dev" );
ctx.load( "classpath:/org/boom/bang/config/xml/*-config.xml" );
ctx.refresh();

Categories