How to integrate Flyway into our spring-batch jdbc application - spring

We have a spring-batch application with DB2 jdbc data source. Want to add Flyway migration capabilities to our app. I've been exploring this article, it makes perfect sense, except the section that mentions how to specify the 'entityManagerFactory' - their example is for JPA with Hibernate,and it looks like this:
<!-- Entity Manager Factory configuration -->
<bean id="entityManagerFactory" class="o.s.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="flyway">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="o.s.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="${jpa.database}"/>
</bean>
</property>
</bean>
Our app is simple JDBC datasource for db2. How can I define that <bean id="entityManagerFactory" so that Spring recognizes it as a managed Bean? Do I even need to specify the entityManagerFactory bean configuration?

No, you don't have to specify the entityMangerFactory bean. The flyway migrations don't have to be beans.
This is an example configuration for flyway migrations:
#Configuration
public class FlywayInitializer {
#Autowired
private DataSource dataSource;
#PostConstruct()
private void startMigrations() {
Flyway flyway = new Flyway();
flyway.setDataSource(dataSource);
flyway.setLocations("db/migrations");
flyway.setSchemas("public");
flyway.setSqlMigrationPrefix("H");
flyway.migrate();
}
}
We start by creating a new Flyway object. The javax.Sql.DataSource is the only bean that flyway needs. Flyway needs the data from this bean so it can connect to the database.
Then we configure the locations where the migrations are located, the schemas for flyway (the first schema is the one where the schema_version table will be created) and the migration prefix for the migrations (for example, my migrations look like this: H1__init_db.sql).
There are also a lot of other properties that can be set. Once you are done with configuring the flyway object, you call the migrate method in order to execute the migrations.

Related

setting up JDBCTemplate in Spring using java configuration file

I read in Spring in Action that a good way to set up JDBCTemplate is adding this in the Spring config file:
<jee:jndi-lookup id="dbDataSource" jndi-name="jdbc/AOICMainDB" expected-type="javax.sql.DataSource" />
<bean id="jdbcTemplateDB2" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dbDataSource" />
</bean>
it makes sense, now we can autowire jdbcTemplateDB2 in a DAO and do jdbcTemplate stuff with it.
but how would I set this up using a java config file? Specifically I'm not sure how the jee: namespace translates over to java confg.
The jee:jndi-lookup is just syntactical sugar for the JndiObjectFactoryBean.
The spring documentation provides a before and after example like so:
Before…​
<bean id="simple" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/MyDataSource"/>
</bean>
After…​
<jee:jndi-lookup id="simple" jndi-name="jdbc/MyDataSource">
</jee:jndi-lookup>
Now to convert this into a java config you will need to do something like this:
#Bean
public JndiObjectFactoryBean simple() {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("jdbc/MyDataSource");
return bean;
}
Then you can just retrieve the jndi object from the bean.
References:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/xsd-configuration.html#xsd-config-body-schemas-jee-jndi-lookup-environment-single
Disclaimer: The public void afterPropertiesSet() must run to populate the jndi object.
Your question should be: Who is running the JNDI service that will give the data source to my app?
If your app doesn't run on a Java EE app server with a JNDI service available, the answer is "No one." You should use a DriverManager data source in that case.
If your app does run on a Java EE app server with a JNDI service available, you have to know how to set up your data source in the pool.

Define multiple entityManagerFactory bean using Spring Java #Configuration

I am using multiple databases in my system. I am using AtomikosDataSourceBean to enable xa distributed transaction among multiple dbs.
In spring-configuration.xml file I can create beans for two separate EntityManagerFactory let say entityManagerFactory1 and entityManagerFactory2. But when I do it using Spring Java #Configuration, I get error.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined
If I create one as entityManagerFactory and another as entityManagerFactory1 then I get error as
Caused by: java.lang.IllegalArgumentException: Not an managed type: class com.tom.boon.core.model.Person
for Enitities created under entityManagerFactory1.
Can someone help me in figuring out how to define two separte entityManagerFactory in a Spring Java #Configuration.
You don't really provide that much detail about your configurations. Assuming that those are fairly straightforward as they should be, then you have two beans defined: entityManagerFactory1 and entityManagerFactory2
You need to refer to these via #Resource as follows for the first usage:
#Resource(name = "entityManagerFactory1")
EntityManager entityManager
and in the other usage:
#Resource(name = "entityManagerFactory2")
EntityManager entityManager
This should work, unless something else is wrong. If that is the case, please provide more details about what you are doing. Hope this helps.
In your configuration file, make use the persistenceUnitName property as follows:
<bean id="foo" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceFoo"/>
<property name="persistenceUnitName" value="foo"/>
</bean>
<bean id="bar" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceBar"/>
<property name="persistenceUnitName" value="bar"/>
</bean>
See how dataSources are different for them. You can define different connection properties in dataSourceFoo and dataSourceBar. Then simply use:
#PersistenceContext(unitName = "foo")
private EntityManager foo;
#PersistenceContext(unitName = "bar")
private EntityManager bar;
and EntityManagers foo and bar should connect to different databases.
Do not forget, you need the <context:annotation-config /> element in your configuration file if you want Spring to recognize #PersistenceContext annotation.

