10 Replies Latest reply on Dec 15, 2011 2:27 AM by Sertac Anadollu

    ViewScoped and seam managed persistence

    Andrew Wheeler Newbie

      I use seam managed persistence context (SMPC) as described in the Seam persistence module. I use a mix of conversation scoped and view scoped pages. When using a view scoped page it is not possible to use optimistic transactions. The SMPC is conversation scoped which is not promoted to long running at the end of the request so is lost (At least I get manual flush!) This leads to performing merge on every request to the backing bean to avoid Lazy initialization exceptions (think multiple ajax requests and eventual submit).


      I was wondering if there is a way to use SMPC with view scoped context? If it is possible, is it a good design practice?


      I'm not too bothered, just curious, as my framework re-merges backing bean entities if not in the current context so I don't have merge statements everywhere.


        • 1. Re: ViewScoped and seam managed persistence
          Jason Porter Master

          Certainly. Simply change @ConversationScoped to @ViewScoped. If it doesn't work, please create a bug in Seam Persistence.


          There isn't anything wrong with that design at all :)

          • 2. Re: ViewScoped and seam managed persistence
            Andrew Wheeler Newbie

            Thanks Jason. I thought someone would say that. What then happens to my Conversation scoped pages? Probably cause a bit of havoc when navigating from one page to the next within the same conversation.


            I was going to have a crack at adding two declarations, with the second for the view scoped annotation as:



                 
            @ExtensionManaged
            @Produces 
            @PersistenceUnit
            @ViewScoped
            EntityManagerFactory viewScopedScoped;     
            



            Of course that does not work as javax.faces.bean.ViewScoped is not permitted in that context. Perhaps a rewrite with a custom seam annotation such as @PersistenceScope(ViewScoped) or @PersistenceScope(ConversationScoped)

            • 3. Re: ViewScoped and seam managed persistence
              Andrew Wheeler Newbie

              Added a JIRA


              https://issues.jboss.org/browse/SEAMPERSIST-65


              If anyone else is interested please post some feedback.

              • 4. Re: ViewScoped and seam managed persistence
                Jason Porter Master

                I actually like the idea of adding the @PersistenceScope(Class<? extends Annotation>) I think it helps clear things up, or maybe call it @PersistenceUnitScopedAs thoughts?

                • 5. Re: ViewScoped and seam managed persistence
                  Andrew Wheeler Newbie

                  The issue I raised has been closed (by Stuart) as it is a fault with ViewScoped annotation. Or, more explicitly with seam faces re-using the ViewScoped annotation from javax.faces.bean package.


                  One simple suggestion is for the seam faces team to create their own annotation as they're the ones implementing the scope. You could even call it @PageScoped to be different.


                  Do you think I should re-raise the JIRA for faces?

                  • 6. Re: ViewScoped and seam managed persistence
                    Brian Leathem Master

                    Problems with the viewscope are tracked via:
                    https://issues.jboss.org/browse/SEAMFACES-44


                    Feel free to add a comment to the issue.

                    • 7. Re: ViewScoped and seam managed persistence
                      Anthony Ogier Newbie

                      You can also write your own @ViewScoped :


                      @Inherited
                      @javax.faces.bean.ViewScoped
                      @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
                      @Retention(RetentionPolicy.RUNTIME)
                      public @interface ViewScoped {}



                      And use it on your EntityManagerFactory. My problem now with this is that I got some

                      org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

                      problems with my @Version Entities... and if I use the @ConversationScoped it doesn't flush my modifications in the conversation ! I think I'll open a JIRA for that last problem...

                      • 8. Re: ViewScoped and seam managed persistence
                        Jason Porter Master

                        Anthony, are you sure you're not in MANUAL flush mode?

                        • 9. Re: ViewScoped and seam managed persistence
                          Andrew Wheeler Newbie

                          I'm sure the real problem is that you can't mix SMPC between view scoped and conversation scoped. If you declare the EntityManagerFactory as view scoped then the SMPC will be destroyed if you move between pages in a conversation (hence no flush!).


                          Every page request starts a conversation scope - unless it is promoted to long running it is destroyed. Declaring the EntityManagerFactory as conversation scoped means request scoped and view scoped pages have the benefit of SMPC. In this case an open session in view. But this is really only the case for the first request of a view scoped page. Subsequent requests (via ajax or submit) will mean the backing entities are disconnected from the previous session.


                          I think seam needs an alternative annotation like I suggested before. Something like @PersistenceScope(ViewScope, ConversationScope) would mean the SMPC can be stored in either context. In fact the annotation really specifies an ordered list of scopes in which it should be stored. So in this case the SMPC would be stored in the view scope if available otherwise the conversation scope.

                          • 10. Re: ViewScoped and seam managed persistence
                            Sertac Anadollu Newbie


                            Qualifier



                            @Qualifier
                            @Target({ TYPE, METHOD, PARAMETER, FIELD })
                            @Retention(RUNTIME)
                            @Documented
                            public @interface ViewScopedEntityManager
                            {
                            
                            }
                            


                            Producer





                            @Named
                            @ViewScoped
                            public class ViewScopedDataSourceProducer implements Serializable
                            {
                            
                               private static final long serialVersionUID = -2825518020404347295L;
                            
                               @PersistenceUnit
                               EntityManagerFactory emf;
                               
                               private EntityManager entityManager;
                               
                               
                               @PostConstruct
                               public void init(){
                                  entityManager = emf.createEntityManager();
                               }
                               
                               @Produces
                               @ViewScopedEntityManager
                               public EntityManager getEntityManager()
                               {
                                  return entityManager;
                               }   
                            }
                            
                            



                            And use it anywhere like these




                            @Inject
                            @ViewScopedEntityManager
                            EntityManager entityManager;
                            





                            Anatolian