Community   SpringSource   Projects    Downloads    Documentation    Forums    Training   Exchange   Blogs

Go Back   Spring Community Forums > Core Spring Projects > Data Access

Reply
 
Thread Tools Display Modes
  #1  
Old Aug 26th, 2008, 09:53 AM
claudio4j claudio4j is offline
Junior Member
 
Join Date: Aug 2008
Posts: 6
Exclamation Spring JTA not working with glassfish

I am trying to work with a mixture of implementations. Using SpringJPA to inject PersistenceContext and use it into service classes.

When I try to issue a em.save(), a RollbackException: Transaction marked for rollback is throw

Code:
[#|2008-08-26T08:18:52.620-0300|WARNING|sun-appserver9.1|javax.enterprise.system.stream.err|_ThreadID=21;_ThreadName=httpSSLWorkerThread-8080-3;_RequestID=25faab58-7d4c-4ea9-baec-070ff871a281;|org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Transaction marked for rollback.
        at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1031)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:709)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:678)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at $Proxy47.save(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.wicket.proxy.LazyInitProxyFactory$JdkHandler.invoke(LazyInitProxyFactory.java:416)
        at org.apache.wicket.proxy.$Proxy50.save(Unknown Source)
        at br.com.evconf.ui.AccountAction$1.onSubmit(AccountAction.java:57)
        at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1355)
        at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:810)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:183)
        at org.apache.wicket.request.target.component.listener.ListenerInterfaceRequestTarget.processEvents(ListenerInterfaceRequestTarget.java:73)


Caused by: javax.transaction.RollbackException: Transaction marked for rollback.
        at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:440)
        at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371)
        at com.sun.enterprise.transaction.TransactionManagerHelper.commit(TransactionManagerHelper.java:63)
        at org.springframework.transaction.jta.UserTransactionAdapter.commit(UserTransactionAdapter.java:76)
        at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1028)
See the system I am working on:

* Glassfish v2 ur2 (9.1_02 build b04-fcs)
* Hibernate Core 3.3.0
* Hibernate EM 3.4.0
* Spring 2.5.5

Code:
Jar files at WEB-INF/lib
antlr-2.7.6.jar
cglib-nodep-2.1_3.jar
commons-beanutils-1.7.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
ejb3-persistence.jar
hibernate3.jar
hibernate-annotations.jar
hibernate-cglib-repack-2.1_3.jar
hibernate-commons-annotations.jar
hibernate-entitymanager.jar
javassist-3.4.GA.jar
jcl-over-slf4j-1.5.2.jar
log4j-1.2.14.jar
slf4j-api-1.5.2.jar
slf4j-log4j12-1.5.2.jar
spring.jar
wicket-1.3.4.jar
wicket-auth-roles-1.3.4.jar
wicket-datetime-1.3.4.jar
wicket-extensions-1.3.4.jar
wicket-ioc-1.3.4.jar
wicket-objectsizeof-agent-1.3.4.jar
wicket-spring-1.3.4.jar
wicket-spring-annot-1.3.4.jar
Configuration files

* Wherever you see "myPU", "myDS", I have changed the real names.

persistence.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" spring forum doesn't allow to post XML namespaces>
    <persistence-unit name="myPU" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>jdbc/myds</jta-data-source>
        <class>...many model classes...</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.SunONETransactionManagerLookup"/>
        </properties>
    </persistence-unit>
</persistence>
applicationContext.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<beans .... spring forum doesn't allow to post XML namespaces>
           
    <bean id="entityManagerFactory"
            class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
        <property name="dataSource" ref="datasource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
                <!--<property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />-->
            </bean>
        </property>
        <property name="persistenceUnitName" value="myPU" />
    </bean>
    
    <jee:jndi-lookup id="datasource" jndi-name="jdbc/myds" />
    
    <tx:annotation-driven transaction-manager="transactionManager" />
    
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

    <bean id="supportAccount" class="my.impl.AccountSupportImpl" />
</beans>
See below, the interface and implementation

Java interface
Code:
@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public E save(E e);
Java class
Code:
public E save(E e) {
  logger.debug("entity save");
  if (e.getId() == null) {
    try {
    em.persist(e);
    logger.debug("entity persist - success");
  } catch (RuntimeException err) {
    logger.debug("entity persist - fail");
    e.setId(null);
    throw err;
  }
} else
  e = em.merge(e);
  return e;
}

What I have done before:

1) Use RESOURCE_LOCAL: Glassfish doesn't allow, because it is a managed environment

2) Tried to use the tips provided on other posts (see threads named "GlassFish, Hibernate, JTA, CMT" number 58034 and "JPA , Spring 2.x , Glassfish V2 " number 48191), with no success

* spring forum doesn't allow to post links for the first time, what a difficult.

3) If a lookup_class is not specified at persistence.xml, hibernate throws: HibernateException: The chosen transaction strategy requires access to the JTA TransactionManager

