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

asookazian do-not-reply at jboss.com
Fri Feb 1 18:12:08 EST 2008


Is it correct to assume that "create=true" is unnecessary for the @In annotation below b/c it is already in the components.xml (auto-create="true")??

SecurityAuditAction:

package com.cox.beans.session;
  | 
  | import java.sql.Timestamp;
  | import java.util.ArrayList;
  | import java.util.Date;
  | import java.util.List;
  | 
  | import javax.annotation.PostConstruct;
  | import javax.annotation.PreDestroy;
  | import javax.ejb.PostActivate;
  | import javax.ejb.PrePassivate;
  | import javax.ejb.Remove;
  | import javax.ejb.Stateful;
  | import javax.ejb.TransactionAttribute;
  | import javax.ejb.TransactionAttributeType;
  | import javax.faces.model.SelectItem;
  | import javax.persistence.EntityManager;
  | 
  | import org.jboss.seam.annotations.Begin;
  | import org.jboss.seam.annotations.Destroy;
  | import org.jboss.seam.annotations.End;
  | import org.jboss.seam.annotations.Factory;
  | import org.jboss.seam.annotations.FlushModeType;
  | 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.annotations.datamodel.DataModel;
  | import org.jboss.seam.annotations.datamodel.DataModelSelectionIndex;
  | import org.jboss.seam.log.Log;
  | import org.jboss.seam.security.Identity;
  | import org.jboss.seam.web.Session;
  | 
  | import com.cox.beans.entity.TblSecurityAuditNote;
  | import com.cox.beans.entity.TblSecurityAuditWorking;
  | import com.cox.beans.entity.User;
  | import com.cox.util.SecurityAuditConstants;
  | import com.cox.util.SecurityAuditProperties;
  | 
  | 
  | 
  | 
  | @Stateful
  | @Name("securityAuditAction")
  | public class SecurityAuditAction implements SecurityAuditLocal {
  | 	
  | 	@Logger 
  | 	private Log log;
  | 	
  | 	@In
  | 	private Identity identity;
  | 			
  | 	// using EXTENDED for PersistenceContextType was causing premature update transaction commit to DB when clicking 'no' on radio button...
  | 	// 12/17/07 - org.hibernate.PersistentObjectException: detached entity passed to persist: com.cox.beans.entity.TblSecurityAuditNote
  | 	/*
  | 	 * http://www.jboss.org/index.html?module=bb&op=viewtopic&t=107263
  | 
  | 	“what are the reasons for the PersistentObjectException to occur?”
  | 
  | 	“If the entity is detached ;) You need to make sure your persistence context spans the life all 
  | 	the operations you perform with that instance of the entity.” <-- P. Muir
  | 	
  | 	attempting to fix this exception by using Extended PersistenceContextType again...  now entites will not detach from persistence context
  | 	
  | 	12/18/07 - now attempting SMPC as per section 8.3.3 of Seam ref pdf: we would prefer that all changes are held in memory and only written 
  | 				to the database when the conversation ends successfully. This allows for truly atomic conversations
  | 	 */
  | 	
  | 	//@PersistenceContext(unitName="boIcomsSecurityAudit", type=PersistenceContextType.EXTENDED)
  | 	//private EntityManager emICOMS;
  | 	
  | 	@In(value="BoIcomsEntityManager") 
  | 	EntityManager emICOMS;
  | 	
  | 	//@In(required=false) @Out
  | 	@In(required=false)
  | 	private User user;
  | 		
  | 	@In(required=false)	
  | 	private List<TblSecurityAuditNote[]> noteList = new ArrayList<TblSecurityAuditNote[]>();
  | 	
  | 	@In(create=true)
  | 	private NoteLocal noteAction;
  | 	
  | 	@In(create=true)
  | 	private PeerLocal peerAction;
  | 	
  | 	private List<SelectItem> myRadioButtonList;
  | 
  | 	private List noteLoadList;
  | 		
  | 	@DataModel(value="myAuditList")
  | 	private List myAuditList;
  | 	
  | 	private String networkId = "";
  | 			
  | 	@DataModelSelectionIndex(value="myAuditList")	
  | 	private int currentRowNum;	
  | 		
  | 	//adding empty constructor callback lifecycle methods for debugging purposes (interceptor will output when they get called)
  | 	
  | 	public SecurityAuditAction() {}
  | 	
  | 	@PostConstruct
  | 	public void postConstruct() {
  | 		log.info("in postConstruct");
  | 	}
  | 	
  | 	@PostActivate
  | 	public void postActivate() {
  | 		log.info("in postActivate");
  | 	}
  | 	
  | 	@PrePassivate
  | 	public void prePassivate() {
  | 		log.info("in prePassivate");
  | 		
  | 	}
  | 	
  | 	@PreDestroy
  | 	public void preDestroy() {
  | 		log.info("in preDestroy");
  | 		
  | 	}
  | 	
  | 	private Object[] getMyAuditListSelection() {
  | 		return (Object[])myAuditList.get(currentRowNum);
  | 	}
  | 	
  | 	@End
  | 	public void invalidateSession() {
  | 		
  | 		//user selected a peer from peer selectOneMenu, so invalidate session and continue...
  | 				
  | 		Session.instance().invalidate();
  | 		
  | 		//findAuditList2();
  | 	}
  | 				
  | 	// 12-03/07 - got following exception when I clicked cancel in modalPanel:
  | 	// Caused by java.lang.IllegalStateException with message: "begin method invoked from a long-running conversation, try using @Begin(join=true) on method: findAuditList" 
  | 	// adding join=true...
  | 		
  | 	@Begin(join=true, flushMode=FlushModeType.MANUAL)   // <-- use this with SMPC	
  |     @Factory("myAuditList")
  |     public void findAuditList()
  |     {			
  | 		Boolean hardCodeEmployeeId = Boolean.parseBoolean(SecurityAuditProperties.getPropertyObject().getProperty(SecurityAuditConstants.HARD_CODE_EMPLOYEE_ID));
  | 		Integer employeeId;
  | 		
  | 		if (hardCodeEmployeeId) {  //if true in props file then we're testing only...
  | 			
  | 			employeeId = peerAction.getEmployeeId().intValue();
  | 			
  | 			if (employeeId == null) {	
  | 				
  | 				employeeId = Integer.parseInt(SecurityAuditProperties.getPropertyObject().getProperty(SecurityAuditConstants.EMPLOYEE_ID)); //using btkach id for now;
  | 			}
  | 		}
  | 		else {
  | 						
  | 			employeeId = peerAction.getEmployeeId().intValue();
  | 	    	
  | 		}	
  | 			myAuditList = emICOMS.createQuery("SELECT gem, tsaw "+
  | 										"FROM TblSecurityAuditWorking tsaw, "+					
  | 										"GlobalEmployeeMaster gem "+				
  | 										"WHERE tsaw.id.siteId 		= gem.id.siteId "+
  | 										"AND tsaw.id.employeeNumber = gem.id.employeeNumber "+				
  | 										"AND tsaw.reportToId 		= :employeeId " +
  | 										"ORDER BY tsaw.id.employeeNumber ASC")
  | 										.setParameter("employeeId", employeeId)
  | 										.getResultList();    	
  | 		    
  | 			//reset/clear instance variables in Note SFSB...
  | 			noteAction.reset();
  | 			
  | 			//instantiate null valued noteList
  | 	    	noteAction.initialize(myAuditList);
  | 	    	    	
  | 	    	log.info("in findAuditList(): myAuditList.size() = " + myAuditList.size());
  | 	    	
  | 	    	noteLoadList = emICOMS.createQuery("SELECT saw.id.siteId, saw.id.employeeNumber, "+
  | 								    	"("+
  | 								    	"SELECT count(san) as AcctApprovedNoteCount "+
  | 								    	"FROM TblSecurityAuditNote san "+
  | 								    	"WHERE san.siteId = saw.id.siteId "+
  | 								    	"AND san.employeeNumber = saw.id.employeeNumber "+
  | 								    	"AND san.noteType = 'accountApproved' "+
  | 								    	") as AcctApprovedCount, "+
  | 								    	"("+
  | 								    	"SELECT count(san) as secLevelApprovedNoteCount "+
  | 								    	"FROM TblSecurityAuditNote san "+
  | 								    	"WHERE san.siteId = saw.id.siteId "+
  | 								    	"AND san.employeeNumber = saw.id.employeeNumber "+
  | 								    	"AND san.noteType = 'secLevelApproved' "+
  | 								    	") as secLevelApprovedCount, "+
  | 								    	"("+
  | 								    	"SELECT count(san) as adjLimitApprovedNoteCount "+
  | 								    	"FROM TblSecurityAuditNote san "+
  | 								    	"WHERE san.siteId = saw.id.siteId "+
  | 								    	"AND san.employeeNumber = saw.id.employeeNumber "+
  | 								    	"AND san.noteType = 'adjLimitApproved' "+
  | 								    	") as adjLimitApprovedCount "+
  | 								    	"FROM TblSecurityAuditWorking saw "+
  | 								    	"WHERE saw.reportToId = :employeeId")
  | 								    	.setParameter("employeeId", employeeId)
  | 								    	.getResultList();
  | 	    	
  | 	    	
  | 	    	
  | 	    	log.info("in findAuditList(): noteLoadList.size() = " + noteLoadList.size());
  | 	    	
  | 	    	
  |     	
  |     }
  | 	
  | 	public Boolean getLoadedNote(Integer rowIndex, String colName) {
  | 		if (rowIndex > -1) {
  | 			Object[] myArray = (Object[])noteLoadList.get(rowIndex);  
  | 			Long count = (Long)myArray[convertColName(colName).intValue()];
  | 			if (count > 0)
  | 				return true;
  | 			else
  | 				return false;
  | 		}
  | 		else
  | 			return false;
  | 	}
  | 	
  | 	private Integer convertColName(String colName) {
  | 		
  | 		if (SecurityAuditConstants.COL_ONE_NAME.equals(colName)) {
  | 			return SecurityAuditConstants.SECURITY_ACTION_COL_ONE_VALUE;
  | 		}
  | 		else if (SecurityAuditConstants.COL_TWO_NAME.equals(colName)) {
  | 			return SecurityAuditConstants.SECURITY_ACTION_COL_TWO_VALUE;
  | 		}
  | 		else if (SecurityAuditConstants.COL_THREE_NAME.equals(colName)) {
  | 			return SecurityAuditConstants.SECURITY_ACTION_COL_THREE_VALUE;
  | 		}
  | 		else
  | 			return 0;
  | 		
  | 	}
  |     
  |     public List<SelectItem> getSecurityAuditRadioButtons() {
  | 		myRadioButtonList = new ArrayList<SelectItem>();
  | 		myRadioButtonList.add(new SelectItem("true", "Yes", "Yes it is"));
  | 		myRadioButtonList.add(new SelectItem("false", "No", "No it isn't"));
  | 		return myRadioButtonList;
  | 	}
  |         
  |     public String getHeader() {    	
  |     	return "Please enter your note for the associate";		
  | 	}
  |     
  |     @End
  |     @TransactionAttribute(TransactionAttributeType.REQUIRED)  //REQUIRED is default, but added for clarity
  |     public void submit() {
  |     	
  |     	Object[] myAuditListSelection = getMyAuditListSelection();
  |     	
  |     	TblSecurityAuditWorking tsaw = (TblSecurityAuditWorking)myAuditListSelection[1];
  |     	 	
  |     	//determine what status to assign to each row/employee based on answers to radio buttons...
  |     	
  |     	//RULES: if yes/yes/yes --> green
  |     	//       if any no(s)  --> yellow
  |     	//       if none selected --> red
  |     	
  |     	Boolean icomsAccountApproved 	= tsaw.getIcomsAccountApproved()==null?false:tsaw.getIcomsAccountApproved();    	
  |     	Boolean adjustmentLimitApproved = tsaw.getAdjustmentLimitApproved()==null?false:tsaw.getAdjustmentLimitApproved();    	
  |     	Boolean securityLevelApproved 	= tsaw.getSecurityLevelApproved()==null?false:tsaw.getSecurityLevelApproved();
  |     	
  |     	if ( icomsAccountApproved && adjustmentLimitApproved && securityLevelApproved ) {
  |     		//green    		
  |     		tsaw.setAuditProgress(SecurityAuditConstants.AUDIT_COMPLETE);
  |     	}
  |     	else if ( !icomsAccountApproved || !adjustmentLimitApproved || !securityLevelApproved ) {
  |     		//yellow    		 
  |     		tsaw.setAuditProgress(SecurityAuditConstants.AUDIT_WAITING_ICOMS);
  |     	}    	
  |     	else {
  |     		//yellow    		
  |     		tsaw.setAuditProgress(SecurityAuditConstants.AUDIT_WAITING_ICOMS);
  |     	}
  |     	
  |     	Date myDate = new Date();
  | 		Long myTime = myDate.getTime();
  | 		Timestamp myTimeStamp = new Timestamp(myTime);
  | 		tsaw.setTimeStamp(myTimeStamp);
  |     	
  |     	emICOMS.merge(tsaw);
  |     		
  |     	//check to see if there are any notes for each radio button for this employee/row
  |     	//then update/insert accordingly
  |     	
  |     	//TO DO: move the hard-coding 3 for # of updateable columns in dataTable to resource bundle
  |     	
  |     	// TO DO: noteAction.submit() was moved to action listener attribute in modalPanels...
  |     	//call submit to ensure new note is added to array
  |     	//noteAction.submit();
  |     	
  |     	for (int colNum = 0; colNum < SecurityAuditConstants.MAX_COLUMNS; colNum++) {
  |     		
  |     		TblSecurityAuditNote note = getTblSecurityAuditNote(currentRowNum, colNum);
  |     		
  |     		if (note != null) {
  |     			
  |     			log.info("myNotes["+currentRowNum+"]["+colNum+"]: noteId = " + note.getNoteId() + " noteText = " + note.getNoteText());    	
  |     			    			
  |     			emICOMS.persist(note);
  |     			
  |     			//fix transaction failed when user inserts multiple notes for two columns in the same row by setting current note in array to null...			
  |     			//this was happening when you add a note to col C and save, then add a note to col B and save (the loop
  |     			//was calling persist(note) on an already persisted entity and there would be a primary key violation
  |     			//so Hibernate throws an exception:
  |     			//org.hibernate.PersistentObjectException: detached entity passed to persist: com.cox.beans.entity.TblSecurityAuditNote
  |     			
  |     			/* AS - 01/16/08 - commenting to test to see if this code block is the root cause of the
  |     			 * not reRendering of the graphic icon when you enter the first note and submit in modalPanel 
  |     			 * results: it was the root cause! leaving commented as the above transaction failed problem is now not occurring
  |     			TblSecurityAuditNote[] myNoteArray = noteList.get(currentRowNum);
  | 				myNoteArray[colNum] = null;								
  | 				noteList.set(currentRowNum, myNoteArray);
  | 				*/
  |     		}
  |     	}
  |     	
  |     	emICOMS.flush();
  |  
  |     }
  |         
  |     private TblSecurityAuditNote getTblSecurityAuditNote(Integer rowIndex, Integer colNum) {		
  | 		rowIndex = rowIndex==null?0:rowIndex;
  | 		colNum 	 = colNum==null?0:colNum;
  | 				
  | 		if (noteList != null) {
  | 			try {
  | 				TblSecurityAuditNote[] myNoteArray = noteList.get(rowIndex);
  | 				return myNoteArray[colNum];
  | 			}
  | 			catch (IndexOutOfBoundsException e) {
  | 				if (rowIndex != null && rowIndex < 0) {
  | 					e.printStackTrace();
  | 					throw e;
  | 				}
  | 				return null;
  | 			}
  | 		}
  | 		else {
  | 			return null;
  | 		}
  | 	}
  |     
  | 	public String processGraphicImage(Integer auditProgress) {		
  | 		switch (auditProgress) {
  | 	        case 0:  return SecurityAuditConstants.RED_GRAPHIC;
  | 	        case 1:  return SecurityAuditConstants.YELLOW_GRAPHIC; 
  | 	        case 2:  return SecurityAuditConstants.GREEN_GRAPHIC;         
  | 	        default: return SecurityAuditConstants.RED_GRAPHIC;
  | 		}
  |     }
  | 	
  | 	public String processNoteImage() {		
  | 		return SecurityAuditConstants.NOTE_GRAPHIC;
  | 	}
  | 
  | 	private String getNetworkId() {
  |     	if (networkId.equals("")) 
  |     		return identity.getUsername();    	
  |     	else 
  |     		return networkId;
  |     }
  | 	
  |     private void setNetworkId(String networkId) {
  |     	//log.info("in setNetworkId(): networkId = " + networkId);
  |     	this.networkId = networkId;
  |     }
  |     
  |     private Integer getEmployeeId() {
  |     	String networkId = getNetworkId()==null?"":getNetworkId();
  | 		
  | 		List myList = emICOMS.createQuery("from User u where u.networkId = :networkId").setParameter("networkId", networkId).getResultList(); 
  | 		User newUser = (User)myList.get(0);
  | 		
  | 		Integer employeeId = newUser.getEmployeeId().intValue();
  | 		
  | 		return employeeId; 
  |     }
  |    	
  |         
  | 	@Remove @Destroy
  | 	public void destroy() {
  | 		
  | 	}
  | 
  | 		
  | 	 
  | 
  | }

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

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




More information about the jboss-user mailing list