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

        Rafal Hajdacki wrote on Jun 01, 2009 22:45:



        This is one thing I agree on with GKing and one main reason I liked Seam from the beginning (no forced layering and patterns like Struts/EJB2.x!)


        Me too. But from my point of view Gavin is insisting on this last artificial layer. :-)



        What do you mean exactly by last artificial layer?  Does that comment refer to DAO layer and/or entity class?


        GKing is most likely not the only one in the EG's insisting on this IMO.


        Most likely there is some agreement from Linda DeMichiel and Mike Keith as well (I'm just guessing so shoot me if I'm wrong :).


        It sounds like your intent here is to somehow collapse this last artificial layer into the entity class and therefore take the JPA entity class back to what it was in EJB2.x as an entity bean which was more similar to Active Record pattern.


        If you add injection and domain logic to your entity class, will it still be easily tested outside the EJB container?  This was one of the main problems with EJB2.x and prior...


        • 31. Re: Injection into entity beans
          hajdi

          Arbi Sookazian wrote on Jun 01, 2009 22:38:


          CBauer presented an auditing solution IIRC in Bauer/King book.  Also........

          The Envers project aims to enable easy auditing/versioning of persistent classes. All that you have to do is annotate your persistent class or some of its properties, that you want to audit, with @Audited. For each audited entity, a table will be created, which will hold the history of changes made to the entity. You can then retrieve and query historical data without much effort.

          source: http://www.jboss.org/envers/

          So what is it about one of these two solutions that is insufficient for your logging/auditing use case?

          Do you need one audit table for all entities or one audit table for each entity?



          This approach is perfectly fine for simple auditing that just audits database operations. Unfortunately auditing in many cases is more complex then that. Imagine that auditing operations are use case specific and take different number of arguments for each use case. These arguments are not always related to changed entity and can't be provide in a declarative way. Add that it has to be plugabble to support different outputs. How would you handle such a use case?

          • 32. Re: Injection into entity beans
            hajdi



            This is one thing I agree on with GKing and one main reason I liked Seam from the beginning (no forced layering and patterns like Struts/EJB2.x!)

            Me too. But from my point of view Gavin is insisting on this last artificial layer. :-)

            What do you mean exactly by last artificial layer?  Does that comment refer to DAO layer and/or entity class?


            This last layer are entities that shouldn't access other objects. For me they are just objects that have wider scope than application scoped beans and it is up to domain logic design to decided what should access what.



            GKing is most likely not the only one in the EG's insisting on this IMO.


            I am sure he is not the only one. From my experience I would even say that proponents of injection into entities are the minority. But I may be wrong. At least most applications I worked with doesn't use this kind of injection. :-)



            Most likely there is some agreement from Linda DeMichiel and Mike Keith as well (I'm just guessing so shoot me if I'm wrong :).


            I would really like to know all the arguments against this approach. I am not here to convince others to my view. I want to validate whether my view is valid. I haven't heard convincing argument yet though. Or maybe I am missing something.



            It sounds like your intent here is to somehow collapse this last artificial layer into the entity class and therefore take the JPA entity class back to what it was in EJB2.x as an entity bean which was more similar to Active Record pattern.


            No, I just want to treat entity as a real object that can access other objects using DI. :-)



            If you add injection and domain logic to your entity class, will it still be easily tested outside the EJB container?
            This was one of the main problems with EJB2.x and prior...


            Are your service objects testable outside EJB container? From my perspective entities can depend on objects located in other context. DI should provide these dependencies. Entity shouldn't know how they are provided. In test you can provide them manually or use DI framework for that. Similar to service objects.

            • 33. Re: Injection into entity beans
              gonorrhea

              Rafal Hajdacki wrote on Jun 01, 2009 23:00:



              Arbi Sookazian wrote on Jun 01, 2009 22:38:


              CBauer presented an auditing solution IIRC in Bauer/King book.  Also........

              The Envers project aims to enable easy auditing/versioning of persistent classes. All that you have to do is annotate your persistent class or some of its properties, that you want to audit, with @Audited. For each audited entity, a table will be created, which will hold the history of changes made to the entity. You can then retrieve and query historical data without much effort.

              source: http://www.jboss.org/envers/

              So what is it about one of these two solutions that is insufficient for your logging/auditing use case?

              Do you need one audit table for all entities or one audit table for each entity?



              This approach is perfectly fine for simple auditing that just audits database operations. Unfortunately auditing in many cases is more complex then that. Imagine that auditing operations are use case specific and take different number of arguments for each use case. These arguments are not always related to changed entity and can't be provide in a declarative way. Add that it has to be plugabble to support different outputs. How would you handle such a use case?



              Well unfortunatley, that's most likely not a typical use case.  Which reminds me of my attempt a few months back (and GKing is well aware of this) to convince the JPA 2.0 EG regarding MANUAL flushMode as follows:



              Regarding section 3.6.2 of JPA 2.0 EDR spec, the proposal is to add a
              MANUAL value and associated semantics in related parts of the spec to
              FlushModeType enum which currently only supports COMMIT and AUTO (since
              JPA 1.0)

              Mike Keith vehemently opposed.  In fact, JPA 2.0 AFAIK does not support stored procs (Hibernate does).


              My point is this:  these outlying spec requests and/or use cases may not be seriously considered.


              The JCP is inundated with technical and political problems (the latter is unfortunate) and what is even more unfortunate is that you should be able to discuss this topic and other JSR/JCP related topics freely on discussion boards/forums sponsored by Sun but that's not currently available AFAIK.

              • 34. Re: Injection into entity beans

                Arbi Sookazian wrote on Jun 01, 2009 06:44:



                But if you really dislike anemic models, then use RoR or similar.


                AFAIK RoR is as anemic (or more) than @Entities, if you really do not like anemic models, use Apple EOF or Cayenne both of them help you create an architecture where the business logic is inside your entities, an approach completly different from the ActiveRecord one.




                  Or find a way to integrate that into your JEE apps.  Hey, at least the DTO pattern is now an anti-pattern in EJB3...


                Is it? We still need them.



                My concern is not so much the anemic domain problem as much as when will OODBMS and JEE integration become a JSR so we don't need to use ORM anymore.  RDBMS has been around since the 70's, no?  I know a lot of corporations are using RDBMS but finally they will be phased out with new technology like OODBMS.  Ted Neward has blogged about the OODBMS topic a lot.


                Many have tried that approach, and it has failed, specially performance wise, I do not think that the future are OODBMS, I think the future, if we are lucky, will be when we recognize  that current RDBMS are not really relational, and what we dislike about them is not that they have relational limitations, what we dislike is that SQL is full of flaws, and we really  need is a TRDBMs database with a truly relational language.

                • 35. Re: Injection into entity beans

                  Arbi Sookazian wrote on Jun 01, 2009 07:59:



                  I prefer not to have business logic in my entity classes.



                  Then you like to create Anemic Domain Models




                  But I guess the argument is, if for some reason we need to add business logic to entity class, then we may need injections?



                  Well, in some architectures/frameworks, the entity class is known as business object, so, it makes sense that the business objects has the business logic inside it.




                  But why do you need to have the biz logic in the entity class in the first place?  What's wrong with separation of concerns and doing the biz logic in a JavaBean or EJB?




                  There is nothing wrong.. if you like Anemic Domain Models




                  Or what about allowing DI in entity classes only via XML, not annotations?

                  How much do you really gain by adding biz logic methods to entity class?  Perhaps you won't have to repeat code in multiple business components (DRY principle) if it's already a method in the entity class...



                  Think for example that you want all the purchases for a client, with an ORM, you tipically get them using client.getPurchases(); Now let say you want all the purchases in year 2000.... Does it make sense to be able to write: client.getPurchasesFromYear(2000); But you can not do that, because there is no way to inject the entityManager (or the purchases DAO) in to the client entity. So you end up with 2 very different ways of querying stuff, and in my experience you end up needing to query for the purchases of a client using may different filters (by year, between dates, by total cost, etc, etc). If you can ot write those queries as methods for the customer... then you will have to do that on a DAO (and if you use DAOs, then you are creating an Anemic Domain Model)




                  Overall, I'm siding with GKing on this one until somebody provides a concrete example of why/when you'd need DI in entity classes and what the gain/advantage is...


                  Take a look at this presentation Make Roles Explicit. Now think how convenient is to have IoC for the time when you need to change the implementation of a particular role to new, more efficient one, or to a new persistence service. That is why it would be really nice to have IoC on entities (it is not that it can not be done without it, we can do with plain JDBC anything that can be done with JPA, it is that it would be a lot more convenient)


                  • 36. Re: Injection into entity beans
                    genman

                    There wouldn't any difficulty with wrapping the JPA EntityManager with your own that did injection. Actually sounds rather trivial to do with the SPI classes.


                    I think to win people over you should show some examples of this in practice.

                    • 37. Re: Injection into entity beans

                      Arbi Sookazian wrote on Jun 02, 2009 00:22:


                      Well unfortunatley, that's most likely not a typical use case. 



                      Well, what is typical and what is not is very relative...and since Envers is pretty new I guess that Rafal approach is more common... specially since AFAIK Envers is Hibernate specific...




                      Which reminds me of my attempt a few months back (and GKing is well aware of this) to convince the JPA 2.0 EG regarding MANUAL flushMode as follows:

                      Regarding section 3.6.2 of JPA 2.0 EDR spec, the proposal is to add a
                      MANUAL value and associated semantics in related parts of the spec to
                      FlushModeType enum which currently only supports COMMIT and AUTO (since
                      JPA 1.0)


                      Mike Keith vehemently opposed.  In fact, JPA 2.0 AFAIK does not support stored procs (Hibernate does).



                      I do not see the relationship between MANUAL flushMode , and Injection into entity beans, but I do have a hard time understanding why MANUAL is needed... I also tried to convince the EclipseLink team to help me find a way to emulate FlushMode.MANUAL, to migrate to EclipseLink and avoid this hibernate bug, and take advantage of EclipseLink nested units of work (that are IMO a good match for nested conversations), but I end up convinced there was no real reason to have FlushMode.MANUAL (it would be nice to have a code example explaining what is so good about FlushMode.MANUAL, because I really do not get it) .




                      My point is this:  these outlying spec requests and/or use cases may not be seriously considered.

                      The JCP is inundated with technical and political problems (the latter is unfortunate) and what is even more unfortunate is that you should be able to discuss this topic and other JSR/JCP related topics freely on discussion boards/forums sponsored by Sun but that's not currently available AFAIK.


                      Yes, I agree 100% with you that we should have discussion boards/forums sponsored by Sun to discuss this kind of things, (maybe nabble will help with that? or maybe now that Sun is part of Oracle there will be a section for that in oracle forums?). I hope there be a way to ask Oracle for that.

                      • 38. Re: Injection into entity beans

                        Elias Ross wrote on Jun 02, 2009 08:32:


                        There wouldn't any difficulty with wrapping the JPA EntityManager with your own that did injection. Actually sounds rather trivial to do with the SPI classes.

                        I think to win people over you should show some examples of this in practice.



                        Examples... like this presentation? ;)

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

                          it would be nice to have a code example explaining what is so good about FlushMode.MANUAL, because I really do not get it

                          @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?

                          • 40. Re: Injection into entity beans

                            And Seam could be adapted to achieve the same affect with em.setFlushMode(COMMIT); or not?


                            em.setFlushMode(MANUAL); delays flushing until em.flush();, em.setFlushMode(COMMIT) delays flushing until em.getTransaction().commit(); what is the big difference?.

                            • 41. Re: Injection into entity beans
                              gonorrhea

                              Gavin King wrote on Jun 02, 2009 18:38:


                              it would be nice to have a code example explaining what is so good about FlushMode.MANUAL, because I really do not get it

                              @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?



                              GKing's above statement is true if you are using sequences (e.g. Oracle).  If you are using IDENTITY to generate the next PK value, then it's possible that there will be premature commits/tx's to the db prior the em.flush() at the end of the LRC.


                              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. 


                              SiA:



                              If the entity identifier is generated during an insertion (i.e., auto-increment
                              column), then even with manual flushing, a flush occurs after a call
                              to persist(). This is necessary since each managed entity in the persistence
                              context must be assigned an identifier. To avoid the flush, you
                              need to set the id-generation strategy to sequence (not identity).

                              In any event, this technique (atomic conversations) using SMPC (in Seam) and Hibernate MANUAL flush takes advantage of the 1st level cache of JPA/Hibernate.  This means that your app will be less chatty that other apps that use stored procs, for example.


                              If you think about this scenario, you don't even have to write a single JPAQL/HQL API statement to persist the data:


                              3 pages in a LRC (wizard).  all pages, the user updates the form data and submits.  the final submit button on the 3rd page flushes the EntityManager and ends the LRC.  You don't need to write a single line of JPA code b/c at when the tx commits, the PersistenceContext is synchronized with the db tables (this is called write-behind).


                              SiA:



                              Maintain a persistence context —The persistence context is an in-memory cache of
                              all entity instances that have been loaded into memory by this manager. It is the
                              key to optimizing performance and enabling write-behind database operations
                              (queued SQL statements). It's often referred to as the first-level cache. The terms
                              persistence context and persistence manager are often used interchangeably.
                              • 42. Re: Injection into entity beans
                                gavin.king

                                Because a JTA transaction corresponds to a database-level transaction. You are suggesting holding a database session and transaction open across user-think time? What happens if there is a limit to the number of available connections (this is how relational databases are priced). What happens if the user goes away - the connection/transaction gets cleaned up by a timeout?


                                This is something that has always been discouraged in applications that need to scale to many users. Now, it's not clear to me that this isn't just a problem with how today's JDBC drivers / relational databases are implemented, but I've not yet heard anyone saying that this advice is now out of date and that it is now perfectly fine to hold on to connections/transactions.


                                Now, could you, conceptually, introduce come kind of optimistic transaction abstraction in the JTA layer? Yes, it is probably conceptually possible, but I think there would be a huge resistance to that, since it would require a major rethink to how statement-oriented APIs like JDBC work.

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

                                  true if you are using sequences (e.g. Oracle). If you are using IDENTITY to generate the next PK value, then it's possible that there will be premature commits/tx's to the db prior the em.flush() at the end of the LRC.

                                  Arguably this is just a limitation in how Hibernate currently implements this feature. There's nothing conceptually broken about delaying id generation until the explicit flush occurs. Hibernate just doesn't know how to do this today.

                                  • 44. Re: Injection into entity beans

                                    Gavin King wrote on Jun 02, 2009 19:45:


                                    true if you are using sequences (e.g. Oracle). If you are using IDENTITY to generate the next PK value, then it's possible that there will be premature commits/tx's to the db prior the em.flush() at the end of the LRC.

                                    Arguably this is just a limitation in how Hibernate currently implements this feature. There's nothing conceptually broken about delaying id generation until the explicit flush occurs. Hibernate just doesn't know how to do this today.


                                    I was about to write that this limitation was not existent on EclipseLink, but you beat me by writing that this is just a limitation in how Hibernate currently implements this feature, not an intrinsic ORM or even JPA limitation.