Importance of BC4J temp tables(PS_TXN table & PS_TXN_SEQ) and Persistent Collections Facility in Oracle ADF

Sharing is Caring

Recently I have seen a new exception in my production environment while 7 users working on the deployed application, this was JBO28030: Could not insert the row into PS_TXN table.

[2013-08-12T14:06:58.191+05:30] [AdminServer] [WARNING] [ADF_FACES-00009] [oracle.adf.view.rich.component.fragment.UIXRegion] [tid: [ACTIVE].ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'] [userId: 11] [ecid: a8c0f3836ec62479:-26ea53cb:1407155e369:-8000-00000000000006e7,0] [APP: EBIZADF.ear] Error processing viewId: /ApplicationRoleTF/AppRole URI: /AppRole.jsff actual-URI: /AppRole.jsff.[[
oracle.jbo.PCollException: JBO-28030: Could not insert row into table PS_TXN, collection id 420,356, persistent id 1
 at oracle.jbo.PCollException.throwException(PCollException.java:36)
 at oracle.jbo.pcoll.OraclePersistManager.insert(OraclePersistManager.java:1905)
 at oracle.jbo.pcoll.PCollNode.passivateElem(PCollNode.java:564)
 at oracle.jbo.pcoll.PCollNode.passivate(PCollNode.java:688)
 at oracle.jbo.pcoll.PCollNode.passivateBranch(PCollNode.java:647)
 at oracle.jbo.pcoll.PCollection.passivate(PCollection.java:464)
 at oracle.jbo.server.DBSerializer.passivateRootAM(DBSerializer.java:294)
 at oracle.jbo.server.DBSerializer.passivateRootAM(DBSerializer.java:267)
 at oracle.jbo.server.ApplicationModuleImpl.passivateStateInternal(ApplicationModuleImpl.java:6046)
 at oracle.jbo.server.ApplicationModuleImpl.passivateState(ApplicationModuleImpl.java:5906)
 at oracle.jbo.common.ampool.DefaultConnectionStrategy.reconnect(DefaultConnectionStrategy.java:290)
 at oracle.jbo.server.ApplicationPoolMessageHandler.doPoolReconnect(ApplicationPoolMessageHandler.java:609)
 at oracle.jbo.server.ApplicationPoolMessageHandler.doPoolMessage(ApplicationPoolMessageHandler.java:399)
 at oracle.jbo.server.ApplicationModuleImpl.doPoolMessage(ApplicationModuleImpl.java:9053)
 at oracle.jbo.common.ampool.ApplicationPoolImpl.sendPoolMessage(ApplicationPoolImpl.java:4606)
 at oracle.jbo.common.ampool.ApplicationPoolImpl.prepareApplicationModule(ApplicationPoolImpl.java:2536)
 at oracle.jbo.common.ampool.ApplicationPoolImpl.doCheckout(ApplicationPoolImpl.java:2346)
 at oracle.jbo.common.ampool.ApplicationPoolImpl.useApplicationModule(ApplicationPoolImpl.java:3245)
 at oracle.jbo.common.ampool.SessionCookieImpl.useApplicationModule(SessionCookieImpl.java:571)
 at oracle.jbo.http.HttpSessionCookieImpl.useApplicationModule(HttpSessionCookieImpl.java:234)
 at oracle.jbo.common.ampool.SessionCookieImpl.useApplicationModule(SessionCookieImpl.java:504)
 at oracle.jbo.common.ampool.SessionCookieImpl.useApplicationModule(SessionCookieImpl.java:499)
 at oracle.adf.model.bc4j.DCJboDataControl.initializeApplicationModule(DCJboDataControl.java:517)
 at oracle.adf.model.bc4j.DCJboDataControl.getApplicationModule(DCJboDataControl.java:867)
 at oracle.adf.model.binding.DCBindingContainer.findDataControl(DCBindingContainer.java:1659)
 at oracle.adf.model.binding.DCIteratorBinding.initDataControl(DCIteratorBinding.java:2542)
 at oracle.adf.model.binding.DCIteratorBinding.getDataControl(DCIteratorBinding.java:2477)
 at oracle.adf.model.binding.DCIteratorBinding.getCheckedDataControl(DCIteratorBinding.java:2571)
 at oracle.adf.model.binding.DCIteratorBinding.executeQueryIfNeeded(DCIteratorBinding.java:2219)
 at oracle.adf.model.binding.DCBindingContainer.internalRefreshControl(DCBindingContainer.java:3279)
 at oracle.adf.model.binding.DCBindingContainer.refresh(DCBindingContainer.java:2906)
 at oracle.adf.controller.internal.binding.TaskFlowRegionController.doRegionRefresh(TaskFlowRegionController.java:284)
 at oracle.adf.controller.internal.binding.TaskFlowRegionController.refreshRegion(TaskFlowRegionController.java:134)
 at oracle.adf.model.binding.DCBindingContainer.internalRefreshControl(DCBindingContainer.java:3237)
 at oracle.adf.model.binding.DCBindingContainer.refresh(DCBindingContainer.java:2906)
 at oracle.adf.controller.v2.lifecycle.PageLifecycleImpl.prepareModel(PageLifecycleImpl.java:115)
 at oracle.adf.controller.faces.lifecycle.FacesPageLifecycle.prepareModel(FacesPageLifecycle.java:392)
 at oracle.adf.controller.v2.lifecycle.Lifecycle$2.execute(Lifecycle.java:149)
 at oracle.adfinternal.controller.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:197)
 at oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener.access$400(ADFPhaseListener.java:23)
 at oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener$PhaseInvokerImpl.startPageLifecycle(ADFPhaseListener.java:238)
 at oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener$1.after(ADFPhaseListener.java:274)
 at oracle.adfinternal.controller.faces.lifecycle.ADFPhaseListener.afterPhase(ADFPhaseListener.java:75)
 at oracle.adfinternal.controller.faces.lifecycle.ADFLifecyclePhaseListener.afterPhase(ADFLifecyclePhaseListener.java:53)
 at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase(LifecycleImpl.java:447)
 at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:202)
 at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
 at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
 at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
 at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:301)
 at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at oracle.adf.model.servlet.ADFBindingFilter.doFilter(ADFBindingFilter.java:173)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at oracle.adfinternal.view.faces.webapp.rich.RegistrationFilter.doFilter(RegistrationFilter.java:125)
 at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:468)
 at oracle.adfinternal.view.faces.activedata.AdsFilter.doFilter(AdsFilter.java:60)
 at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:468)
 at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:293)
 at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:199)
 at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at oracle.adf.library.webapp.LibraryFilter.doFilter(LibraryFilter.java:180)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at oracle.security.jps.ee.http.JpsAbsFilter$1.run(JpsAbsFilter.java:119)
 at oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:315)
 at oracle.security.jps.ee.util.JpsPlatformUtil.runJaasMode(JpsPlatformUtil.java:442)
 at oracle.security.jps.ee.http.JpsAbsFilter.runJaasMode(JpsAbsFilter.java:103)
 at oracle.security.jps.ee.http.JpsAbsFilter.doFilter(JpsAbsFilter.java:171)
 at oracle.security.jps.ee.http.JpsFilter.doFilter(JpsFilter.java:71)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at oracle.dms.servlet.DMSServletFilter.doFilter(DMSServletFilter.java:139)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
 at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
 at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3730)
 at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3696)
 at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
 at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
 at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2273)
 at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2179)
 at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1490)
 at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256)
 at weblogic.work.ExecuteThread.run(ExecuteThread.java:221)

