Announcement Announcement Module
Collapse
No announcement yet.
Dependency injection becoming configuration injection? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dependency injection becoming configuration injection?

    Hi,

    I'm pondering on some design issue and would like some feedback. In a current project, we decided to use some of Spring to build up our beans and wire them together. That works perfect.

    Basically, we're using a bunch of DAO's, with the underlying data-source differing from LDAP to a remote SOAP service to a local jdbc db.

    We wire the appropriate implementation together in our application context, and when we want to test locally, just inject some stub implementation instead of the real thing.

    Now one of us took that a tad further and decided to inject implementation-specific configuration parameters into the beans as well. For instance, if the implementation needed is one that calls a remote SOAP service, stuff like the username/password/endpoint url all get injected through the application content xml file.

    These parameters of course are implementation-specific.

    It used to be that each implementation read it's configuration from a properties file (either a separate one or an application-global one).

    I can't seem to make up my mind but somehow it doesn't feel right. Dependency injection seems to be about wiring beans together so client code doesn't have to be aware of the actual implementation, just code against the interface.

    This is more like configuration injection?

    On one hand, our DAO's that read from the db do get their DataSource injected (so we can use the pooled one in the appserver and a simple one during local testing), that feels ok. But having usernames/passwords/url's/authentication method and all injected as well...

    Thoughts anyone?

    Thanks,

    Bas.

  • #2
    You inject the configuration parameters in the implementations, but the implementations are based on some interface that is injected into the bean that needs it.

    Example:
    Code:
    interface NotifyService{
       void notify(String msg);
    }
    
    class SmtpNotifyService implements NotifyService{
        private String url, login,password;//with getters and setters
    
       void notify(String msg){
             SmptConnection con = ..create some connection with url,login,password
             con.send(msg);
       }
    }
    
    class SomeObject{
        private NotifyService notifyService;//getter and setter.
    
        void doSomething(){
              notifyService.notify("I did something");
        }
    }
    
    <bean id="notifyService" class="SmtpNotifyService">
        <property name="password" value="foo"/>
        <property name="login" value="bar"/>
        <property name="url" value="blabla"/>
    </bean>
    
    <bean id="someObject class="SomeObject">
        <property name="notifyService" ref="notifyService"/>
    </bean>
    The SomeObject has no clue about the implementation of the injected NotifyService, so it still is programmed against an interface.

    But I`m not sure if this is what you mean (it feels to obvious). So: can you elaborate?

    Comment


    • #3
      Hi,

      Originally posted by Alarmnummer
      You inject the configuration parameters in the implementations, but the implementations are based on some interface that is injected into the bean that needs it.
      That's true. The client's still coding to the interface. All good.


      Originally posted by Alarmnummer
      The SomeObject has no clue about the implementation of the injected NotifyService, so it still is programmed against an interface.

      But I`m not sure if this is what you mean (it feels to obvious). So: can you elaborate?
      It could very well be obvious; it's my first shot at using Spring (at last!).

      The point is: configuring the actual implementations to use in the applicationContext.xml makes very good sense, it's just that I wonder if it also makes good sense to inject *all* configuration parameters this way.

      We used to put those in some properties file in the classpath, the implementing classes would get those by themselves, without the client code having to bother providing the configuration. All of a sudden, our implementing classes pretty much require Spring as they no longer get their configuration by themselves. Suppose I wanted to use some implementing DAO class, MovieDAOSOAPImpl, but not Spring.

      Instead of doing this:

      MovieDAO d = new MovieDAOSOAPImpl();

      and relying on MovieDAOSOAPImpl reading it's properties from movie.properties, the client code has to provide all the properties:

      MovieDAO d = new MovieDAOSOAPImpl();

      d.setEndPointUrl(...);
      d.setUserName(...);
      d.setPassword(...);
      d.setProxy(....);

      I don't know, I haven't figured it out, it's a judgement call I suppose. Or maybe I'm just too chicken to dive into Spring head-first (I rather put my toe in first)

      Dependency injection seems to be about wiring together your implementing classes; about relations from one bean to the next etc..

      Now all of a sudden, we have the original properties file, that gets included in our applicationContext.xml using a propertyConfigurer, and all those parameters are used to configure the beans (stuff like usernames/password/url's etc.). We're not only injecting depencies anymore but also all our configuration parameters. On the other hand, configuration data sort of is a dependency as well, perhaps.

      Cheers,

      Bas.

      Comment


      • #4
        Originally posted by bas-i
        Hi,

        It could very well be obvious; it's my first shot at using Spring (at last!).

        The point is: configuring the actual implementations to use in the applicationContext.xml makes very good sense, it's just that I wonder if it also makes good sense to inject *all* configuration parameters this way.
        In most cases I put the parameters in Spring. I wire up complete systems.. from very fine grained dependencies (like configuration parameters) to much large grained dependencies (like dao`s).

        If you don`t want configuration parameters in Spring, you could externalise them with a property file and let Spring read the property file.

        Now you can write something like this:
        Code:
        <bean id="notifyService" class="SmtpNotifyService">
           <property name="password" value="${password}"/>
           <property name="loginname" value="${loginname}"/>
           <property name="url" value="${url}"/>
        </bean>
        and a property file:
        Code:
        password = foo
        loginname = bar
        url = someurl
        Check the the following documentation for more information:
        http://static.springframework.org/sp...ry-customizing

        I don't know, I haven't figured it out, it's a judgement call I suppose. Or maybe I'm just too chicken to dive into Spring head-first (I rather put my toe in first)
        Personally I don`t like my objects to be aware of some configuration source. It makes them less reusable and less controlable (so testing is more difficult). I personally love the fact that my objects only implement some core functionality and I can remove other issues (a lot of them are solved by Spring).

        Comment


        • #5
          I think DI is equally valid and important for configuration parameters as for wiring up collaborators. In fact, the first version of the code I wrote that went onto become Spring focused on configuration parameters, rather than wiring up object graphs.

          Comment


          • #6
            Hi,

            I'm sort of beginning to see the light

            When doing something new I usually want to have a balance with how far to take things. One small step at a time.

            When you move away from the original way of implementing classes that read their own configuration (which possibly is bad but still a fact of life in our codebase) and have them injected, you're pretty much committing to do it like that everywhere from now on (having the client read the config and call 5 setters on the implementing class does *not* sound like a good idea). Hm. Did I mention I like small steps?

            Looking back at our code, it is a big improvement to what it was 2 weeks ago: it's much smaller (no more configuration reading, no tons of factories etc.) and testing is so much more convenient.

            I think I'm a convert!

            Cheers, and thanks for your input,

            Bas.

            Comment


            • #7
              Originally posted by bas-i
              Hi,

              I'm sort of beginning to see the light
              Great I`m using Spring for more than a year and I still see new lights. I do a lot of multithreading in my systems and since Spring I have seen a complete street with megawatt lighttowers in them.

              And the best of this all is that my codebase is influenced by ideas from Spring (and a lot of new insights on my side), but isn`t dependant on Spring. I could use it in another IOC container or can wire the objects in plain old java.

              When doing something new I usually want to have a balance with how far to take things. One small step at a time.
              This is my preferred style too. If you don`t have a good foundation, you have nothing at all. First small steps and then bigger steps.

              When you move away from the original way of implementing classes that read their own configuration (which possibly is bad but still a fact of life in our codebase) and have them injected, you're pretty much committing to do it like that everywhere from now on (having the client read the config and call 5 setters on the implementing class does *not* sound like a good idea). Hm. Did I mention I like small steps?
              If these arguments are very important, I prefer the constructor injection (you don`t have to worry about setters if you don`t have them).

              And having a static factory method in your class isn`t that bad, if you still have access to the constructor that accepts the 'base' arguments.

              bad:

              Code:
              class Foo{
                  String a;
                  String b;
              
                  public Foo(String propertyfile){
                       Properties props = new Properties(propertyfile);
                       a = props.get("a");
                       b = props.get("b");
                  }
              }
              good:
              Code:
              class Foo{
                  
                  public static Foo createFromPropertyfile(String propertyFile){
                       Properties props = new Properties(propertyfile);
                       return new Foo(props.get("a"),props.get("b"));
                  }
              
                  String a,b;
              
                  public Foo(String a, String b){
                      this.b = a;
                      this.b = b;
                  }
              }
              And you can call this in Spring:
              Code:
              <bean id="foo" 
                       class="Foo"
                       factory-method="createFromPropertyfile">
                  <constructor-arg value="foo.properties"/>
              </bean>
              So having a factory method isn`t that bad, if you still have access to the widest constructor.
              Last edited by Alarmnummer; Nov 14th, 2005, 05:40 AM.

              Comment

              Working...
              X