Announcement Announcement Module
Collapse
No announcement yet.
Dependency Injection for empty domain objects Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dependency Injection for empty domain objects

    Hi all,

    I'm using DependencyInjectionInterceptorFactoryBean to inject dependencies into my domain objects whenever Hibernate loads them.

    However, when the user creates a new (empty) object for insertion, I have a bean with factory methods to return empty domain objects.

    The question is how to inject their dependencies most elegantly, so that the identical dependencies are injected as in the case of Hibernate-loaded beans.

    I thought of two methods:
    1) define prototype beans for each domain object in my ApplicationContext.xml, with the same autowire settings as the DependencyInjectionInterceptorFactoryBean, and get my "factory" bean to return the instance created by the Application Context.
    Problem: no parameter-based constructor logic possible, since the no-argument constructor is called (some domain objects have considerable validation logic currently in the constructor).

    2) Create the domain object using a full-fledged constructor, and then inject the dependencies manually after fetching them from the Application Context.
    Problem: no guarantee that identical dependencies will be injected as in Hibernate-loaded case.

    A third option could be to create the domain object using a full-fledged constructor, and then run some method which would autowire the object for me from a given ApplicationContext. But I'm haven't yet found such a method easily accessible from the App Context.

    Any ideas?
    Best regards,
    Assaf Urieli
    Joliciel Informatique

  • #2
    Have you considered using AutowireCapableBeanFactory's autowire methods? It has two methods of interest: one creates an Object from a Class, autowiring its properties, and another takes an Object and autowires its bean properties. I use AutowireCapableBeanFactory with DependencyInjectionInterceptorFactoryBean whenever I need a new object.

    As for constructors enforcing logic, I think you'll find that causes you difficulty with domain objects reusable for all three common purposes: Hibernate persistence, MVC form backing, and business logic. Pretty much the former two require a default (no arg) constructor. I personally find business logic better enforced via a Spring Validator. A major reason I use AutowireCapableBeanFactor is to inject the Validator in, and then I use an interceptor at persistence time to fire the Validator to ensure the domain logic is in a valid state. You can find more info at http://forum.springframework.org/showthread.php?t=11293.
    Last edited by robyn; May 19th, 2006, 05:14 AM.

    Comment


    • #3
      Hi Ben,

      Thanks for your reply, and for the very interesting threads it refers to.
      A few questions regarding your approach (some of them quite na´ve I'm afraid, so bear with me):
      if creating a new instance, just autowire it from AutowireCapableBeanFactory
      Given an ApplicationContext (which is what I have by implementing ApplicationContextAware in my new domain-object "factory" bean), where do you get an implementation of the AutowireCapableBeanFactory? Do you create a DefaultListableBeanFactory? Can you give the actual code?
      I use AutowireCapableBeanFactory with DependencyInjectionInterceptorFactoryBean whenever I need a new object
      Related question: what do you mean when you say you use it "with" DependencyInjectionInterceptorFactoryBean? Do you use the latter somehow explicitly when creating new beans (as opposed to Hibernate-loaded beans)?

      - Have a bindSupport() method which configures domain object-wide properties (eg a Person object with a firstName and lastName, upon bindSupport() it updates the displayName)
      - Have a validate() method which calls the Validator, throwing BindException if any problems
      I have the following situation: following user manipulation, the parent object examines the state of it's child object graph, and depending on which changes were made,
      a) makes changes to the state of other child objects
      b) sends messages (actually persistable entities as well) to other users having previously manipulated this object's hierarchy.

      I see in your interface that you insist validate does not change the state of the object, but only reports errors.
      Would you place all of the above into bindSupport?

      - A BindAndValidateInterceptor and BindAndValidateAdvisor wires against all DAO implementations to call the domain object's bindAndValidate()
      - Spring MVC controllers use the normal Validator approach and call bindSupport() in the onBind() method
      I'm probably missing something here, but let's say in your MVC controller, you first bind the domain object (calling bindSupport), and then automatically call the Validator, and then, in onSubmit, you actually persist the changes through a service layer call.
      However, when you persist the object, the DAO layer "update" gets called, which in turn calls bindAndValidate()... So that both bind and validate get called twice. Is this what happens?
      If so, assuming (as in the above case), the bindSupport method makes other changes to the child object hierarchy (and possibly creates other objects for persistence), I would need some kind of boolean safeguard to make sure it only gets called once. All of which seems a bit messy!

      Hopefully I'm making sense, and sorry if any of these questions result from a complete misunderstanding!

      Comment


      • #4
        Originally posted by assaf
        Given an ApplicationContext (which is what I have by implementing ApplicationContextAware in my new domain-object "factory" bean), where do you get an implementation of the AutowireCapableBeanFactory? Do you create a DefaultListableBeanFactory? Can you give the actual code?
        Sure, this will do it:

        Code:
        public SomeClass implements BeanFactoryAware {
          private AutowireCapableBeanFactory acbf;
          public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            if (!(beanFactory instanceof AutowireCapableBeanFactory)) {
              throw new IllegalArgumentException("BeanFactory must be AutowireCapableBeanFactory");
            }
            this.acbf = (AutowireCapableBeanFactory) beanFactory;
          }
        }
        Originally posted by assaf
        I use AutowireCapableBeanFactory with DependencyInjectionInterceptorFactoryBean whenever I need a new object.
        Related question: what do you mean when you say you use it "with" DependencyInjectionInterceptorFactoryBean? Do you use the latter somehow explicitly when creating new beans (as opposed to Hibernate-loaded beans)?
        Sorry for being unclear here. When I have domain objects that I will be persisting via Hibernate, I use the DependencyInjectionInterceptorFactoryBean when retrieving those objects from Hibernate. I use the AutowireCapableBeanFactory.autowire methods when I am first creating those objects, before they are ever persisted. That's because my validation approach needs a Validator, and autowiring (via AutowireCapableBeanFactory for new instances, via DependencyInjectionInterceptorFactoryBean for existing instances) is an easy way to inject the Validator.

        Originally posted by assaf
        I see in your interface that you insist validate does not change the state of the object, but only reports errors.
        Would you place all of the above into bindSupport?
        Yes, the bindSupport method is allowed to change the object as it wishes. Validate is not supposed to change the object, given it theoretically should be dealing with a fully valid object by the time is is called.

        Originally posted by assaf
        I'm probably missing something here, but let's say in your MVC controller, you first bind the domain object (calling bindSupport), and then automatically call the Validator, and then, in onSubmit, you actually persist the changes through a service layer call.
        However, when you persist the object, the DAO layer "update" gets called, which in turn calls bindAndValidate()... So that both bind and validate get called twice. Is this what happens?
        Yes, it gets called twice. It needs to happen this way in case your services layer modifies the object in some way, making it invalid. This is why the interceptor sits on the DAO methods, because it's the last chance before it is actually saved. We could have taken that a step further and used a Hibernate Interceptor, but then bindSupport() could never modify the object. It's also non-portable to other persistence frameworks if you did that.

        Originally posted by assaf
        If so, assuming (as in the above case), the bindSupport method makes other changes to the child object hierarchy (and possibly creates other objects for persistence), I would need some kind of boolean safeguard to make sure it only gets called once. All of which seems a bit messy!
        If you're simply modifying properties in the child object hierarchy, what's the problem? It isn't too much of a performance problem to do that. Now if you are creating additional child objects, isn't there some sort of logic you could embed in your domain object to determine whether or not all the necessary child objects have been created? Working around the "only gets called once" won't work, because bindAndValidate() is designed to also be called by any business method that requires a guaranteed valid object state. So you could have a third, forth and fifth call as well in a given use case. As such I'd either leave creating the child objects to some other class (most likely the services layer method that implements the given use case) or embed necessary logic into the domain object to control whether or not it needs an additional child.

        Hope this helps.

        Comment


        • #5
          Thanks for your help! Works like a charm now...

          Comment


          • #6
            Ben Alex,your answer is great!


            High Power Green Laser Pointer
            Last edited by barcajunior; Oct 4th, 2010, 02:38 AM.

            Comment

            Working...
            X