1 2 3 4 Previous Next 59 Replies Latest reply on Jun 11, 2009 1:35 PM by luxspes Go to original post
      • 45. Re: Injection into entity beans

        Arbi Sookazian wrote on Jun 02, 2009 19:39:


        I never got a technical explanation (note the closedness of the JCP in this respect) from Mike Keith regarding why he was opposed to MANUAL flush, most likely a political issue, who knows. 



        I think that the problem is that we do not carefully try to understand the perspective from the other people, we just do not place on their shoes, for example, back when I used EOF I never had this kind of problems, I had others, but transactions were plain easy, all I had to do:


        List customers = editingContext.fetch(someQuery)
        List merchandises = editingContext.fetch(someQuery)
        
        Customer customer = customers[0];
        Customer merchandise = merchandise[0];
        
        Order order =editingContext.create(Order.class);
        order.setCustomer(customer);
        order.getMerchandises().add(merchandise)
        
        editingContext.saveAllChanges();
        



        And that was it. just a call to saveAllChanges and things were persisted in to the database, I did not had to worry about JDBC, JTA, transaction boundaries, the enditingContext handled it all (even offering nestedEditingContext) and this was more than 10 years ago. Basically no transaction was commited until saveAllChanges, all other queries were done in readonly transparent-transactions why Hibernate (or JPA) can not work that way? why I can not just query stuff in a transactionless (from the JPA user perspective) way and only worry about transactions when I commit? When I tried to explaing FlushMode.MANUAL to the EclipseLink guys they told me EclipseLink would do it (but I am not sure if they actually understood what I was asking for) they told me:



        douglas.clarke@xxxxxxxxxx (Doug Clarke) wrote:

        Making changes within a entity manager acting as an extended persistence context where the complete set of conversation changes are committed in a single transaction does make sense and is very common. JPA supports this through its support for joining of an extended persistence context with a transaction.



        So... they seem to believe it is possible to avoid having a an open transaction during user think time using this support for extended persistence context... Are they crazy? or.. what are they talking about?




        • 46. Re: Injection into entity beans
          hajdi

          @Stateful @ConversationScoped
          public class OrderConversation {
          
              @PersistenceContext(type=EXTENDED) EntityManager em;
              @Current Conversation conversation;
              private Order order;
          
              public Order getOrder() { return order; }
          
              public void load(int id) {
                  conversation.begin();
                  em.setFlushMode(MANUAL);
                  order = em.get(User.class, id);
              }
          
              public void addLineItemByAjax(Product product, int quantity) {
                  order.addLineItem( new LineItem(product, quantity) );
              }
          
              public void removeLineItemByAjax(LineItem li) {
                  order.removeLineItem(li);
              }
          
              public void commitAllChanges() {
                  em.flush();
                  conversation.end();
              }
          
          }



          All changes are written to the database atomically at the end of the conversation. What's not to get?



          Yes, from my point of view MANUAL flush mode is very handy and just makes sense in JPA. Gavin are you aware of any discussions in EG to add it to JPA 2?

          • 47. Re: Injection into entity beans
            gavin.king

            What Doug is trying to say is that you can try to do it this way:


            @Stateful @ConversationScoped
            @Transaction(NOT_SUPPORTED)
            public class OrderConversation {
            
                @PersistenceContext(type=EXTENDED) EntityManager em;
                @Current Conversation conversation;
                private Order order;
            
                public Order getOrder() { return order; }
            
                public void load(int id) {
                    conversation.begin();
                    order = em.get(User.class, id);
                }
            
                public void addLineItemByAjax(Product product, int quantity) {
                    order.addLineItem( new LineItem(product, quantity) );
                }
            
                public void removeLineItemByAjax(LineItem li) {
                    order.removeLineItem(li);
                }
            
                @Transaction(REQUIRED)
                public void commitAllChanges() {
                    em.isOpen();
                    conversation.end();
                }
            
            }



            Now, personally, I find this amazingly unnatural. As a side-effect of the @Transaction(REQUIRED) declaration and call to em.isOpen() on commitAllChanges(), the persistence context gets flushed and all the work you did outside of transactions in previous method calls gets committed.


            But the bigger problems are:



            1. Persistence context propagation is now broken - if I call a stateless session bean, the persistence context does not propagate, so any work it does is either committed non-atomically (i.e. immediately) or not at all. Work done by stateless session beans is not able to form part of the atomic long-running optimistic transaction.

            2. I now can't perform my reads inside JTA transactions. The reads have to happen with autocommit on, which takes away my ability to ask for transaction isolation. Now, sure, the overarching optimistic transaction is not going to have the isolation semantics of a pessimistic transaction, but now I can't even get repeatable reads inside the individual requests.


            • 48. Re: Injection into entity beans
              gavin.king

              Rafal Hajdacki wrote on Jun 02, 2009 21:09:

              Yes, from my point of view MANUAL flush mode is very handy and just makes sense in JPA. Gavin are you aware of any discussions in EG to add it to JPA 2?


              No, it won't be in JPA2. Perhaps in JPA 2.1 I might be able to talk people into supporting some kind of compromise solution using something like this:


              @Stateful @ConversationScoped
              @Transaction(OPTIMISTIC)
              public class OrderConversation {
              
                  @PersistenceContext(type=EXTENDED) EntityManager em;
                  @Current Conversation conversation;
                  @Current OptimisticTransaction optimisticTransaction;
                  private Order order;
              
                  public Order getOrder() { return order; }
              
                  public void load(int id) {
                      conversation.begin();
                      optimisticTransaction.begin();
                      order = em.get(User.class, id);
                  }
              
                  public void addLineItemByAjax(Product product, int quantity) {
                      order.addLineItem( new LineItem(product, quantity) );
                  }
              
                  public void removeLineItemByAjax(LineItem li) {
                      order.removeLineItem(li);
                  }
              
                  public void commitAllChanges() {
                      optimisticTransaction.commit();
                      conversation.end();
                  }
              
              }



              It doesn't quite give you everything you have with FlushMode.NEVER but it might be acceptable to Oracle who, as far as I know, are the only folks objecting to this feature.

              • 49. Re: Injection into entity beans

                Gavin King wrote on Jun 02, 2009 22:17:





                So, basically your initial example is not really an example on what is so good about FlushMode.MANUAL (because there is a counter example, you wrote it yourself) that shows that theres is an alternative standard way of doing the same thing... So I ask again, can you show me an example that actually shows how the persistence context propagation gets broken by not using FlushMode.MANUAL? An example that could be shown to someone in the EclipseLink team with the message: This is impossible to do in EclipseLink because yo do not have FlushMode.MANUAL and that would leave them baffled.



                Now, personally, I find this amazingly unnatural. As a side-effect of the @Transaction(REQUIRED) declaration and call to em.isOpen() on commitAllChanges(), the persistence context gets flushed and all the work you did outside of transactions in previous method calls gets committed.


                Ok, so, FlushMode.MANUAL is a shortcut to to basically the same thing an extended persistence context do? Nice but, shouldnt we prefere the standard solution (like Seam did by preferring JSF over Wicket ;-) )




                But the bigger problems are:

                Persistence context propagation is now broken - if I call a stateless session bean, the persistence context does not propagate, so any work it does is either committed non-atomically (i.e. immediately) or not at all. Work done by stateless session beans is not able to form part of the atomic long-running optimistic transaction.



                And why is that? Does this mean that extended persistence contexts can only be used in Stateful EJBs? and why it can not be fixed by altering the way extended persistence contexts work but without creating FlushType.MANUAL? What do the guys of EclipseLink do when someone reports this as a bug or as requested feature? Has anyone tried that? Does this mean that extended persistence contexts are actually a feature of stateful EJBs and not a feature usable from Seam POJOs(Specially not the stateless ones)  or from a JSE application? )



                I now can't perform my reads inside JTA transactions. The reads have to happen with autocommit on, which takes away my ability to ask for transaction isolation. Now, sure, the overarching optimistic transaction is not going to have the isolation semantics of a pessimistic transaction, but now I can't even get repeatable reads inside the individual requests.



                I also said something similar to the EclipseLink guys, and this was the answer. If I am going to get inconsistencies between requests, maybe I do not care about getting them between query calls... if that is the case... does that mean that FlushMode.MANUAL is useless for me?

                • 50. Re: Injection into entity beans
                  gavin.king

                  So I ask again, can you show me an example that actually shows how the persistence context propagation gets broken by not using FlushMode.MANUAL? An example that could be shown to someone in the EclipseLink team with the message: This is impossible to do in EclipseLink because yo do not have FlushMode.MANUAL and that would leave them baffled.

                  Huh, I just told you what can't be done, I'm sure you have enough knowledge of this stuff to figure out the rest yourself. It's not my job to write examples to help the EclipseLink team improve their product!


                  But here's a starting point for the kind of things I'm thinking about:


                  @Stateful @ConversationScoped
                  public class OrderConversation {
                  
                      @Current OrderDao orderDao;
                      @Current ProductDao productDao;
                      @Current Conversation conversation;
                      private Order order;
                  
                      public Order getOrder() { return order; }
                  
                      public void load(int id) {
                          conversation.begin();
                          em.setFlushMode(MANUAL);
                          order = orderDao.find(id);
                      }
                  
                      public void addLineItemByAjax(in productId, int quantity) {
                          Product product = productDao.find(productId);
                          order.addLineItem( new LineItem(product, quantity) );
                      }
                  
                      public void removeLineItemByAjax(LineItem li) {
                          order.removeLineItem(li);
                      }
                  
                      public void commitAllChanges() {
                          em.flush();
                          conversation.end();
                      }
                  
                  }
                  
                  @Stateless 
                  OrderDao {
                      @PersistenceContext EntityManager em;
                          
                      public Order find(int id) {
                          return em.find(Order.class, id);
                      }
                      
                  }
                  
                  @Stateless 
                  ProductDao {
                      @PersistenceContext EntityManager em;
                          
                      public Product find(int id) {
                          return em.find(Product.class, id);
                      }
                          
                  }



                  In this example, the persistence context propagates to the XxxxxDaos, so the Order and the Product belong to the same persistence context, and remain attached to it for the entire optimistic transaction. If you try to use Transaction(NOT_SUPPORTED), this will not be the case. The Order will not be attached when commitAllChanges() is called, and the LineItem changes will not be persisted. I don't think you will be able to rewrite this example without FlushMode.MANUAL.

                  • 51. Re: Injection into entity beans
                    gavin.king

                    Ok, so, FlushMode.MANUAL is a shortcut to to basically the same thing an extended persistence context do?

                    No. I explained that to you. Please try reading and understanding before arguing. Geez.



                    And why is that? Does this mean that extended persistence contexts can only be used in Stateful EJBs?

                    You can find the answer to this question and more in the JPA 1.0 specification.



                    and why it can not be fixed by altering the way extended persistence contexts work but without creating FlushType.MANUAL?

                    Whatever change you would make would be more or less functionally equivalent to FlushMode.MANUAL. Of course you could call it FooBar.IM_BEING_REALLY_DENSE if you prefer.



                    What do the guys of EclipseLink do when someone reports this as a bug or as requested feature? Has anyone tried that?

                    I have no idea. Why are you asking me what EclipseLink users do?



                    Does this mean that extended persistence contexts are actually a feature of stateful EJBs and not a feature usable from Seam POJOs(Specially not the stateless ones) or from a JSE application?

                    You can find the answers to these questions and more in the JPA 1.0 specification and the Seam documentation.



                    I also said something similar to the EclipseLink guys, and this was the answer. If I am going to get inconsistencies between requests, maybe I do not care about getting them between query calls... if that is the case... does that mean that FlushMode.MANUAL is useless for me?

                    I just told you about the problem with persisence context propagation but you decided to deliberately not understand what I was explaining.

                    • 52. Re: Injection into entity beans
                      gavin.king

                      Perhaps in JPA 2.1 I might be able to talk people into supporting some kind of compromise solution using something like this

                      Note that I'm not advocating that this is a great solution. I don't think it's better to introduce a whole new kind of transaction notion in EE and then have to define its demarcation and propagation rules than to introduce a new FlushMode. The new FlushMode is a far simpler solution.

                      • 53. Re: Injection into entity beans

                        Gavin King wrote on Jun 02, 2009 23:55:



                        What do the guys of EclipseLink do when someone reports this as a bug or as requested feature? Has anyone tried that?

                        I have no idea. Why are you asking me what EclipseLink users do?


                        Well, it seems to me like it would be a nice idea to make those Oracle guys accept FlushMode.MANUAL in to the JPA spec, and I way to that would be to submit a bug in to EclipseLink bugtracker, asking for a way to do something that can only be done with FlushMode.MANUAL, that way they would be forced to implement a comparable solution (or even just accept to add FlushMode.MANUAL to the spec). That is, of course, if they do not dismiss bug without reading and understanding before rejecting them. Geez. :-P




                        I just told you about the problem with persistence context propagation but you decided to deliberately not understand what I was explaining.



                        Yes you told me about the problem with persisence context propagation, but I was hoping for a concrete example, you just told me it breaks but did not explain me why it breaks. If you have a link or know a book with a guide that explains why it breaks, that would be good enough for me, but it really be great if you could explain it and provide an example.


                        Please do not get me wrong, I really appreciate that you take time to answer this questions in this forum, I know you are one of the greatest experts in this stuff, but sometimes you do exactly what you are accusing me of doing, you just start arguing without reading carefully and without trying to see it from the POV of someone without all your knowledge.


                        OTOH maybe its my Karma from all the times I have been dismissive with people with less knowledge than me... :'(

                        • 54. Re: Injection into entity beans

                          Oh, I see that you did provide an example, see, I knew you could no really be a bad guy :-D

                          • 55. Re: Injection into entity beans

                            I posted a link to this discussion in the EclipseLink mailing list, and got this answer:




                            James Sutherland wrote



                            Not sure I understand but you seem to want to ignore the container JPA transactions correct?



                            Normally when using EJB any work you do inside a JTA transaction will be committed when that JTA transaction commits, normally at the end of the SessionBean method, or when the JTA transaction is committed explicitly.  You seem to want your EntityManager transaction to span multiple server calls, and multiple JTA transactions.  For this I think you would want to use an application managed EntityManager.  Either do not use JTA at all, just use EntityManager transactions and commit whenever you desire, or use joinTransaction() when you wish to commit to commit along with the active JTA transaction.




                            So, it seems that an application managed EntityManager can be used to achive conversational behavior... and all without support of FlushMode.MANUAL... If course asked him in return:




                            Francisco Peredo wrote


                            And this application managed EntityManager will give this conversational handling of transactions even when used inside @Stateless EJBs? and if it can be used on @Stateless EJBS... Can you offer any insights on why Gavin thinks it can not be used with @Stateless EJBS? (Or am I plain interpreting him wrong?)



                            But he still has not responded...


                            What I would really like to understand is if FlushMode.MANUAL actually makes it possible to integrate conversational behavior with persistence in a way that is really impossible to achieve without it, or it is more like a much more convenient way to do things that are possible anyway.

                            • 56. Re: Injection into entity beans
                              gavin.king

                              There is no persistence context propagation for application-managed EntityManagers, of course! Nor is there when there is no JTA transaction active.

                              • 57. Re: Injection into entity beans
                                gonorrhea

                                You seem to want your EntityManager transaction to span multiple server calls, and multiple JTA transactions.

                                Isn't that what extended container-managed PCs were designed to handle?  They are scoped to the lifetime of a SFSB, not just one method/tx.  And the SMPC in Seam is conversation-scoped, thus you can use it for multiple SFSBs or JavaBeans, not just one.


                                I don't understand why he's recommending application-managed EntityManagers.  Typically it's recommended to use container-managed EntityManagers in JEE envmts.


                                In any event, GKing is correct as per section 5.7 of JPA 2.0 spec:



                                The extended persistence context obtained from the application-managed entity manager is a stand-alone persistence context—it is not propagated with the transaction.

                                However, the spec does state:



                                An application-managed entity manager may be either a JTA entity manager or a resource-local entity manager.

                                Plus, who wants to do trivial stuff like em.close();?  Isn't that what the container is for???

                                • 58. Re: Injection into entity beans

                                  Arbi Sookazian wrote on Jun 11, 2009 01:54:


                                  You seem to want your EntityManager transaction to span multiple server calls, and multiple JTA transactions.

                                  Isn't that what extended container-managed PCs were designed to handle?  They are scoped to the lifetime of a SFSB, not just one method/tx.  And the SMPC in Seam is conversation-scoped, thus you can use it for multiple SFSBs or JavaBeans, not just one.

                                  I don't understand why he's recommending application-managed EntityManagers.  Typically it's recommended to use container-managed EntityManagers in JEE envmts.


                                  Mmmm, I wonder what is the real difference between a container-managed EntityManager and an application managed one, after all, WebBeans should allow me to store any object at the conversation context... why shouldn't it allow me to store an application managed EntityManager ?. And use EntityManager transactions to commit when I desire to do so. It of course wouldn't care about JTA, but isn't FlushMode.MANUAL  a way to ignore JTA commits until we decide to not ignore them anymore? And for that, according to Sutherland I can use joinTransaction().


                                  I am not saying this is a better solution than FlushMode.MANUAL, it does sound more cumbersome, I am just saying that from a practical POV it could achieve the same effect.



                                  In any event, GKing is correct as per section 5.7 of JPA 2.0 spec:

                                  The extended persistence context obtained from the application-managed entity manager is a stand-alone persistence context—it is not propagated with the transaction.

                                  However, the spec does state:

                                  An application-managed entity manager may be either a JTA entity manager or a resource-local entity manager.

                                  Plus, who wants to do trivial stuff like em.close();?  Isn't that what the container is for???


                                  Of course nobody wants to deal with that stuff, and of course FlushMode.MANUAL in combination with Seam is a lot more comfortable than doing what the EclipseLink guys says is the standard way of dealing with this problem, that is not what I am discussing here, what I want to understand (again) if it is plain impossible to do this without FlushMode.MANUAL, or if FlushMode.MANUAL is a convenience api sugar (and I love api sugar, but I like to know when I am using it)


                                  For example what if I where to write (wouldn't this give me an application managed entity manager that would work with its own entitymanager transactions until I decided to join the JTA transaction using joinTransaction() and effectively (but cumbersomely) emulate FlushMode.MANUAL?):


                                  
                                  @Produces @ConversationScoped 
                                  public EntityManager getPaymentStrategy() {
                                   return EntityManagerFactory.createEntityManager();  
                                  }
                                  
                                  



                                  And then inject the conversation-scoped PC like this:


                                  @Current EntityManager theConversationScopedEntityManager;
                                  

                                  • 59. Re: Injection into entity beans

                                    Sorry, made a copy & paste mistake (posted getPaymentStrategy instead of getTheConversationScopedEntityManager), here comes again:



                                    For example what if I where to write (wouldn't this give me an application managed entity manager that would work with its own entitymanager transactions until I decided to join the JTA transaction using joinTransaction() and effectively (but cumbersomely) emulate FlushMode.MANUAL?):


                                    @Produces @ConversationScoped 
                                    public EntityManager getTheConversationScopedEntityManager() {
                                     return EntityManagerFactory.createEntityManager();  
                                    }
                                    



                                    And then inject the conversation-scoped PC like this:


                                    @Current EntityManager theConversationScopedEntityManager;
                                    

                                    1 2 3 4 Previous Next