[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