Unit Testing based on JNDI , ejb and spring

In my application I am injecting some of services based on EJB with use of Spring IOC through JndiObjectFactoryBean like below mentioned so during run the junit I am getting this exception "java.lang.IllegalArgumentException: This JNDI operation is not implemented by the JNDI provider."
Could some please let me know how I'll configure for Junit.
<bean id="xxxMenuItemService" class="xxxMenuItemServiceyyy">
<property name="xxxMenuItemDelegator" ref="xxxMenuItemDelegator" />
</bean>
<bean id="approveMenuItemServiceRemote"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"
value="ejb/XXXXXXXX" />
have a look at the SimpleNamingContextBuilder from org.springframework.mock as it provides a full context builder where you can bind mock or other objects for use by Spring's JNDI lookup.
One thing to do though is to make sure you build the SimpleNamingContextBuilder in the static #BeforeClass of JUnit 4. this means that it is all initialized and waiting before the Spring Application Context is started and you won't have any JNDI lookup failures.

Spring JTA transaction with JPA and jndi datasource for Websphere

I am having multiple datasource and one one database configured with JPA. I am using websphere 7. I want all these datasouces to be configured as global transactions. I am using below spring configurations but the transactions are not working as expected global transaction. If one db is failing then the other db is getting commited which is not expected as single global transactions. Can you please help me where i m doing incorrect,
I am having 2 datasouce one as configured below with id="us_icfs_datasource" and another using JPA
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/persistenceUnit"/>
<bean id="pabpp" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<!-- Needed for #Transactional annotation -->
<tx:annotation-driven/>
<jee:jndi-lookup id="US_ICFS_DATASORCE"
jndi-name="jdbc/financing_tools_docgen_txtmgr"
cache="true"
resource-ref="true"
proxy-interface="javax.sql.DataSource" />
also I have added below code in web.xml
<persistence-unit-ref>
<persistence-unit-ref-name>persistence/persistenceUnit</persistence-unit-ref-name>
<persistence-unit-name>persistenceUnit</persistence-unit-name>
</persistence-unit-ref>
<persistence-context-ref>
<persistence-context-ref-name>persistence/persistenceUnit</persistence-context-ref-name>
<persistence-unit-name>persistenceUnit</persistence-unit-name>
</persistence-context-ref>
below is my code where i m using transaction
> #Transactional public TemplateMapping addTemplateMapping(User user,
> TemplateMapping templateMapping) throws
> TemplateMappingServiceException { .... }
On Websphere you should use this bean to hook into the Websphere transaction manager:
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
See also this article
EDIT:
In order to use 2-phase commit (i.e. ensuring consistency across multiple resources), you will need to use XA data sources. See this article for details.
First of all your data sources that participate in global transaction must be of javax.sql.XADataSource type.
You also have to set transaction type in your persistence unit to JTA (not RESOURCE_LOCAL).
And you need to inform your JPA implementation that you want to do global transactions.

Configuring Datasource in Spring 3.0

Hello guys I have configured a connection pool and JNDI resource in glassfish 2.1. I can get the Datasource via lookup method in my projects and everything works good. However I decided to try Spring framework and to use my existing connection pool.
In the Spring context file I have the following:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/name" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
<bean id="dao" class="com.mycompany.mavenproject3.Dao">
<property name="simpleJdbcTemplate" ref="jdbcTemplate"/>
</bean>
When I deploy the project I get:
java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required]
Is there anything else I have to configure in that file or in any other file in order to get the Datasource?
Presumably, com.mycompany.mavenproject3.Dao extends JdbcDaoSupport, but you're setting a property named simpleJdbcTemplate on it, leading me to believe that you've defined your own property to hold the template since that doesn't exist on Spring's implementation. It's therefore complaining at you because you're required to set either the dataSource property or the jdbcTemplate property of the JdbcDaoSupport object before using it, exactly like it's telling you. Change <property name="simpleJdbcTemplate"... to <property name="jdbcTemplate"....
If your DAO doesn't extend JdbcDaoSupport, then find what does and remove it or set its properties appropriately.
You can also call your datasource directly in your dao bean, don't need to do an another bean for jdbcTemplate. So your context file become something like this:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/name" />
<bean id="dao" class="com.mycompany.mavenproject3.Dao">
<property name="dataSource" ref="dataSource"/>
</bean>
After you just have to extends JdbcDaoSupport spring class (in which contain the getter and setter of datasource) on your Dao class.

Resources