Java Spring MVC Project external database configuration with .properties file - java

I am trying external configuration with properties file. dataSource bean is defined in security-context-xml file and hibernate.cfg.xml use them for database informations and sessionFactory.
I want externally dataSource configuration with encrypted password.
Used code following:
<context:property-placeholder
location="classpath:sample.properties" ignore-unresolvable="true" />
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="driverClassName"
value="oracle.jdbc.OracleDriver" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation"
value="classpath:hibernate.cfg.xml" />
</bean>
And sample.properties file is:
jdbc.url="*****"
jdbc.username="****"
jdbc.password="****"
This didn't work and throws exception:
Caused by: java.sql.SQLException: Cannot create JDBC driver of class 'oracle.jdbc.OracleDriver' for connect URL '${jdbc.url}'
at org.apache.commons.dbcp2.BasicDataSource.createConnectionFactory(BasicDataSource.java:2023)
at org.apache.commons.dbcp2.BasicDataSource.createDataSource(BasicDataSource.java:1897)
at org.apache.commons.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1413)
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:139)
at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:380)
at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:228)
... 56 more

Related

Hibernate trying to find hibernate.cfg.xml when configured by spring

I have configured Hibernate(5.2.6) via spring(4.3.5) But when I run my Junit(4.12) tests it gives out an error saying that it could not locate hibernate.cfg.xml file. Can anyone help me out?
After I run the Junit test, tables are created in database but data is not added, I can see the sql queries being run as I have enables show_sql
did you specify hibernate configured xml file name in web.xml.?
if not specify name of xml file in web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:hibernateContext.xml</param-value>
</context-param>
How is applicationContext is configured for spring and hibernate integration?
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:properties/jdbc.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<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>
<!-- Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="configLocation">
<value>classpath:hibernate/hibernate.cfg.xml</value>
</property>
</bean>

Change the default datasource in spring batch

I want to use mysql database in spring batch application. Where should I keep my XML file with the details of datasource.
currently i have kept the env-context.xml in src/main/resources/META-INF/batch/override/manager
Content of env-context.xml:
<!-- connect to database -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/demo_db" />
<property name="username" value="testuser" />
<property name="password" value="12345" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
The common approach is to put this kind of configuration parameters into a properties file in order to externalize them as they will change from one environment to another.
It can be done as next:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:datasource.properties</value>
</property>
</bean>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${datasource.driver}" />
<property name="url" value="${datasource.url}" />
<property name="username" value="${datasource.username}" />
<property name="password" value="${datasource.password}" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
Then you put your file datasource.properties into the classpath, this file will have a content of type:
datasource.driver=com.mysql.jdbc.Driver
datasource.url=jdbc:mysql://localhost:3306/demo_db
datasource.username=testuser
datasource.password=12345

Reading Dual/Multiple Properties in Spring

I'm trying to read the application specific properties from database, and I'm trying to keep the database credentials in properties file.
So I need to load both properties (File and DB), while the application is
loading.
I'm having my configuration as follows.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="WEB-INF/config/db.properties"/>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="properties">
<bean class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
<constructor-arg>
<bean class="org.apache.commons.configuration.DatabaseConfiguration">
<constructor-arg type="javax.sql.DataSource" ref="postgresqlDataSource"/>
<constructor-arg value="TBL_APP_SETTINGS"/>
<constructor-arg value="PROP_KEY"/>
<constructor-arg value="PROP_VALUE"/>
</bean>
</constructor-arg>
</bean>
</property>
</bean>
<bean id="postgresqlDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="url" value="${db.url}"/>
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.pass}"/>
<property name="initialSize" value="1"/>
<property name="maxActive" value="5"/>
<property name="validationQuery" value="SELECT 1"/>
<property name="timeBetweenEvictionRunsMillis" value="5000"/>
<property name="removeAbandonedTimeout" value="60"/>
<property name="minEvictableIdleTimeMillis" value="30000"/>
<property name="minIdle" value="3"/>
</bean>
It's throwing error for ${db.url}
please help how to do this? thanks in advance.
The easiest way is to externalize some of your config properties the guide is on spring.io site. You can pass properies as java system properties or command line arguments
The second way is to write your own PropertyPlaceholderConfigurer which will read properties from application.yml and from the database
I believe the easiest way you can do it is writing credentials into the spring xml and import it to your main xml and reference them as beans:
<bean id="dbUrl" class="java.lang.String">
<constructor-arg type="java.lang.String" value="jdbc://..."/>
</bean>
... same for dbUser and dbPassword
And then refer to the value using ref.

