Have the following configuration in a java project-
<bean id="testTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="testDataSource" />
</bean>
<bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect" factory-method="aspectOf">
<property name="transactionManager" ref="testTxManager" />
</bean>
But in the DOA java class, #transactional is not used over any of the methods.
Will Transaction management be still applicable on these methods?
Related
Im using JPA with Hibernate implementation and using JpaTransactionManager to mange transactions.
Below is my application context file
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="defaultDataSource" ref="dataSource" />
</bean>
<bean id="entityManagerFactory" primary="true"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="infra_services" />
</bean>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
I have defined my service class as below
#Service
#Transactional
public class ComponentService {
I execute queries in dao layer as below
Query q = entityManager.createQuery(
"SELECT cc.component FROM "
+ this.typeParameterClass.getSimpleName()
+ " cc WHERE cc.caseload.id = ? ").setParameter(1,
caseloadId);
Collection<Component> ddd =q.getResultList();
for (Component c : ddd) {
System.out.println(c.getComponentId());
System.out.println(c.getComponentRelationships2());
}
return ddd;
I started with select queries. While executing the line System.out.println(c.getComponentRelationships2()); getting could not initialize proxy - no Session] with root cause exception
Not sure why the session is not available here. Please help me on this.
If your service is not in the same context as the one where <tx:annotation-driven /> then it's not working. Because it only look for bean in the same context. Extract from spring doc:
#EnableTransactionManagement and only looks for #Transactional on beans in the same application context they are defined in. This means that, if you put annotation driven configuration in a WebApplicationContext for a DispatcherServlet, it only checks for #Transactional beans in your controllers, and not your services. See Section 21.2, “The DispatcherServlet” for more information.
I have an existing code which is written using Spring + Hibernate session factory. I have DAOs written using sessionFactory which are transactional.
#Transactional
public class WorkingDAO<T> {
private SessionFactory sessionFactory;
public void save(T t){
sessionFactory.getCurrentSession().save(t);
}
}
I have unit tests which tests for this DAO which were working fine. Now i want to use Spring JPA so to reduce the effort of writing DAO classes. So I used the following configuration
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect"/>
<property name="jpaProperties">
....
</bean>
<bean id="SessionFactory" factory-bean="entityManagerFactory"
factory-method="getSessionFactory" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven/>
However my older unit tests are failing after using the above configuration. Can i use the existing SessionFactory ? or do i have to migrate to the entityManager ?
I am using Spring and trying to setup a global transaction spanning over two MS SQL Server DBs. The app is running inside Tomcat 6.
I have these definitions:
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
....
</bean>
<bean id="sessionFactory1"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource1"/>
....
</bean>
<bean id="hibernateTransactionManager1"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory1"/>
</property>
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
....
</bean>
<bean id="sessionFactory2"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource2"/>
....
</bean>
<bean id="hibernateTransactionManager2"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory2"/>
</property>
</bean>
Then also, each DAO is linked either to sessionFactory1 or to sessionFactory2.
<bean name="stateHibernateDao" class="com.project.dao.StateHibernateDao">
<property name="sessionFactory" ref="sessionFactory1"/>
</bean>
Also, I recently added these two.
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
<property name="transactionTimeout" value="300" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
I am trying to programmatically manage the global transaction
(this is some old legacy code and I don't want to change it too
much so I prefer keeping this managed programmatically).
So now I have this UserTransaction ut (injected from Spring), so I call ut.begin(), do some DB/DAO operations to the two DBs through the DAOs, then I call ut.commit().
The thing is that even before the ut.commit() call, I can see the data is already committed to the DBs?!
I don't think Atomikos is aware of my two DBs, their data sources, session factories, etc. I don't think it starts any transactions on them. Looks like they are not enlisted at all in the global transaction.
To me it seems that each DB/DAO operation goes to the SQL Server on its own, so SQL Server creates an implicit transaction for just that DAO/DB operation, applies the operation and commits the implicit the transaction.
But 1) and 2) are just guesses of mine.
My questions:
Do I need to start the two DB transactions myself (but OK, this is what I am currently doing and I am trying to get rid of; that's why I am trying to use Atomikos to start with)?
How I can configure all this correctly so that when I call ut.begin() it begins a global transaction to the two DBs and when I call ut.commit() it commits it?
I haven't played with JTA recently so seems to me I am missing something quite basic here. What is it?
Edit 1
<bean id="globalTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="atomikosUserTransaction"/>
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="allowCustomIsolationLevels" value="true" />
<property name="transactionSynchronization" value="2" />
</bean>
I am using JUnit 4 to test Dao Access with Spring (annotations) and JPA (hibernate). The datasource is configured through JNDI(Weblogic) with an ORacle(Backend). This persistence is configured with just the name and a RESOURCE_LOCAL transaction-type
The application context file contains notations for annotations, JPA config, transactions, and default package and configuration for annotation detection.
I am using Junit4 like so:
ApplicationContext
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="workRequest"/>
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="${database.target}"/>
<property name="showSql" value="${database.showSql}" />
<property name="generateDdl" value="${database.generateDdl}" />
</bean>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>workRequest</value>
</property>
<property name="jndiEnvironment">
<props>
<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
<prop key="java.naming.provider.url">t3://localhost:7001</prop>
</props>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
JUnit TestCase
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class AssignmentDaoTest {
private AssignmentDao assignmentDao;
#Test
public void readAll() {
assertNotNull("assignmentDao cannot be null", assignmentDao);
List<Assignment> assignments = assignmentDao.findAll();
assertNotNull("There are no assignments yet", assignments);
}
}
regardless of what changes I make I get:
No unique bean of type [javax.persistence.EntityManager] is defined
Any hint on what this could be. I am running the tests inside eclipse.
Your Spring context has a bean definition using LocalContainerEntityManagerFactoryBean. This creates an EntityManagerFactory, not an EntityManager.
AssignmentDao needs to get itself wired with an EntityManagerFactory.
Alternatively, you can replace the LocalContainerEntityManagerFactoryBean with a LocalEntityManagerFactoryBean, which will create an EntityManager directly. However, you need to be careful with that one, it has some downsides. See that part of the Spring docs for a full explanation of the options.
It's confusing, because the naming conventions of JPA and Spring overlap each other, so naming these classes is a real bugger.
I'm trying to add one more database/schema/persistenceUnit in my project and I'm receiving the error:
No unique bean of type [javax.persistence.EntityManagerFactory] is defined: expected single bean but found 2
I google/api allot and could not found why spring is complaining about my configuration.
Here is part of my applicationContext.xml
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="transactionManager" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${show.hibernate.sql}" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
</bean>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${database.driver}" />
<property name="url" ...
<property name="testOnBorrow" value="true" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactoryREST" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSourceREST" />
<property name="persistenceUnitName" value="REST" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${show.hibernate.sql}" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
</bean>
</property>
</bean>
<bean id="dataSourceREST" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${database.driver}" />
...
<property name="testOnBorrow" value="true" />
</bean>
<bean id="transactionManagerREST" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryREST" />
</bean>
<tx:annotation-driven transaction-manager="REST"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
Some questions:
Do I need to have two tx:annotation-driven ?
Do I need to specify persistenceUnitName in the factory ?
I'm putting some notes of my digg in spring forum (LINK)
Well thats it... any help will be glad!
With Spring, you need to have only one EntityManagerFactory.
What you are looking for is describe in the Spring documentation at the chapiter 13.5.1.4 : "Deals with multiple persitence units"
I copy/paste the text :
"13.5.1.4 Dealing with multiple persistence units
For applications that rely on multiple persistence units locations, stored in various JARS in the classpath, for example, Spring offers the PersistenceUnitManager to act as a central repository and to avoid the persistence units discovery process, which can be expensive. The default implementation allows multiple locations to be specified that are parsed and later retrieved through the persistence unit name. (By default, the classpath is searched for META-INF/persistence.xml files.)
<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>org/springframework/orm/jpa/domain/persistence-multi.xml</value>
<value>classpath:/my/package/**/custom-persistence.xml</value>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="dataSources">
<map>
<entry key="localDataSource" value-ref="local-db"/>
<entry key="remoteDataSource" value-ref="remote-db"/>
</map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="remoteDataSource"/>
</bean>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="pum"/>
<property name="persistenceUnitName" value="myCustomUnit"/>
</bean>
The default implementation allows customization of the PersistenceUnitInfo instances, before they are fed to the JPA provider, declaratively through its properties, which affect all hosted units, or programmatically, through the PersistenceUnitPostProcessor, which allows persistence unit selection. If no PersistenceUnitManager is specified, one is created and used internally by LocalContainerEntityManagerFactoryBean."
This exceptions means that you are trying to autowire EntityManagerFactory by type. Do you have any #Autowired annotation in your code?
Aslo, when using #PersistenceContext, set the unit attribute correctly. And (I'm not sure if this is a proper thing to do) - try setting the name attribute to your respective factory name.
Also, check if you haven't copy-pasted incorrectly the REST transaction manager - now there is no such bean REST
Ensure all of your #PersistenceContext specify unitName. I haven't figured out how to tell Spring that a particular EMF or PersistenceUnit is the default. I thought specifying primary="true" on the default EMF would work but doesn't appear to
Do I need to specify persistenceUnitName in the factory ?
If you've got multiple persistence units, you do need to specify which ones the factories will use.
More to the heart of the matter, see SPR-3955. To summarize, versions prior to Spring 3.0M4 do not support multiple transaction managers with #Transactional. Nor do I believe it honors the "unitName" attribute for #PersistenceContext, so you can't specify that either.
For an example of how I worked around this by explicitly injecting EntityManagerFactorys and using AOP to re-enable #Transactional, see my sample app