Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: v3.0.1
    • Fix Version/s: None
    • Component/s: entity-persistence
    • Labels:
      None
    • Environment:

      Unix & WinXP

      Description

      I have a stateless EJB method that updates a JPA Entity. (Many similar, in fact). When I call the update method for a CERTAIN entity with a CERTAIN id, I get an exception that seems to be the result of a bug somewhere deep down in Glassfish. It's reproducible for THAT entity type with THAT id, but no other.

      Also, afterwards (but on WinXP only) normal JPA queries to that entity type (or perhaps a related entity - I can't figure it out) just hang forever. I have to redeploy and restart Glassfish for the problem to go away.

      My web/ejb application works fine otherwise, with many entities implemented in exactly the same way. It seems to me that in some rare unfortunate circumstance, the bug is triggred.

      I'll be happy to provide further information, as needed.

      Here's a traceback of the event:

      2011-01-07 13:59:11.441 WARN [http-thread-pool-8181-(1)] (error_jsp._jspService:191) - Server got unhandled exception: javax.ejb.EJBException: Transaction aborted AT com.sun.ejb.containers.BaseContainer.completeNewTx:5046 BaseContainer.postInvokeTx:4805 BaseContainer.postInvoke:2004 BaseContainer.postInvoke:1955 EJBLocalObjectInvocationHandler.invoke:198 EJBLocalObjectInvocationHandlerDelegate.invoke:84 $Proxy302.update AdminServlet.doPost:1196 HttpServlet.service:754 HttpServlet.service:847 StandardWrapper.service:1523 ApplicationFilterChain.internalDoFilter:343 ApplicationFilterChain.doFilter:215 RequestLogFilter.doFilter:62 ApplicationFilterChain.internalDoFilter:256 ApplicationFilterChain.doFilter:215 MainFilter.doFilter:41 ApplicationFilterChain.internalDoFilter:256 ApplicationFilterChain.doFilter:215 StandardWrapperValve.invoke:277 StandardContextValve.invoke:188 StandardPipeline.invoke:641 WebPipeline.invoke:97 PESessionLockingStandardPipeline.invoke:85 StandardHostValve.invoke:185 CoyoteAdapter.doService:325 CoyoteAdapter.service:226 ContainerMapper.service:165 ProcessorTask.invokeAdapter:791 ProcessorTask.doProcess:693 ProcessorTask.process:954 DefaultProtocolFilter.execute:170 DefaultProtocolChain.executeProtocolFilter:135 DefaultProtocolChain.execute:102 DefaultProtocolChain.execute:88 HttpProtocolChain.execute:76 ProtocolChainContextTask.doCall:53 SelectionKeyContextTask.call:57 ContextTask.run:69 AbstractThreadPool$Worker.doWork:330 AbstractThreadPool$Worker.run:309 Thread.run:662 CAUSED BY: javax.transaction.RollbackException: Transaction marked for rollback. AT com.sun.enterprise.transaction.JavaEETransactionImpl.commit:450 JavaEETransactionManagerSimplified.commit:837 BaseContainer.completeNewTx:5040 BaseContainer.postInvokeTx:4805 BaseContainer.postInvoke:2004 BaseContainer.postInvoke:1955 EJBLocalObjectInvocationHandler.invoke:198 EJBLocalObjectInvocationHandlerDelegate.invoke:84 $Proxy302.update AdminServlet.doPost:1196 HttpServlet.service:754 HttpServlet.service:847 StandardWrapper.service:1523 ApplicationFilterChain.internalDoFilter:343 ApplicationFilterChain.doFilter:215 RequestLogFilter.doFilter:62 ApplicationFilterChain.internalDoFilter:256 ApplicationFilterChain.doFilter:215 MainFilter.doFilter:41 ApplicationFilterChain.internalDoFilter:256 ApplicationFilterChain.doFilter:215 StandardWrapperValve.invoke:277 StandardContextValve.invoke:188 StandardPipeline.invoke:641 WebPipeline.invoke:97 PESessionLockingStandardPipeline.invoke:85 StandardHostValve.invoke:185 CoyoteAdapter.doService:325 CoyoteAdapter.service:226 ContainerMapper.service:165 ProcessorTask.invokeAdapter:791 ProcessorTask.doProcess:693 ProcessorTask.process:954 DefaultProtocolFilter.execute:170 DefaultProtocolChain.executeProtocolFilter:135 DefaultProtocolChain.execute:102 DefaultProtocolChain.execute:88 HttpProtocolChain.execute:76 ProtocolChainContextTask.doCall:53 SelectionKeyContextTask.call:57 ContextTask.run:69 AbstractThreadPool$Worker.doWork:330 AbstractThreadPool$Worker.run:309 Thread.run:662 CAUSED BY: java.util.ConcurrentModificationException AT java.util.AbstractList$Itr.checkForComodification:372 AbstractList$Itr.next:343 CollectionChangeRecord.mergeRecord:270 ObjectChangeSet.mergeObjectChanges:604 UnitOfWorkChangeSet.mergeObjectChanges:481 AttributeChangeTrackingPolicy.createObjectChangeSet:63 DeferredChangeDetectionPolicy.calculateChanges:89 AttributeChangeTrackingPolicy.calculateChangesForExistingObject:47 DatabaseQueryMechanism.updateObjectForWriteWithChangeSet:1091 UpdateObjectQuery.executeCommitWithChangeSet:84 DatabaseQueryMechanism.executeWriteWithChangeSet:286 WriteObjectQuery.executeDatabaseQuery:58 DatabaseQuery.execute:675 DatabaseQuery.executeInUnitOfWork:589 ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery:109 ObjectLevelModifyQuery.executeInUnitOfWork:86 UnitOfWorkImpl.internalExecuteQuery:2857 AbstractSession.executeQuery:1225 AbstractSession.executeQuery:1207 AbstractSession.executeQuery:1167 CommitManager.commitChangedObjectsForClassWithChangeSet:233 CommitManager.commitAllObjectsForClassWithChangeSet:163 CommitManager.commitAllObjectsWithChangeSet:116 AbstractSession.writeAllObjectsWithChangeSet:3260 UnitOfWorkImpl.commitToDatabase:1403 RepeatableWriteUnitOfWork.commitToDatabase:547 UnitOfWorkImpl.commitToDatabaseWithChangeSet:1508 UnitOfWorkImpl.issueSQLbeforeCompletion:3128 RepeatableWriteUnitOfWork.issueSQLbeforeCompletion:268 AbstractSynchronizationListener.beforeCompletion:157 JTASynchronizationListener.beforeCompletion:68 JavaEETransactionImpl.commit:412 JavaEETransactionManagerSimplified.commit:837 BaseContainer.completeNewTx:5040 BaseContainer.postInvokeTx:4805 BaseContainer.postInvoke:2004 BaseContainer.postInvoke:1955 EJBLocalObjectInvocationHandler.invoke:198 EJBLocalObjectInvocationHandlerDelegate.invoke:84 $Proxy302.update AdminServlet.doPost:1196 HttpServlet.service:754 HttpServlet.service:847 StandardWrapper.service:1523 ApplicationFilterChain.internalDoFilter:343 ApplicationFilterChain.doFilter:215 RequestLogFilter.doFilter:62 ApplicationFilterChain.internalDoFilter:256 ApplicationFilterChain.doFilter:215 MainFilter.doFilter:41 ApplicationFilterChain.internalDoFilter:256 ApplicationFilterChain.doFilter:215 StandardWrapperValve.invoke:277 StandardContextValve.invoke:188 StandardPipeline.invoke:641 WebPipeline.invoke:97 PESessionLockingStandardPipeline.invoke:85 StandardHostValve.invoke:185 CoyoteAdapter.doService:325 CoyoteAdapter.service:226 ContainerMapper.service:165 ProcessorTask.invokeAdapter:791 ProcessorTask.doProcess:693 ProcessorTask.process:954 DefaultProtocolFilter.execute:170 DefaultProtocolChain.executeProtocolFilter:135 DefaultProtocolChain.execute:102 DefaultProtocolChain.execute:88 HttpProtocolChain.execute:76 ProtocolChainContextTask.doCall:53 SelectionKeyContextTask.call:57 ContextTask.run:69 AbstractThreadPool$Worker.doWork:330 AbstractThreadPool$Worker.run:309 Thread.run:662

        Activity

        Hide
        Mitesh Meswani added a comment - - edited

        I do not think it is necessary to try this with 3.1. I think you have nailed the issue. It is not good idea to call sort() on a getter when you have PROPERTIES access. This is because the persistence provider also uses the getter to access the entity state and that may result in issue like the one you are running into. For a simpler ordering than the one you desire, it would be best to use @OrderBy. You might have to use another getter(that does not correspond to persistence property) that does sorting for you

        >The problem occurs iff the CarModelGroup has at least one CarModel, but not for an empty CarModelGroup.
        Can you please distill a reproducible test with data set you described. That would help a lot to get to bottom of this to issue faster.

        Show
        Mitesh Meswani added a comment - - edited I do not think it is necessary to try this with 3.1. I think you have nailed the issue. It is not good idea to call sort() on a getter when you have PROPERTIES access. This is because the persistence provider also uses the getter to access the entity state and that may result in issue like the one you are running into. For a simpler ordering than the one you desire, it would be best to use @OrderBy. You might have to use another getter(that does not correspond to persistence property) that does sorting for you >The problem occurs iff the CarModelGroup has at least one CarModel, but not for an empty CarModelGroup. Can you please distill a reproducible test with data set you described. That would help a lot to get to bottom of this to issue faster.
        Hide
        tmpsa added a comment -

        > For a simpler ordering than the one you desire, it would be best to use @OrderBy.

        Indeed. I do just that in many other entities. And in this case, I would love to do something like @OrderBy("CarMaker.name, name, year"), but JPA does not appear to support @OrderBy on a related entity. So I have to settle for my less elegant solution with a hand-coded sorter.

        > You might have to use another getter(that does not correspond to persistence property) that does sorting for you.

        I'm not sure how I could do that. The list is used in serveral places, accessed in JSPs with EL. (Very convenient!) And even if I write a @Transient getter method that does the sorting, it would have to access the list in the same way as the vanilla getter. And that would cause the same problem, I presume.

        Is manual sorting in a entity getter method really illegal in JPA?

        > Can you please distill a reproducible test with data set you described. That would help a lot to get to bottom of this to issue faster.

        I guess I could write a small webapp (with a database, entities, EJBs, servlet and JSP) that reproduces the problem, but that is a non-trivial task that would take serveral days.

        Show
        tmpsa added a comment - > For a simpler ordering than the one you desire, it would be best to use @OrderBy. Indeed. I do just that in many other entities. And in this case, I would love to do something like @OrderBy("CarMaker.name, name, year"), but JPA does not appear to support @OrderBy on a related entity. So I have to settle for my less elegant solution with a hand-coded sorter. > You might have to use another getter(that does not correspond to persistence property) that does sorting for you. I'm not sure how I could do that. The list is used in serveral places, accessed in JSPs with EL. (Very convenient!) And even if I write a @Transient getter method that does the sorting, it would have to access the list in the same way as the vanilla getter. And that would cause the same problem, I presume. Is manual sorting in a entity getter method really illegal in JPA? > Can you please distill a reproducible test with data set you described. That would help a lot to get to bottom of this to issue faster. I guess I could write a small webapp (with a database, entities, EJBs, servlet and JSP) that reproduces the problem, but that is a non-trivial task that would take serveral days.
        Hide
        Mitesh Meswani added a comment -

        >I'm not sure how I could do that. The list is used in serveral places, accessed in JSPs with EL. (Very convenient!) And even if I write a @Transient getter method >that does the sorting, it would have to access the list in the same way as the vanilla getter. And that would cause the same problem, I presume.
        It should not. The @Transient method will not be used by the persistence provider to access state of your entity.

        >Is manual sorting in a entity getter method really illegal in JPA?
        The spec does not say either way. However it is not good practice to do it. The persistence provider will call into your method when ever it wants to access state of your entity. This will result in the sort being performed. Not optimal.

        >I guess I could write a small webapp (with a database, entities, EJBs, servlet and JSP) that reproduces the problem
        We do not need a fancy front end for the reproduction. All we need is some sql scripts that populate the data that you think recreates the issue and a call into EJB that accesses and updates the data.

        Show
        Mitesh Meswani added a comment - >I'm not sure how I could do that. The list is used in serveral places, accessed in JSPs with EL. (Very convenient!) And even if I write a @Transient getter method >that does the sorting, it would have to access the list in the same way as the vanilla getter. And that would cause the same problem, I presume. It should not. The @Transient method will not be used by the persistence provider to access state of your entity. >Is manual sorting in a entity getter method really illegal in JPA? The spec does not say either way. However it is not good practice to do it. The persistence provider will call into your method when ever it wants to access state of your entity. This will result in the sort being performed. Not optimal. >I guess I could write a small webapp (with a database, entities, EJBs, servlet and JSP) that reproduces the problem We do not need a fancy front end for the reproduction. All we need is some sql scripts that populate the data that you think recreates the issue and a call into EJB that accesses and updates the data.
        Hide
        tmpsa added a comment -

        > The @Transient method will not be used by the persistence provider to access state of your entity.

        I just tried to use such a @Transient access method that does the sorting, and it seems to be a successful workaround.

        By the way, I have a strong hunch that my previously reported bug was also caused by manual sorting inside an entity getter (of a List), see
        http://java.net/jira/browse/GLASSFISH-14972

        Hope this helps in further narrowing down the problem.

        (It would still be a significant task to create a full-fledged bug-reproducing EJB application that accesses and updates some data. I could mail you directly with the source of the related EJBs and Entities, if you wish).

        Show
        tmpsa added a comment - > The @Transient method will not be used by the persistence provider to access state of your entity. I just tried to use such a @Transient access method that does the sorting, and it seems to be a successful workaround. By the way, I have a strong hunch that my previously reported bug was also caused by manual sorting inside an entity getter (of a List), see http://java.net/jira/browse/GLASSFISH-14972 Hope this helps in further narrowing down the problem. (It would still be a significant task to create a full-fledged bug-reproducing EJB application that accesses and updates some data. I could mail you directly with the source of the related EJBs and Entities, if you wish).
        Hide
        Mitesh Meswani added a comment -

        The usage pattern of calling sort() in properties based getter is not recommended

        Show
        Mitesh Meswani added a comment - The usage pattern of calling sort() in properties based getter is not recommended

          People

          • Assignee:
            Mitesh Meswani
            Reporter:
            tmpsa
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Due:
              Created:
              Updated:
              Resolved: