13 Replies Latest reply on Sep 13, 2009 9:49 PM by itays100

    Seam with DAO Best Practice for reuse

    itays100

      Hello,
      I succeeded creating a seam project using the Hibernate Example.
      I have one design problem with this solution:
      Althought seam users avoid layers in thier application I find this a bit problematic. Reuse of code in somthing that I can just throught out.


      For instance take a look in the following Action:
      @Scope(EVENT)
      @Name("register")
      public class RegisterAction
      {

         @In
         private User user;
        
         @In
         private Session bookingDatabase;
        
         @In
         private FacesMessages facesMessages;
        
         private String verify;
        
         private boolean registered;
        
         public void register()
         {
            if ( user.getPassword().equals(verify) )
            {
               List existing = bookingDatabase.createQuery("select u.username from User u where u.username=#{user.username}")
                  .list();
               if (existing.size()==0)
               {
                  bookingDatabase.persist(user);
                  facesMessages.add("Successfully registered as #{user.username}");
                  registered = true;
               }
               else
               {
                  facesMessages.addToControl("username", "Username #{user.username} already exists");
               }
            }
            else
            {
               facesMessages.add("verify", "Re-enter your password");
               verify=null;
            }
         }


      I would like to create a DAO layer that should be injected to a seam component.
      Somthing like:
      @In
         private User user;
      @In
         private UserDao useDao;

      public void register()
         {
            if ( user.getPassword().equals(verify) )
            {
               List existing = userDao.getUser(user.getUserName());
               if (existing == null)
               {
                  userDao.saveUser(user);
                  facesMessages.add("Successfully registered as #{user.username}");
                  registered = true;
               }
      }


      My question is how the UserDao class should be design to support the implementation above ?


      I tried google but find only seam integration or more complicated slolution.


      Please provide an example with your solution if any.
      Thanks!

        • 1. Re: Seam with DAO Best Practice for reuse
          itays100

          Itay Sahar wrote on Sep 05, 2009 15:51:

          Hello,
          I succeeded creating a seam project using the Hibernate Example.

          I have one design problem with this solution:
          Althought seam users avoid layers in thier application I find this a bit problematic. Reuse of code in somthing that I can just throught out.

          For instance take a look in the following Action:
          '
          @Scope(EVENT)
          @Name("register")
          public class RegisterAction
          {<BR>
             @In
             private User user;
            
             @In
             private Session bookingDatabase;
            
             @In
             private FacesMessages facesMessages;
            
             private String verify;
            
             private boolean registered;
            
             public void register()
             {
                if ( user.getPassword().equals(verify) )
                {
                   List existing = bookingDatabase.createQuery("select u.username from User u where u.username=#{user.username}")
                      .list();
                   if (existing.size()==0)
                   {
                      bookingDatabase.persist(user);
                      facesMessages.add("Successfully registered as #{user.username}");
                      registered = true;
                   }
                   else
                   {
                      facesMessages.addToControl("username", "Username #{user.username} already exists");
                   }
             }

          '
          I would like to create a DAO layer that should be injected to a seam component.
          Somthing like:
          @In
             private User user;
          @In
             private UserDao useDao;

          public void register()
             {
                if ( user.getPassword().equals(verify) )
                {
                   List existing = userDao.getUser(user.getUserName());
                   if (existing == null)
                   {
                      userDao.saveUser(user);
                      facesMessages.add("Successfully registered as #{user.username}");
                      registered = true;
                   }
          }


          My question is how the UserDao class should be design to support the implementation above ?

          I tried google but find only seam integration or more complicated slolution.

          Please provide an example with your solution if any.
          Thanks!


          Click HELP for text formatting instructions. Then edit this text and check the preview.

          • 2. Re: Seam with DAO Best Practice for reuse
            itays100

            Itay Sahar wrote on Sep 05, 2009 16:11:



            Itay Sahar wrote on Sep 05, 2009 15:51:

            Hello,
            I succeeded creating a seam project using the Hibernate Example.

            I have one design problem with this solution:
            Althought seam users avoid layers in thier application I find this a bit problematic. Reuse of code in somthing that I can just throught out.

            For instance take a look in the following Action:
            |@Scope(EVENT)
            @Name("register")
            public class RegisterAction
            {<BR>
               @In
               private User user;
               
               @In
               private Session bookingDatabase;
               
               @In
               private FacesMessages facesMessages;
               
               private String verify;
               
               private boolean registered;
               
               public void register()
               {
                  if ( user.getPassword().equals(verify) )
                  {
                     List existing = bookingDatabase.createQuery("select u.username from User u where u.username=#{user.username}")
                        .list();
                     if (existing.size()==0)
                     {
                        bookingDatabase.persist(user);
                        facesMessages.add("Successfully registered as #{user.username}");
                        registered = true;
                     }
                     else
                     {
                        facesMessages.addToControl("username", "Username #{user.username} already exists");
                     }
               }|
            


            I would like to create a DAO layer that should be injected to a seam component.
            Somthing like:
            |@In
               private User user;
            @In
               private UserDao useDao;
            
             public void register()
               {
                  if ( user.getPassword().equals(verify) )
                  {
                     List existing = userDao.getUser(user.getUserName());
                     if (existing == null)
                     {
                        userDao.saveUser(user);
                        facesMessages.add("Successfully registered as #{user.username}");
                        registered = true;
                     }
            }|
            


            My question is how the UserDao class should be design to support the implementation above ?

            I tried google but find only seam integration or more complicated slolution.

            Please provide an example with your solution if any.
            Thanks!


            Click HELP for text formatting instructions. Then edit this text and check the preview.


            Click HELP for text formatting instructions. Then edit this text and check the preview.

            • 3. Re: Seam with DAO Best Practice for reuse
              asookazian

              Althought seam users avoid layers in thier application

              this is not necessarily true.  Seam does not require layering.  But you may certainly add as many layers as you need.


              The DAO class needs to have the following code in it:


              @In private EntityManager entityManager;


              in order to inject the SMPC and perform the CRUD operations.

              • 4. Re: Seam with DAO Best Practice for reuse
                itays100
                Thanks for your reply Arbi.

                I realy try to find an example of DAO implementation that will integrate with seam.
                Injecting the EntityManager is a good start but it seem to me
                that there are more issue to resolve. For instance:

                1. What should be the scope of the DAO (it should be a seam         component ?

                2. What about the User component? It should be injecting to the DAO?
                Otherwize to code below won't work.
                entityManager.createQuery("select u.username from User u where u.username=#{user.username}")

                Thanks
                • 5. Re: Seam with DAO Best Practice for reuse
                  phantasmo

                  Wait a sec... Isn't this just reinventing EntityHome?

                  • 6. Re: Seam with DAO Best Practice for reuse
                    itays100
                    DAO Layer should be EntityHome alternative. Not say is not good.
                    EntityHome is good but what if this layer should be reuse in other application which is not web application (using seam) ?

                    The main purposes of DAO layer are two:

                    1. Seperate the database calls from the presentation layer.
                    2. Allow other application/layer to use it.

                    EntityHome solution is not exactly answer these purposes. For instance, you can use #personHome.persist(#person) directly from the page.

                    I would like to know if someone has an example of DAO class that integrate seam.

                    Thanks
                    • 7. Re: Seam with DAO Best Practice for reuse
                      mail.micke

                      If you want to remove Seam dependencies completely from the DAO (not using the annotations), then you could use Spring to manage them.
                      This is what we do, not because we want to avoid Seam but because we migrated an old application using Spring to Seam and just kept the services and DAOs in the Spring config.


                      If you don't mind using the Seam annotations, just create the DAOs as Seam components (with the appropriate scope).


                      Regarding having the user injected, you could simply pass this in as an argument to the DAO.


                      Regards,
                      micke

                      • 8. Re: Seam with DAO Best Practice for reuse
                        christian.bauer

                        Seam does not require annotations on component classes/interfaces. You can configure injection etc. completely in XML. You can take the same old Spring DAO classes and wire them with Seam XML into your Seam application. Of course, if they got you with their FooTemplate lock-in API, you would have to remove that first to clean up your classes for use without Spring.


                        • 9. Re: Seam with DAO Best Practice for reuse
                          itays100

                          Micke,



                          just create the DAOs as Seam components (with the appropriate scope).

                          This is exactly what I'm asking (see the original message).
                          How seam create an instance and inject it to the RegisterAction.


                          Please note I'm using Hibernate and not ejb so i guess
                          the dao should have a Hibernate Session injected.
                          I add code sample for this but seam should create an instance in application scope right ?


                          @Name("UserDao")
                          @Scope(ScopeType.APPLICATION)
                          public class CustomerDaoHibernateImpl {
                                    
                               @In
                               private Session bookingDatabase; 



                          Christian,


                          I know about seam integration with spring beans but tring to avoid it.
                          I prefer using annotation rather then configure spring bean in xml.


                          Thanks

                          • 10. Re: Seam with DAO Best Practice for reuse
                            itays100

                            I got the implementation below works!


                            @Name("userDao")
                            @Scope(ScopeType.APPLICATION)
                            @Startup
                            public class CustomerDaoHibernateImpl implements CustomerDao {
                                      
                                 @In
                                 private Session bookingDatabase;



                            Do you find somthing wrong with it ?
                            This component purpose is a DAO for users/accounts data.


                            Thanks for your comments.

                            • 11. Re: Seam with DAO Best Practice for reuse
                              swd847

                              Don't use application scope, this means that you will only ever have one instance of the DAO in the application, so you have to synchronize it which kills concurrency. At the moment you have a race condition where two separate users could access the same session.


                              There should probably be some kind of warning about application scoped components and injection in the docs.



                              You probably want the component to be event scoped.

                              • 12. Re: Seam with DAO Best Practice for reuse
                                itays100

                                I guess you right about synchronize here is not a good practice.
                                I'd finally came with the following solution:


                                '@Name(userDao)
                                @Scope(ScopeType.EVENT)
                                @AutoCreate
                                public class CustomerDaoHibernateImpl implements CustomerDao {
                                          
                                     @In
                                     private Session bookingDatabase;'


                                • 13. Re: Seam with DAO Best Practice for reuse
                                  itays100

                                  I guess you right about synchronize here is not a good practice. I came with the following solution:


                                  @Name("userDao")
                                  @Scope(ScopeType.EVENT)
                                  @AutoCreate
                                  public class CustomerDaoHibernateImpl implements CustomerDao {
                                            
                                       @In
                                       private Session bookingDatabase;