I've a problem with the Flyway schema upgrader for Spring. Following code exists in my servlet.xml
<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://localhost/database"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</bean>
<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate" depends-on="dataSource">
<property name="dataSource" ref="dataSource"/>
</bean>
But how to set the migration script directory or rather whats the default directory?
Everything is explained in the excellent documentation:
If you want to alter the default directory (which is db/migration as shown on the picture above), I believe this should work (see: Flyway.setBaseDir()):
<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate" depends-on="dataSource">
<property name="dataSource" ref="dataSource"/>
<property name="baseDir" value="my/migrations/path"/>
</bean>
Related
I want to create a restService with Springboot. But I want a configurable datasource, I want to have the capacity to add a new datasource when I want. But I have this exception :
> No qualifying bean of type 'javax.sql.DataSource' available: expected
> single matching bean but found 2
And I'm using this code :
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="database" value="ORACLE"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:9999:TEST"/>
<property name="username" value="test"/>
<property name="password" value="test"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<!-- spring based scanning for entity classes-->
<property name="packagesToScan" value="com.orange.aurore.model.entity"/>
<property name="persistenceUnitName" value="msPersistenceUnit" />
</bean>
<bean id="controllerService" class="...controller.impl.ControllerServiceImpl">
<property name="entityManager" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource"/>
</bean>
and :
<bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:9999:TEST"/>
<property name="username" value="test2"/>
<property name="password" value="test2"/>
</bean>
<bean id="entityManagerFactory2" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource2"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<!-- spring based scanning for entity classes-->
<property name="packagesToScan" value="com.orange.aurore.model.entity"/>
<property name="persistenceUnitName" value="msPersistenceUnit2" />
</bean>
<bean id="controllerService2" class="...controller.impl.ControllerServiceImpl">
<property name="entityManager" ref="entityManagerFactory2" />
<property name="dataSource" ref="dataSource2"/>
</bean>
and in java code :
public void setEntityManager(final HibernateEntityManagerFactory entityManager) {
final RepositoryFactorySupport factorySupport = new JpaRepositoryFactory(entityManager.createEntityManager());
controlRepository = factorySupport.getRepository(ObjControlRepository.class);
Thanks you for your help.
It was a stupide mistake I juste add primary="true" for one of my two configuration.
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
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.
I currently use this configuration for my projects:
<bean id="dataSource" class="oracle.jdbc.pool.OracleDataSource"
destroy-method="close">
<property name="URL" ...
<property name="user" ...
<property name="password" ...
<property name="connectionCachingEnabled" value="true" />
And it works fine, pretty fast.
I happened to see, on an old project (spring 2.5) this configuration:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url"...
<property name="username" ...
<property name="password" ...
</bean>
From documentation it would seem that this last option does not make use of a connection pool. I see no reason to use this configuration over mine, but it still exists so I am curious: where's the advantage/limitation?
1st configuration is oracle specific, whereas 2nd configuration is generic. You can explicitly define driver class.
This is the only major difference I can see in them other than connection pool support of OracleDataSource.
You can use it for generic behavior as mentioned below:
<bean id="baseDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
abstract="true">
<property name="username" value="user"/>
<property name="password" value="pwd" />
</bean>
<bean id="mySqlDataSource" parent="baseDataSource">
<property name="driverClassName" value="${mySQL.driver}" />
<property name="url" value="${mySQL.url}"/>
</bean>
<bean id="oracleDataSource" parent="baseDataSource">
<property name="driverClassName" value="${oracle.driver}" />
<property name="url" value="${oracle.url}"/>
</bean>
Property values you can externalized.
You can explore Apache Jakarta Commons DBCP which has all the features of DriverManagerDataSource
along with connection pool feature.
Say I have the following bean:
<bean id="some-bean" class="com.icyrock.example.SomeBean">
<property name="pa1" value="va1"/>
<property name="pa2" value="va2"/>
<property name="pa3" value="va3"/>
<property name="pa4" value="va4"/>
<property name="pa5" value="va5"/>
<property name="pa5">
<bean class="com.icyrock.example.SomeOtherBean>
<property name="px1" value="vx1"/>
<property name="px2" value="vx2"/>
<property name="px3" value="vx3"/>
<property name="px4" value="vx4"/>
<property name="px5" value="vx5"/>
</bean>
</property>
</bean>
I'd like to separate this into blocks along the lines:
<block id="b1">
<property name="pa1" value="va1"/>
<property name="pa2" value="va2"/>
<property name="pa3" value="va3"/>
</block>
<block id="b2">
<property name="pa4" value="va4"/>
<property name="pa5" value="va5"/>
</block>
<block id="b3">
<property name="px1" value="vx1"/>
<property name="px2" value="vx2"/>
</block>
<block id="b4">
<property name="px3" value="vx3"/>
<property name="px4" value="vx4"/>
<property name="px5" value="vx5"/>
</block>
<bean id="some-bean" class="com.icyrock.example.SomeBean">
<block-ref id="b1"/>
<block-ref id="b2"/>
<property name="pa5">
<bean class="com.icyrock.example.SomeOtherBean>
<block-ref id="b3"/>
<block-ref id="b4"/>
</bean>
</property>
</bean>
where block and block-ref are imaginary Spring tags just to illustrate the idea.
Is there a way to do this without:
Changing the Java classes (e.g. to accept the map of properties or a subclass)
Using anything not already in Spring itself (i.e. anything along the lines of building some factories/property-setters/whatever else to use in Spring context file(s) or so)
The purpose would be to reuse definitions (i.e. blocks) without making any relationships (e.g. parent-child relationships or things like that). As an example, this is standard JDBC data-source definition:
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<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>
(example from here). If there are different servers that are accessed, it can be the case that they share the same driver (so driverClassName would be the shared) and it also can be the case they use the same credentials (so username and password would be the shared). I'd like to do something like:
<block id="driver-credentials">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</block>
<bean id="ds1" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="${jdbc.url1}"/>
<block-ref id="driver-credentials"/>
</bean>
<bean id="ds2" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="${jdbc.url2}"/>
<block-ref id="driver-credentials"/>
</bean>
<bean id="ds3" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="${jdbc.url3}"/>
<block-ref id="driver-credentials"/>
</bean>
or something along these lines. Obviously this can be a parent-child for this simple example, I'm just wondering about a mixin-type solution. Pretty much the same thing Spring offers for multiple files, except on the bean level.
Opinions on why doing the above would not be good or alternative ways to do it are welcome.
Parent child with merge = true on child is the one supported by spring. merge does act as mixin (in a way for collections), right?