And I was not able to understand why this exception occurs, I googled about it and found some very interesting facts about BC4J.

BC4J creates the temporary database object (PS_TXN and PS_TXN_SEQ), that are used by ADF to maintain the state of user session as per DB, it has the facility to store temporary data in BLOB column to avoid out of memory problem.
visit this link to read about these objects- (How to manage PS_TXN and PS_TXN_SEQ)
http://www.oracle.com/technetwork/developer-tools/jdev/overview/bc4j-temp-tables-087270.html#ID34

now I have seen cascading exception after this oracle.jbo.PcollException, PColl refers to the persistent collection facility.
when ADF was unable to insert data in the PS_TXN table, java.sql.SQLException occurs, connection forcefully closed

Caused by: oracle.jbo.JboException: JBO-29000: Unexpected exception caught: java.sql.SQLException, msg=Connection has already been closed.
 at oracle.jbo.server.DBTransactionImpl.getDatabaseProductName(DBTransactionImpl.java:1248)
 at oracle.jbo.server.DBTransactionImpl.getInternalConnection(DBTransactionImpl.java:1355)
 at oracle.jbo.server.DBTransactionImpl.getPersistManagerConnection(DBTransactionImpl.java:1282)
 at oracle.jbo.pcoll.PCollManager.ensureConnection(PCollManager.java:486)
 at oracle.jbo.pcoll.OraclePersistManager.getConnection(OraclePersistManager.java:153)
 at oracle.jbo.pcoll.OraclePersistManager.insert(OraclePersistManager.java:1885)
 at oracle.jbo.pcoll.PCollNode.passivateElem(PCollNode.java:564)
 at oracle.jbo.pcoll.PCollNode.passivate(PCollNode.java:688)
 at oracle.jbo.pcoll.PCollNode.passivateBranch(PCollNode.java:647)
 at oracle.jbo.pcoll.PCollection.passivate(PCollection.java:464)
 at oracle.jbo.server.DBSerializer.passivateRootAM(DBSerializer.java:294)
 at oracle.jbo.server.DBSerializer.passivateRootAM(DBSerializer.java:267)
 at oracle.jbo.server.ApplicationModuleImpl.passivateStateInternal(ApplicationModuleImpl.java:6046)
 at oracle.jbo.server.ApplicationModuleImpl.passivateState(ApplicationModuleImpl.java:5906)

 

    • Now I have counted rows in PS_TXN, there were more 3000 rows, have cleared all rows

    • After this again 7 users worked for 3hrs and there was no exception, no bizarre behaviour
    • Now once the connection is closed, ADF errors start coming out as NullPointerException