SFTP with DefaultSftpSessionFactory by SSH trust throws exception

I have requirement to download/upload all txt file from SFTP server.
I am using Spring configuration as org.springframework.integration.sftp.session.DefaultSftpSessionFactory
and inbound
its throws ServletContext resource not found.
Here password would be blank
<bean id="acceptAllFileListFilter" class="org.springframework.integration.file.filters.AcceptAllFileListFilter" />
<bean id="inboundSftpSessionFactory" class="org.springframework.integration.file.remote.session.CachingSessionFactory">
<constructor-arg ref="inboundDefaultSftpSessionFactory" />
</bean>
<bean id="inboundDefaultSftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${sftp.host}" />
<property name="privateKey" value="/home/tech/id_rsa"/>
<property name="privateKeyPassphrase" value="${sftp.private.key.passphrase}"/>
<property name="port" value="${sftp.port}" />
<property name="user" value="${sftp.user}" />
<property name="password" value="${sftp.password}" />
</bean>
....
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/home/tech/id_rsa]
at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:141)
at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.initJschSession(DefaultSftpSessionFactory.java:371)
at org.springframework.integration.sftp.session.DefaultSftpSessionFactory.getSession(DefaultSftpSessionFactory.java:347)
... 27 more
File is exist at specified location
when i tried with password configuration then its working fine.
The file isn't at the specified location, as it tries to load the file from the root of the application and it isn't located there. It is located on the file system but that isn't what you specified.
Prefix the property value with file:.
<bean id="inboundDefaultSftpSessionFactory" class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
<property name="host" value="${sftp.host}" />
<property name="privateKey" value="file:/home/tech/id_rsa"/>
<property name="privateKeyPassphrase" value="${sftp.private.key.passphrase}"/>
<property name="port" value="${sftp.port}" />
<property name="user" value="${sftp.user}" />
<property name="password" value="${sftp.password}" />
</bean>
See the reference guide for more information on resource loading.

The order of loading locations in Spring #ContextConfiguration

I'm using the following configuration for my db integration test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:spring/spring-master.xml"})
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
#Transactional()
public class EmployeeAccessPropertyTest {
spring-master.xml loads spring config files in the following order:
<import resource="classpath:spring/db/dev-datasource-config.xml"/>
<import resource="classpath:spring/db/jpa-config.xml"/>
<import resource="classpath:spring/db/transaction-config.xml"/>
<import resource="classpath:spring/db/component-config.xml"/>
dev-datasource-config.xml defines dataSource and initializes db scheme via liquibase:
<context:property-placeholder location="classpath:db/config/dev-data-access.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="liquibase" class="liquibase.integration.spring.SpringLiquibase">
<property name="dataSource" ref="dataSource" />
<property name="changeLog" value="classpath:db/changelog/db.changelog-master.xml" />
<property name="dropFirst" value="true" />
</bean>
Now, when I run test, I'm getting the following error:
javax.persistence.PersistenceException: [PersistenceUnit: studentPersistenceUnit] Unable to build EntityManagerFactory
...
Caused by: org.hibernate.HibernateException: Missing table: employees
It seems, table is not created when entityManagerFactory is initialized (in the jpa-config.xml file). Ok, I generate scheme via liquibase maven plugin first:
mvn initialize liquibase:update
Comment the following db scheme generation via Spring context:
<!--<bean id="liquibase" class="liquibase.integration.spring.SpringLiquibase">-->
<!--<property name="dataSource" ref="dataSource" />-->
<!--<property name="changeLog" value="classpath:db/changelog/db.changelog-master.xml" />-->
<!--<property name="dropFirst" value="true" />-->
<!--</bean>-->
And the problem is gone. What can I do to make sure that Spring first loads dev-datasource-config.xml, initializes the liquibase bean and only then loads jpa-config.xml where which looks like:
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource"/>
Use the 'depends-on' attribute, as described in spring manual:
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-factory-dependson
E.g.
<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />

Categories