I saw there are some transactionmanager related to appservers at org.springframework.transaction.jta package, but there is not one to glassfish. Is this the missing piece ?

What else can I do to make it work ?

Thanks

Claudio Miranda

Last edited by claudio4j; Aug 26th, 2008 at 09:59 AM.
Reply With Quote
  #2  
Old Aug 26th, 2008, 11:10 AM
Marten Deinum Marten Deinum is offline
Senior Member
 
Join Date: Jun 2006
Location: The Netherlands
Posts: 8,095
Default

Quote:
I saw there are some transactionmanager related to appservers at org.springframework.transaction.jta package, but there is not one to glassfish. Is this the missing piece ?
I suggest the reference guide before you start guessing at issues which aren't there.

First off all I would start by removing the double configuration, you specify a datasource in your application context and persistence.xml the same goes for some properties. Remove the duplication.

Instead of the JtaTransactionManager try the code below.
Code:
<tx:jta-transaction-manager />
Your configuration looks ok, you are using a correct XA capable datasource aren't you?
__________________
Marten Deinum
  • Senior software Engineer/Architect
  • SpringSource Certified Trainer
Conspect ICT diensten
Blog
Use the [ code ] tags, young padawan
Reply With Quote
  #3  
Old Aug 26th, 2008, 11:54 AM
claudio4j claudio4j is offline
Junior Member
 
Join Date: Aug 2008
Posts: 6
Default

Quote:
Originally Posted by Marten Deinum View Post
I suggest the reference guide before you start guessing at issues which aren't there.

First off all I would start by removing the double configuration, you specify a datasource in your application context and persistence.xml the same goes for some properties. Remove the duplication.
I read the reference guide, searched spring forums and the internet overall.

And it looked like the datasource shall be referenced from applicationContext.xml.
For now the datasource is only declared at persistence.xml.

Quote:
Originally Posted by Marten Deinum View Post
Instead of the JtaTransactionManager try the code below.
Code:
<tx:jta-transaction-manager />
This the current applicationContext.xml
Code:
<beans ...lot of xml schemas...>
           
    <bean id="entityManagerFactory"  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
            </bean>
        </property>
        <property name="persistenceUnitName" value="myPU" />
    </bean>
  
  <tx:annotation-driven transaction-manager="transactionManager" />
  <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
  <tx:jta-transaction-manager />
  <bean id="supportAccount" class="my.impl.impl.AccountSupportImpl" />
</beans>

Quote:
Originally Posted by Marten Deinum View Post
Your configuration looks ok, you are using a correct XA capable datasource aren't you?
Yes, postgresql XA driver
org.postgresql.xa.PGXADataSource
postgresql-8.2-508.jdbc4.jar

At the end, the same error remains:

Code:
org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Transaction marked for rollback.
        at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1031)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:709)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:678)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)

RollbackException: Transaction marked for rollback.
        at com.sun.enterprise.distributedtx.J2EETransaction.commit(J2EETransaction.java:440)
        at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:371)
        at com.sun.enterprise.distributedtx.UserTransactionImpl.commit(UserTransactionImpl.java:197)
        at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1028)
Thank you very much for your time.

If you can point out alternatives, it will be very appreciated.
Reply With Quote
  #4  
Old Aug 27th, 2008, 12:57 AM
Marten Deinum Marten Deinum is offline
Senior Member
 
Join Date: Jun 2006
Location: The Netherlands
Posts: 8,095
Default

Can you post the whole stacktrace. Your configuration looks ok, seems more like a glassfish thing.

Quote:
I read the reference guide, searched spring forums and the internet overall.
Quote:
And it looked like the datasource shall be referenced from applicationContext.xml.
For now the datasource is only declared at persistence.xml.
A common approach is to configure all your things in the applicationContext.xml (datasource etc) and leave only the mapped classes in your persistence.xml. You could even remove those if I'm not mistaken leaving a very thin persistence.xml. Although I don't think it makes a difference just wanted to let you know.
The reference guide explains for which application servers we have native support and for which not. That explains the different TransactionManager classes for certain servers.
__________________
Marten Deinum
  • Senior software Engineer/Architect
  • SpringSource Certified Trainer
Conspect ICT diensten
Blog
Use the [ code ] tags, young padawan
Reply With Quote
  #5  
Old Aug 27th, 2008, 07:23 AM
claudio4j claudio4j is offline
Junior Member
 
Join Date: Aug 2008
Posts: 6
Default

I did a small .war application, where I can reproduce the issue

claudius .com. br/spring-hib-gf.tar.gz