javax.faces.el.EvaluationException: java.lang.NullPointerException
 at org.apache.myfaces.trinidad.component.MethodExpressionMethodBinding.invoke(MethodExpressionMethodBinding.java:51)
 at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:98)
 at org.apache.myfaces.trinidad.component.UIXCommand.broadcast(UIXCommand.java:190)
 at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:783)
 at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1248)

 

  • Finally what I come to know that in order to avoid this kind of exceptions, we have to schedule a job to clear data in PS_TXN

What PS_TXN stores-

  • PS_TXN structure- 
    PS_TXN table
     
    • Suppose you have a search query with more than 10000 records and that is on the page as af:table, when the user scrolls through the table to view records then to avoid out of memory problem bc4j stores extra result set in a temporary storage (PS_TXN) in the BLOB column
    • When AM (Application Module) passivates and in AM pooling dofailover is set to true, pending state and changes are stored in this table

<AM-Pooling jbo.dofailover="true"/>

 

  • In case of Multiple users, session information stored in PS_TXN, each user session must be serialised with the database, otherwise, database object can’t behave as per separate user session
  • to test a scenario, I have deleted all data from PS_TXN in default HR Schema and created an ADF application  that makes uses of HR‘s tables

 

  • Run that application, till few operations on application there was no data in the PS_TXN table when I opened application in 3 browser’s window and then performed some operations after this there were 2 rows in PS_TXN, it means ADF automatically insert data in PS_TXN for the state, session, AM Changes. developer need not worry about it

At-last summary is – Always keep in mind these DB objects if you are facing unexpected behaviour of ADF application in production multi-user) environment, if your application working perfectly on development environment but not in production always check it and schedule a job to clear table PS_TXN

Related Posts

0 thoughts on “Importance of BC4J temp tables(PS_TXN table & PS_TXN_SEQ) and Persistent Collections Facility in Oracle ADF”

  1. In which schema these table and sequence PS_TXN , PS_TXN_SEQ are stored in DB ?

    is it SOA_INFRA schema or application level schemas ?

  2. Hi Ashish,

    How to delete all data from PS_TXN table programatically or is there any way to delete whenever server restarts.
    FYI:
    I am using glassfish server.

Leave a Reply

Your email address will not be published. Required fields are marked *