[jboss-user] [JBoss Seam] - Re: SMPC and could not enlist in transaction exception

asookazian do-not-reply at jboss.com
Mon Feb 4 16:59:50 EST 2008


After doing some root-cause analysis I was able to reproduce the behavior with a simpler set of code as below.  The key thing here is that by default, the transaction type in EJB3/JPA is REQUIRES.  If you set getNoteLogList() and getPeers() methods' transaction types to REQUIRES_NEW, the exception is *not* reproduceable.

This indicates that when use case is executed (user navigates to JSF), there is a distributed transaction that is happening b/c BoIcomsEntityManager SMPC is based on db 1 and CoxIMEntityManager SMPC is based on db 2 and the first transaction is propagating to the 2nd one.

.xhtml:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  |                       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  | <ui:composition xmlns="http://www.w3.org/1999/xhtml"
  |                 xmlns:s="http://jboss.com/products/seam/taglib"
  |                 xmlns:ui="http://java.sun.com/jsf/facelets"
  |                 xmlns:f="http://java.sun.com/jsf/core"
  |                 xmlns:h="http://java.sun.com/jsf/html"
  |                 xmlns:rich="http://richfaces.ajax4jsf.org/rich"
  |                 xmlns:a4j="https://ajax4jsf.dev.java.net/ajax" 
  | 				xmlns:c="http://java.sun.com/jstl/core"          
  |                 template="layout/template.xhtml">
  |                 
  | 
  | 
  | <ui:define name="mainContent">
  | 
  | 		<h:form>
  |    						
  | 			<!--  <h:dataTable value="#{testPeerAction.getPeers()}"/>   -->
  | 			
  | 			<h:dataTable value="#{testUserBean.getNoteLogList()}"/>
  | 			
  | 			<h:dataTable value="#{testPeerAction.getPeers()}"/>
  | 				
  |    		</h:form>    
  | 
  | </ui:define> 
  | </ui:composition>
  | 	

It doesn't matter what order the methods are listed in the above .xhtml (you will get the exception for the latter method).

TestUserBean SFSB:

import java.util.List;
  | 
  | import javax.ejb.Remove;
  | import javax.ejb.Stateful;
  | import javax.persistence.EntityManager;
  | 
  | import org.jboss.seam.annotations.Destroy;
  | import org.jboss.seam.annotations.In;
  | import org.jboss.seam.annotations.Logger;
  | import org.jboss.seam.annotations.Name;
  | import org.jboss.seam.annotations.Out;
  | import org.jboss.seam.log.Log;
  | 
  | 
  | @Stateful
  | @Name("testUserBean")
  | public class TestUserBean implements TestUserLocal {
  | 	
  | 	@Logger
  | 	private Log log;
  | 	
  | 	@In(value="BoIcomsEntityManager") 
  | 	EntityManager emICOMS;
  | 	
  | 	@Out(required=false)
  | 	private List testNoteLogList;
  | 	
  | 	//@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  | 	public List getNoteLogList() {
  | 		log.info("in getNoteLogList()");
  | 			
  | 		testNoteLogList = emICOMS.createQuery("SELECT san "+
  | 									"FROM TblSecurityAuditNote san")
  | 									.getResultList();
  | 		
  | 		log.info("in getNoteLogList(): testNoteLogList.size() = " + testNoteLogList.size());
  | 		
  | 		return testNoteLogList;
  | 		
  | 	}
  | 	
  | 	@Remove @Destroy
  | 	public void destroy() {}
  | 
  | }

TestPeerAction SFSB:

import java.util.List;
  | import java.util.ListIterator;
  | import java.util.Map;
  | import java.util.TreeMap;
  | 
  | import javax.ejb.Remove;
  | import javax.ejb.Stateful;
  | import javax.persistence.EntityManager;
  | 
  | import org.jboss.seam.ScopeType;
  | import org.jboss.seam.annotations.Destroy;
  | import org.jboss.seam.annotations.In;
  | import org.jboss.seam.annotations.Logger;
  | import org.jboss.seam.annotations.Name;
  | import org.jboss.seam.annotations.Scope;
  | import org.jboss.seam.log.Log;
  | 
  | import com.cox.beans.entity.User;
  | import com.cox.util.SecurityAuditConstants;
  | import com.cox.util.SecurityAuditProperties;
  | 
  | @Stateful
  | @Name("testPeerAction")
  | //using Session scope so that the processValueChange instance variables will not be nulled out...
  | @Scope(ScopeType.SESSION)
  | public class TestPeerAction implements TestPeerLocal {
  | 	
  | 	@In(value="CoxIMEntityManager") 
  | 	EntityManager emCoxIM;
  | 	
  | 	@Logger
  | 	private Log log;	
  | 	private Long employeeId;		
  | 	private List peerList;
  | 	
  | 	@Remove @Destroy
  | 	public void destroy() {
  | 		
  | 	}
  | 	
  | 	//@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
  | 	public Map<String, Long> getPeers() {
  | 		
  | 		Boolean hardCodeEmployeeId = Boolean.parseBoolean(SecurityAuditProperties.getPropertyObject().getProperty(SecurityAuditConstants.HARD_CODE_EMPLOYEE_ID));
  | 		
  | 		if (hardCodeEmployeeId && employeeId == null) {
  | 			employeeId = Long.parseLong(SecurityAuditProperties.getPropertyObject().getProperty(SecurityAuditConstants.EMPLOYEE_ID));
  | 		}
  | 		
  | 		Map<String,Long> map = new TreeMap<String,Long>();
  | 		
  | 		peerList = emCoxIM.createQuery("SELECT user1 "+				
  | 				"FROM User user1 "+					
  | 				"WHERE user1.hierarchyPath in "+
  | 				"(SELECT user2.hierarchyPath "+
  | 				"FROM User user2 "+
  | 				"WHERE user2.employeeId = :employeeId "+
  | 				"AND user2.isActive = 1) "+
  | 				"AND user1.isActive = 1 ")				
  | 				.setParameter("employeeId", employeeId)
  | 				.getResultList();
  | 		
  | 		log.info("in getPeers(): peerList.size() = " + peerList.size());
  | 		
  | 		ListIterator<User> it = peerList.listIterator();
  | 		while(it.hasNext()) {
  | 			User user = (User)it.next();			
  | 			map.put(user.getFirstName()+ " " + user.getLastName(), user.getEmployeeId());
  | 		}
  | 				
  | 		return map;
  | 	}
  | 	
  | 	
  | }


View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4126364#4126364

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4126364



More information about the jboss-user mailing list