Getting current transaction reference of JpaTransactionManager - spring

We have started transaction in our service layer with #Transactional (org.springframework.transaction.annotation.Transactional). We need to get current transaction reference in data access layer? Is there any way we can get reference of current transaction?
Below is the transaction configuration in our case:
JPA Configuration
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:persistenceUnitName="pUnitName"
p:persistenceXmlLocation="classpath*:persistence.xml"
p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter">
<property name="loadTimeWeaver">
<bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" />
<bean id="jpaAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:database="ORACLE" p:showSql="true" />

Related

Reg Spring Batch Transaction

My Requirement is I need to have two datasource connected to Spring Batch Application.
1) One for Spring Batch Jobs and Executions storing
2) One for Business Data Stroing, Processing and Retreiving.
I know that there are lot of solutions for achieving this. But I have achieved by setting the second datasource as primary. The problem is the second datasource is not coming under transaction scope instead it is committing for each sql statement executing expecially through jdbctemplate.
As I can't able to edit my question. I am writing another Post in detail
My Requirement is I need to have two datasource connected to Spring Batch Application.
1) One for Spring Batch Jobs and Executions storing
2) One for Business Data Stroing, Processing and Retreiving.
In env-context.xml I have following configuration
<!-- Enable annotations-->
<context:annotation-config/>
<bean primary="true" id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/DB2XADS"/>
</bean>
<!-- Creating TransactionManager Bean, since JDBC we are creating of type
DataSourceTransactionManager -->
<bean id="transactionManager" primary="true"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- jdbcTemplate uses dataSource -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="batchTransactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager"/>
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager" />
</bean>
In override-context.xml I have the following code
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- jdbcTemplate uses dataSource -->
<bean id="batchDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:/MySqlDS"/>
</bean>
<bean class="com.honda.pddabulk.utility.MyBatchConfigurer">
<property name="dataSource" ref="batchDataSource" />
</bean>
<!-- Use this to set additional properties on beans at run time -->
<bean id="placeholderProperties"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/org/springframework/batch/admin/bootstrap/batch.properties
</value>
<value>classpath:/batch/batch-mysql.properties</value>
<value>classpath:log4j.properties</value>
</list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="true"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="order" value="1"/>
</bean>
<!-- Overrider job repository -->
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="databaseType" value="mysql"/>
<property name="dataSource" ref="batchDataSource"/>
<property name="tablePrefix" value="${batch.table.prefix}"/>
<property name="maxVarCharLength" value="2000"/>
<property name="isolationLevelForCreate" value="ISOLATION_SERIALIZABLE"/>
<property name="transactionManager" ref="batchTransactionManager"/>
</bean>
<!-- Override job service -->
<bean id="jobService" class="org.springframework.batch.admin.service.SimpleJobServiceFactoryBean">
<property name="tablePrefix" value="${batch.table.prefix}"/>
<property name="jobRepository" ref="jobRepository"/>
<property name="jobLauncher" ref="jobLauncher"/>
<property name="jobLocator" ref="jobRegistry"/>
<property name="dataSource" ref="batchDataSource"/>
</bean>
<!-- Override job launcher -->
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor" ref="jobLauncherTaskExecutor" />
</bean>
<task:executor id="jobLauncherTaskExecutor" pool-size="21" rejection-policy="ABORT" />
<!-- Override job explorer -->
<bean id="jobExplorer"
class="org.springframework.batch.core.explore.support.JobExplorerFactoryBean">
<property name="tablePrefix" value="${batch.table.prefix}"/>
<property name="dataSource" ref="batchDataSource"/>
</bean>
In job-config.xml I have the following code
<context:component-scan base-package="com.honda.*">
<context:exclude-filter type="regex"
expression="com.honda.pddabulk.utility.MyBatch*" />
</context:component-scan>
I have the custom Batch configurer set. Now the problem is when I try to execute queries with jdbctemplate for update and insert it is not under transaction which means #Transactional is not working.
Rather commit is happening for each method call. The example is
#Transactional
public void checkInsertion() throws Exception{
try{
jdbcTemplate.update("INSERT INTO TABLE_NAME(COLUMN1, COLUMN2) VALUES( 'A','AF' );
throw new PddaException("custom error");
}catch(Exception ex){
int count=jdbcTemplate.update("ROLLBACK");
log.info("DATA HAS BEEN ROLLBACKED SUCCESSFULLY... "+count);
throw ex;
}
}
In the above code I am trying to insert data and immediately I am also throwing a exception which means the insert should happen but commit will not. So we will not be able to see any data but unfortunately the commit is happening. Please some one help

How to reopen JPA EntityManager after it gets invalidated with an exception

I have a simple spring/hibernate/jpa based application. I am trying to iteration through a list of records from an xml file and persist it into a DB table.
I have 35 records and 3 of them has null values for certain fields which are mandatory in the table.
I get this error:
org.hibernate.AssertionFailure: null id in com.pilogics.gogabbar.domain.model.entity.UserActivity entry (don't flush the Session after an exception occurs)..
As I don't have control of the data coming through a file, I want to simply skip those 3 records and carry on. But since the entityManager object is invalidated, do have to reinitialize it?
Also, I have this config in spring fopr entity manager factory:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath:jpa/persistence.xml" />
<property name="persistenceUnitName" value="gg-rw" />
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.pilogics.gogabbar.infra.persistence.hibernate.pojo.*" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>
And spring injects the entity manager to a dao class:
#PersistenceContext(unitName="gg-rw")
protected EntityManager entityManagerRw;
How can I reinitialize entityManager object in my catch block to carry on with the remaining records?

Spring JpaTransactionManager not saving Activiti entities to DB

Nothing about Activiti is being saved to database. Application entities ARE being saved to database. Below, in order are, the spring file, persitence.xml file and the test case.
Using SQL Server profiler, I see a separate database transaction being started for the database interaction caused by Activiti and further I see that separate transaction being rolled back instead of being committed. Other application db interaction is happening on another transaction and this particular transaction is being committed.
I thought, given my configurations, Activiti database interaction would happen on the same transaction as the rest of the application. I have gone through my configuration files and code numerous times and do not see anything wrong therein. Any ideas why a separate transaction is being started for the Activiti db interactions?
Of course the previous item is the critical question. However, it would also be interesting to know why is that separate transaction being rolled back?
Spring file :
<context:annotation-config/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="ActivitiTrialDataSource" class="org.apache.commons.dbcp.BasicDataSource" >
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver" />
<property name="url" value="jdbc:jtds:sqlserver://localhost:1433/ActivitiTrial" />
<property name="username" value="ActivitiTrial" />
<property name="password" value="ActivitiTrial" />
<property name="defaultAutoCommit" value="false" />
<property name="initialSize" value="5" />
</bean>
<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="ActivitiTrialDataSource" />
<property name="persistenceUnitName" value="ActivitiTrial"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- Activiti -->
<bean id="activitiDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<property name="targetDataSource" ref="ActivitiTrialDataSource" />
</bean>
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="databaseType" value="mssql" />
<property name="dataSource" ref="activitiDataSource" />
<property name="transactionsExternallyManaged" value="true" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="false" />
<property name="history" value="audit" />
<property name="jobExecutorActivate" value="false" />
</bean>
<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
<bean id="activitiRepositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
<bean id="activitiRuntimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
<bean id="activitiTaskService" factory-bean="processEngine" factory-method="getTaskService" />
<bean id="activitiHistoryService" factory-bean="processEngine" factory-method="getHistoryService" />
<bean id="activitiManagementService" factory-bean="processEngine" factory-method="getManagementService" />
persitence.xml file:
<persistence-unit name="ActivitiTrial">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.archive.autodetection" value="hbm,class"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.hbm2ddl.auto" value="none"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.ejb.metamodel.generation" value="disabled"/>
</properties>
</persistence-unit>
Test case:
#RunWith(SpringJUnit4ClassRunner.class)
#TransactionConfiguration(defaultRollback=false)
#ContextConfiguration({"classpath:/springApplicationContext.xml"})
public class TrialTest {
#Autowired
RepositoryService activitiRepositoryService;
#Autowired
RuntimeService activitiRuntimeService;
#Autowired
TaskService activitiTaskService;
#PersistenceContext(unitName="ActivitiTrial")
EntityManager entityManager;
#Test
#Transactional
public void trialTest() throws Exception {
long entryMilliseconds = new Date().getTime();
activitiRepositoryService.createDeployment().addClasspathResource("process-definitions/neville.bpmn20.xml").deploy();
ApplicationEntity applicationEntity1 = new ApplicationEntity();
applicationEntity1.name = "App entity 1";
applicationEntity1.createDate = new Date();
Session hibernateSessionBeforeActiviti = ((Session) entityManager.getDelegate());
entityManager.persist(applicationEntity1);
entityManager.flush();
Map<String, Object> processVariables = new HashMap<String, Object>();
processVariables.put("ApplicationEntityID", applicationEntity1.id);
ProcessInstance processInstance = activitiRuntimeService.startProcessInstanceByKey("neville", processVariables);
String processInstanceId = processInstance.getId();
Task userTask = activitiTaskService.createTaskQuery().processInstanceId(processInstanceId).list().get(0);
ApplicationEntity applicationEntity2 = new ApplicationEntity();
applicationEntity2.name = "App entity 2";
applicationEntity2.createDate = new Date();
Session hibernateSessionAfterActiviti = ((Session) entityManager.getDelegate());
entityManager.persist(applicationEntity2);
entityManager.flush();
System.out.println("Leaving trialTest() in : " + (new Date().getTime() - entryMilliseconds) + " milliseconds.");
}
}
I've solved this problem by resolving conflict between MyBatis (JDBC) and Hibernate (JPA):
You should add jpaVendorAdapter property to entityManagerFactory bean:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="ActivitiTrialDataSource" />
<property name="persistenceUnitName" value="ActivitiTrial"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
</bean>
For more details see answer of this question.
I've already waste a lot of time trying to pass common transaction manager to Spring and Activiti - and no result. No mean of full answer to your question, but I hope it will save you some time
Activiti forum:
http://forums.activiti.org/content/activiti-doesnt-submit-rollback
http://forums.activiti.org/content/activitispringhibernate-common-transaction-manager
Demo:
These repos illustrate that Activiti don't accept jpa/hibernate transactions:
https://github.com/JOLO-/activiti-jpa-spring-transaction-demo.git
https://github.com/JOLO-/activiti-hibernate-spring-transaction-demo.git
You also can see demo https://github.com/Activiti/Activiti (Activiti + Spring + Bitronix) it may help (I have no time to check it yet).
P.S.
As an alternative to common transaction I see compensation events.

Spring JPA/Hibernate in standalone app

I am utilizing spring in non web application and I am using hibernate for working with DB. Problem I am experiencing is that while "registerShutdownHook();" does close spring context container it does not properly shut down and close resources for JPA so my connections to DB are getting maxed out.
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="pu" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="showSql" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
I use configuration presented above to fire up JPA layer and use "#Transactional" annotations to inject EM's into DAO's.
Maybe someone could help me out what am I missing or how should I handle proper closing of JPA sessions in standalone environment ?
Thank you,
P.S. Exception I am getting is: java.net.SocketException: No buffer space available (maximum connections reached?): connect
1.Create transaction manager as follow :
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="persistenceUnitName" value="persistanceUnit"/>
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="classpath:persistence.xml"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${db.orm.showsql}" />
<property name="generateDdl" value="${db.orm.generateDdl}" />
<property name="database" value="${db.type}"/>
<property name="databasePlatform" value="${db.orm.dialect}" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
2.use persistance.xml(should be in classpath)
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="persistanceUnit" transaction-type="RESOURCE_LOCAL">
<description>Oracle db Persistence Unit</description>
<class>com.company.YourModelClass</class>
<properties/>
</persistence-unit>
</persistence>
3.Add following annotation in applicationContext.xml
<context:component-scan base-package="com.yourcompany.basepackage" />
4.annoatate your Entitymanager in service class like:
#PersistenceContext
private EntityManager em = null;
5.Inject TrasnsactionManager to :
private PlatformTransactionManager platformTransactionManager = null;
6.persist object like:
platformTransactionManager .persist(obj);
This is another example of application Context.xml with JPA. It works fine for me.
<context:property-placeholder location=”classpath:jdbc.properties”/>
<!– Connection Pool –>
<bean id=”dataSource” destroy-method=”close”>
<property name=”driverClass” value=”${jdbc.driverClass}”/>
<property name=”jdbcUrl” value=”${jdbc.url}”/>
<property name=”user” value=”${jdbc.username}”/>
<property name=”password” value=”${jdbc.password}”/>
</bean>
<!– JPA EntityManagerFactory –>
<bean id=”entityManagerFactory”
p:dataSource-ref=”dataSource”>
<property name=”jpaVendorAdapter”>
<bean>
<property name=”database” value=”${jdbc.database}”/>
<property name=”showSql” value=”${jdbc.showSql}”/>
</bean>
</property>
</bean>
<!– Transaction manager for a single JPA EntityManagerFactory (alternative to JTA) –>
<bean id=”transactionManager”
p:entityManagerFactory-ref=”entityManagerFactory”/>
<!– Activates various annotations to be detected in bean classes for eg #Autowired–>
<context:annotation-config/>
<!– enable the configuration of transactional behavior based on annotations –>
<tx:annotation-driven transaction-manager=”transactionManager”/>
<!– Property Configurator –>
<bean id=”propertyConfigurer”>
<property name=”location” value=”jdbc.properties”/>
</bean>
<context:component-scan base-package=”com.test.dao”/>
</beans>

Spring JPA provider produces wring exception on optimistic lock failure

In case there is failure in optimistic locking I expect JPA entity manager to throw javax.persistence.OptimisticLockingException
Yet when I use spring orm jpa it provides ObjectOptimisticLockingException which is not related with expected one - so the question is, WTF? Do I misunderstand JPA documentation, or did the spring guys ignored standarts?
Most funny thing is that in JUnit test case proper exception is thrown ( Wrapping StaleObjectException ),
while in web app it is FUBAR. Spring configuration is reused for unit test.
Here is some code for clarity :
<!-- JPA entity manager configuration -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="testOnBorrow" value="${database.testonborrow}"/>
<property name="validationQuery" value="${database.validationquery}"/>
</bean>
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="defaultDataSource" ref="dataSource"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager"/>
<property name="persistenceUnitName" value="provisioning"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true"/>
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.dialect" value="${hibernate.dialect}"/>
<entry key="hibernate.hbm2ddl.auto" value="${hibernate.hbm2ddl.auto}" />
<entry key="hibernate.hbm2ddl.delimiter.type" value="InnoDB" />
<entry key="hibernate.show_sql" value="${hibernate.show_sql}" />
</map>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<context:annotation-config/>
<tx:annotation-driven/>
It's not a bug, it's a feature. Spring's HibernateTemplate and its interceptors around repositories translate exceptions into Spring exceptions. The idea is that if you have a Hibernate-based DAO, an iBatis-based DAO or a JDBC-based DAO, they all throw the same types of exceptions, so that the client code doesn't have to care.
See http://static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/dao.html#dao-exceptions

Resources