1 2 Previous Next 15 Replies Latest reply on Oct 14, 2005 1:08 AM by Christian Bauer

    How to deal with DAOs?

    Mario Ivankovits Newbie

      Hi!

      We have some classes like caveatemptor.HiA-SE/src/java/org/hibernate/ce/auction/dao/CommentDAO.javacaveatemptor.HiA-SE/src/java/org/hibernate/ce/auction/dao/CommentDAO.java

      The point is, in your Seam examples you implement the complete business logic within your action or backing classes.
      We moved them to DAOs and Process classes.
      I would like to keep the DAOs as it is not unlikely to have the same queries in different backing-beans, but we need access to the session.
      We use something like Storage.getSession() to retrieve the current hibernate session from a ThreadLocal.

      Is there a way to retrieve the entityManager for the current scope in seam?

      Thanks!

        • 1. Re: How to deal with DAOs?
          Christian Bauer Master

          You should simply make your DAOs EJB3 session beans and get the EM injected...

          • 2. Re: How to deal with DAOs?
            Christian Bauer Master

            In case this isn't clear, you can then tread them as stateless service components in Seam and inject them into your event processing components.

            • 3. Re: How to deal with DAOs?
              Mario Ivankovits Newbie

              Thanks!
              I skimmed through your trailblaizer demo and maybe we can change our DBOs/Processes accordingly. Our JSF/Hibernate application is young enough and it might not be too late.

              Our application has another ThreadLocal which has some impact on the configuration of the hibernate sessionFactory.
              For what I have seen it might be possible to archive this by implementing our own ManagedHibernateSession.

              Any objections I might not see yet?

              Thanks!

              • 4. Re: How to deal with DAOs?
                Christian Bauer Master

                "Binding to threads" is a bad idea in a JEE application server, especially if you use EJBs. One request might be processed in several threads.

                • 5. Re: How to deal with DAOs?
                  Mario Ivankovits Newbie

                  This means I should get rid of this ThreadLocal and try to bind my special values in ApplicationScope, right?

                  It should be possible to access the ApplicationScope then in ManagedHibernateSession, is it?

                  • 6. Re: How to deal with DAOs?
                    Christian Bauer Master

                    You should make all your thread-bound stuff a Seam component, in the right context and scope.

                    • 7. Re: How to deal with DAOs?
                      Patrick Angeles Novice

                      Christian,

                      If I'm reading your post right, this is what you recommend doing...

                      @Stateless
                      @Name ("someDao")
                      public class SomeDao
                      {
                      @PersistentContext
                      EntityManager em ;
                      ...
                      }

                      then in the action class...

                      @Stateful
                      @Scope (EVENT)
                      @Name ("someAction")
                      @Interceptor (SeamInterceptor.class)
                      public class SomeAction
                      {
                      @In
                      SomeDao someDao ;

                      public void action ()
                      {
                      SomeEntity e = someDao.find (id) ;
                      // etc.
                      }
                      ...
                      }

                      Is this correct?

                      • 8. Re: How to deal with DAOs?
                        Administrator Administrator Novice

                        Yes, but I wouldn't know why an EVENT component would have to be stateful :)

                        • 9. Re: How to deal with DAOs?
                          Patrick Angeles Novice

                          My bad, as you can see that code wasn't written to compile :)

                          On the same subject, I did try what you suggested today and got it to work. However, I've found there are some tradeoffs to coding the DAOs as Stateless EJBs:

                          1. More difficult to unit-test outside of the container. (I know, there's the Embeddable EJB engine, but it is yet another thing I'd need to learn to set up.)

                          2. Requires at least two files per DAO (the @Stateless bean, and a @Local interface). The latter is trivial, but it's still work unless I set up some sort of code generator. After all, the only thing a @Stateless bean DAO has over a POJO DAO is the ability to inject the @PersistenceContext. I'd like to minimize the number of files needed, as I'm looking at a system with 100+ entities.

                          3. For most of my entities, I don't even need the @Stateless bean, because I could use a generic DAO for basic persistence calls (merge, find, etc.) My original plan was to extend the generic DAO only when a particular entity has special queries. (Further reducing the number of required classes.)

                          So know, I'm considering the following approach:

                          1. Go back to using POJO DAOs, starting with a generic DAO which I can extend per entity if I need special services from the persistence layer.
                          2. The POJO DAOs will take an EntityManager on the constructor, or have the EM be a settable property.
                          3. The @PersistenceContext is still injected onto the Action class.
                          4. Action class will have as follows:

                          // seam annotations go here...
                          public class SomeAction extends Action
                          {
                          @PersistenceContext EntityManager entityManager ;
                          
                          public String doIt ()
                          {
                           GenericPojoDAO<SomeEntity> dao = new GenericPojoDAO<SomeEntity>(entityManager) ;
                           SomeEntity e = dao.find (id) ;
                           ...
                           /*
                           or, if I had extended the generic dao:
                           public class AnotherEntityDao
                           extends GenericPojoDAO<AnotherEntity>
                           */
                           AnotherEntityDao aeDao = new AnotherEntityDao (entityManager) ;
                           AnotherEntity ae = aeDao.specialQuery (param1, param2) ;
                          
                          }
                          
                          }
                          


                          I'm new to EJBs so I'd like to ask the forum if are there any pitfalls to this approach.


                          • 10. Re: How to deal with DAOs?
                            Patrick Angeles Novice

                            Add this to the drawbacks of injecting @PersistenceContext on SSB DAOs:

                            4. Unable to specify @PersistenceContext (type = EXTENDED) when needed for a conversation.

                            • 11. Re: How to deal with DAOs?
                              Patrick Angeles Novice

                              Add this to the drawbacks of injecting @PersistenceContext on SSB DAOs:

                              4. Unable to specify @PersistenceContext (type = EXTENDED) when needed for a conversation.

                              • 12. Re: How to deal with DAOs?
                                Christian Bauer Master

                                OK, points noted and I see we have a lot to do to make this better understandable. The main problem here is documentation.

                                1. We are working on the packaging (maybe down to 1 JAR) and configuration of E-EJB3 etc. I promise it will be a lot easier soon.

                                2. This is a good requirement that you can turn into a feature. One interface per DAO type and possibly many implementations are a good thing to keep code portable and maintainable.

                                3. The part of @Stateless that you need are the cross-cutting concerns you can apply. Override of transactions/breaking transaction propagation at the DAO implementation level. The separate file is an issue, for the generics pattern. I've noticed that as well at some point and think we need to do something...

                                4. This is by design, you need @Stateful if you want to keep the state of the PersistenceContext that has to be extended.

                                5. You can test DAOs in integration by setting an EntityManager you look up when constructing the DAO.

                                • 13. Re: How to deal with DAOs?
                                  Christian Bauer Master

                                  last sentence "before setting it as a constructor argument when instantiating a DAO". Not looking it up inside the constructor.

                                  • 14. Re: How to deal with DAOs?
                                    Patrick Angeles Novice

                                    Christian,

                                    I understood your points 1 and 5 well enough, but need help parsing the rest.

                                    "christian.bauer@jboss.com" wrote:

                                    1. We are working on the packaging (maybe down to 1 JAR) and configuration of E-EJB3 etc. I promise it will be a lot easier soon.


                                    Sweet


                                    2. This is a good requirement that you can turn into a feature. One interface per DAO type and possibly many implementations are a good thing to keep code portable and maintainable.

                                    3. The part of @Stateless that you need are the cross-cutting concerns you can apply. Override of transactions/breaking transaction propagation at the DAO implementation level. The separate file is an issue, for the generics pattern. I've noticed that as well at some point and think we need to do something...


                                    Are you saying 1 entity = 1 concrete, non-generic dao? Which basically means if we wanted to use generics, we should still extend the generic class for each concrete entity. (Similar to the HiA GenericEjb3Bean pattern.) I didn't think of using one interface per DAO type, however... that helps keep the # of files down.


                                    4. This is by design, you need @Stateful if you want to keep the state of the PersistenceContext that has to be extended.

                                    So if I wanted to implement a conversation using EJB3 DAOs, the DAO code would essentially have to be aware that it will be used in a conversation? (IOW, DAO will need to know in advance if it needs to be @Stateful and with an extended @PersistenceContext.) This essentially gives the DAO higher awareness of business logic. My concept of a DAO is that it is a dumb object that is only aware of the underlying DB schema. In fact, I've been trying to code for SEAM in a manner such that I can essentially package all the Entities/DAOs in one jar (or .par) and it can be used by any number of .ear/.war packages, and maybe someday by POJOs. Maybe I'm misunderstanding something...


                                    5. You can test DAOs in integration by setting an EntityManager you look up when constructing the DAO.


                                    Yep, I didn't think of that...

                                    As for transaction demarcation, I would almost prefer to keep that outside of the DAOs. I think the concept of a transaction is closely linked to business logic and is probably best handled by the Action beans.



                                    1 2 Previous Next