You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.
| Online: | 6 Members of 12451 |
| Forum: Seam Users |
20. Apr 2009, 13:39 America/New_York | Link |
Hello !
I have two datasources MySql 5.1 and Postgres 8.0 and I'm trying to implement a standard bank example with XA Transaction and 2 phase commit. Unfortunately, I have a problem that I can't resolve. Please help me !
This is my configurations:
persistance.xml
<persistence-unit name="mybank">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/mysqlXADatasource</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="jboss.entity.manager.factory.jndi.name" value="java:/mybankEntityManagerFactory"/>
</properties>
</persistence-unit>
<persistence-unit name="pgbank">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/pgbankDatasource</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="jboss.entity.manager.factory.jndi.name" value="java:/pgbankEntityManagerFactory"/>
</properties>
</persistence-unit>
seamxa-ds.xml
<datasources>
<xa-datasource>
<jndi-name>mysqlXADatasource</jndi-name>
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
<xa-datasource-property name="ServerName">localhost</xa-datasource-property>
<xa-datasource-property name="PortNumber">3306</xa-datasource-property>
<xa-datasource-property name="DatabaseName">mybank</xa-datasource-property>
<xa-datasource-property name="User">root</xa-datasource-property>
<xa-datasource-property name="Password">mysql</xa-datasource-property>
<track-connection-by-tx></track-connection-by-tx>
</xa-datasource>
<xa-datasource>
<jndi-name>pgbankDatasource</jndi-name>
<xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
<xa-datasource-property name="ServerName">localhost</xa-datasource-property>
<xa-datasource-property name="PortNumber">5432</xa-datasource-property>
<xa-datasource-property name="DatabaseName">pgbank</xa-datasource-property>
<xa-datasource-property name="User">postgres</xa-datasource-property>
<xa-datasource-property name="Password">postgres</xa-datasource-property>
<track-connection-by-tx></track-connection-by-tx>
</xa-datasource>
</datasources>
components.xml
<core:init debug="@debug@" jndi-pattern="@jndiPattern@"/>
<core:manager concurrent-request-timeout="500"
conversation-timeout="120000"
conversation-id-parameter="cid"
parent-conversation-id-parameter="pid"/>
<persistence:managed-persistence-context name="entityManager"
auto-create="true"
persistence-unit-jndi-name="java:/seamxaEntityManagerFactory"/>
<drools:rule-base name="securityRules">
<drools:rule-files>
<value>/security.drl</value>
</drools:rule-files>
</drools:rule-base>
<security:rule-based-permission-resolver security-rules="#{securityRules}"/>
<security:identity authenticate-method="#{authenticator.authenticate}" remember-me="true"/>
<event type="org.jboss.seam.security.notLoggedIn">
<action execute="#{redirect.captureCurrentView}"/>
</event>
<event type="org.jboss.seam.security.loginSuccessful">
<action execute="#{redirect.returnToCapturedView}"/>
</event>
<mail:mail-session host="localhost" port="2525" username="test" password="test" />
Test.java
@Stateless
@Name("testy")
@Transactional
public class Test implements TestI {
@PersistenceContext(unitName="pgbank")
private EntityManager entityManager;
@PersistenceContext(unitName="mybank")
private EntityManager em;
@Transactional(TransactionPropagationType.REQUIRED)
public void start() {
int error = 0;
em.createQuery("update Account a set balance = 33000 where id = 1").executeUpdate();
if (error != 0)
throw new EJBException("ERROR !!");
entityManager.createQuery("update Account a set balance = 33000 where id = 1").executeUpdate();
}
}
JBoss 4.2.3 Log
13:21:46,625 INFO [STDOUT] Hibernate:
update
account
set
balance=33000
where
id=1
13:21:46,656 INFO [STDOUT] Hibernate:
update
account
set
balance=33000
where
id=1
13:21:46,781 WARN [loggerI18N] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] XAResourceRecord.prepare - prepare failed with exception XAException.XAER_RMERR
13:21:46,781 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_50] - Prepare phase of action a01040f:1162:49ec5a80:37 received heuristic decision: TwoPhaseOutcome.HEURISTIC_HAZARD
13:21:46,781 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_36] - BasicAction.End() - prepare phase of action-id a01040f:1162:49ec5a80:37 failed.
13:21:46,781 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_37] - Received heuristic: TwoPhaseOutcome.HEURISTIC_HAZARD .
13:21:46,781 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_38] - Action Aborting
13:21:46,812 WARN [SeamPhaseListener] uncaught exception, passing to exception handler
java.lang.IllegalStateException: Could not commit transaction
at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:626)
at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:605)
at org.jboss.seam.jsf.SeamPhaseListener.handleTransactionsAfterPhase(SeamPhaseListener.java:343)
at org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:243)
at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:194)
at com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:175)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:114)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:38)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:150)
at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:379)
at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:506)
at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:44)
at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
at java.lang.Thread.run(Unknown Source)
Caused by: javax.transaction.HeuristicMixedException
at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1397)
at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)
at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.commit(ServerVMClientUserTransaction.java:140)
at org.jboss.seam.transaction.UTTransaction.commit(UTTransaction.java:52)
at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:614)
... 49 more
What's wrong with my code ?
By the looks of it you want to control your own transactions so you need to put this in your components.xml:
<core:init transaction-management-enabled="false"/> <transaction:no-transaction />
Cory.
Postgres 8.0 does not support two phase commit, you need 8.1 or better. I would say that is the root cause of your problem.
Oh yes you were right Stuart now everything is working fine ... Thank you !
But I have another question ...
Like I understand in my implementation the transaction menager was an application server (JBoss) and he perform all the work associated with two phase commit.
And how can I define my own transaction menager (is it possible ?) to control the transaction status step by step ? I can't find any source code example with seam and ejb3, I find only theories how does 2PC work :(
How to do implementation ... ? Each tip will be a valuable.
Paweł.
If you have two or more underlying transactional resources that do not support TPC then there is nothing you can do. If you only have 1 transactional resource it can still participate in two phase commit by commiting the 1st phase in all resources that support TPC, commiting the resource that does not support TPC and then commiting the second phase for the TPC resources. Anunta should support this out of the box, I am sure I have seen a wiki page on jboss.org with how to do this.
I use PostgreSQL 8.4 and I had the same problem. It looks like max_prepared_transactions parameter is not set in postgresql.conf by default, so there are no XA transactions available. When I set this value to 5, it just works correctly.
According to this page, max_prepared_transactions should be twice as much as max-pool-size of the xa-datasource.
Thanks for this one. As a side note, the default max-pool-size of JBoss is 20 (according to configdatasources), so a reasonable size would be 40. Don't try too high, since PostgreSQL allocates shared memory segments for the connections as per the comments in postgresql.conf, and it runs out of this mem quite quickly.
The error you get from arjuna if you don't increase this value above 0 is the same if you try to use multiple 1-phase resources:
23:54:02,180 WARN [loggerI18N] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] [com.arjuna.ats.internal.jta.resources.arjunacore.preparefailed] XAResourceRecord.prepare - prepare failed with exception XAException.XAER_RMERR 23:54:02,182 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_50] - Prepare phase of action 7f000101:db31:4c29198f:152 received heuristic decision: TwoPhaseOutcome.HEURISTIC_HAZARD 23:54:02,182 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_36] - BasicAction.End() - prepare phase of action-id 7f000101:db31:4c29198f:152 failed. 23:54:02,182 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_37] - Received heuristic: TwoPhaseOutcome.HEURISTIC_HAZARD . 23:54:02,182 WARN [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.BasicAction_38] - Action Aborting