9 Replies Latest reply on Mar 25, 2006 10:21 AM by Emmanuel Bernard

    SLSB Facade in front of Entity?

    Brian Chaikelson Newbie

      Is it good practice to use a SLSB in front of the EJB 3.0 entity POJO? Clients would always use this facade to access create(), remove(), finders, etc, rather than calling the entity directly.

      This is the pattern implied by the 2.1 --> 3.0 entity migration article at http://www.oracle.com/technology/pub/articles/vohra_ejb.html (Oracle appserver-centric, but generalizable to all EJB 3.0 implementations). In terms of the finders, the entity itself would contain the NamedQuery annotations, which are referenced by the facade's query methods.

      Another option would involve putting more logic in the entity itself, perhaps static methods to accomplish the above tasks (create, remove, finders) so clients would access the entity directly.

      Here are some pro/con arguments for the facade:

      (pro) If EJB 3.0 entity POJOs are meant to flow through the system as value objects (and I know this is arguable), then the create, remove, finder methods might clutter their interface. A facade provides a layer of indirection so that the entities look more like simple value objects (although on steroids with annotations).

      (pro) A facade is a nice place to put the potentially useful load-level logic suggested by Martin and illustrated by r_q_d in this forum (http://www.jboss.com/index.html?module=bb&op=viewtopic&t=73263&postdays=0&postorder=asc&start=20)

      (con) Yet another layer of SLSBs - EJB 3.0 was supposed to "simplify" my architecture

      (con) Performance concerns with an additional SLSB (I don't think this a major issue)

      Thanks in advance for your input!

        • 1. Re: SLSB Facade in front of Entity?
          Dan Greening Newbie

          Brian and I are very interested in thoughts on this. Please weigh in if you've worked with EJB3.

          I think having an SLSB facade in front of every entity bean, at least the way I've seen it done, is an anti-pattern. Here's my argument:

          One purpose could be to eliminate the need for passing in an EntityManager when finding or storing entities, letting an EM be injected into each SLSB. However, if you create separate EntityManagers for every entity bean via these SLSB facades, you eliminate transaction atomicity (how can you start a transaction, make several entity-related operations possibly on different entities, and then commit the whole caboodle without passing around a single EntityManager?). And so, if you use this (anti)pattern, when you want to perform complex activities that require atomicity over several entities, you must add parallel find/create operations that take an entity manager. Now you have created more complexity and maintenance headaches for the convenience of omitting EMs in a few cases. (In the final version of JavaEE5, I believe you can inject EntityManagers into Servlets, which makes NOT using SLSB facades even easier.)

          OK, suppose we agree with the previous paragraph. Let's fix our pattern by passing the entity manager to all these functions in the SLSB. Now we have the question of whether these find/create/remove operations require an SLSB. I think not, because the SLSB doesn't buy us anything. We wanted it before, because of the ability to inject the EntityManager, but now we are passing the EM around instead. No need for SLSB.

          OK, now let's suppose we agree with the previous two paragraphs. So we turn this facade into a class that has some (static) methods with EntityManager passed in. Well, remove and create are irrelevant now, because the direct call through the EM is simpler: em.remove(entity) and em.persist(entity) versus Fascade.remove(em,entity) and Fascade.persist(em,entity). What remains is complex find operations. I think simpler EJB3 find operations are best coded as annotations with @NamedQuery like this:

          customers = em.createNamedQuery("findAllCustomersWithName")
          .setParameter("custName", "Smith")
          .getResultList();

          Sometimes find operations can get complex, requiring loops or conditionals and multiple SQL requests. One can argue, and I think fairly, that simple named queries AND these more complex find operations really ought to be encapsulated in a method like this:

          static public List findCustomerWithName(
          EntityManager em,
          String name) {
          return em.createNamedQuery("findAllCustomersWithName")
          .setParameter("custName", "Smith")
          .getResultList();
          }

          I would put this method in the POJO itself. Brian is thinking it might belong in a fascade class. So this is the jist of this pattern vs. anti-pattern argument:

          Brian and I both think we SHOULD capture complex find operations either in the POJO itself as a static method, OR we should capture these complex find operations in some separate fascade. I'm mildly opposed to putting complex find operations in a separate fascade, because it bothers me that methods that solely deal with the POJO are put somewhere else, increasing maintenance problems. However I can see an opposing argument maybe.

          If you have thoughts on this, could you please discuss?

          • 2. Re: SLSB Facade in front of Entity?
            Patrick Angeles Novice

            What's wrong with using Generic DAOs?

            • 3. Re: SLSB Facade in front of Entity?
              Emmanuel Bernard Master

              the entitymanager is the same for all session beans executed in a single transaction.

              • 4. Re: SLSB Facade in front of Entity?
                Dan Greening Newbie

                epbernard: Thanks! Very interesting. How is the transaction demarcated? By the first call into the EJB jar file? (And then transaction completes upon return?)

                patrick_ibg: I thought GenericDAOs were primarily for abstracting away different storage mechanisms. This is really a question about where the find methods belong. Do they belong as static methods on the POJO class with the EM as a first parameter?

                I don't think this is a fact-based question, more like a pattern "what's a good way to do it" question.

                I think this question will come up frequently as people start to use EJB3 persistence.

                • 5. Re: SLSB Facade in front of Entity?
                  Vance Karimi Newbie

                  greening: I think your question has a lot of merit. We are also undecided as to which strategy will prove to be the 'pattern' in the end. AndroMDA now has a EJB3 cartridge and the finder methods exist in entity POJOs as static methods with EntityManager as the first argument to the finder method. This was designed that way because of the limitations of generics, code generation and UML. I've seen tutorials use this strategy, but others are strictly against passing the EntityManager to the POJO and maintaing everything related to the facade class.

                  • 6. Re: SLSB Facade in front of Entity?
                    Emmanuel Bernard Master

                    I don't like the AndroMDA solution
                    A DAO should be represented as a @Staleless session beam where @PersistenceContext EM em is used to inject the appropriate EM

                    The transaction is started regarding the @TransactionAttribute annotation, this is very much like EJB2 except that you can define one of the transaction strategies through annotations.

                    • 7. Re: SLSB Facade in front of Entity?
                      Nic Holbrook Newbie

                      Well, I think a proxy is pretty simple. I don't write them for every entity and don't see a need for it. Here's my simple interface.

                      public interface ServiceProxy
                      {
                      void insert( Serializable transientInstance );

                      void remove( Serializable persistentInstance );

                      T update( T detachedInstance );

                      T findById( Class transientInstance, Serializable id );

                      List findByNamedQuery( String queryName, Map<String, Serializable> queryParams );

                      List findAll( Class transientInstance );
                      }

                      Works great for me. I only expose what is required by the client. This covers almost all the cases. For other cases, I add a service method to the proxy.

                      • 8. Re: SLSB Facade in front of Entity?
                        Alex Greif Newbie

                         

                        "epbernard" wrote:
                        the entitymanager is the same for all session beans executed in a single transaction.


                        I tried this with the following code

                        @Stateful
                        @Remote(ShoppingCart.class)
                        public class ShoppingCartBean implements ShoppingCart, java.io.Serializable
                        {
                         @PersistenceContext
                         private EntityManager manager;
                         private Order order;
                        
                         @EJB
                         private MyDao myDao;
                        
                         public void buy(String product, int quantity, double price)
                         {
                         if (order == null) order = new Order();
                         order.addPurchase(product, quantity, price);
                         }
                        
                         public Order getOrder()
                         {
                         return order;
                         }
                        
                         @Remove
                         @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
                         public void checkout()
                         {
                         System.out.println("ShoppingCartBean.checkout() - myDao: " + myDao);
                         System.out.println("ShoppingCartBean.checkout() - manager: " + manager);
                         myDao.doSomething();
                         manager.persist(order);
                         }
                        }
                        
                        -----------------------------------------------------------
                        
                        @Stateless
                        @Local(MyDao.class)
                        public class MyDaoBean implements MyDao {
                        
                         @PersistenceContext
                         private EntityManager manager;
                        
                         public void doSomething() {
                         System.out.println("myDao.doSomething() - manager: " + manager);
                         Order order = new Order();
                         order.addPurchase("bla", 1, 10);
                         manager.persist(order);
                         }
                        }
                        


                        The output is the following :

                        14:41:21,586 INFO [STDOUT] ShoppingCartBean.checkout() - myDao: org.jboss.tutorial.entity.bean.MyDaoBean
                        14:41:21,586 INFO [STDOUT] ShoppingCartBean.checkout() - manager: org.jboss.ejb3.entity.InjectedEntityManager@1e17cff
                        14:41:21,626 INFO [STDOUT] myDao.doSomething() - manager: org.jboss.ejb3.entity.InjectedEntityManager@1a4835a
                        


                        Could anybody please explain, why the entity managers have different hashcodes? This means they are different instances. Are these entityManagers really both the same?

                        Alex.