Loading ...
Sorry, an error occurred while loading the content.
 

Re: [domaindrivendesign] Re: Improving application design with a rich domain model

Expand Messages
  • Jing Xue
    ... Hi Geert, Could you please elaborate on how exactly the interference happens? I m interested in learning more details about this, because we ve been using
    Message 1 of 12 , Sep 4, 2007
      Quoting Geert Pante <geertpante@...>:

      > The possibility of injecting a repository into an entity does enable
      > some interesting designs indeed. Unfortunately the Hibernate's CGLib
      > instrumentation does not work together nicely with Spring's
      > @Configurable annotation based injection: Spring injects your
      > @Configurable beans whenever a constructor is called, but that
      > interferes with Hibernate's lifecycle when loading entity beans, both
      > lazy or eagerly.

      Hi Geert,

      Could you please elaborate on how exactly the interference happens?
      I'm interested in learning more details about this, because we've been
      using @Configurable to inject into domain objects loaded by hibernate
      without noticing any issues.

      Thanks.
      --
      Jing Xue
    • Chris Richardson
      Sean, I m glad that you liked the presentation. The MoneyTransferService I describe in the presentation is a simplified but typical service in the applications
      Message 2 of 12 , Sep 4, 2007
        Sean,

        I'm glad that you liked the presentation.

        The MoneyTransferService I describe in the presentation is a simplified but typical service in the applications I work on.

        public class MoneyTransferServiceImpl implements MoneyTransferService {

            public MoneyTransferServiceImpl(AccountRepository accountRepository,
                    BankingTransactionRepository bankingTransactionRepository) {...}
            }

            public BankingTransaction transfer(String fromAccountId,
                    String toAccountId, double amount) throws MoneyTransferException {
                Account fromAccount = accountRepository.findAccount(fromAccountId);
                Account toAccount = accountRepository.findAccount (toAccountId);
                fromAccount.debit(amount);
                toAccount.credit(amount);
                TransferTransaction txn = new TransferTransaction(fromAccount,
                        toAccount, amount, new Date());
                bankingTransactionRepository.addTransaction(txn);
                return txn;
            }

        }

        (and, yes, this could probably be shorted to return fromAccount.transferTo(toAccount, amount) , and money shouldn't be a double :-) )

        The services are invoked by the web tier, e.g. Spring MVC controller. Each service method is a few lines of code that takes object ids + other data as parameters; calls some repositories to load some entities and then invokes some methods on those entities to do some work etc. You could probably characterize this as an application service rather than domain service but if your services are simple like this one then having a separate domain service isn't generally valuable. However, if the service was fatter and manipulated, for example, XML messages or DTOs, then moving the domain logic into a separate domain service might be a good idea.

        Chris

        --
        Enterprise POJO consulting - http://www.chrisrichardson.net
        Author, POJOs in Action - http://www.manning.com/crichardson
        Enterprise POJOs blog - http://chris-richardson.blog-city.com
        Speaking in 2007 at JavaOne, SpringOne, the Colorado Software Summit, the Spring Experience



        On 8/31/07, dkode8880 <dkode8880@...> wrote:

        Chris,

        This is an excellent description covering many topics. There was a couple of things in
        there I was not aware of.

        Can you go more in depth on how services should be used in the domain? I was under the
        impression that the Service Layer should be a combination of multiple Repositories to
        accomplish some sort of group work. Is this accurate?

        Thanks again for the excellent webcast!

        Sean

        --- In domaindrivendesign@yahoogroups.com, "Chris Richardson"


        <chris.e.richardson@...> wrote:
        >
        > Hi,
        >
        > Back in June at the SpringOne conference I gave a talk on improving
        > application design with a rich domain model. The video of the talk has
        > now been published. You can find out more about the talk and links to
        > the video and slides by going here
        > http://www.chrisrichardson.net/springOne2007.html .
        >
        > It would be great to get your feedback.
        >
        > Chris
        >
        > --
        > Author, POJOs in Action - http://www.manning.com/crichardson
        > Enterprise POJO consulting - http://www.chrisrichardson.net
        > Enterprise POJOs blog - http://chris-richardson.blog-city.com
        > Speaking in 2007 at the Colorado Software Summit and the Spring Experience
        >




      • Chris Richardson
        Hi Brad, Glad you liked the presentation. Injecting dependencies into entities is definitely useful and avoids passing dependencies through many levels of
        Message 3 of 12 , Sep 4, 2007
          Hi Brad,

          Glad you liked the presentation.

          Injecting dependencies into entities is definitely useful and avoids passing dependencies through many levels of method calls. However, using it in your application involves tradeoffs. For example, Spring's @Configurable is pretty powerful but since it is AspectJ-based you either have to use ajc (change your build) or load-time weaving (slow startup). It can also make it difficult to test your code without Spring if the code is relying on Spring to complete the initialization of objects. The other option is for your application to inject dependencies when it instantiates an entity and to use a Hibernate Interceptor to make Hibernate do it. This can work but doesn't handle the scenario where your entities are serialized/deserialized, e.g. HttpSession replication.

          Perhaps I'm old fashioned but I don't have a good feeling about Entity.save() - I like EntityDao.save()...

          Chris

          --
          Enterprise POJO consulting - http://www.chrisrichardson.net
          Author, POJOs in Action - http://www.manning.com/crichardson
          Enterprise POJOs blog - http://chris-richardson.blog-city.com
          Speaking in 2007 at JavaOne, SpringOne, the Colorado Software Summit, the Spring Experience


          On 8/31/07, Brad Neighbors <bneighbors@...> wrote:

          Excellent presentation, Chris.
           
          My team and I have been practicing DDD for the past year or so, and have a significant and robust stack at this point.  We use Spring and Hibernate and we were most interested in the injection of services *into* a domain entity.  (in your presentation around 27:30)
           
          I've been considering that as a way to make working with entities in Java (especially persisting them) have the same "feel" as they do in say, Grails.  In Grails, as you may be aware, you can write code like myEntity.save(), although that class doesn't have a save() method on it- it is configured at runtime using (I believe) Groovy's ExpandoMetaClass feature.
           
          Using the @Configurable and injecting a repository into an entity, in Java, would allow one to write myEntity.save(myEntityRepository).  Food for thought I suppose.
           
          Thanks,
           
          Brad
           


          From: domaindrivendesign@yahoogroups.com [mailto:domaindrivendesign@yahoogro ups.com] On Behalf Of Chris Richardson
          Sent: Monday, August 27, 2007 6:42 AM
          To: domaindrivendesign@yahoogroups.com
          Subject: [domaindrivendesign] Improving application design with a rich domain model

          Hi,

          Back in June at the SpringOne conference I gave a talk on improving
          application design with a rich domain model. The video of the talk has
          now been published. You can find out more about the talk and links to
          the video and slides by going here
          http://www.chrisrichardson.net/springOne2007.html .

          It would be great to get your feedback.

          Chris

          --
          Author, POJOs in Action - http://www.manning.com/crichardson
          Enterprise POJO consulting - http://www.chrisrichardson.net
          Enterprise POJOs blog - http://chris-richardson.blog-city.com
          Speaking in 2007 at the Colorado Software Summit and the Spring Experience




        • Geert Pante
          ... Hi Jing, I remember struggling with this for a while. One of the first issues I had was that Hibernate calls a default constructor of persisted objects to
          Message 4 of 12 , Sep 5, 2007
            --- In domaindrivendesign@yahoogroups.com, Jing Xue <jingxue@...> wrote:
            > Quoting Geert Pante <geertpante@...>:
            >
            > The possibility of injecting a repository into an entity does enable
            > some interesting designs indeed. Unfortunately the Hibernate's CGLib
            > instrumentation does not work together nicely with Spring's
            > @Configurable annotation based injection: Spring injects your
            > @Configurable beans whenever a constructor is called, but that
            > interferes with Hibernate's lifecycle when loading entity beans,
            > both lazy or eagerly.
            >>>>>>>>>>>>>>>>>>>>>>>
            > Hi Geert,
            >
            > Could you please elaborate on how exactly the interference happens?
            > I'm interested in learning more details about this, because we've
            > been using @Configurable to inject into domain objects loaded by
            > hibernate without noticing any issues.
            >>>>>>>>>>>>>>>>>>>>>>>>

            Hi Jing,

            I remember struggling with this for a while. One of the first issues I
            had was that Hibernate calls a default constructor of persisted
            objects to find out what the 'unsaved value' of the primary key is.
            This happens _during_ the hibernate sessionfactory construction. If we
            then inject using @Configurable a DAO that depends on the
            sessionfactory, we get a cyclic dependency.

            Further, it didn't seem to be a good idea to intercept constructors.
            90% of all loaded domain objects are read-only. The injected services
            are only needed when the domain object needs to change state. For
            performance reasons, we decided to inject lazily, and intercepted the
            getBlaBlaService() method in the Domain Object.
          • dkode8880
            Chris, Thanks again, This is the thinking that I was having so I m glad I have the right idea. I currently am using C# and I use Castle MonoRail for my MVC
            Message 5 of 12 , Sep 5, 2007
              Chris,

              Thanks again, This is the thinking that I was having so I'm glad I
              have the right idea. I currently am using C# and I use Castle
              MonoRail for my MVC framework and Castle Windsor for my IoC
              container. So same idea.

              Thank you for replying! Cheers!

              Sean

              --- In domaindrivendesign@yahoogroups.com, "Chris Richardson"
              <chris.e.richardson@...> wrote:
              >
              > Sean,
              >
              > I'm glad that you liked the presentation.
              >
              > The MoneyTransferService I describe in the presentation is a
              simplified but
              > typical service in the applications I work on.
              >
              > public class MoneyTransferServiceImpl implements
              MoneyTransferService {
              >
              > public MoneyTransferServiceImpl(AccountRepository
              accountRepository,
              > BankingTransactionRepository
              bankingTransactionRepository) {...}
              > }
              >
              > public BankingTransaction transfer(String fromAccountId,
              > String toAccountId, double amount) throws
              MoneyTransferException
              > {
              > Account fromAccount = accountRepository.findAccount
              (fromAccountId);
              > Account toAccount = accountRepository.findAccount
              (toAccountId);
              > fromAccount.debit(amount);
              > toAccount.credit(amount);
              > TransferTransaction txn = new TransferTransaction
              (fromAccount,
              > toAccount, amount, new Date());
              > bankingTransactionRepository.addTransaction(txn);
              > return txn;
              > }
              >
              > }
              >
              > (and, yes, this could probably be shorted to return
              > fromAccount.transferTo(toAccount,
              > amount) , and money shouldn't be a double :-) )
              >
              > The services are invoked by the web tier, e.g. Spring MVC
              controller. Each
              > service method is a few lines of code that takes object ids + other
              data as
              > parameters; calls some repositories to load some entities and then
              invokes
              > some methods on those entities to do some work etc. You could
              probably
              > characterize this as an application service rather than domain
              service but
              > if your services are simple like this one then having a separate
              domain
              > service isn't generally valuable. However, if the service was
              fatter and
              > manipulated, for example, XML messages or DTOs, then moving the
              domain logic
              > into a separate domain service might be a good idea.
              >
              > Chris
              >
              > --
              > Enterprise POJO consulting - http://www.chrisrichardson.net
              > Author, POJOs in Action - http://www.manning.com/crichardson
              > Enterprise POJOs blog - http://chris-richardson.blog-city.com
              > Speaking in 2007 at JavaOne, SpringOne, the Colorado Software
              Summit, the
              > Spring Experience
              >
              >
              >
              > On 8/31/07, dkode8880 <dkode8880@...> wrote:
              > >
              > > Chris,
              > >
              > > This is an excellent description covering many topics. There was
              a couple
              > > of things in
              > > there I was not aware of.
              > >
              > > Can you go more in depth on how services should be used in the
              domain? I
              > > was under the
              > > impression that the Service Layer should be a combination of
              multiple
              > > Repositories to
              > > accomplish some sort of group work. Is this accurate?
              > >
              > > Thanks again for the excellent webcast!
              > >
              > > Sean
              > >
              > > --- In domaindrivendesign@yahoogroups.com<domaindrivendesign%
              40yahoogroups.com>,
              > > "Chris Richardson"
              > >
              > > <chris.e.richardson@> wrote:
              > > >
              > > > Hi,
              > > >
              > > > Back in June at the SpringOne conference I gave a talk on
              improving
              > > > application design with a rich domain model. The video of the
              talk has
              > > > now been published. You can find out more about the talk and
              links to
              > > > the video and slides by going here
              > > > http://www.chrisrichardson.net/springOne2007.html .
              > > >
              > > > It would be great to get your feedback.
              > > >
              > > > Chris
              > > >
              > > > --
              > > > Author, POJOs in Action - http://www.manning.com/crichardson
              > > > Enterprise POJO consulting - http://www.chrisrichardson.net
              > > > Enterprise POJOs blog - http://chris-richardson.blog-city.com
              > > > Speaking in 2007 at the Colorado Software Summit and the Spring
              > > Experience
              > > >
              > >
              > >
              > >
              >
            • Jing Xue
              ... Hi, ... Ah, I see. Yeah, that s a well known gotcha . I actually even blogged about it a while ago:
              Message 6 of 12 , Sep 5, 2007
                Quoting Geert Pante <geertpante@...>:

                > --- In domaindrivendesign@yahoogroups.com, Jing Xue <jingxue@...> wrote:
                > Hi Jing,

                Hi,

                > I remember struggling with this for a while. One of the first issues I
                > had was that Hibernate calls a default constructor of persisted
                > objects to find out what the 'unsaved value' of the primary key is.
                > This happens _during_ the hibernate sessionfactory construction. If we
                > then inject using @Configurable a DAO that depends on the
                > sessionfactory, we get a cyclic dependency.

                Ah, I see. Yeah, that's a well known "gotcha". I actually even blogged
                about it a while ago:
                http://www.digizenstudio.com/blog/2006/02/06/the-circular-bean-reference-problem-in-spring-20s-arbitrary-domain-object-wiring/

                > Further, it didn't seem to be a good idea to intercept constructors.
                > 90% of all loaded domain objects are read-only. The injected services
                > are only needed when the domain object needs to change state. For
                > performance reasons, we decided to inject lazily, and intercepted the
                > getBlaBlaService() method in the Domain Object.

                Indeed, that's another valid approach which I toyed around for a
                little too, but in the end there are just some issues I can't get
                myself comfortable with (maybe you can help me sort out some of these
                as I'm sure you've thought it through):

                1. Intercepting getAService() would mean that the code everywhere
                needs to remember to call getAService() instead of using this.aService.

                2. From performance standpoint, every time getAService() gets called,
                it has to call getBean().

                3. There are many cases where services aren't necessarily for
                modifying an object, but for the object to performance its part of the
                domain logic. For instance, we had this User class that had a
                PasswordHashStrategy injected (not strictly a service, but as
                meaningful in this context) to handle password hashing.

                Cheers.
                --
                Jing
              Your message has been successfully submitted and would be delivered to recipients shortly.