9 Replies Latest reply on Feb 16, 2007 8:58 PM by vk101

    Remove from list using EntityHome

      How would you remove an entity using EntityHome when you're in a list of those entities (populated either using the query's resultList or dataModel property)?

      I can maybe see how you could do it from within a page that is centered around that one entity, but not from a list of many of those entities. How could I do this?

        • 1. Re: Remove from list using EntityHome
          pmuir

          Use page parameters:

          <s:link action="#{entityHome.remove}">
           <f:param name="entityId" value="#{entity.id}" />
          </s:link>


          <page view-id="/blah.xhtml">
           <param name="entityId" value="#{entityHome.id}" />
          </page>


          • 2. Re: Remove from list using EntityHome

            I was afraid you'd say that :) Just kidding...I actually experimented with a different approach, and it goes about 90% of the way...maybe you could tell me why it isn't working. (Sure I'll end up using the parameters way if this doesn't work, but working through this will help me understand Seam better...)

            In my components.xml:

            <!-- where myEntityQuery is also defined in this components.xml -->
            <factory name="myFactory" value="myEntityQuery.dataModel" />


            In my xhtml within an h:column:

            <h:commandLink value="..." action="#{myEntityHome.remove}" />


            In my MyEntityHome:

            @In("#{myFactory.rowData}")
            public void setInstance(MyEntity my) {
             super.setInstance(my);
            }


            Believe it or not, this setup goes about 90% of the way in my debugger...the "my" parameter gets correctly passed to setInstance, the EntityHome's "instance" variable is set correctly, and the remove method is called while instance is set! But for some reason the entity doesn't get removed, setInstance then gets called a second time before the request is over, this time with null passed to setInstance.

            Why might setInstance be getting called twice? I don't think I'm doing anything special apart from what I've indicated above... Please help.

            I could try using rowIndex instead of rowData and setting the id instead of the instance, but I'm not sure that would change anything...

            • 3. Re: Remove from list using EntityHome
              pmuir

              This is an equally valid way of doing it (and neat as well - avoids exposing your id's to the world) but I guess it's tricky to get working.

              My best guess as to why it fails from what you've said is that by passing the instance through the datamodel like that it has become unmanaged so cannot be removed - you can check this by calling entityManager.contains(). Setting by Id rather than instance might just work (use it with my.getId rather than rowIndex).

              And beware of the fact that a remove won't remove the entity from memory - it just detaches it from the persistence context.

              • 4. Re: Remove from list using EntityHome

                 

                "petemuir" wrote:
                My best guess as to why it fails from what you've said is that by passing the instance through the datamodel like that it has become unmanaged so cannot be removed - you can check this by calling entityManager.contains(). Setting by Id rather than instance might just work (use it with my.getId rather than rowIndex).


                Where should I set the breakpoint in my debugger to do an entityManager.contains() check?

                Or if it's better to output a FacesMessage with this value, where should I put that debugging line?


                And beware of the fact that a remove won't remove the entity from memory - it just detaches it from the persistence context.


                So the refreshed page after the delete would still show the removed entity in the list right? But if I look in my DB, am I correct to say I should no longer see it there (if things work correctly) even though it's still in memory?

                Next question is why does this happen - isn't entity-query EVENT-scoped, which means that on the next refresh it doesn't exist and has to hit the DB again?

                Thanks a lot.

                • 5. Re: Remove from list using EntityHome
                  pmuir

                   

                  "lightbulb432" wrote:
                  "petemuir" wrote:
                  My best guess as to why it fails from what you've said is that by passing the instance through the datamodel like that it has become unmanaged so cannot be removed - you can check this by calling entityManager.contains(). Setting by Id rather than instance might just work (use it with my.getId rather than rowIndex).


                  Where should I set the breakpoint in my debugger to do an entityManager.contains() check?

                  Or if it's better to output a FacesMessage with this value, where should I put that debugging line?


                  I don't think there is anywhere really existing in EntityHome you can put that. So I guess you could subclass EntityHome and override remove and do it there. Or if you are really clever with your debugger you should be able to get it to run to evaluate that line without it being in your code ;)


                  And beware of the fact that a remove won't remove the entity from memory - it just detaches it from the persistence context.


                  So the refreshed page after the delete would still show the removed entity in the list right? But if I look in my DB, am I correct to say I should no longer see it there (if things work correctly) even though it's still in memory?

                  Next question is why does this happen - isn't entity-query EVENT-scoped, which means that on the next refresh it doesn't exist and has to hit the DB again?

                  Thanks a lot.


                  It might do - it depends on how your contexts are set up, whether you refresh your lists etc. But yes, it should no longer be in the db.

                  IIRC EntityQuery is conversation scoped. So you would need to use removeFromStatefulContexts to ensure it is refreshed I think...

                  • 6. Re: Remove from list using EntityHome

                    I tried using the id by changing to the following, but it complained that rowData doesn't have an "id":

                    @In("#{myFactory.rowData.id}")
                    public void setInstance(MyEntity my) {
                     super.setInstance(my);
                    }


                    (Shouldn't rowData have an id if the underlying entity has an "id", which it does?)

                    How would I implement your suggestion to "use my.getId rather than rowIndex"?

                    • 7. Re: Remove from list using EntityHome

                      (Of course I meant setId in both cases where I put setInstance in the previous post)

                      • 8. Re: Remove from list using EntityHome

                        I'm getting the following exception that says the row is unavailable, which is just crazy because the debugger clearly shows the correct value being passed to setInstance:

                        @In("#{myFactory.rowData}")
                        public void setInstance(MyEntity my) {
                         super.setInstance(my);
                        }


                        Why could this be happening?

                        javax.faces.el.EvaluationException: Cannot get value for expression '#{association.name}'
                         at org.apache.myfaces.el.ValueBindingImpl.getValue(ValueBindingImpl.java:402)
                         at org.jboss.seam.core.Expressions$1.getValue(Expressions.java:53)
                         at org.jboss.seam.core.Interpolator.interpolateExpressions(Interpolator.java:88)
                         at org.jboss.seam.core.Interpolator.interpolate(Interpolator.java:67)
                         at org.jboss.seam.core.FacesMessages.createFacesMessage(FacesMessages.java:318)
                         at org.jboss.seam.core.FacesMessages$2.run(FacesMessages.java:222)
                         at org.jboss.seam.core.FacesMessages.runTasks(FacesMessages.java:132)
                         at org.jboss.seam.core.FacesMessages.afterPhase(FacesMessages.java:142)
                         at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:109)
                         at org.apache.myfaces.lifecycle.PhaseListenerManager.informPhaseListenersAfter(PhaseListenerManager.java:89)
                         at org.apache.myfaces.lifecycle.LifecycleImpl.invokeApplication(LifecycleImpl.java:345)
                         at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:86)
                         at javax.faces.webapp.FacesServlet.service(FacesServlet.java:137)
                         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
                         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                         at org.jboss.seam.servlet.SeamRedirectFilter.doFilter(SeamRedirectFilter.java:29)
                         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
                         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                         at org.jboss.seam.servlet.SeamExceptionFilter.doFilter(SeamExceptionFilter.java:43)
                         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
                         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                         at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
                         at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
                         at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
                         at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
                         at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
                         at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
                         at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
                         at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
                         at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
                         at org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156)
                         at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
                         at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
                         at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
                         at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
                         at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
                         at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
                         at java.lang.Thread.run(Unknown Source)
                        Caused by: javax.faces.el.EvaluationException: Cannot get value for expression '#{associations.rowData}'
                         at org.apache.myfaces.el.ValueBindingImpl.getValue(ValueBindingImpl.java:402)
                         at org.jboss.seam.core.Expressions$1.getValue(Expressions.java:53)
                         at org.jboss.seam.Component.getInstanceToInject(Component.java:1878)
                         at org.jboss.seam.Component.injectMethods(Component.java:1364)
                         at org.jboss.seam.Component.inject(Component.java:1155)
                         at org.jboss.seam.interceptors.BijectionInterceptor.bijectNonreentrantComponent(BijectionInterceptor.java:76)
                         at org.jboss.seam.interceptors.BijectionInterceptor.bijectComponent(BijectionInterceptor.java:58)
                         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                         at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.jboss.seam.util.Reflections.invoke(Reflections.java:18)
                         at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
                         at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
                         at org.jboss.seam.interceptors.ManagedEntityIdentityInterceptor.aroundInvoke(ManagedEntityIdentityInterceptor.java:36)
                         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                         at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.jboss.seam.util.Reflections.invoke(Reflections.java:18)
                         at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
                         at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
                         at org.jboss.seam.interceptors.OutcomeInterceptor.interceptOutcome(OutcomeInterceptor.java:21)
                         at sun.reflect.GeneratedMethodAccessor349.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.jboss.seam.util.Reflections.invoke(Reflections.java:18)
                         at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
                         at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
                         at org.jboss.seam.interceptors.RollbackInterceptor.rollbackIfNecessary(RollbackInterceptor.java:29)
                         at sun.reflect.GeneratedMethodAccessor359.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.jboss.seam.util.Reflections.invoke(Reflections.java:18)
                         at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
                         at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
                         at org.jboss.seam.interceptors.ConversationInterceptor.endOrBeginLongRunningConversation(ConversationInterceptor.java:52)
                         at sun.reflect.GeneratedMethodAccessor348.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.jboss.seam.util.Reflections.invoke(Reflections.java:18)
                         at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
                         at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
                         at org.jboss.seam.interceptors.TransactionInterceptor$1.work(TransactionInterceptor.java:28)
                         at org.jboss.seam.util.Work.workInTransaction(Work.java:37)
                         at org.jboss.seam.interceptors.TransactionInterceptor.doInTransactionIfNecessary(TransactionInterceptor.java:23)
                         at sun.reflect.GeneratedMethodAccessor358.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.jboss.seam.util.Reflections.invoke(Reflections.java:18)
                         at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
                         at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
                         at org.jboss.seam.interceptors.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:27)
                         at sun.reflect.GeneratedMethodAccessor347.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.jboss.seam.util.Reflections.invoke(Reflections.java:18)
                         at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
                         at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
                         at org.jboss.seam.intercept.RootInterceptor.createSeamInvocationContext(RootInterceptor.java:144)
                         at org.jboss.seam.intercept.RootInterceptor.invokeInContexts(RootInterceptor.java:129)
                         at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:102)
                         at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:145)
                         at org.jboss.seam.intercept.JavaBeanInterceptor.intercept(JavaBeanInterceptor.java:80)
                         at com.test.entity.home.AssociationHome$$EnhancerByCGLIB$$d22d137f.init(<generated>)
                         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                         at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.jboss.seam.util.Reflections.invoke(Reflections.java:18)
                         at org.jboss.seam.util.Reflections.invokeAndWrap(Reflections.java:102)
                         at org.jboss.seam.Component.callComponentMethod(Component.java:1835)
                         at org.jboss.seam.Component.getInstanceFromFactory(Component.java:1722)
                         at org.jboss.seam.Component.getInstance(Component.java:1659)
                         at org.jboss.seam.Component.getInstance(Component.java:1636)
                         at org.jboss.seam.jsf.SeamVariableResolver.resolveVariable(SeamVariableResolver.java:53)
                         at org.apache.myfaces.config.LastVariableResolverInChain.resolveVariable(LastVariableResolverInChain.java:42)
                         at org.apache.myfaces.el.ValueBindingImpl$ELVariableResolver.resolveVariable(ValueBindingImpl.java:574)
                         at org.apache.commons.el.NamedValue.evaluate(NamedValue.java:124)
                         at org.apache.commons.el.ComplexValue.evaluate(ComplexValue.java:140)
                         at org.apache.myfaces.el.ValueBindingImpl.getValue(ValueBindingImpl.java:383)
                         ... 38 more
                        Caused by: javax.faces.el.EvaluationException: Exception getting value of property rowData of base of type : org.jboss.seam.jsf.ListDataModel
                         at org.apache.myfaces.el.PropertyResolverImpl.getValue(PropertyResolverImpl.java:96)
                         at org.apache.myfaces.el.ELParserHelper$MyPropertySuffix.evaluate(ELParserHelper.java:532)
                         at org.apache.commons.el.ComplexValue.evaluate(ComplexValue.java:145)
                         at org.apache.myfaces.el.ValueBindingImpl.getValue(ValueBindingImpl.java:383)
                         ... 118 more
                        Caused by: javax.faces.el.EvaluationException: Bean: org.jboss.seam.jsf.ListDataModel, property: rowData
                         at org.apache.myfaces.el.PropertyResolverImpl.getProperty(PropertyResolverImpl.java:442)
                         at org.apache.myfaces.el.PropertyResolverImpl.getValue(PropertyResolverImpl.java:82)
                         ... 121 more
                        Caused by: java.lang.reflect.InvocationTargetException
                         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                         at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
                         at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
                         at java.lang.reflect.Method.invoke(Unknown Source)
                         at org.apache.myfaces.el.PropertyResolverImpl.getProperty(PropertyResolverImpl.java:438)
                         ... 122 more
                        Caused by: java.lang.IllegalArgumentException: row is unavailable
                         at javax.faces.model.ListDataModel.getRowData(ListDataModel.java:63)
                         ... 127 more


                        • 9. Re: Remove from list using EntityHome

                          You can ignore all of the above. The problem, believe it or not, is when the deletedMessage contains an expression of the current instance of the EntityHome.

                          In the code below, if my deletedMessage in public String getDeletedMessage() contains #{myEntity.myProperty}, then the factory to get the row data is run again (to evaluate "myEntity") with a null value for "instance"...but if I leave it as a String with no EL in it, then it's fine.

                          Am I outjecting to the correct scope of CONVERSATION? What could be wrong with putting EL of the current instance in the message?

                          @Factory(value="myEntity",scope=ScopeType.CONVERSATION)
                          public MyEntity returnMyEntity() { return getInstance(); }