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

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?

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

Getting current transaction reference of JpaTransactionManager

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" />

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.

java.lang.ClassNotFoundException: org.hibernate.engine.SessionFactoryImplementor

i am trying to migrate to hibernate 4.1.0.Final with spring 3.1.1.RELEASE
and following is my configuration for hibernate:
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="${project.groupId}.domain" />
<!-- control the behavior of Hibernate at runtime,All are optional and
have reasonable default values -->
<property name="hibernateProperties">
<value>
<!-- hibernate.dialect: allows Hibernate to generate SQL optimized for
a particular relational database -->
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hbm2ddl.auto=create-drop
hibernate.show_sql=false
hibernate.jdbc.fetch_size=100
hibernate.jdbc.batch_size=100
hibernate.jdbc.batch_versioned_data=true
hibernate.order_inserts=true
hibernate.order_updates=true
hibernate.cache.use_query_cache=false
hibernate.cache.use_second_level_cache=false
</value>
</property>
</bean>
<!-- provides properties to hibernate to make it able to create session
factory. Hibernate uses instance of session bean of type -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<!-- responsible for creating sessionFactory opening transactions and binding
them to the current thread context. -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="nestedTransactionAllowed" value="true" />
</bean>
<!-- get exception translation from HibernateException into DataAccessException
hierarchy -->
<bean
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
but when trying to run the application, i got the following exception:
java.lang.ClassNotFoundException: org.hibernate.engine.SessionFactoryImplementor
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1678)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1523)
please advise why i get this error, and how to fix it, thanks.
Try using the org.springframework.orm.hibernate4.HibernateTransactionManager
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>

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