Announcement Announcement Module
Collapse
No announcement yet.
DAO Reference Inside an Entity Domain Object? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    cepage: Cool description "playing whack-a-mole with Hibernate API's."

    Comment


    • #17
      I asked Eric Evans (author of Domain Driven Design) about whether a domain object (or an Entity as he calls it) should hold a reference to a DAO (or a Repository as he calls it), as in my parent/child example that started this forum topic. My question and his answer are posted here: http://groups.yahoo.com/group/domain...n/message/2305.

      To summarize, his answer was that the client of the parent domain object should hold the reference to the DAO that loads that child domain objects. In other words, the parent would NOT hold the reference and would NOT need to be injected with the DAO dependency. I found his answer to be somewhat surprising because he is a huge proponent encapsulating both data and behaviour in domain objects.

      Ideally, it would be nice to encapsulate the DAO in the parent but it seems from the answers in this discussion that this may not be practical because of potential problems with DI, transactional demarcation and serialization. In particular, I'm a bit nervous to try the HibernateInterceptor solution...it seems a bit too magical to me.

      FYI, you guys really should read Rod Johnson's posts about hydrating Hibernate objects that cepage referred to above.

      Comment


      • #18
        Originally posted by cyboc
        FYI, you guys really should read Rod Johnson's posts about hydrating Hibernate objects that cepage referred to above.
        Oh, yah, also check out these:
        http://thread.gmane.org/gmane.comp.j...work.user/3402
        http://thread.gmane.org/gmane.comp.j...work.user/3513

        Comment


        • #19
          Excellent thread. The related reading is also very good.

          My conclusion is that the neatest way (not ideal, but best of the bunch) is to provide the collaborator to the method call.

          Comment


          • #20
            Originally posted by cepage
            Originally posted by dejanp
            As far as I tried it, it works with no problems whatsoever.
            It only works with Hibernate2, and it only works with a couple of methods, like session.load(). Using methods like query.list() or creating an object in Hibernate do nothing, and you need to inject yourself.

            I believe that Rod is, correctly, taking a step back and trying to figure out a more holistic approach to this problem than playing whack-a-mole with Hibernate API's.
            Making it H3 compatible is trivial. DI on list() and such works, of course - the whole thing would be useless otherwise. If you create your objects, there is no injection, as usual. If you use prototype driven injection (and you should, autowire is not exactly performant) you can fetch new instances from the context, like any other bean.

            Comment


            • #21
              Good discussions. I'd prefer that Domain object hold a DAO object.
              It's so hard to inject DAO object into a domain object because domain objects are out of spring container's control. But we may use "Service Locator" to get a dao reference. The code looks like this:
              Code:
              class MyParentEntity 
              { 
              	private MyDao myDao = (MyDao)ApplicationContextHolder.getContext().getBean("myDao");
                public int getSum( FilteringParams params) 
                { 
                  return myDao.getSum(params, this); 
                } 
              }
              AOP may faciliate Domain object's transaction demarcation. AspectJ is my choice.
              [/code]

              Comment


              • #22
                Originally posted by dejanp
                DI on list() and such works, of course - the whole thing would be useless otherwise.
                Are you saying that because that's how you think it should work, or because you have tried it?

                In my tests with actual code, DI works on session.load() and session.find(), but not query.list().

                Comment


                • #23
                  Originally posted by cepage
                  Originally posted by dejanp
                  DI on list() and such works, of course - the whole thing would be useless otherwise.
                  Are you saying that because that's how you think it should work, or because you have tried it?

                  In my tests with actual code, DI works on session.load() and session.find(), but not query.list().
                  In my tests that use HibernateTemplate.find() which internally uses query.list() it works. Hibernate 3.

                  If it doesn't work in some version I'd consider it a Hibernate bug really.

                  Comment


                  • #24
                    Originally posted by dejanp
                    In my tests that use HibernateTemplate.find() which internally uses query.list() it works. Hibernate 3.
                    Thanks, I will give this a try under Hibernate3. Anyway, my original point was that this is a half-implemented solution (that we can get working with some hacking) in the sandbox, and right now a finished solution is not scheduled until 1.4, probably a year off.

                    I think smart people can reasonably disagree on this issue, but let's say you have two possible approaches on how to delete a user record from within a process object:

                    user.remove()

                    or

                    _userDao.remove(user)

                    In my opinion, the second approach introduces a bad code smell. You should minimize the number of collaborators and dependencies in a given class. The first approach has one, the second approach has two.

                    More to the point, the process was already dependent on the user object to begin with (it had a reference to the user object). The second approach introduces a brand new dependency on the UserDao interface which didn't need to be there before.

                    (In my apps, only Spring-managed factories and domain objects know about the DAOs. My process objects never directly reference the DAOs)

                    So, I feel the first approach promotes greater application stability by reducing the number of external dependencies.

                    Comment


                    • #25
                      Originally posted by Savagearts
                      But we may use "Service Locator" to get a dao reference. The code looks like this:
                      Code:
                      class MyParentEntity 
                      { 
                      	private MyDao myDao = (MyDao)ApplicationContextHolder.getContext().getBean("myDao");
                        public int getSum( FilteringParams params) 
                        { 
                          return myDao.getSum(params, this); 
                        } 
                      }
                      Yeah, I fell into this trap, and then got killed in my integration testing. As soon as I start using something like AbstractDependencyInjectionSpringContextTest that doesn't use the above approach to procure the ApplicationContext, you start ending up with two ApplicationContexts intermingling in your integration tests. Singletons suddenly aren't singletons anymore, and bad things happen.

                      I'm guessing that this sort of scenario is why the gurus discourage the use of ContextSingletonBeanFactoryLocator.

                      Comment


                      • #26
                        Originally posted by cepage
                        AbstractDependencyInjectionSpringContextTest[/b] that doesn't use the above approach to procure the ApplicationContext, you start ending up with two ApplicationContexts intermingling in your integration tests. Singletons suddenly aren't singletons anymore, and bad things happen.

                        I'm guessing that this sort of scenario is why the gurus discourage the use of ContextSingletonBeanFactoryLocator.
                        I often write a ApplicationContextHolder Bean that implements ApplicationContextAware interface. This bean simply holds a ApplicationContext reference. So whenever using AbstractDependencyInjectionSpringContextTest, Everything is ok.
                        Code:
                        public class ApplicationContextHolder implements ApplicationContextAware{
                            private static ApplicationContext applicationContext;
                        
                            public static ApplicationContext getContext(){
                                return applicationContext;
                            }
                        
                            public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
                                ApplicationContextHolder.applicationContext = applicationContext;
                            }
                        }

                        Comment


                        • #27
                          Originally posted by cepage
                          Yeah, I fell into this trap, and then got killed in my integration testing. As soon as I start using something like AbstractDependencyInjectionSpringContextTest that doesn't use the above approach to procure the ApplicationContext, you start ending up with two ApplicationContexts intermingling in your integration tests. Singletons suddenly aren't singletons anymore, and bad things happen.

                          I'm guessing that this sort of scenario is why the gurus discourage the use of ContextSingletonBeanFactoryLocator.
                          I wrote an AppContextCollector that is basically a (true) singleton map that passively collects contexts:
                          http://www.digizenstudio.com/blog/20...unintrusively/

                          Comment


                          • #28
                            I just posted another blog entry summarizing an Aspectwerkz-based approach to intercept a getXXXDAO call and return a DAO bean reference:
                            http://www.digizenstudio.com/blog/20...omain-objects/

                            It's not strictly "injecting" per se, as it doesn't need the domain object to have a field for the reference being injected. The basic idea is the same as the lookup-method in Spring.

                            Let me know if I'm slipping too far into the dark side...

                            Comment


                            • #29
                              Nice simple solution.

                              Still not *ideal*, but getting there

                              Comment


                              • #30
                                Thanks, Jing and Savage. That's very helpful.

                                Comment

                                Working...
                                X