10 Replies Latest reply on Dec 21, 2007 12:29 PM by Arbi Sookazian

    Update transactions occurring prematurely in Seam app

    Arbi Sookazian Master

      This may be a EntityManager flush issue but not sure...

      I have the following xhtml for a Seam2.0.0.GA web app backed by 2 SFSB's (one conversation scoped and the other session scoped). The problem is when user clicks 'yes' for any radio button in any row of the form/dataTable, an update transaction is persisted to the database for that row/column. The update should only happen when user clicks submit in one of the rich:modalPanel forms.

      I've ran this test case thru the debugger several times and the submit method is not being called. I'm thinking the EntityManager/PersistenceContext is being automatically flushed somehow but not sure if or when this is happening. I did remove the a4j:support tag for one of the columns and moved the js function call to onclick event handler. The table did not get updated like before. So somehow the a4j:support is causing this to happen I think...

      Any hints? thx.

      <h:form id="mainForm">
      
       <h:outputText value="No Direct Reports" rendered="#{myAuditList != null and myAuditList.rowCount==0}"/>
       <h:dataTable id="dataTable1" value="#{myAuditList}" var="myRow" rendered="#{myAuditList != null and myAuditList.rowCount > 0}"
       styleClass="dataTable" rowClasses="oddRow, evenRow" frame="hsides">
       <h:column>
       <f:facet name="header">Status</f:facet>
      
       <h:graphicImage id="statusImage" value="#{securityAuditAction.processGraphicImage(myRow[1].auditProgress)}"/>
       </h:column>
       <h:column>
       <f:facet name="header">Employee Name</f:facet>
      
       <!-- siteId and employeeNumber hidden fields are used for all radio buttons -->
       <h:outputText id="employeeName" value="#{myRow[0].id.employeeName}"/>
       <h:inputHidden id="employeeNameHidden" value="#{myRow[0].id.employeeName}"/>
       <h:inputHidden id="siteId" value="#{myRow[0].id.siteId}"/>
       <h:inputHidden id="employeeNumber" value="#{myRow[0].id.employeeNumber}"/>
       </h:column>
      
       <h:column>
       <f:facet name="header">SiteId</f:facet>
      
       <h:outputText value="#{myRow[0].id.siteId}"/>
       </h:column>
      
       <h:column>
       <f:facet name="header">EmployeeNumber</f:facet>
      
       <h:outputText value="#{myRow[0].id.employeeNumber}"/>
       </h:column>
      
       <h:column>
       <f:facet name="header">Adjustment Limit</f:facet>
      
       <h:outputText value="#{myRow[0].id.employeeNumber}"/>
       </h:column>
      
      
       <h:column>
       <f:facet name="header">Account Approved?</f:facet>
      
       <h:panelGrid columns="2">
       <h:selectOneRadio id="accountApprovedRB" value="#{myRow[1].icomsAccountApproved}">
      
       <a4j:support event="onclick"
       oncomplete="processNote(#{myAuditList.getRowIndex()}, 'accountApproved')"
       action="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'accountApproved', myAuditList)}"
       ajaxSingle="true"
       reRender="mainForm"/>
      
       <f:selectItems value="#{securityAuditAction.securityAuditRadioButtons}" />
       </h:selectOneRadio>
      
       <h:graphicImage id="acctGraphic" value="/img/icon_edit.gif"
       rendered="#{noteAction.getRenderNoteGraphic(myAuditList.getRowIndex(), 'accountApproved') ||
       securityAuditAction.getLoadedNote(myAuditList.getRowIndex(), 'accountApproved')}">
       <a4j:support event="onclick"
       onclick="editNote(#{myAuditList.getRowIndex()}, 'accountApproved')"
       actionListener="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'accountApproved', myAuditList)}"/>
       </h:graphicImage>
       </h:panelGrid>
       </h:column>
      
      
       <h:column>
       <f:facet name="header">Security Level Approved?</f:facet>
      
       <h:panelGrid columns="2">
       <h:selectOneRadio id="securityLevelApprovedRB" value="#{myRow[1].securityLevelApproved}"
       rendered="#{noteAction.getRenderRadioButtons(myAuditList.getRowIndex())}">
       <a4j:support event="onclick"
       oncomplete="processNote(#{myAuditList.getRowIndex()}, 'secLevelApproved')"
       action="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'secLevelApproved', myAuditList)}"/>
       <f:selectItems value="#{securityAuditAction.securityAuditRadioButtons}" />
       </h:selectOneRadio>
       <h:graphicImage id="securityLevelGraphic" value="/img/icon_edit.gif"
       rendered="#{noteAction.getRenderNoteGraphic(myAuditList.getRowIndex(), 'secLevelApproved') ||
       securityAuditAction.getLoadedNote(myAuditList.getRowIndex(), 'secLevelApproved')}">
       <a4j:support event="onclick"
       onclick="editNote(#{myAuditList.getRowIndex()}, 'secLevelApproved')"
       action="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'secLevelApproved', myAuditList)}"
       reRender="out3"
       />
       </h:graphicImage>
       </h:panelGrid>
       </h:column>
      
      
       <h:column>
       <f:facet name="header">Adjustment Limit Approved?</f:facet>
      
       <!-- <h:panelGrid columns="2"> -->
       <h:panelGrid columns="3">
       <h:selectOneRadio id="adjustmentLimitApprovedRB" value="#{myRow[1].adjustmentLimitApproved}"
       rendered="#{noteAction.getRenderRadioButtons(myAuditList.getRowIndex())}">
       <a4j:support event="onclick"
       oncomplete="processNote(#{myAuditList.getRowIndex()}, 'adjLimitApproved')"
       action="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'adjLimitApproved', myAuditList)}"/>
       <f:selectItems value="#{securityAuditAction.securityAuditRadioButtons}" />
       </h:selectOneRadio>
       <h:graphicImage id="adjLimitGraphic" value="/img/icon_edit.gif"
       rendered="#{noteAction.getRenderNoteGraphic(myAuditList.getRowIndex(), 'adjLimitApproved') ||
       securityAuditAction.getLoadedNote(myAuditList.getRowIndex(), 'adjLimitApproved')}">
       <a4j:support event="onclick"
       oncomplete="editNote(#{myAuditList.getRowIndex()}, 'adjLimitApproved')"
       actionListener="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'adjLimitApproved', myAuditList)}"
       reRender="mpNoteAndEmployeeSubmit"/>
       </h:graphicImage>
       <h:commandButton id="submitEmployee" value="Submit" actionListener="#{securityAuditAction.submit}" style="visibility:hidden"/>
       </h:panelGrid>
       </h:column>
      
       </h:dataTable>
      
       </h:form>


        • 1. Re: Update transactions occurring prematurely in Seam app
          Arbi Sookazian Master

          here's the server.log output:

          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.afterPhase
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.util.Naming] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.util.Naming] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.jsf.SeamPhaseListener] committing transaction after phase: INVOKE_APPLICATION 5
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.util.Naming] JNDI InitialContext properties:{java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory, java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces}
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.transaction.UTTransaction] committing JTA transaction
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.Component] instantiating Seam component: org.jboss.seam.core.events
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.Component] initializing new instance of: org.jboss.seam.core.events
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.Component] done initializing: org.jboss.seam.core.events
          2007-12-18 11:08:28,146 DEBUG [org.jboss.seam.core.Events] Processing event:org.jboss.seam.beforeTransactionCompletion
          2007-12-18 11:08:28,146 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] processing flush-time cascades
          2007-12-18 11:08:28,146 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] dirty checking collections
          2007-12-18 11:08:28,146 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 insertions, 1 updates, 0 deletions to 10 objects
          2007-12-18 11:08:28,146 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
          2007-12-18 11:08:28,146 DEBUG [org.hibernate.pretty.Printer] listing entities:
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.GlobalEmployeeMaster{id=component[siteId,employeeNumber,userId,employeeName,addressLine1,addressLine2,addressLine3,searchName,socialSecurityNbr,homeTelephoneAreaCode,homeTelephoneExchange,homeTelephoneNumber,empBusinessAreaCode,empBusinessExchange,busPhoneNumber,empBusPhoneExtension,overridePct,commissionAmt,salesManagerCode,vehicleAssigned,unitsSoldWeek1,unitsSoldWeek2,unitsSoldWeek3,unitsSoldWeek4,lastWeekNumberPaid,ytdAnnuityCommsEarned,ytdBonusesEarned,aptUnitsSoldWeek1,aptUnitsSoldWeek2,aptUnitsSoldWeek3,aptUnitsSoldWeek4,resUnitsSoldWeek1,resUnitsSoldWeek2,resUnitsSoldWeek3,resUnitsSoldWeek4,employeeOutque,userSkillLevel,fsmEmployee,defaultSalesReason,employeeDispatchPool1,employeeDispatchPool2,employeeDispatchPool3,employeeDispatchPool4,employeeDispatchPool5,reportsTo,companyNumber,divisionNumber,franchiseNumber,employeeTypeCode]{employeeDispatchPool2= , salesManagerCode= , commissionAmt=0.0, empBusPhoneExtension= , addressLine2=TEMP EFF 12/10/07, aptUnitsSoldWeek2=0, reportsTo=74047, homeTelephoneExchange=0, employeeDispatchPool1= , homeTelephoneNumber=0, unitsSoldWeek2=0, vehicleAssigned=N, resUnitsSoldWeek3=0, busPhoneNumber=0, aptUnitsSoldWeek1=0, franchiseNumber=0, employeeNumber=74043, employeeDispatchPool3= , empBusinessAreaCode=0, employeeOutque=*DEFAULT, unitsSoldWeek4=0, addressLine3= , employeeDispatchPool4= , companyNumber=0, socialSecurityNbr=900066004, aptUnitsSoldWeek3=0, userSkillLevel=N, resUnitsSoldWeek2=0, overridePct=0.0, ytdBonusesEarned=0.0, searchName=GONZALEZ, userId=ORGJOGON, siteId=333, lastWeekNumberPaid=0, divisionNumber=0, aptUnitsSoldWeek4=0, employeeTypeCode=08, addressLine1=SOFTWARE DEVELOPER, unitsSoldWeek3=0, defaultSalesReason= , employeeDispatchPool5= , empBusinessExchange=0, resUnitsSoldWeek1=0, resUnitsSoldWeek4=0, employeeName=JONATHAN GONZALEZ, unitsSoldWeek1=0, fsmEmployee=N, homeTelephoneAreaCode=0, ytdAnnuityCommsEarned=0.0}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.TblSecurityAuditWorking{auditProgress=0, reportToId=900050881, auditYear=2007, securityLevelApproved=null, icomsAccountApproved=null, adjustmentLimitApproved=null, auditQuarter=4, id=component[siteId,employeeNumber]{siteId=333, employeeNumber=74055}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.GlobalEmployeeMaster{id=component[siteId,employeeNumber,userId,employeeName,addressLine1,addressLine2,addressLine3,searchName,socialSecurityNbr,homeTelephoneAreaCode,homeTelephoneExchange,homeTelephoneNumber,empBusinessAreaCode,empBusinessExchange,busPhoneNumber,empBusPhoneExtension,overridePct,commissionAmt,salesManagerCode,vehicleAssigned,unitsSoldWeek1,unitsSoldWeek2,unitsSoldWeek3,unitsSoldWeek4,lastWeekNumberPaid,ytdAnnuityCommsEarned,ytdBonusesEarned,aptUnitsSoldWeek1,aptUnitsSoldWeek2,aptUnitsSoldWeek3,aptUnitsSoldWeek4,resUnitsSoldWeek1,resUnitsSoldWeek2,resUnitsSoldWeek3,resUnitsSoldWeek4,employeeOutque,userSkillLevel,fsmEmployee,defaultSalesReason,employeeDispatchPool1,employeeDispatchPool2,employeeDispatchPool3,employeeDispatchPool4,employeeDispatchPool5,reportsTo,companyNumber,divisionNumber,franchiseNumber,employeeTypeCode]{employeeDispatchPool2= , salesManagerCode= , commissionAmt=0.0, empBusPhoneExtension= , addressLine2=NEW HIRE 7/23/07, aptUnitsSoldWeek2=0, reportsTo=74047, homeTelephoneExchange=0, employeeDispatchPool1= , homeTelephoneNumber=0, unitsSoldWeek2=0, vehicleAssigned=N, resUnitsSoldWeek3=0, busPhoneNumber=0, aptUnitsSoldWeek1=0, franchiseNumber=0, employeeNumber=74055, employeeDispatchPool3= , empBusinessAreaCode=0, employeeOutque=*DEFAULT, unitsSoldWeek4=0, addressLine3= , employeeDispatchPool4= , companyNumber=0, socialSecurityNbr=900069053, aptUnitsSoldWeek3=0, userSkillLevel=N, resUnitsSoldWeek2=0, overridePct=0.0, ytdBonusesEarned=0.0, searchName=SOOKAZIAN, userId=ORGARSOO, siteId=333, lastWeekNumberPaid=0, divisionNumber=0, aptUnitsSoldWeek4=0, employeeTypeCode=08, addressLine1=SOFTWARE DEVELOPER, unitsSoldWeek3=0, defaultSalesReason= , employeeDispatchPool5= , empBusinessExchange=0, resUnitsSoldWeek1=0, resUnitsSoldWeek4=0, employeeName=ARBI SOOKIAZIAN, unitsSoldWeek1=0, fsmEmployee=N, homeTelephoneAreaCode=0, ytdAnnuityCommsEarned=0.0}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.GlobalEmployeeMaster{id=component[siteId,employeeNumber,userId,employeeName,addressLine1,addressLine2,addressLine3,searchName,socialSecurityNbr,homeTelephoneAreaCode,homeTelephoneExchange,homeTelephoneNumber,empBusinessAreaCode,empBusinessExchange,busPhoneNumber,empBusPhoneExtension,overridePct,commissionAmt,salesManagerCode,vehicleAssigned,unitsSoldWeek1,unitsSoldWeek2,unitsSoldWeek3,unitsSoldWeek4,lastWeekNumberPaid,ytdAnnuityCommsEarned,ytdBonusesEarned,aptUnitsSoldWeek1,aptUnitsSoldWeek2,aptUnitsSoldWeek3,aptUnitsSoldWeek4,resUnitsSoldWeek1,resUnitsSoldWeek2,resUnitsSoldWeek3,resUnitsSoldWeek4,employeeOutque,userSkillLevel,fsmEmployee,defaultSalesReason,employeeDispatchPool1,employeeDispatchPool2,employeeDispatchPool3,employeeDispatchPool4,employeeDispatchPool5,reportsTo,companyNumber,divisionNumber,franchiseNumber,employeeTypeCode]{employeeDispatchPool2= , salesManagerCode= , commissionAmt=0.0, empBusPhoneExtension= , addressLine2= , aptUnitsSoldWeek2=0, reportsTo=74047, homeTelephoneExchange=0, employeeDispatchPool1= , homeTelephoneNumber=0, unitsSoldWeek2=0, vehicleAssigned=N, resUnitsSoldWeek3=0, busPhoneNumber=0, aptUnitsSoldWeek1=0, franchiseNumber=0, employeeNumber=74052, employeeDispatchPool3= , empBusinessAreaCode=0, employeeOutque=*DEFAULT, unitsSoldWeek4=0, addressLine3= , employeeDispatchPool4= , companyNumber=0, socialSecurityNbr=900069801, aptUnitsSoldWeek3=0, userSkillLevel=N, resUnitsSoldWeek2=0, overridePct=0.0, ytdBonusesEarned=0.0, searchName=ABANDO, userId=ORGANABA, siteId=333, lastWeekNumberPaid=0, divisionNumber=0, aptUnitsSoldWeek4=0, employeeTypeCode=08, addressLine1=REPORTING ANALYST, unitsSoldWeek3=0, defaultSalesReason= , employeeDispatchPool5= , empBusinessExchange=0, resUnitsSoldWeek1=0, resUnitsSoldWeek4=0, employeeName=ANGELIE ABANDO, unitsSoldWeek1=0, fsmEmployee=N, homeTelephoneAreaCode=0, ytdAnnuityCommsEarned=0.0}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.GlobalEmployeeMaster{id=component[siteId,employeeNumber,userId,employeeName,addressLine1,addressLine2,addressLine3,searchName,socialSecurityNbr,homeTelephoneAreaCode,homeTelephoneExchange,homeTelephoneNumber,empBusinessAreaCode,empBusinessExchange,busPhoneNumber,empBusPhoneExtension,overridePct,commissionAmt,salesManagerCode,vehicleAssigned,unitsSoldWeek1,unitsSoldWeek2,unitsSoldWeek3,unitsSoldWeek4,lastWeekNumberPaid,ytdAnnuityCommsEarned,ytdBonusesEarned,aptUnitsSoldWeek1,aptUnitsSoldWeek2,aptUnitsSoldWeek3,aptUnitsSoldWeek4,resUnitsSoldWeek1,resUnitsSoldWeek2,resUnitsSoldWeek3,resUnitsSoldWeek4,employeeOutque,userSkillLevel,fsmEmployee,defaultSalesReason,employeeDispatchPool1,employeeDispatchPool2,employeeDispatchPool3,employeeDispatchPool4,employeeDispatchPool5,reportsTo,companyNumber,divisionNumber,franchiseNumber,employeeTypeCode]{employeeDispatchPool2= , salesManagerCode= , commissionAmt=0.0, empBusPhoneExtension= , addressLine2= , aptUnitsSoldWeek2=0, reportsTo=74047, homeTelephoneExchange=0, employeeDispatchPool1= , homeTelephoneNumber=0, unitsSoldWeek2=0, vehicleAssigned=N, resUnitsSoldWeek3=0, busPhoneNumber=0, aptUnitsSoldWeek1=0, franchiseNumber=0, employeeNumber=74040, employeeDispatchPool3= , empBusinessAreaCode=0, employeeOutque=*DEFAULT, unitsSoldWeek4=0, addressLine3= , employeeDispatchPool4= , companyNumber=0, socialSecurityNbr=900001042, aptUnitsSoldWeek3=0, userSkillLevel=N, resUnitsSoldWeek2=0, overridePct=0.0, ytdBonusesEarned=0.0, searchName=BELL, userId=ORGMIWBE, siteId=333, lastWeekNumberPaid=0, divisionNumber=0, aptUnitsSoldWeek4=0, employeeTypeCode=08, addressLine1=SOFTEWARE DEVELOPER, unitsSoldWeek3=0, defaultSalesReason= , employeeDispatchPool5= , empBusinessExchange=0, resUnitsSoldWeek1=0, resUnitsSoldWeek4=0, employeeName=MIKE BELL, unitsSoldWeek1=0, fsmEmployee=N, homeTelephoneAreaCode=0, ytdAnnuityCommsEarned=0.0}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.TblSecurityAuditWorking{auditProgress=0, reportToId=900050881, auditYear=2007, securityLevelApproved=null, icomsAccountApproved=null, adjustmentLimitApproved=null, auditQuarter=4, id=component[siteId,employeeNumber]{siteId=333, employeeNumber=74052}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.TblSecurityAuditWorking{auditProgress=0, reportToId=900050881, auditYear=2007, securityLevelApproved=null, icomsAccountApproved=null, adjustmentLimitApproved=null, auditQuarter=4, id=component[siteId,employeeNumber]{siteId=333, employeeNumber=74050}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.TblSecurityAuditWorking{auditProgress=0, reportToId=900050881, auditYear=2007, securityLevelApproved=null, icomsAccountApproved=true, adjustmentLimitApproved=null, auditQuarter=4, id=component[siteId,employeeNumber]{siteId=333, employeeNumber=74040}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.TblSecurityAuditWorking{auditProgress=0, reportToId=900050881, auditYear=2007, securityLevelApproved=null, icomsAccountApproved=true, adjustmentLimitApproved=null, auditQuarter=4, id=component[siteId,employeeNumber]{siteId=333, employeeNumber=74043}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.pretty.Printer] com.cox.beans.entity.GlobalEmployeeMaster{id=component[siteId,employeeNumber,userId,employeeName,addressLine1,addressLine2,addressLine3,searchName,socialSecurityNbr,homeTelephoneAreaCode,homeTelephoneExchange,homeTelephoneNumber,empBusinessAreaCode,empBusinessExchange,busPhoneNumber,empBusPhoneExtension,overridePct,commissionAmt,salesManagerCode,vehicleAssigned,unitsSoldWeek1,unitsSoldWeek2,unitsSoldWeek3,unitsSoldWeek4,lastWeekNumberPaid,ytdAnnuityCommsEarned,ytdBonusesEarned,aptUnitsSoldWeek1,aptUnitsSoldWeek2,aptUnitsSoldWeek3,aptUnitsSoldWeek4,resUnitsSoldWeek1,resUnitsSoldWeek2,resUnitsSoldWeek3,resUnitsSoldWeek4,employeeOutque,userSkillLevel,fsmEmployee,defaultSalesReason,employeeDispatchPool1,employeeDispatchPool2,employeeDispatchPool3,employeeDispatchPool4,employeeDispatchPool5,reportsTo,companyNumber,divisionNumber,franchiseNumber,employeeTypeCode]{employeeDispatchPool2= , salesManagerCode= , commissionAmt=0.0, empBusPhoneExtension= , addressLine2=BUSINESS SUPPORT SERVICES, aptUnitsSoldWeek2=0, reportsTo=74047, homeTelephoneExchange=0, employeeDispatchPool1= , homeTelephoneNumber=0, unitsSoldWeek2=0, vehicleAssigned=N, resUnitsSoldWeek3=0, busPhoneNumber=0, aptUnitsSoldWeek1=0, franchiseNumber=0, employeeNumber=74050, employeeDispatchPool3= , empBusinessAreaCode=0, employeeOutque=*DEFAULT, unitsSoldWeek4=0, addressLine3=START DATE: 11/8/04 TEMP, employeeDispatchPool4= , companyNumber=0, socialSecurityNbr=900056641, aptUnitsSoldWeek3=0, userSkillLevel=N, resUnitsSoldWeek2=0, overridePct=0.0, ytdBonusesEarned=0.0, searchName=MCLEAN, userId=ORGERMCL, siteId=333, lastWeekNumberPaid=0, divisionNumber=0, aptUnitsSoldWeek4=0, employeeTypeCode=08, addressLine1=ULTS ADMIN, unitsSoldWeek3=0, defaultSalesReason=M1, employeeDispatchPool5= , empBusinessExchange=0, resUnitsSoldWeek1=0, resUnitsSoldWeek4=0, employeeName=ERIC MCLEAN, unitsSoldWeek1=0, fsmEmployee=N, homeTelephoneAreaCode=0, ytdAnnuityCommsEarned=0.0}}
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.jdbc.ConnectionManager] opening JDBC connection
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.SQL] update boIcomsSecurityAudit.dbo.tblSecurityAuditWorking set ICOMS_ACCOUNT_APPROVED=?, ADJUSTMENT_LIMIT_APPROVED=?, SECURITY_LEVEL_APPROVED=?, ReportToID=?, AuditQuarter=?, AuditYear=?, AuditProgress=? where SITE_ID=? and EMPLOYEE_NUMBER=?
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.jdbc.AbstractBatcher] about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.jdbc.ConnectionManager] skipping aggressive-release due to flush cycle
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.jdbc.ConnectionManager] aggressively releasing JDBC connection
          2007-12-18 11:08:28,161 DEBUG [org.hibernate.jdbc.ConnectionManager] releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]



          • 2. Re: Update transactions occurring prematurely in Seam app
            Pete Muir Master

            Are you using manual flush mode? Or bypassUpdates on the a:support?

            • 3. Re: Update transactions occurring prematurely in Seam app
              Arbi Sookazian Master

              I tried using the following and in the debugger I'm seeing that in myAuditList (3rd param in action method) that row's value for the radio button clicked 'yes' is null. If I remove the 'bypassUpdates' from a4j:support, the value shows as true. I tried this twice to make sure...

              xhtml:

              <h:selectOneRadio id="accountApprovedRB" value="#{myRow[1].icomsAccountApproved}">
              
               <a4j:support event="onclick"
               oncomplete="processNote(#{myAuditList.getRowIndex()}, 'accountApproved')"
               action="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'accountApproved', myAuditList)}"
               ajaxSingle="true"
               bypassUpdates="true"
               reRender="mainForm"/>


              SFSB:


              @PersistenceContext(unitName="boIcomsSecurityAudit", type=PersistenceContextType.EXTENDED)
               private EntityManager emICOMS;
              
              @Begin(join=true, flushMode=FlushModeType.MANUAL) // <-- use this with SMPC
               //@Begin(join=true)
               @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();
              
               if (employeeId == null) {
              
               employeeId = Integer.parseInt(SecurityAuditProperties.getPropertyObject().getProperty(SecurityAuditConstants.EMPLOYEE_ID)); //using btkach id for now;
               }
               }
               else {
               log.info("in getAuditList(): user.getUserId() = " + user.getUserId() + " user.getBillingId() = " + user.getBillingId());
              
               //employeeId = getEmployeeId();
              
               employeeId = peerAction.getEmployeeId();
              
               }
               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();
              
               //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")
               .getResultList();
              
              
              
               log.info("in findAuditList(): noteLoadList.size() = " + noteLoadList.size());
              
              
              
               }


              • 4. Re: Update transactions occurring prematurely in Seam app
                Arbi Sookazian Master

                If I replace EXTENDED PersistenceContext with SMPC, will it solve the premature update to the table?

                I will try that now with flushMode=MANUAL and w/o bypassUpdates in a4j:support.

                • 5. Re: Update transactions occurring prematurely in Seam app
                  Arbi Sookazian Master

                  SEAM 2.0.0.GA
                  JBOSS 4.2.1.GA

                  So I tried using SMPC and it still updates the record prematurely (before @End submit method is executed). There is another SFSB (session-scope) but it should not have anything to do with this particular table persistence. Here is the current code:

                  SFSB:

                  package com.cox.beans.session;
                  
                  import java.util.ArrayList;
                  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 javax.persistence.PersistenceContext;
                  import javax.persistence.PersistenceContextType;
                  
                  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 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
                   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")
                   //this is the row number of the underlying collection
                   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);
                   }
                  
                   // 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
                   //@Begin(join=true)
                   @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();
                  
                   if (employeeId == null) {
                  
                   employeeId = Integer.parseInt(SecurityAuditProperties.getPropertyObject().getProperty(SecurityAuditConstants.EMPLOYEE_ID)); //using btkach id for now;
                   }
                   }
                   else {
                   log.info("in getAuditList(): user.getUserId() = " + user.getUserId() + " user.getBillingId() = " + user.getBillingId());
                  
                   //employeeId = getEmployeeId();
                  
                   employeeId = peerAction.getEmployeeId();
                  
                   }
                   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();
                  
                   //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")
                   .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);
                   }
                  
                   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 i = 0; i < 3; i++) {
                   TblSecurityAuditNote note = getTblSecurityAuditNote(currentRowNum, i);
                   if (note != null) {
                   log.info("myNotes["+currentRowNum+"]["+i+"]: noteText = " + note.getNoteText());
                   emICOMS.persist(note);
                   }
                   }
                  
                   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;
                   }
                   }
                  
                   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() {
                  
                   }
                  
                  
                  
                  
                  }


                  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">
                  
                   <script type="text/javascript"
                   src="seam/resource/remoting/resource/remote.js">
                   </script>
                  
                   <script type="text/javascript"
                   src="seam/resource/remoting/interface.js?noteAction">
                   </script>
                  
                   <script type="text/javascript"
                   src="seam/resource/remoting/interface.js?securityAuditAction">
                   </script>
                  
                   <script type="text/javascript"
                   src="js/securityAudit.js">
                   </script>
                  
                   <h:messages styleClass="message"/>
                  
                   <rich:panel>
                   <h:form id="peerForm">
                   <h:selectOneMenu id="selectPeer" value="#{peerAction.employeeId}">
                   <a4j:support event="onchange"
                   action="#{securityAuditAction.findAuditList}"
                   ajaxSingle="true"
                   reRender="mainForm"/>
                   <f:selectItems value="#{peerAction.peers}" />
                   </h:selectOneMenu>
                   </h:form>
                   </rich:panel>
                  
                   <rich:panel>
                   <h:form id="mainForm">
                  
                   <h:outputText value="No Direct Reports" rendered="#{myAuditList != null and myAuditList.rowCount==0}"/>
                   <h:dataTable id="dataTable1" value="#{myAuditList}" var="myRow" rendered="#{myAuditList != null and myAuditList.rowCount > 0}"
                   styleClass="dataTable" rowClasses="oddRow, evenRow" frame="hsides">
                   <h:column>
                   <f:facet name="header">Status</f:facet>
                  
                   <h:graphicImage id="statusImage" value="#{securityAuditAction.processGraphicImage(myRow[1].auditProgress)}"/>
                   </h:column>
                   <h:column>
                   <f:facet name="header">Employee Name</f:facet>
                  
                   <!-- siteId and employeeNumber hidden fields are used for all radio buttons -->
                   <h:outputText id="employeeName" value="#{myRow[0].id.employeeName}"/>
                   <h:inputHidden id="employeeNameHidden" value="#{myRow[0].id.employeeName}"/>
                   <h:inputHidden id="siteId" value="#{myRow[0].id.siteId}"/>
                   <h:inputHidden id="employeeNumber" value="#{myRow[0].id.employeeNumber}"/>
                   </h:column>
                  
                   <h:column>
                   <f:facet name="header">SiteId</f:facet>
                  
                   <h:outputText value="#{myRow[0].id.siteId}"/>
                   </h:column>
                  
                   <h:column>
                   <f:facet name="header">EmployeeNumber</f:facet>
                  
                   <h:outputText value="#{myRow[0].id.employeeNumber}"/>
                   </h:column>
                  
                   <h:column>
                   <f:facet name="header">Adjustment Limit</f:facet>
                  
                   <h:outputText value="#{myRow[0].id.employeeNumber}"/>
                   </h:column>
                  
                  
                   <h:column>
                   <f:facet name="header">Account Approved?</f:facet>
                  
                   <h:panelGrid columns="2">
                   <h:selectOneRadio id="accountApprovedRB" value="#{myRow[1].icomsAccountApproved}">
                  
                   <a4j:support event="onclick"
                   oncomplete="processNote(#{myAuditList.getRowIndex()}, 'accountApproved')"
                   action="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'accountApproved', myAuditList)}"
                   ajaxSingle="true"
                   reRender="mainForm"/>
                  
                   <f:selectItems value="#{securityAuditAction.securityAuditRadioButtons}" />
                   </h:selectOneRadio>
                  
                   <h:graphicImage id="acctGraphic" value="/img/icon_edit.gif"
                   rendered="#{noteAction.getRenderNoteGraphic(myAuditList.getRowIndex(), 'accountApproved') ||
                   securityAuditAction.getLoadedNote(myAuditList.getRowIndex(), 'accountApproved')}">
                   <a4j:support event="onclick"
                   onclick="editNote(#{myAuditList.getRowIndex()}, 'accountApproved')"
                   actionListener="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'accountApproved', myAuditList)}"/>
                   </h:graphicImage>
                   </h:panelGrid>
                   </h:column>
                  
                  
                   <h:column>
                   <f:facet name="header">Security Level Approved?</f:facet>
                  
                   <h:panelGrid columns="2">
                   <h:selectOneRadio id="securityLevelApprovedRB" value="#{myRow[1].securityLevelApproved}"
                   rendered="#{noteAction.getRenderRadioButtons(myAuditList.getRowIndex())}">
                   <a4j:support event="onclick"
                   oncomplete="processNote(#{myAuditList.getRowIndex()}, 'secLevelApproved')"
                   action="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'secLevelApproved', myAuditList)}"/>
                   <f:selectItems value="#{securityAuditAction.securityAuditRadioButtons}" />
                   </h:selectOneRadio>
                   <h:graphicImage id="securityLevelGraphic" value="/img/icon_edit.gif"
                   rendered="#{noteAction.getRenderNoteGraphic(myAuditList.getRowIndex(), 'secLevelApproved') ||
                   securityAuditAction.getLoadedNote(myAuditList.getRowIndex(), 'secLevelApproved')}">
                   <a4j:support event="onclick"
                   onclick="editNote(#{myAuditList.getRowIndex()}, 'secLevelApproved')"
                   action="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'secLevelApproved', myAuditList)}"
                   reRender="out3"
                   />
                   </h:graphicImage>
                   </h:panelGrid>
                   </h:column>
                  
                  
                   <h:column>
                   <f:facet name="header">Adjustment Limit Approved?</f:facet>
                  
                   <!-- <h:panelGrid columns="2"> -->
                   <h:panelGrid columns="3">
                   <h:selectOneRadio id="adjustmentLimitApprovedRB" value="#{myRow[1].adjustmentLimitApproved}"
                   rendered="#{noteAction.getRenderRadioButtons(myAuditList.getRowIndex())}">
                   <a4j:support event="onclick"
                   oncomplete="processNote(#{myAuditList.getRowIndex()}, 'adjLimitApproved')"
                   action="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'adjLimitApproved', myAuditList)}"/>
                   <f:selectItems value="#{securityAuditAction.securityAuditRadioButtons}" />
                   </h:selectOneRadio>
                   <h:graphicImage id="adjLimitGraphic" value="/img/icon_edit.gif"
                   rendered="#{noteAction.getRenderNoteGraphic(myAuditList.getRowIndex(), 'adjLimitApproved') ||
                   securityAuditAction.getLoadedNote(myAuditList.getRowIndex(), 'adjLimitApproved')}">
                   <a4j:support event="onclick"
                   oncomplete="editNote(#{myAuditList.getRowIndex()}, 'adjLimitApproved')"
                   actionListener="#{noteAction.setCurrentData(myAuditList.getRowIndex(), 'adjLimitApproved', myAuditList)}"
                   reRender="mpNoteAndEmployeeSubmit"/>
                   </h:graphicImage>
                   <h:commandButton id="submitEmployee" value="Submit" actionListener="#{securityAuditAction.submit}" style="visibility:hidden"/>
                   </h:panelGrid>
                   </h:column>
                  
                   </h:dataTable>
                  
                   </h:form>
                   </rich:panel>
                  
                   <center>
                   <a4j:status>
                   <f:facet name="start">
                   <h:graphicImage value="/img/spinner.gif" height="50" width="50"/>
                   </f:facet>
                   </a4j:status>
                   </center>
                  
                   <!-- note only -->
                   <rich:modalPanel id="mpNote" minHeight="200" minWidth="450"
                   height="500" width="500" zindex="2000">
                  
                   <f:facet name="header">
                   <a4j:form id="a4jHeaderForm1">
                   <h:outputText id="headerText1" value=""/>
                   </a4j:form>
                   </f:facet>
                  
                  
                   <h:form id="noteLogList1">
                   <h:dataTable value="#{noteAction.getNoteLogList()}" var="myRow" rendered="noteAction.getNoteLogList() != null">
                   <h:column width="400">
                   <f:facet name="header">NoteText</f:facet>
                   <h:outputText value="#{myRow.noteText}"/>
                   </h:column>
                  
                   <h:column>
                   <f:facet name="header">TimeStamp</f:facet>
                   <h:outputText value="#{myRow.timeStamp}">
                   <s:convertDateTime dateStyle="short" timeStyle="medium" type="both"/>
                   </h:outputText>
                   </h:column>
                   </h:dataTable>
                   </h:form>
                  
                  
                   <a4j:form id="a4jMainForm1">
                   <h:panelGrid columns="2" style="vertical-align:middle">
                   <h:outputText id="description1" value=""/>
                   <BR/>
                   <h:inputTextarea id="noteText1" value="#{noteAction.noteText}" rows="6" cols="50">
                   <a4j:support event="onkeyup" reRender="out1" />
                   </h:inputTextarea>
                  
                   <h:inputHidden id="modalPanelName" value="mpNote"/>
                  
                   <h:panelGroup id="out1">
                   <a4j:commandButton id="submit1" value="submit" action="#{noteAction.submit}"
                   onclick="Richfaces.hideModalPanel('mpNote')"
                   oncomplete="selectFalseCurrentRadioButton()"
                   rendered="#{not empty noteAction.noteText2}"
                   reRender="mainForm"/>
                   </h:panelGroup>
                   <BR/>
                   <a4j:commandButton value="cancel" onclick="Richfaces.hideModalPanel('mpNote');unselectCurrentRadioButton()"/>
                   </h:panelGrid>
                   </a4j:form>
                   </rich:modalPanel>
                  
                   <!-- no note, row data submit only -->
                   <rich:modalPanel id="mpEmployeeSubmit" minHeight="200" minWidth="450"
                   height="500" width="500" zindex="2000">
                  
                   <f:facet name="header">
                   <a4j:form id="a4jHeaderForm2">
                   <h:outputText id="headerText2" value=""/>
                   </a4j:form>
                   </f:facet>
                  
                   <a4j:form id="a4jMainForm2">
                   <h:panelGrid columns="2" style="vertical-align:middle">
                   <h:outputText id="description2" value=""/>
                   <BR/>
                  
                   <h:inputHidden id="modalPanelName" value="mpEmployeeSubmit"/>
                  
                   <a4j:commandButton value="submit" oncomplete="clickDataTableSubmit();Richfaces.hideModalPanel('mpEmployeeSubmit')"/>
                   <BR/>
                   <a4j:commandButton value="cancel" onclick="Richfaces.hideModalPanel('mpEmployeeSubmit');unselectCurrentRadioButton()"/>
                  
                   </h:panelGrid>
                   </a4j:form>
                   </rich:modalPanel>
                  
                   <!-- note and row data submit -->
                  
                   <rich:modalPanel id="mpNoteAndEmployeeSubmit" minHeight="200" minWidth="450"
                   height="500" width="500" zindex="2000">
                  
                   <f:facet name="header">
                   <a4j:form id="a4jHeaderForm3">
                   <h:outputText id="headerText3" value=""/>
                   </a4j:form>
                   </f:facet>
                   <a4j:outputPanel id="out3" ajaxRendered="true">
                   <h:form id="noteLogList2">
                   <rich:datascroller align="left" for="myList" maxPages="20" rendered="#{noteAction.getNoteLogList() ne null}"/>
                   <rich:spacer height="30" rendered="#{noteAction.getNoteLogList() ne null}"/>
                   <rich:dataTable width="483" id="myList" rows="10"
                   value="#{noteAction.getNoteLogList()}" var="myRow"
                   rendered="#{noteAction.getNoteLogList() ne null}">
                   <f:facet name="header">
                   <rich:columnGroup>
                   <h:column>
                   <h:outputText styleClass="headerText" value="NoteText" />
                   </h:column>
                   <h:column>
                   <h:outputText styleClass="headerText" value="TimeStamp" />
                   </h:column>
                   </rich:columnGroup>
                   </f:facet>
                  
                   <h:column>
                   <h:outputText value="#{myRow.noteText}"/>
                   </h:column>
                   <h:column>
                   <h:outputText value="#{myRow.timeStamp}">
                   <s:convertDateTime dateStyle="short" timeStyle="medium" type="both"/>
                   </h:outputText>
                   </h:column>
                   </rich:dataTable>
                   </h:form>
                   </a4j:outputPanel>
                   <a4j:form id="a4jMainForm3">
                   <h:panelGrid columns="2" style="vertical-align:middle">
                   <h:outputText id="description3" value=""/>
                   <BR/>
                  
                   <h:inputTextarea id="noteText3" value="#{noteAction.noteText}" rows="6" cols="50">
                   <a4j:support event="onkeyup" reRender="out3" />
                   </h:inputTextarea>
                  
                   <h:inputHidden id="modalPanelName" value="mpNoteAndEmployeeSubmit"/>
                  
                   <h:panelGroup id="out3">
                   <a4j:commandButton id="submit3" value="submit" action="#{noteAction.submit}" oncomplete="clickDataTableSubmit();Richfaces.hideModalPanel('mpNoteAndEmployeeSubmit')"
                   rendered="#{not empty noteAction.noteText2}">
                   </a4j:commandButton>
                   </h:panelGroup>
                  
                   <BR/>
                  
                   <a4j:commandButton value="cancel" onclick="Richfaces.hideModalPanel('mpNoteAndEmployeeSubmit');unselectCurrentRadioButton()"/>
                   </h:panelGrid>
                   </a4j:form>
                  
                   </rich:modalPanel>
                  
                  
                  </ui:define>
                  </ui:composition>


                  components.xml:

                  <?xml version="1.0" encoding="UTF-8"?>
                  <components xmlns="http://jboss.com/products/seam/components"
                   xmlns:core="http://jboss.com/products/seam/core"
                   xmlns:persistence="http://jboss.com/products/seam/persistence"
                   xmlns:drools="http://jboss.com/products/seam/drools"
                   xmlns:bpm="http://jboss.com/products/seam/bpm"
                   xmlns:security="http://jboss.com/products/seam/security"
                   xmlns:mail="http://jboss.com/products/seam/mail"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation=
                   "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.0.xsd
                   http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.0.xsd
                   http://jboss.com/products/seam/drools http://jboss.com/products/seam/drools-2.0.xsd
                   http://jboss.com/products/seam/bpm http://jboss.com/products/seam/bpm-2.0.xsd
                   http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.0.xsd
                   http://jboss.com/products/seam/mail http://jboss.com/products/seam/mail-2.0.xsd
                   http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd">
                  
                   <core:init debug="@debug@" jndi-pattern="@jndiPattern@"/>
                  
                   <core:manager concurrent-request-timeout="500"
                   conversation-timeout="120000"
                   conversation-id-parameter="cid"/>
                  
                   <persistence:managed-persistence-context name="CoxIMEntityManager"
                   auto-create="true"
                   persistence-unit-jndi-name="java:/securityAuditCoxIMEntityManagerFactory"/>
                   <persistence:managed-persistence-context name="CoxDSSEntityManager"
                   auto-create="true"
                   persistence-unit-jndi-name="java:/securityAuditCoxDSSEntityManagerFactory"/>
                   <persistence:managed-persistence-context name="BoIcomsEntityManager"
                   auto-create="true"
                   persistence-unit-jndi-name="java:/securityAuditCoxIMEntityManagerFactory"/>
                  
                   <drools:rule-base name="securityRules">
                   <drools:rule-files>
                   <value>/security.drl</value>
                   </drools:rule-files>
                   </drools:rule-base>
                  
                   <security:identity authenticate-method="#{authenticator.authenticate}"
                   security-rules="#{securityRules}"/>
                  
                   <event type="org.jboss.seam.notLoggedIn">
                   <action execute="#{redirect.captureCurrentView}"/>
                   </event>
                   <event type="org.jboss.seam.postAuthenticate">
                   <action execute="#{redirect.returnToCapturedView}"/>
                   </event>
                  
                   <mail:mail-session host="localhost" port="2525" username="test" password="test" />
                  
                   <!-- For use with jBPM pageflow or process management -->
                   <!--
                   <bpm:jbpm>
                   <bpm:process-definitions></bpm:process-definitions>
                   <bpm:pageflow-definitions></bpm:pageflow-definitions>
                   </bpm:jbpm>
                   -->
                  
                  </components>


                  persistence.xml:

                  <?xml version="1.0" encoding="UTF-8"?>
                  <!-- Persistence deployment descriptor for dev profile -->
                  <persistence xmlns="http://java.sun.com/xml/ns/persistence"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
                   version="1.0">
                  
                   <persistence-unit name="boIcomsSecurityAudit">
                   <provider>org.hibernate.ejb.HibernatePersistence</provider>
                   <jta-data-source>java:/boIcomsSecurityAuditDatasource</jta-data-source>
                   <properties>
                   <property name="jboss.entity.manager.factory.jndi.name" value="java:/securityAuditBoIcomsEntityManagerFactory"/>
                   </properties>
                   </persistence-unit>
                  
                   <persistence-unit name="coxDSSDatasource">
                   <provider>org.hibernate.ejb.HibernatePersistence</provider>
                   <jta-data-source>java:/coxDSSDatasource</jta-data-source>
                   <properties>
                   <property name="jboss.entity.manager.factory.jndi.name" value="java:/securityAuditCoxDSSEntityManagerFactory"/>
                   </properties>
                   </persistence-unit>
                  
                   <persistence-unit name="coxIMDatasource">
                   <provider>org.hibernate.ejb.HibernatePersistence</provider>
                   <jta-data-source>java:/coxIMDatasource</jta-data-source>
                   <properties>
                   <property name="jboss.entity.manager.factory.jndi.name" value="java:/securityAuditCoxIMEntityManagerFactory"/>
                   </properties>
                   </persistence-unit>
                  
                  </persistence>


                  • 6. Re: Update transactions occurring prematurely in Seam app
                    Arbi Sookazian Master

                    Hey it works now! Not sure if JBoss wasn't picking up the deployment or what (I had to remove an @Out annotation as well that wasn't being used).

                    The premature update is gone with flushMode=MANUAL and SMPC. thanks!

                    • 7. Re: Update transactions occurring prematurely in Seam app
                      Arbi Sookazian Master

                      I noticed that when I reverted to the @PersistenceContext (EXTENDED) config without SMPC but with flushMode=MANUAL on @Begin, the problem was reproduced.

                      So the key is SMPC + flushMode=MANUAL.

                      Please correct me if that statement is wrong.

                      • 8. Re: Update transactions occurring prematurely in Seam app
                        Arbi Sookazian Master

                        On pg. 814 of JPA/Hibernate book, it talks about TransactionalSeamPhaseListener. I am currently not using this in my faces-config.xml. Is it required to use this with SMPC and flushMode=MANUAL?

                        <?xml version='1.0' encoding='UTF-8'?>
                        <faces-config version="1.2"
                         xmlns="http://java.sun.com/xml/ns/javaee"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
                        
                         <application>
                         <locale-config>
                         <default-locale>en</default-locale>
                         </locale-config>
                         <!-- Disabled when using Ajax4JSF -->
                         <!--
                         <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
                         -->
                         </application>
                        
                        </faces-config>


                        • 9. Re: Update transactions occurring prematurely in Seam app
                          Pete Muir Master

                          This is enabled by default in Seam 2.

                          • 10. Re: Update transactions occurring prematurely in Seam app
                            Arbi Sookazian Master

                            Ok, thanks! I did not see a keyword hit on 'TransactionalSeamPhaseListener' in the 2.0.0.GA ref pdf so I got a little confused when comparing with the Seam chapter in Bauer/king book.

                            thanks again.