(remove the space between the words, as spring forum doesn't allow to post URLs)

deploy the application: dist/spring-hib-gf.war,
The source code and configuration files are part of that .tar.gz

url: loca lhost :<PORT> /t/app/p

Requirements to deploy
- postgresql 8.2.9
- jdbc/jtatest PostgreSQL XA datasource (org.postgresql.xa.PGXADataSource)
at jdbc connection pool add a special property to make glassfish use only JDBC 3 features: JDBC30DataSource=true

Then, the guilty exception is revealed:
Code:
2008-08-27 00:18:53 [WARN] org.hibernate.util.JDBCExceptionReporter|SQL Error: 0, SQLState: null
2008-08-27 00:18:53 [ERROR] org.hibernate.util.JDBCExceptionReporter|Batch entry 0 insert into Person (name, id) values (Oxygen, 300) was aborted.  Call getNextException to see the cause.
2008-08-27 00:18:53 [WARN] org.hibernate.util.JDBCExceptionReporter|SQL Error: 0, SQLState: 23502
2008-08-27 00:18:53 [ERROR] org.hibernate.util.JDBCExceptionReporter|ERROR: null value in column "per_id" violates not-null constraint
2008-08-27 00:18:53 [ERROR] org.hibernate.event.def.AbstractFlushingEventListener|Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
        at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
        at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
....
Caused by: java.sql.BatchUpdateException: Batch entry 0 insert into Person (name, id) values (Oxygen, 300) was aborted.  Call getNextException to see the cause.
        at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2534)
        at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1328)
        at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:352)
        at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2669)
Looks like the "select next_val" statement is not under the same transaction as the "insert".

I have used postgresql+sequeces+hibernate in the past, but not together to spring and JPA, and it worked well.

Probably if I use BMT, it can work, but its not worth, I prefer the @Transactional approach.

So I have 2 issues now
1) How to make it work with postgresql
2) Why the complete stacktrace is not displayed at the console, as the log4j configuration looks to be ok


Code:
<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>/WEB-INF/classes/log4j.properties</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
Code:
log4j.rootLogger=INFO, SYSOUT

log4j.appender.SYSOUT=org.apache.log4j.ConsoleAppender
log4j.appender.SYSOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.SYSOUT.Threshold=INFO
log4j.appender.SYSOUT.layout.ConversionPattern=%-4r %-5p %c %x - %m%n


####  appender
log4j.appender.LOGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.LOGFILE.File=${com.sun.aas.instanceRoot}/logs/apps_out.log
# Set the maximum log file size (use KB, MB or GB)
log4j.appender.LOGFILE.MaxFileSize=2000KB
# Set the number of log files (0 means no backup files at all)
log4j.appender.LOGFILE.MaxBackupIndex=2
# Append to the end of the file or overwrites the file at start.
log4j.appender.LOGFILE.Append=false
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%p] %c|%m%n

log4j.logger.org.apache.wicket=WARN
log4j.logger.org.hibernate=WARN
log4j.logger.com.mchange=WARN
log4j.logger.br.com.evconf=DEBUG
log4j.logger.org.springframework=INFO
For now I will try to use MySQL 5 (InnoDB), as this is a new project.

Thanks again
Reply With Quote
  #6  
Old Aug 27th, 2008, 08:08 AM
claudio4j claudio4j is offline
Junior Member
 
Join Date: Aug 2008
Posts: 6
Default

Just to let you know, I have updated the demo application spring-hib-gf.tar.gz.

For now there are 2 entities, Person <relation to> Address

Try to run them, the same exception reported at the 1st thread will be throw. The bad: there is no logging as stated on the previous thread, about the null value in column "per_id" violates not-null constraint

This example, demonstrates exactly the issue I am having.

I have configured @Transaction at the method that calls the em.persist() (see class TestPage, onSubmit method)

Next step, I will try to use MySQL 5 (InnoDB)

Thanks
Reply With Quote
  #7  
Old Aug 27th, 2008, 09:09 AM
Marten Deinum Marten Deinum is offline
Senior Member
 
Join Date: Jun 2006
Location: The Netherlands
Posts: 8,095
Default

There are 2 strange things and 1 thing I wonder

1) The @Transactional on your onSubmit method isn't doing anything
2) You should define the @Transactional on the implementation not the interface.
3) Also I'm not sure if it is wise to mark your Service and EntityManager transient

However only number 2 should influence the way your transactions work.

@Transactional only works on beans that spring knows about. The TestPage is not a page that is configured in a spring context.
__________________
Marten Deinum
  • Senior software Engineer/Architect
  • SpringSource Certified Trainer
Conspect ICT diensten
Blog
Use the [ code ] tags, young padawan
Reply With Quote
  #8  
Old Aug 27th, 2008, 10:14 AM
claudio4j claudio4j is offline
Junior Member
 
Join Date: Aug 2008
Posts: 6
Default

Quote:
1) The @Transactional on your onSubmit method isn't doing anything
2) You should define the @Transactional on the implementation not the interface.
You are right, it is working now.

Thank you for your time, very appreciated.
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -5. The time now is 10:59 AM.


Contegix provides first-class managed hosting and partial sponsorship of these forums.

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.