1 2 Previous Next 16 Replies Latest reply on Dec 7, 2008 4:56 AM by matt.drees

    SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?

    meetoblivion

      Hi there


      I'm trying to understand all of the implications of using application scoped SFSB.  I'm not too concerned about the synchronization issues, as the bulk of the use for these SFSB's is for querying, rather than updating (the main writing is down by a secondary process, and the front end is about 90% query)


      Initially, I defined all of my DAO's as Stateful, and in the ApplicationScope.  I did this so I can easily fetch properties from entities that can be pulled as needed (LAZY vs. EAGER fetching).


      After deploying this and the secondary process (both j2ee apps, deployed on the same box) to the test environment, we began seeing OutOfMemoryErrors.  The first thing I thought of was the SFSB DAO's.  As a test, I changed the annotations to Stateless and switched the persistence type.  I haven't seen the OutOfMemoryErrors yet.  I'm now stuck with a solution on how to retrieve the entities across page views.


      the main entity i'm concerned about is the user, which represents the logged in user.  I've been throwing this into a custom wrapper of identity.


      I've considered the following, since the properties in question are all FK relationships.


      - Add a query to the other objects to retrieve based on the parent.
      - change the stateful type to session.


      Any other ideas?

        • 1. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
          pedrosena

          Hi,


          Your DAOs should be Stateless, they do not need to mantain State, what should be Conversation Scoped is your EntityManager, it is the object that need to maintain information about the entities loaded, not the DAO.


          Try to do this and use fetch Lazy in your collections, usually OutOfMemory errors are associated with fetch Eager and entities that has a couple of OneToMany associations


          Hope this helps,


          Pedro Sena

          • 2. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
            meetoblivion

            Ok, well you can't define an entity with multiple eager collection loads (atleast, I can't, it throws an error on startup about that).  Beyond that, I'm not sure how to define an entitymanager to be stateful (or maybe stateless, as I believe the stateful entitymanager is the equivalent of extended persistence context; which is why I used stateful dao's initially).


            I thank you for your reply, but I guess I need more information for what you recommended.

            • 3. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
              pedrosena

              Hi John,


              First of all, take a look at Seam-managed persistence contexts


              Using the entityManager this way, you should insert it using @In instead of @PersistenceContext, that way your entityManager lifecycle will be managed by Seam and you don't need to take core of it.


              Using this approach, a Stateless DAO and Fetch lazy should solve your problem.


              Regards,


              Pedro Sena

              • 4. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                meetoblivion

                Pedro,


                Thank you for the information.  I added the seam managed entity manager like this:


                (components.xml)
                   <persistence:managed-persistence-context name="blogDatabase"
                                                  auto-create="true"
                                   persistence-unit-jndi-name="java:/EntityManagerFactories/blogData"/>                 
                (persistence.xml)
                <property name="jboss.entity.manager.factory.jndi.name" value="java:/EntityManagerFactories/blogData"/>

                And in the DAOs (actually, the base class):
                        @In
                        private EntityManager blogDatabase;



                and I can verify that it's working on the pages that used to work fine by seeing them render correctly, so it hasn't broken anything.


                Unfortunately, now I'm getting a LazyInitializationException where I was getting another error before.


                LazyInitializationException failed to lazily initialize a collection of role: com.tad.apps.blog.entity.User.blogs, no session or session was closed
                org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.tad.apps.blog.entity.User.blogs, no session or session was closed

                • 5. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                  meetoblivion

                  Ok, just to add more information...


                  I changed some settings to pull a lazy init'd list from the same object during the login process, meaning the transaction was still open, part of the same auth method, and it worked fine.

                  • 6. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                    pedrosena

                    Hi John,


                    I'm not sure about it, BUT I believe that the problem is the way that you are dealing with transactions.


                    The Seam-managed entity manager is scoped in conversation context, for this reason, should not deal with transactions by yourself(I suppose that you are using @Transaction annotations, right ?)


                    Intead of do this, try to demarcate your use case with a conversation, it can be propagated for many request.


                    More information about how to do this Here


                    PS: I'm newbie to Seam too, I'm not sure about it, but is what I believe, hope you have time to make a little test and please, do not forget to post the results here :).


                    Regards,


                    Pedro Sena

                    • 7. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                      meetoblivion

                      I do not want to use conversations, as this entity has to be alive for the entire session, not just a single conversation - I don't see a reason to scope the app conversation level, when everything's already supposed to be in the session level.  I am not using @Transaction anywhere either.


                      You do raise a good point though.


                      1. My DAO's are app scoped.  Maybe they should be relegated to session scope?  I have been considering this for a bit, and was a bit worried about performance; though now that they're SLSB's this shouldn't be as big of a problem.
                      2. This EM you pointed me to is conversation scoped, yet I don't want to use conversations for everything (most things are either PAGE/EVENT styled, or session; except the DAOs).  Assuming I move DAOs to session scope, how do I move the em to session scope?


                      I think my answer's on this page:


                      http://www.redhat.com/docs/en-US/JBossEnterpriseApplicationPlatform/4.3.0.cp02fp01/html/SeamReferenceGuide/ch10s03s03.html


                      though, it's still talking about conversation scoped EM.

                      • 8. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                        meetoblivion

                        Any other ideas? Anyone?  This is a killer issue - if I can't work around it I'm going to have to scrap using Seam.

                        • 9. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                          meetoblivion

                          BTW - don't hesitate to tell me well, you're doing it wrong. I can accept that.  I'm more interested in understanding why what I decided is wrong than having an ego.

                          • 10. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                            matt.drees

                            Hi John,



                            John Ament wrote on Nov 30, 2008 18:21:


                            I do not want to use conversations, as this entity has to be alive for the entire session, not just a single conversation


                            I'm not sure you actually want that.  Generally, persistence contexts are meant to be short-lived.  If you keep them around a long time, they cache every single entity you read from the db.  (This may be what was causing your OOME problems.)


                            So for session-scoped objects, like a User object, one approach is to do the initial loading up front, and keep it around as a disconnected/unmanaged object. 


                            Or sometimes you'd just keep the userId around, and do a lookup whenever you need a connected/managed User.
                            See, for example, this wiki page.




                            1. My DAO's are app scoped.  Maybe they should be relegated to session scope?  I have been considering this for a bit, and was a bit worried about performance; though now that they're SLSB's this shouldn't be as big of a problem.


                            Unless you're really storing session-ish data in your DAOs (in private fields), you probably don't need session-scoped DAOs.  Most of the time an SLSB is fine.



                            2. This EM you pointed me to is conversation scoped, yet I don't want to use conversations for everything (most things are either PAGE/EVENT styled, or session; except the DAOs). 


                            As long as you're not using long-running conversations (@Begin, @End, etc), the conversation scope is pretty similar to the Event scope.  I'd go ahead and use the conversation scope for your entityManager, and page/event/stateless scope for everything else. 





                            I think my answer's on this page:

                            http://www.redhat.com/docs/en-US/JBossEnterpriseApplicationPlatform/4.3.0.cp02fp01/html/SeamReferenceGuide/ch10s03s03.html

                            though, it's still talking about conversation scoped EM.


                            That url gives me a 404.
                            But generally, conversation is exactly the scope you want for a persistence context.



                            Does this make sense?  I can clarify if needed.

                            • 11. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                              meetoblivion

                              Hi Matt,


                              What you wrote does in fact make sense.  I do have a couple of more questions.


                              1. Assuming that I go with the approach of detached entities, what is the best way to retrieve the lazily fetched child entities?  Is it a matter of:


                              List<SomeObject> someObjectList = q.getResultList();
                              (where I retrieve via a separate query).
                              or can I do something like:
                              List<SomeObject> someObjectList = myUser.getSomeObjectList();


                              Obviously I know I can query for it, I'm just wondering if there's any way of pulling a lazy fetch list from an entity that's already been detached.


                              Looking over my application some more, the behavior appears to be more like the detached entity approach, that's why I'm heading that road.  It looks like this issue will only come up when I try to access the User object (since almost everything in my app is user driven).


                              2. Is the conversation scoped EM any different than the TRANSACTION PersistenceContext? 


                              Thanks.

                              • 12. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                                matt.drees

                                John Ament wrote on Dec 02, 2008 13:21:


                                1. Assuming that I go with the approach of detached entities, what is the best way to retrieve the lazily fetched child entities?  Is it a matter of:

                                List<SomeObject> someObjectList = q.getResultList();
                                (where I retrieve via a separate query).
                                or can I do something like:
                                List<SomeObject> someObjectList = myUser.getSomeObjectList();

                                Obviously I know I can query for it, I'm just wondering if there's any way of pulling a lazy fetch list from an entity that's already been detached.


                                No, you can't directly lazy-load a list from a detached entity, so you can't do myUser.getSomeObjectList() by itself.  Like you said, you could use a separate query.  But what might be easier is merging myUser, so something like


                                User myUser = getUserFromSessionOrWherever();
                                User attachedUser = entityManager.merge(myUser);
                                List<SomeObject> someObjectList = myUser.getSomeObjectList();
                                



                                The merge operation does an extra query, but IMO that's not a biggie.




                                2. Is the conversation scoped EM any different than the TRANSACTION PersistenceContext? 


                                Disclaimer: I haven't worked much with transaction scoped persistence contexts.


                                A conversation scoped persistence context starts very near the beginning of a request, and lasts until after the page is rendered (note that this may occur after a redirect).  The ejb-provided transaction scoped persistence context starts and ends with the transaction.  So, how different they are depends on your transaction strategy.  If your transaction is limited to an EJB method boundary which is called in the invoke application phase, then the persistence context won't be open during the render response phase.  This can make you vulnerable to LIEs if you're not careful.


                                Also, if you ever want to commit a transaction, and then after that continue to lazy-load relationships, you'll need to have a persistence context that outlasts the transaction.  This is where a SMPC comes in handy.

                                • 13. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                                  meetoblivion

                                  Hmm just had a chance tonight to look at this some more (guess that's what happens when you've got a real job too).


                                  Looks like merge is throwing a NPE in this case.  I'm using the same @In entityManager.


                                  java.lang.NullPointerException
                                       at org.jboss.seam.persistence.HibernatePersistenceProvider.getSession(HibernatePersistenceProvider.java:355)
                                       at org.jboss.seam.persistence.HibernatePersistenceProvider.getId(HibernatePersistenceProvider.java:163)
                                       at org.jboss.seam.framework.EntityIdentifier.<init>(EntityIdentifier.java:13)
                                       at org.jboss.seam.ui.JpaEntityLoader.createIdentifier(JpaEntityLoader.java:29)
                                       at org.jboss.seam.ui.AbstractEntityLoader.put(AbstractEntityLoader.java:46)
                                       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                                       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                                       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                                       at java.lang.reflect.Method.invoke(Method.java:597)
                                       at org.jboss.seam.util.Reflections.invoke(Reflections.java:22)
                                       at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:31)
                                       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56)
                                       at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:28)
                                       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                                       at org.jboss.seam.transaction.TransactionInterceptor$1.work(TransactionInterceptor.java:40)
                                       at org.jboss.seam.util.Work.workInTransaction(Work.java:47)
                                       at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:34)
                                       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                                       at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44)
                                       at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68)
                                       at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107)
                                       at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:166)
                                       at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:102)
                                       at org.jboss.seam.ui.JpaEntityLoader_$$_javassist_28.put(JpaEntityLoader_$$_javassist_28.java)
                                       at org.jboss.seam.ui.EntityConverter.getAsString(EntityConverter.java:67)
                                       at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getFormattedValue(HtmlBasicRenderer.java:448)
                                       at com.sun.faces.renderkit.html_basic.SelectManyCheckboxListRenderer.renderOption(SelectManyCheckboxListRenderer.java:281)
                                       at com.sun.faces.renderkit.html_basic.SelectManyCheckboxListRenderer.encodeEnd(SelectManyCheckboxListRenderer.java:165)
                                       at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:861)
                                       at org.jboss.seam.ui.util.cdk.RendererBase.renderChild(RendererBase.java:190)
                                       at org.jboss.seam.ui.util.cdk.RendererBase.renderChildren(RendererBase.java:166)
                                       at org.jboss.seam.ui.renderkit.ValidateAllRendererBase.doEncodeChildren(ValidateAllRendererBase.java:33)
                                       at org.jboss.seam.ui.util.cdk.RendererBase.encodeChildren(RendererBase.java:92)
                                       at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
                                       at org.jboss.seam.ui.util.cdk.RendererBase.renderChild(RendererBase.java:186)
                                       at org.jboss.seam.ui.util.cdk.RendererBase.renderChildren(RendererBase.java:166)
                                       at org.jboss.seam.ui.renderkit.DecorateRendererBase.doEncodeChildren(DecorateRendererBase.java:146)
                                       at org.jboss.seam.ui.util.cdk.RendererBase.encodeChildren(RendererBase.java:92)
                                       at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
                                       at org.ajax4jsf.renderkit.RendererBase.renderChild(RendererBase.java:282)
                                       at org.ajax4jsf.renderkit.RendererBase.renderChildren(RendererBase.java:262)
                                       at org.richfaces.renderkit.html.PanelRenderer.doEncodeChildren(PanelRenderer.java:220)
                                       at org.richfaces.renderkit.html.PanelRenderer.doEncodeChildren(PanelRenderer.java:215)
                                       at org.ajax4jsf.renderkit.RendererBase.encodeChildren(RendererBase.java:121)
                                       at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
                                       at org.jboss.seam.ui.util.cdk.RendererBase.renderChild(RendererBase.java:186)
                                       at org.jboss.seam.ui.util.cdk.RendererBase.renderChildren(RendererBase.java:166)
                                       at org.jboss.seam.ui.renderkit.ValidateAllRendererBase.doEncodeChildren(ValidateAllRendererBase.java:33)
                                       at org.jboss.seam.ui.util.cdk.RendererBase.encodeChildren(RendererBase.java:92)
                                       at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
                                       at javax.faces.component.UIComponent.encodeAll(UIComponent.java:936)
                                       at javax.faces.render.Renderer.encodeChildren(Renderer.java:148)
                                       at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
                                       at javax.faces.component.UIComponent.encodeAll(UIComponent.java:936)
                                       at javax.faces.component.UIComponent.encodeAll(UIComponent.java:942)
                                       at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:592)
                                       at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:108)
                                       at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:196)
                                       at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:109)
                                       at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
                                       at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
                                       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
                                       at org.jboss.seam.web.RewriteFilter.doFilter(RewriteFilter.java:63)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.IdentityFilter.doFilter(IdentityFilter.java:38)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:90)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:177)
                                       at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
                                       at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:380)
                                       at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:507)
                                       at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:56)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:51)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
                                       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
                                       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
                                       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:432)
                                       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
                                       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                                       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                                       at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
                                       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                                       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
                                       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
                                       at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
                                       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
                                       at java.lang.Thread.run(Thread.java:619)

                                  • 14. Re: SFSB, Extended PersistenceContext, and ApplicationScope - OutOfMemoryError ?
                                    matt.drees

                                    No, if you look at the stacktrace, it's not merge() that's throwing an NPE.  It's an EntityConverter in your view that is causing that.  From looking through the source code, it looks like JpaEntityLoader is looking up the persistence context, but is getting null.
                                    Is your SMPC named entityManager, exactly?  If not, this could be your problem
                                    If it is named entityManager (or you've otherwise correctly configured EntityLoader to use the name of your SMPC), then I'm not sure what's up.  You might have a throw a breakpoint in there and see why the look-up of the persistence context is null.

                                    1 2 Previous Next