Define multiple entityManagerFactory bean using Spring Java #Configuration - spring

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.

Related

How to integrate Flyway into our spring-batch jdbc application

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.

When does spring use AOP without Aspectj.jar?

I can use annotation #Transactional at the top of my service PersonServiceBean and config transactionManager like below. After that, my service can execute db operations under transaction control through AOP.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
.........
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
<property name="dataSource" ref="dataSource"/>
</bean>
But i didn't include aspectj.jar into my project. How does it work? I heard spring implements AOP through aspectj.
It doesn't use AspectJ by default, but uses proxies (either JDK interface proxies or CGLIB proxies). So, when you inject a transactional bean into another bean, what you get injected is in fact a proxy to your actual bean instance, which intercepts the method calls and starts/commits/rollbacks transactions.
More in the documentation, of course.

context:property-placeholder doesn't resolve references

I have next applicationContext.xml file on the root of classpath:
<context:annotation-config />
<context:property-placeholder location="classpath:props/datasource.properties" />
<bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource"
p:username="${jdbc.username}"
p:password="${jdbc.password}"
p:url="${jdbc.url}"
p:driverClassName="${jdbc.driverclass}"
p:validationQuery="SELECT sysdate FROM dual" />
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:dataSource-ref="datasource"
p:mapperLocations="classpath:mappers/*-mapper.xml" />
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="datasource" />
<bean id="mappeScannerConfigurere" class="org.mybatis.spring.mapper.MapperScannerConfigurer"
p:sqlSessionFactory-ref="sqlSessionFactory"
p:basePackage="com.mypackage" />
props/datasource.properties also exists on the root of classpath with such content:
jdbc.url=myjdbcurl
jdbc.driverclass=myClass
jdbc.username=myUserName
jdbc.password=myPassword
I have a spring managed test where I declare to use previously mentioned applicationContext.xml via next annotations:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:applicationContext.xml"})
When I invoke test method i get next error from spring:
org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '${jdbc.driverclass}'
As I understand sping didn't resolve reference to jdbc.driverclass.
What have I done wrong?
PS: I'm using spring 3.2.3.RELEASE
**
EDIT
**
Perhaps the problem may be in MapperScannerConfigurer. It is a BeanDefinitionRegistryPostProcessor and as Javadoc says:
Extension to the standard BeanFactoryPostProcessor SPI,
allowing for the registration of further bean definitions
before regular BeanFactoryPostProcessor detection kicks in
So MapperScannerConfigurer instantiates datasource object via sqlSessionFactory with BeanFacoryPostProcessor(which is responsible for <context:property-placeholder/>) have not been utilized.
So my question transforms to how to reorder BeanFacoryPostProcessor from <context:property-placeholder/> and BeanDefinitionRegistryPostProcessor(MapperScannerConfigurer)?
Resolved
After a couple hours of investigation I found the solution:
As I said earlier MapperScannerConfigurer is a BeanDefinitionRegistryPostProcessor which fires before BeanFactoryPostProcessor which is responsible for <context:property-placeholder/>. So, during the creation of MapperScannerConfigurer references to external properties will not be resolved. In this case we have to defer the creation of datasource to the time after BeanFactoryPostProcessorhave been applied. We can do that in several ways:
remove p:sqlSessionFactory-ref="sqlSessionFactory" from MapperScannerConfigurer. In this case datasource object will not be created before MapperScannerConfigurer, but after BeanFactoryPostProcessor which is responsible for <context:property-placeholder/>. If you have more than one sqlSessionFactory in applicationContext, than can be some troubles
In versions of mybatis-spring module higher than 1.0.2 there is a possibility to set sqlSessionFactoryBeanName instead of sqlSessionFactory. It helps to resolve PropertyPlaceHolder issue with BeanFactoryPostProcessor. It is a recommended way to solve this issue described in mybatis-spring doc
I was having the same issue and came across this post but I was unable to resolve it the same way maks did. What ended up working for me was to set the ignoreUnresolvablePlaceholders property value to true.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:database.properties</value>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>
I am using Spring 3.2.3.RELEASE as well. I realize this post is over 4 months old but I figured someone might find it useful.
Short form: What is the proper way to load an implementation of: BeanDefinitionRegistryPostProcessor?
Expanded form: Is there a way to load BeanDefinitionRegistryPostProcessor before any beans have been created. If you look at the javadoc:
Extension to the standard {#link BeanFactoryPostProcessor} SPI, allowing for
the registration of further bean definitions before regular
BeanFactoryPostProcessor detection kicks in.
So it's meant to be loaded when bean definitions have been created but before any beans have been created. If we just create it as a regular bean in the application xml then it defeats the purpose of having this bean in the first place.

Setting property reference for a bean programmatically

Right now i am using the following bean entry
<bean id="Service" >
<property name="target">
<bean class="someClass" lazy-init="false">
<property name="SessionFactory1"><ref bean="SessionFactory1"/></property>
<property name="SessionFactory2"><ref bean="SessionFactory2"/></property>
<property name="SessionFactory3"><ref bean="SessionFactory3"/></property>
</bean>
</property>
</bean>
Now the requirement is to first check which all session factories have an active datasource and include those only in the above bean definition. So that the application does not break if we try to initialize a session factory with inactive datasource.
sessionfactory initialization will be take care by using seperate config xml for session factories and loading only the ones with active datasources.
Please help on how can this be achieved.
You can use Spring InitializingBean interface, which makes you implement an afterPropertiesSet() method. This method will be executed after Spring instantiates your class, and you could check if your session factories are available or not.
InitializingBean: Interface to be implemented by beans that need to react once all their properties have been set by a BeanFactory: for example, to perform custom initialization, or merely to check that all mandatory properties have been set.
link: Spring InitializingBean

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