Glassfish, XA Transactions, and PostgreSQL

The other night I was working on the source for ActionBazaar (EJB 3.2 in Action) when I ran into a new problem. In the code that I was writing I was both submitting a message to a JMS queue and also creating a user in a database within stateless session bean. This obviously would use a two-phase commit. When I had setup the JDBC connection pool in Glassfish, I had created it as an XADataSource. Apparently my PostgreSQL setup wasn’t quite setup to handle this as I immediately got this exception:

Exception [java.lang.RuntimeException: org.postgresql.xa.PGXAException: Error preparing transaction] on Resource [prepare] operation.|#]

[#|2012-02-08T23:37:21.962-0500|WARNING|glassfish3.1.1|javax.enterprise.system.core.transaction.com.sun.jts.jtsxa|_ThreadID=22;_ThreadName=Thread-4;|JTS5068: Unexpected error occurred in rollback
org.postgresql.xa.PGXAException: Error rolling back prepared transaction
	at org.postgresql.xa.PGXAConnection.rollback(PGXAConnection.java:406)
	at com.sun.gjc.spi.XAResourceImpl.rollback(XAResourceImpl.java:195)
	at com.sun.jts.jta.TransactionState.rollback(TransactionState.java:193)
	at com.sun.jts.jtsxa.OTSResourceImpl.rollback(OTSResourceImpl.java:333)
	at com.sun.jts.CosTransactions.RegisteredResources.distributeRollback(RegisteredResources.java:1038)
	at com.sun.jts.CosTransactions.TopCoordinator.rollback(TopCoordinator.java:2290)
	at com.sun.jts.CosTransactions.CoordinatorTerm.commit(CoordinatorTerm.java:420)
	at com.sun.jts.CosTransactions.TerminatorImpl.commit(TerminatorImpl.java:250)
	at com.sun.jts.CosTransactions.CurrentImpl.commit(CurrentImpl.java:623)
	at com.sun.jts.jta.TransactionManagerImpl.commit(TransactionManagerImpl.java:323)
	at com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate.commitDistributedTransaction(JavaEETransactionManagerJTSDelegate.java:186)
	at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:858)
	at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:5114)
	at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4879)
	at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2039)
	at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1990)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:222)
	at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
	at $Proxy310.createUser(Unknown Source)
	at com.actionbazaar.controller.BidderAccountController.create(BidderAccountController.java:396)
	at com.actionbazaar.controller.org$jboss$weld$bean-actionbazaar-ManagedBean-class_com$actionbazaar$controller$BidderAccountController_$$_WeldClientProxy.create(org$jboss$weld$bean-actionbazaar-ManagedBean-class_com$actionbazaar$controller$BidderAccountController_$$_WeldClientProxy.java)
	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 com.sun.el.parser.AstValue.invoke(AstValue.java:234)
	at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297)
	at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43)
	at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:56)
	at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
	at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
	at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
	at javax.faces.component.UICommand.broadcast(UICommand.java:315)
	at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
	at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
	at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
	at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
	at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:118)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:217)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
	at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
	at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
	at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174)
	at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
	at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
	at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
	at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
	at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
	at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
	at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
	at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
	at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
	at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
	at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
	at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
	at java.lang.Thread.run(Thread.java:680)
Caused by: org.postgresql.util.PSQLException: ERROR: prepared transaction with identifier "4871251_CwAAAMWkX2BCZWFnbGUsc2VydmVyLFAzNzAw_QmVhZ2xlLHNlcnZlcixQMzcwMCwA" does not exist
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:374)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:302)
	at org.postgresql.xa.PGXAConnection.rollback(PGXAConnection.java:396)
	... 68 more
|#]

Digging into it, I discovered that I had to set set max_prepared_transactions and also lower the shared_buffers. The value set the value for max_prepared_transaction to 20 which is the same as max_connections. These changes were made to postgresql.conf. Changing this file of course required a restart of PostgreSQL – no restart of Glassfish was required. Obviously my database isn’t optimized and this was just a hack to get things operational. In a real production environment a little more tuning would be required.

Published by rcuprak

Ryan Cuprak is an e-formulation analyst at Enginuity PLM and president of the Connecticut Java Users Group that he has run since 2003. At Enginuity PLM he is focused on developing data integrations to convert clients’ data and also user interface development. Prior to joining Enginuity he worked for a startup distributed-computing company, TurboWorx, and Eastman Kodak’s Molecular Imaging Systems group, now part of Carestream Health. At TurboWorx he was a Java developer and also a technical sales engineer supporting both presales and professional services. Cuprak has earned a BS in computer science and biology from Loyola University Chicago. He is a Sun Certified NetBeans IDE Specialist. He can be contacted at rcuprak@acm.org.

8 thoughts on “Glassfish, XA Transactions, and PostgreSQL

  1. I just want to thank you, I’d never find how to resolve that.

    Thank you very much, you save a lot of my time.

Comments are closed.