Issues with depepency injection in latest frameworks.

Here I am going to show some of important limitations to Java and Guice approached to dependency injections, particularly where wiring logic should go.

Java Dependency Injection

public interface LogService {
public void log(String result);
}

@Named(“FileLogService”)
public class FileLogService implements LogService{
public void log(String result){}
}

@Named(“ConsoleLogService”)
public class ConsoleLogService implements LogService{
public void log(String result){}
}

public class LogClient{

@Inject
@Named(“FileLogService”)
private LogConsole logConsole = null;

public void doSomething(){
logConsole.log(“doSomething”);
}
}

This is one way of injecting dependency into client code using Java annotation. As you can see we just hard coded LogClient to FileLogService and there is no way to have LogClient use ConsoleLogService.

Qualifiers wont help here either since they are same as @Named except instead of String it uses annotation to hard code LogClient to particular instance of LogService.
Here is example with Qualifiers.

public interface LogService {
public void log(String result);
}

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface FileLogService {}

@FileLogService
public class FileLogService implements LogService{
public void log(String result){}
}

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface ConsoleLogService {}

@ConsoleLogService
public class ConsoleLogService implements LogService{
public void log(String result){}
}

public class LogClient{

@Inject
@FileLogService
private LogConsole logConsole = null;

public void doSomething(){
logConsole.log(“doSomething”);
}
}

Guice

In Guice the wiring logic is based on number of Binding and Provider implementations.

Linked Bindings

public class LogModule extends AbstractModule {
@Override
protected void configure() {
bind(LogService.class).to(FileLogService.class);
//we cant do this
bind(LogService.class).to(ConsoleLogService.class);

}
}

With Linked Bindings we cant even register more then one implementation of LogService interface thus again hard coding LogClient to FileLogService.

Instance Binding

public class LogModule extends AbstractModule {
@Override
protected void configure() {
bind(LogService.class)
.annotatedWith( Names.named(“FileLogService”) )
.toInstance( new FileLogService() );
bind(LogService.class)
.annotatedWith( Names.named(“ConsoleLogService”) )
.toInstance( new ConsoleLogService() );
}
}

public class LogClient{

private LogService logService = null;

@Inject
public void setLogService(@Named(“FileLogService”) LogService logService) {
this.logService = logService;
}
}

Same story here, we are limited to only one implementation of LogService. We could use more generic name in Names.named but we are still limited to one instance of LogService for every instance of LogClient (we cant configure multiple instance of LogClient with different instances of LogService).

Providers

They are just factories that will still create only one particular instance for LogClient. Event worse, now instead of coding our client to service Java type we are forced to code against provider Java type.

Summary

No matter what approach you take you still end up hard coding your client with particular instance of service it uses. The above examples dont cover all dependency injection use case but all end up with the same issue. There are only 2 ways to do dependency injection the right way:

1. Use plain Spring XML based injection where you define and wire instance manually (no autowiring). If you dont like XML, you can still do the whole thing in Java.

2. Have something like Guice module but instead of one module instance for the whole application use multiple instances configured with one particular LogService.
But you have to be careful with selection of clients and services so not to end up requiring a service that is already registered with different instance.

Finally, all this new dependency injection business is against basic OOP principles. You should never add anything more than a Java type to your client code dependencies (all client code should care is that there are set of method on its dependency it can call), and services should never have any knowledge of client using those. Their wiring should be done only by third party object and it should provide flexibility of wiring different instances of Java client class to different instances of Java services class.

34 comments to Issues with depepency injection in latest frameworks.

  • You are not correct.

    I’ll start with the final paragraph – annotations are metadata. Metadata is either external or internal. But it doesn’t have to do with OOP. Some prefer XML, some prefer the ease and compile-time checking of annotations. I see the point in both (having used both)

    About not being able to dynamically decide what to inject – again incorrect. First, with spring it is also not rather easy – you’d have to hardcode your dependencies in the xml, which is pretty much the same – the xml goes with your deployment. Yes, you can use a FactoryBean to decide dynamically what to inject.

    And in CDI you have quite a lot of ways do do that:
    - use a Producer to instantiate and return whichever implementation you like. You can add a InjectionPoint argument to your producer method and you have the details of the class and field where the injection is happening.

    - use Instance, and dynamically select the desired instance using instance.select(qualifier)

    I’d suggest to ask a question on stackoverflow or in the CDI forums whenever you have doubts about these things.

    And to conclude – I’m a strong spring supporter, and a but anti-JavaEE, but one can’t deny the power and thought that’s put into CDI (contexts and dependency injection, which you call java DI)

  • Tsolak Petrosian

    Thank you for the reply.

    I’ll start with the final paragraph – annotations are metadata. Metadata is either external or internal. But it doesn’t have to do with >>OOP. Some prefer XML, some prefer the ease and compile-time checking of annotations. I see the point in both (having used both)

    I am not arguing against annotations in general thought I much prefer to push this metada somewhere external like XML. A few times (mostly with Hibernate) annotation and their lake of inheritance support have given me problems in the past and forced to fall back to XML definition.

    About not being able to dynamically decide what to inject – again incorrect. First, with spring it is also not rather easy – you’d have >> to hardcode your dependencies in the xml, which is pretty much the same – the xml goes with your deployment. Yes, you can use a >>FactoryBean to decide dynamically what to inject.

    I am sorry but its not “pretty much the same”. XML is not hardcoding, hardcoding happens when Java class contains data that is specific to particular application or environment and cannot be reused in another application.
    XML is your application and thats the place all the wiring happens. Your Java class can (and most likely) be in separate jar that will be reused in different application and wired differently (i.e in one case with FileLogService another with
    ConsoleLogService) or even wiring differently in the same application.

    And in CDI you have quite a lot of ways do do that:
    - use a Producer to instantiate and return whichever implementation you like. You can add a InjectionPoint argument to your producer >>method and you have the details of the class and field where the injection is happening.
    - use Instance, and dynamically select the desired instance using instance.select(qualifier)
    I’d suggest to ask a question on stackoverflow or in the CDI forums whenever you have doubts about these things.

    The mecahnism you are talking still forces client to contain logic of slecting particular instance of the service.
    I challenge you to show me how you can do the following configuration using the mechanisms above:

    <bean id="fileLogService" class="FileLogService"/>

    <bean id="consoleLogService" class="ConsoleLogService"/>

    <bean id="logClient1" class="LogClient">
       <property name="logService" ref="fileLogService"/>
    </bean>

    <bean id="logClient2" class="LogClient">
       <property name="logService" ref="consoleLogService"/>
    </bean>

    And to conclude – I’m a strong spring supporter, and a but anti-JavaEE, but one can’t deny the power and thought that’s put into CDI (contexts and dependency injection, which you call java DI)

    Again I am not against CDI, contrary I have used CDI since before Spring with emerging DI containers, I am just showing the limitations of new CDI containers that avoid traditional third party wiring.

  • The feature of CDI that you are missing is @Alternative and (@Alternative stereotypes). @Alternative lets you select the particular implementation you’re interested in using the beans.xml file. It’s a much cleaner, less verbose solution than Spring’s XML.

    As for XML not being “hardcoding”, that’s simply nonsense, and no-one seriously believes that anymore. XML is code like any other code.

  • Tsolak Petrosian

    I am surprised its personally Gavin King:)

    As for XML not being “hardcoding”, that’s simply nonsense, and no-one seriously believes that anymore. XML is code like any other code.

    I want to start from this comment since I suspect I am still not clear on the actual issue.
    Please not that we are talking here about Spring context XML files.

    - XML is a code, yes. I have never denied it.
    - XML is not hard coded to particular application since it is the application by itself. In contrary to LogClient I am not going to be reusing my XML definition file.

    The feature of CDI that you are missing is @Alternative and (@Alternative stereotypes). @Alternative lets you select the particular implementation you’re interested in using the beans.xml file. It’s a much cleaner, less verbose solution than Spring’s XML.

    I just cant see how this can be clean, it does not even solve the configuration I had in the previous comment.

    Let me show an example using @Alternative:

    @Alternative
    public class FileLogService implements LogService{
    public void log(String result){}
    }

    @Alternative
    public class ConsoleLogService implements LogService{
    public void log(String result){}
    }

    public class LogClient{

    @Inject
    private LogConsole logConsole = null;

    public void doSomething(){
    logConsole.log(“doSomething”);
    }
    }

    and in beans.xml

    <beans xmlns="http://java.sun.com/xml/ns/javaee&quot;
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot;
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd&quot;>

        <alternatives>
            <class>FileLogService</class>
        </alternatives>

    </beans>

    So what we have here:

    1. You still cant have two LogClient instances injected with different implementation classes.

    2. You are only limited to static class alternative, you cant use bean instance as alternative.

    3. It will apply to all injection points that use LogConsole.

    Yes, you made LogClient not to be hardcoded with particular implementation of LogConsole but forced yourself into a trap of limiting you application to use only one implementation of service class.

  • XML is not hard coded to particular application since it is the application by itself. In contrary to LogClient I am not going to be reusing my XML definition file.

    I don’t believe you. If you’re setting up every dependency between every class in XML, which is what you’re arguing for above, then you most certainly *are* going to need to reuse the XML descriptors, since they are simply going to be so long and verbose and full of critical information about the structure of your application.

    1. You still cant have two LogClient instances injected with different implementation classes.

    Yes, of course you can. You differentiate them with qualifiers at the injection point. No this does _not_ hardcode a dependency from client to implementation, since it is indirected through the @Alternative mechanism, which lets you enable/disable a particular implementation of a particular type/qualifier combination. This is just a matter of good qualifier design.

    2. You are only limited to static class alternative, you cant use bean instance as alternative.

    Not true. Use a producer method.

    3. It will apply to all injection points that use LogConsole.

    Not true. That is what qualifiers are for. To differentiate, semantically, the different requirements of the various injection points.

  • P.S. I think part of the problem here is that you have set up a totally bogus example, and then try to prove things in terms of the bogosity of your example. Show me a REAL usecase, and I will show you how to solve it elegantly using CDI.

    No, it obviously does not make sense to choose between a FileLogger and a ConsoleLog on a per-injection point basis. *Clearly*, you choose between file logging and console logging either globally or on a per-module basis. Which is why @Alternative+beans.xml is a *perfect* mechanism to choose between file logging or console logging (beans.xml is per-module). It’s why your “challenge” is totally bogus.

    Now, when you do actually come up with a realistic usecase where you would want to choose between implementations on a per-injection-point basis, I’m really confident that I will be able to show you that qualifiers are an elegant solution to the problem. It’s just the nature of the need to choose on a per-injection-point basis that points to there being some relationship to what the client wants to do with the injected object.

    What you’re not getting is that what you do with one thing in Spring (external XML config), you do with a combination of two orthogonal things in CDI (@Alternative, and qualifiers). The CDI approach might take a couple of hours to get used to if you’re coming from Spring, but in the end it will save you a LOT of typing.

    • Tsolak Petrosian

      I don’t believe you. If you’re setting up every dependency between every class in XML, which is what you’re arguing for above, then you most certainly *are* going to need to reuse the XML descriptors, since they are simply going to be so long and verbose and full of critical information about the structure of your application.

      I dont understand why I need to reuse XML descriptor? The XML descriptor will just be part of my applications “war” or “ear”.
      If you are arguing that my XML will be so big that I have to separate it into a “jar” used across different application archive than its not done
      that way.
      Nothing forces you to only have one big XML file, you can split your configuration into smaller XML files that will be included with one line into
      main XML file.

      3. It will apply to all injection points that use LogConsole.

      Not true. That is what qualifiers are for. To differentiate, semantically, the different requirements of the various injection points.

      We are going in circle here. @Qualifier limits client code to particular service, but to avoid it you are suggesting to use @Alternative instead of @Qualifier, but not to have all clients use the particular service you are now saying to use @Qualifier that defeats the point of using @Alternative.

  • Tsolak Petrosian

    Ok, so you are arguing that there should never be a use case requiring my setup (thats a strong assumption). Here is another real world example with same setup.

    public interface Serializer{
    public void serialize(Object object, Writer witer);
    }

    public class XMLSErializer implements Serializer{
    public void serialize(Object object, Writer witer){..}
    }

    public class JSONSErializer implements Serializer{
    public void serialize(Object object, Writer witer){..}
    }

    public class WSController extends AbstractContoller{
    public Serializer serializer = null;

    public void handleRequest(HttpServletRequest request, HttpServletResponse response){
    String id = request.getParameter(“id”);
    Object entity = //get from DAO
    serializer.serialize( entity, response.getWriter() );
    }

    }

    <bean id="xmlSerializer" class="XMLSerializer"/>

      <bean id="jsonErializer" class="JSONSerializer"/>

      <!– will be accessed like http://yourdomain/xml –>
      <bean id="/xml" class="WSController">
         <property name="serializer" ref="xmlSerializer"/>
      </bean>

      <!– will be accessed like http://yourdomain/json –>
      <bean id="/json" class="WSController">
        <property name="serializer" ref="jsonSerializer"/>
      </bean>

    Here we created two controllers that will render entity queried from DAO as JSON or XML. Your proposition of @Alternative wont work here since the selection of service is done runtime insteadof deployment time.

  • Here is another real world example with same setup.

    Your example can easily be handled using a producer method.

    Though personally I would do it by simply creating two subclasses of WSController. I personally never use XML to implement a simple inheritance hierarchy. I like keeping as much as possible in Java where it can be easily understood and refactored. But then I guess it’s a matter of personal taste whether you prefer XML with its ugly syntax and generally crappy tooling or Java with its much nicer syntax and excellent tooling. My personal feeling is that I would definitely never work on a project with folks who prefer to use XML to do what you just did above. But I have the luxury of being able to choose who I work with. Not everyone does.

    If you are arguing that my XML will be so big that I have to separate it into a “jar” used across different application archive than its not done that way.

    I am arguing that it will be so big that the majority of its content will be *exactly* the same between different deployments of the system. I’m also arguing that if your application can’t possibly run without this chunk of XML, then the XML is simply not “configuration” as that word is usually understood by English-speakers (people whose brains are not damaged by over-exposure to Spring).

    Configuration is something you don’t mind typing from scratch when you create a new deployment of the system – and it is a very good practice to make sure that your application can run with *zero* configuration, using defaults. If your process for “configuring” a new deployment of the system is to copy/paste hundreds of lines of XML code, you’re simply not doing “configuration” as I understand the word. By my definition of “configuration”, your XML file is not configuration, it is code that defines the implementation of your system. In that case, it’s much better to express that code using Java.

    We are going in circle here. @Qualifier limits client code to particular service, but to avoid it you are suggesting to use @Alternative instead of @Qualifier, but not to have all clients use the particular service you are now saying to use @Qualifier that defeats the point of using @Alternative.

    Don’t be dense. I’m suggesting to use a combination of the two features. They solve different “parts” of the problem. It’s not “use qualifiers xor use @Alternative”. It’s “use qualifiers _with_ @Alternative”. And, very occasionally, you might need to introduce something extra, for example, a producer or a new subclass to solve some of the less common cases. That’s not in *any way* a bad thing or a limitation of CDI. The Whole Point of CDI is to let you express all this stuff in Java. If you start from the point of view that CDI can’t do something unless it can do it using a pure XML solution, then you’re simply missing the point. We tried to provide a solution where you write Java *instead* of XML, while leaving the flexibility to reconfigure things at deployment time.

  • To be clear, here is my preferred solution to your problem. (Not the only solution, just the one I prefer.)

    @XML
    class XmlWsController extends WsController {
    @Inject XMLWSController(XmlSerializer s) {
    super(serializer)
    }
    }

    @JSON
    class JsonWsController extends WsController {
    @Inject XMLWSController(JsonSerializer s) {
    super(serializer)
    }
    }

    And, of course, if you need the power to enable/disable these individually, depending upon the deployment, just annotate one of them @Alternative.

    Unlike your XML-based solution, my solution is 100% typesafe :-)

    And don’t come back at me trying to complain that I’m “forcing” you to write Java code instead of XML. Java is a better language with better tooling, and you’re a Java developer.

    • Tsolak Petrosian

      I will keep my reply short since you finally showed your solution to my use case.

      1. What you just showed whould have been laughed in the old days, because you just misused inheritance and defined 2 new classes just to be able to pass two different object to the class.

      2. You guys are so into this no XML war that everytime someone mentions XML (just for example) you start proving that its bad.

      You really like things to be in Java? Then do this:

      XMLSErializer xmlSerializer = new XMLSErializer();
      JSONSErializer jsonSerializer = new JSONSErializer();

      WSController xmlWSController = new WSController();
      xmlWSController.setSerializer(xmlSerializer);

      WSController jsonWSController = new WSController();
      jsonWSController.setSerializer(jsonSerializer);

      HttpHandler httpHandler = //look up or create
      httpHandler.register(“/xml”, xmlWSController);
      httpHandler.register(“/json”, jsonWSController);

      Its all pure Java no XML, and very simple.
      Its just people tend to make thing complex and come up with framework that supposedly would make it easy.

  • I will keep my reply short since you finally showed your solution to my use case.

    I showed one solution since you started out claiming that there were no solutions. There are others.

    What you just showed whould have been laughed in the old days, because you just misused inheritance and defined 2 new classes just to be able to pass two different object to the class.

    In the “old days”, needing to leave your primary programming language and start using a whole different language “just to be able to pass two different object to the class” would have been laughed at even harder and longer. Trust me. In fact, most of us non-Spring zealots laugh at the idea even today. However laughable my solution is, yours is way, way, more laughable.

    An I don’t actually believe that there’s anything much laughable about the code above. It’s a perfectly reasonable way to implement the two kinds of WSController you have in the system, given the information we have so far. Given more information about the requirements, perhaps we will find ourselves pushed in a different direction. I just wrote down the most straight-forward solution to the problem as presented by you.

    But, FTR, if you don’t like using inheritance here, there are other solutions that don’t require the use of inheritance. For example, you could use two producer methods as follows:

    @Produces @XML WsController xmlWsController(@New WsController c, @XML Serializer s) {
    c.setSerializer(s);
    return c;
    }

    @Produces @JSON WsController jsonWsController(@New WsController c, @JSON Serializer s) {
    c.setSerializer(s);
    return c;
    }

    Once again, completely typesafe, unlike your XML/Spring-based solution.

    You guys are so into this no XML war that everytime someone mentions XML (just for example) you start proving that its bad.

    Were you or were you not arguing that an XML-based solution was better? If not, I must have misunderstood everything you just wrote. If so, it seems relevant to point out all the problems of doing things in XML, including loss of typesafety, loss of toolability, etc.

    You really like things to be in Java? Then do this … Its all pure Java no XML, and very simple.

    Fine by me. I quite like that solution, personally, and it’s the solution I use in a whole lot of my own code. (I’m not actually such a dependency injection zealot as some.)

    But it sounds like you don’t actually use this solution in *your* code (since you are arguing for the use of a Spring XML-based solution), so criticizing me for “mak(ing) thing(s) complex” is a bit hypocritical, no? If the framework isn’t helping you, why do you use it?

  • Anyway, the point is, you were arguing that there was no solution to your problem in CDI, and I just showed you two solutions: one using inheritance, once using producer methods. So I guess we’re done here, right?

    • Tsolak Petrosian

      Gavin, I do appreciate you taking time showing me your point of view. I think I should have given example in plain Java code instead of Spring XML to avoid confusion that I am all for XML configuration.

      I do use Spring extensively but thats not for DI but its large library and nice support for Java proxies and AOP. Honestly I see very little use of DI, and I am sure Martin Fowler must be surprised seeing how his idea got such a widespread use.

      In the end I still dont buy your solution (the task was about doing the example wiring without introducing a new class) but let just see how your CDI implementation will stand against the time.

  • In the end I still dont buy your solution (the task was about doing the example wiring without introducing a new class)

    Now that’s just truly an absurd thing to say. Your solution avoided introducing a new class by instead introducing an XML file. WTF is the difference!? (Other than that your XML is non-typesafe and difficult to use with tools.) Why should we prefer the solution that introduces new XML over the solution that introduces new Java? Just because that is what you are used to when you use Spring?

    If the “task” was to do something without writing Java code, then by definition the XML-based solution wins, via the narrow definition of what constitutes the task. But of course, in practice that is never the real task. The real task is to solve interesting problems that users care about using code that is understandable and maintainable. Hell, we could eliminate *any* Java-based solution to *any* problem if we start by defining the “task” so that we are not allowed to write a new class. Pretty soon we will be programming 100% in XML (Remember Jelly, anyone?) And does anyone think that would be an improvement?

    C’mon, man up: tell us how, from a software engineering perspective, with reference to objective criteria such as maintainability, testability, toolability (you’re free to add your own objective criteria), the XML solution should be preferred to the Java solution. Or if you don’t have any argument for that (indeed, certain of your comments suggest you don’t actually believe that), then can we just drop the biased-in-favor-of-XML definition of the “task” and admit that I actually did indeed provide two very viable solutions to the original problem?

    Geez, this is like pulling teeth.

    • Tsolak Petrosian

      Gavin I am puzzled that you dont see basic OO desig being broken with your solutions.
      Do you understand what “separation of concern” in OO means? Its keeping enought information in the object for it to function and remove everything else.

      - First XmlWsController is a badly designed class. Its passed XMLSerialier that it should never care about, since all the methods XmlWsController needs are defined in Serializer interface (basic programing against interfaces). Are you suggesting to extend every bean for every injection points? What about if there are multiple injection points, so we end up with many combinations of classes extending WsController? I am not even mentioned if WsController is a third party class and is defined as final.
      Thats what I mean by introducing a new class. Not a class that will load my wiring (or the XML you are mentioning) but a new class for every injection point of one bean wiring (the more beans are wired the more useless classes you will have).

      - Now @Produces. This works as long as you keep a third Java class that will be injected with HttpHandler and WSController using XML annotation (from producer) and call “register” on HttpHandler with passed WSController.
      If you read my article thats what I was proposing with third party object which in case of Spring is XML and in your case combination of at least one wiring and a Producer Java classes.

  • Do you understand what “separation of concern” in OO means?

    It means keeping different “concerns” in different classes. Which of these classes addresses more than one concern? AFAICT, each addresses a single very well-defined concern.

    Its keeping enought information in the object for it to function and remove everything else.

    I don’t really understand your extremely vague definition. By your definition, how I would know if an “object” had more information in it than it needs to function. What does “object” mean? A class? An instance of a class?

    First XmlWsController is a badly designed class. Its passed XMLSerialier that it should never care about, since all the methods XmlWsController needs are defined in Serializer interface (basic programing against interfaces).

    Oh geez, you really are grabbing at straws here. So write the class like this:

    @XML
    class XmlWsController extends WsController {
    @Inject XMLWSController(@XML Serializer s) {
    super(serializer)
    }
    }

    There, no more direct depdendency XmlSerializer. Happy?

    P.S. I don’t see a whole lot of point to this change, since the whole point of XmlWsController is that it is the WsController that uses an XmlSerializer. That’s its whole nature.

    Are you suggesting to extend every bean for every injection points?

    Certainly not. Are you suggesting to write an XML bean definition for every injection point? No? Then why would I need a subclass for every injection point. You’re being deliberately stupid?

    What about if there are multiple injection points, so we end up with many combinations of classes extending WsController?

    Of course we don’t. Stop being stupid and use your brain. We end up with a subclass for each XML bean declaration in your Spring configuration. (*Extremely* unlikely to be very many of them, given the narrow set of usecases for this kind of thing.)

    I am not even mentioned if WsController is a third party class and is defined as final.

    Once again you’re changing the problem definition by adding new things that weren’t in your original statement of the problem. If WsController is final, use a producer method, obviously.

    Now @Produces. This works as long as you keep a third Java class that will be injected with HttpHandler and WSController using XML annotation (from producer) and call “register” on HttpHandler with passed WSController.

    Right. Which is precisely the same situation you are in with your Spring XML. Your Spring XML defines a “bean” and calls “register”. The only difference is it does it by configuring the framework using XML instead of just writing Java code.

    If you read my article thats what I was proposing with third party object which in case of Spring is XML and in your case combination of at least one wiring and a Producer Java classes.

    So you finally accept that the CDI and Spring solutions are conceptually equivalent? So we are done finally?

  • Of course, I should point out that if you’re really attached to your precious XML, Seam3 has a CDI portable extension (that will work with any CDI implementation) that allows you to define beans using XML, just like in Spring:

    http://docs.jboss.org/seam/3/xml-config/latest/reference/en-US/html_single/

    Personally, I would stick with the Java-based solutions I’ve described here, unless I had a very specific need.

    • Tsolak Petrosian

      I was hoping you would see the problem with your “inheritance” example, but you dont want to accept it which is fine for me.

      My article or our conversation was never about Spring vs Seam (or any other CDI implementation) it was all about the issues with most of CDI wiring options and examples on the web and in Seam documentation.

      I never argued about superiority of XML configuration but I am happy you finally showed your non XML solution, which again proves my original point in the article.

      As for Spring vs Seam lets just leave it to user to decide between Spring and Seam like they have decided between Hibernate and plain JDBC programing.

  • I was hoping you would see the problem with your “inheritance” example, but you dont want to accept it which is fine for me.

    Well, you simply have not explained what the problem is. How is my example less understandable, less maintainable, less typesafe, or less whatever-your-objective-criteria-is than some other solution? You have *asserted* that it is somehow wrong (and somehow less object-oriented, whatever that might mean), but you have not provided any reasons or argument in support of that view.

    This is a huge problem in our industry. People base decisions upon habit and vague feelings instead of actual objective criteria. I think the problem is that computer science courses don’t actually train folks in a scientific or engineering mindset. Folks in our field don’t actually learn how to make decisions on the basis of objective criteria, or to recognize what constitutes a valid argument or relevant evidence. Computing folks tend to have a kind of “magical” view of the world which depends more upon folklore and third-hand-gossip than upon reason.

    Look, let’s go back to your original claims, as written by you in your original blog post:

    No matter what approach you take you still end up hard coding your client with particular instance of service it uses.

    Clearly not true. In both my solutions, WsService has no direct dependency to XmlSerializer or JsonSerializer. We can both agree on that point, right?

    Finally, all this new dependency injection business is against basic OOP principles.

    Very hard to know what OO principle that you consider “basic” is being violated here.

    * Encapsulation of state and behavior?
    * Data abstraction/hiding?
    * Polymorphism?
    * Something else?

    Since there is no formal definition of the term “object oriented”, it’s always better to explain precisely what principle you’re talking about. To your credit you do give some kind of description of the principle you think is being violated. So let’s take a look at what you wrote next:

    You should never add anything more than a Java type to your client code dependencies (all client code should care is that there are set of method on its dependency it can call), and services should never have any knowledge of client using those. Their wiring should be done only by third party object and it should provide flexibility of wiring different instances of Java client class to different instances of Java services class.

    So neither of my solutions “violate” . The client (WsController) has a dependency to a “Java type” (Serializer), and not to anything else. Meanwhile, the implementation (XmlSerializer) of Serializer has no knowledge of WsController. It is all wired together by a separate object (XmlWsController subclass, or the xmlWsController() producer method), and there is plenty of fexibility to wire different implementations of the “services class” (Serializer) through the use of @Alternative/beans.xml.

    Do you *not* agree to this point? Do you still think my solutions don’t fit your own description of the requirements? Am I simply egregiously misreading what you wrote? Care to better formalize your definition of the thing you think is an OO principle that is being violated? Even better, would you do us the favor of showing how your formalized definition relates to the well-known principles of object orientation that the rest of us have heard of and have names for?

    I think part of the problem here comes back to your understanding of the term “hard coding”, which you use in a couple of places. I think you think that any code written in the Java language is “hard coded”. And you think that just because something is written in XML it is necessarily not “hard coded”. But this comes back again to the problem you seem to have with not defining things in terms of objective criteria. If you start by *defining* what you mean by “hard coded” in a technology-neutral way without reference to the XML or Java languages, I think you’ll find it becomes very, very difficult to justify the things you’ve been writing above.

    • Tsolak Petrosian

      Gavin its funny that you are naming people stupid and mentioning computer science but fail to understand this simple rule of inheritance:

      Inheritance is only used for defining a “type”!
      In java you should use inheritance in only 2 cases:

      1. Implementing interface in order to add a type to your class (Polymorphism).
      2. Extend abstract class in order to add a type and some predefined behaviour and maybe code reuse (Polymorphism+templating).

      Extending a class to inject an object does not fall in either category. You use “public” methods to do that!
      XmlWsController is perfect example where inheritance was used instead of composition and even worse the base WsController was already designed to use composition by referencing Serializer throught get/set methods.

      Here is a sample code to show how bad your inheritance approach can be (you seems to understand examples better):

      public interface TranslationService{
      public String translate(String s);
      }

      public class WSTranslationController{

      private TranslationService translationService = null;

      public void handleRequest(HttpServletRequest request, HttpServletResponse response){
      String text = request.getParameter(“text”);
      String translatedText = translationService.translate(text);
      response.getWriter().write(translatedText);
      }
      }

      public class TranslationSwingApp{

      private TranslationService translationService = null;

      public TranslationSwingApp(){
      //setup you swing GUI with TextField and Button to get translation
      }

      public void handleTransletButtonClicj(){
      String text = originalLanguageTextField.getText();
      String translatedText = translationService.translate(text);
      translatedTextField.setText(translatedText);
      }
      }

      public class WicketTranslationWidget{
      //setup all you wicket UI objects

      public void onSubmit(){
      String text = originalLanguageTextField.getText();
      String translatedText = translationService.translate(text);
      translatedTextField.setText(translatedText);
      }

      }

      Lets say that there are 50 TranslationService implementations for each 50 languages.
      With your inheritance example I need to extend 3 classes (WSTranslationController, TranslationSwingApp and WicketTranslationWidget)
      for each TranslationService implementation, in total having 200 classes instead of just having 50 classes + 150 lines of code were
      we call setTranslationService(..) or 150 lines of XML where we do

      <property name="translationService" ref="…"/>

      .

  • Gavin its funny that you are naming people stupid and mentioning computer science but fail to understand this simple rule of inheritance:

    I said you were “being” stupid (i.e. deliberately trying to misunderstand me). I don’t believe you actually are stupid. English is not a good language for saying this. In Spanish I would use “estar” instead of “ser”.

    Inheritance is only used for defining a “type”!

    That’s simply not true. That is one kind of inheritance: type inheritance. There is also implementation inheritance.

    In java you should use inheritance in only 2 cases:

    Oh whooaaa, slow down here. From where, precisely, do you derive the authority to tell me where I should or should not use inheritance. Yet again you’re asserting things instead of providing evidence and argumentation from objective facts. Seriously man, you need to get away from this habit. It’s clearly a tic.

    1. Implementing interface in order to add a type to your class (Polymorphism).

    Rrrm, so when you implement an interface, how are you defining a type? You’re not – you’re implementing the type.

    2. Extend abstract class in order to add a type and some predefined behaviour and maybe code reuse (Polymorphism+templating).

    Extending an abstract class in order to fill in the abstract methods and/or extend the construction logic is also not a case of type inheritance. And my use of inheritance actually falls into this category.

    So your given examples of inheritance actually prove your first statement wrong. Wow.

    Extending a class to inject an object does not fall in either category.

    Extension is one perfectly legitimate way to fill in the contract required by the superclass constructor: i.e. that it needs a collaborating object of some type. You keep *asserting* that this is somehow wrong, but you have so far failed to provide a single reason to believe you. Sorry mate, but the burden of proof in this case falls upon your shoulders. It is the responsibility of the person asserting that a working piece of code is bad to show why it is bad. Otherwise the strong assumption is that if it works, it is acceptable.

    There’s a book I once read called “The logic of real arguments”, which was about how to evaluate an argument written in natural language (as opposed to mathematical formalism) and determine if the author had really proved their point. Really nice little book. I strongly recommend it to you.

    Great I found it on Amazon:

    http://www.amazon.com/Logic-Real-Arguments-Alec-Fisher/dp/0521313414

    You use “public” methods to do that!

    Actually a public method is in theory not really a very good way to do this, because provides the potential for clients to mess with the injected object (which should be an immutable reference). But, understood, Java is not very good at managing immutability, so it is common practice in the industry to use public methods where they are strictly inappropriate. But there’s still a lot of folk who think that injection via methods (v.s. via constructors) is Wrong. Strictly speaking, I agree with them.

    XmlWsController is perfect example where inheritance was used instead of composition.

    Actually I used inheritance to *implement* composition. :-) And in this case there was nothing wrong with that. In some other cases, it might not be the way to go.

    you seems to understand examples better

    Yep, me along with 5 billion other people on the planet :-)

    Lets say that there are 50 TranslationService implementations for each 50 languages.

    Then you have a perfect example for NOT using (plain vanilla) dependency injection. That’s just a nutcase application of DI.

    instead of just having 50 classes + 150 lines of code were
    we call setTranslationService(..) or 150 lines of XML where we do

    LOL, do you really do that?!! You seriously have 50 classes and 150 lines of XML configuration to do this?! You do realize how incredibly ridiculously verbose that is, right? So I had it right all along. You really are a case of a brain-damaged-Spring-user seeing everything as a nail. Dude! Seriously. You need some time outside of Springworld to get back in touch with reality. :-) Instead of trying to educate me on “OO principles”.

  • P.S. Here is what a useful argument against my design looks like:

    This solution is difficult to [maintain/understand/debug/implement/test] because [insert reasons here]. However, my proposed solution using Spring XML is much easier to [maintain/understand/debug/implement/test] because [insert reasons here], and doesn’t introduce significant new problems because [insert reasons here].

    What your argument shouldn’t look like is:

    1. Simple assertion without argument.

    2. Appeal to authority (some book you read where someone with lots of time on their hands expressed their own personal opinion about object oriented design). It doesn’t make any difference whether the authority in question has a well-known name in the field. My Mum’s opinion is just as relevant as Alan Kay’s (i.e. not at all).

    3. Changing the subject or problem statement, for example: “oh, but what if WsController is final”, or introducing some completely different problem with 50 classes instead of 2. A solution was proposed for the case of 2 non-final classes. The solution might not be appropriate for 50 final classes. That doesn’t prove it’s not appropriate for the original problem. You have to show how the solution is inappropriate for the problem that was initially presented, or you should accept that it was indeed a reasonable solution for the original problem, but then explain why and how the original problem didn’t actually capture all the requirements you were really interested in (some words like “sorry, I guess that was a bad example” might help).

    Do you see what I’m getting at here? Trust me, this stuff will help you in your career.

  • So your response is three (3) appeals to authority. You’re really not good at this, are you? Obviously you don’t even understand the authorities you’re reading well enough to be able to translate their arguments into your own words, and show how they actually apply to this situation. That’s frankly really disappointing. You should feel a bit betrayed that your expensive education in computing has left you so unprepared to actually discuss technical issues using logical reasoning and technical arguments.

    At least Erich Gamma and Josh Bloch should be enough authority for you. You can google “Favor composition over inheritance” for more.

    In most quarters, class inheritance for the sole purpose of code reuse has fallen out of favor. The primary concern is that implementation inheritance does not provide any assurance of polymorphic substitutability—an instance of the reusing class cannot necessarily be substituted for an instance of the inherited class.

    The way I use inheritance is clearly *not* for the “sole purpose” of code reuse. Indeed, my subclasses inherit in the public interface of the class they extend and don’t even add any new interface. They are indeed polymorphically substitutable for the superclass and I indeed use them as instances of the superclass. So this argument is totally, completely irrelevant to the case we’re arguing about!

    Now, what this Wikipedia quote is actually talking about is C++-style “private inheritance” where a class inherits the internal implementation of another class but does not re-publish its interface. That’s not the case here. Java doesn’t even have such a construct. The fact that you don’t even understand the basic concern here, or the historical context in which it arose is very, very strong evidence that you should simply not be arguing with folks who actually do know what they are talking about.

    As for your reference to the Bloch text, did you even actually read it?! Quote:

    Inheritance is a powerful feature for code reuse, but it is not always the best tool for the job … It is safe to use inheritance within a package where the subclass and superclass implementations are under the control of the same programmers.

    Which is the case we have here. I don’t think you’ve mentioned that WsController and JsonSerializer are written and maintained be different teams. It certainly sounds unlikely.

    Now, Bloch goes on to describe some actual problems with the use of cross-package inheritance, which revolve around subclasses which call and/or override methods of the superclass. Which is not what I did in my code example. In fact, all my code does is call the constructor of the superclass, which your solutions also do. So the “fragile base class” issue simply doesn’t come into play.

    I hope you are at least familiar with Martin Fowler work on DI (the guy who actually came up with the definition):

    I have indeed (several years ago) briefly read the linked paper, which was written several years after the first “IoC” containers for Java were available. You’re correct that Martin was responsible for coining the buzzword. But I’m not sure how relevant an article that was written like 8 years ago or something (and was last updated in ’04) still is today. I certainly don’t see how it’s relevant to the issue being discussed.

    • Tsolak Petrosian

      Please dont pollute this discussion with your lengthy explanation of substitution. I did not say your example breaks polymorphic substitution (cant even think how in Java you can break it) and please stop commenting on things which I never said (like this case or being pro Spring and XML). The wiki quote was provided to show that implementation inheritance is not favored and instead use of “delegate” is recommended. Its just was mentioning substitution as “primary” reason that not neccesary applicable to our case.

      So your response is three (3) appeals to authority. You’re really not good at this, are you? Obviously you don’t even understand the authorities you’re reading well enough to be able to translate their arguments into your own words, and show how they actually apply to this situation. That’s frankly really disappointing. You should feel a bit betrayed that your expensive education in computing has left you so unprepared to actually discuss technical issues using logical reasoning and technical arguments.

      Thats not a mature behaviour you are showing here. There is no reason to mock about authority here since insteadof me writing the whole chapter for you I am pointing to Bloack’s book as a source, so please give relevant arguments and show what in those articles contradic my comments.
      What I said about inheritance is confirmed by Bloch and others except he mentioned the edge case that is safe to use your example and you jumped on it.

      But lets see what it gives you..

      Here is what Block says about your inheritance case:

      Item 14: Favor composition over inheritance
      Inheritance is a powerful way to achieve code reuse, but it is not always the best tool for the job. Used inappropriately, it leads to fragile software. It is safe to use inheritance within a package, where the subclass and the superclass implementation are under the control of the same programmers. It is also safe to use inheritance when extending classes specifically designed and documented for extension (Item 15). Inheriting from ordinary concrete classes across package boundaries, however, is dangerous. As a reminder, this book uses the word “inheritance” to mean implementation inheritance (when one class extends another).

      Item 15: Design and document for inheritance or else prohibit it
      Item 14 alerted you to the dangers of subclassing a “foreign” class that was not designed and documented for inheritance. So what does it mean for a class to be designed and documented for inheritance? First, the class must document precisely the effects of overriding any method. In other words, the class must document itsself-use of overridable methods: For each public or protected method or constructor, its documentation must indicate which overridable methods it invokes, in what sequence, and how the results of each invocation affect subsequent processing. (By overridable, we mean nonfinal and either public or protected.) More generally, a class must document any circumstances under which it might invoke an overridable method. For example, invocations might come from background threads or static initializers.

      In summary, concrete Class inheritance should not be done against third party classes and needs to be very well documented. This pretty much limits their use to very special case. My original definition says not to use them at all since most developers wont have the need for that special case and will most likely misuse it. But thats not what our discussion is about, so lets continue with your comment on this case:

      Which is the case we have here.

      Did I get it right that you accept the fact that injection via inheritance for third party classes is bad choice?

      I don’t think you’ve mentioned that WsController and JsonSerializer are written and maintained be different teams. It certainly sounds unlikely.

      I am sorry, but I dont have to mention things like this. Java classes can come from different sources, I have never seen any framework putting some type of precondition on this.
      None is going to ask that either before choosing your solution and most certainly will try to use third party library.

  • wangliyu

    Is this the new war between CDI(Guice) and Spring? Can’t believe there is still a Spring die-hard out there. Even Spring3 support annotation (even it’s ugly), The only problem I have with Spring is that Spring guys try to anything they can to avoid standard (I mean JCP spec), so if you are on the boat, you sink with the boat, before it sunk, they won’t tell you anything about it, I was using Spring before Mr. Johnson switching license back and force.

    Anyway, I think CDI is more about “Just DI”, it does provide context (session, conversation and can add customized context), but Spring is suck at here, Spring support AspectJ annotation style (which I really hate, if it possible, just use AspectJ lang), Spring3 has SPEL(WTF name), it’s seems EL + Java binary code, wierd to me, I would prefer just write Java code or I’ll write C.

    BTW, XML isn’t OO, and I wondering where you get educated other than “Spring University”?

    • Tsolak Petrosian

      BTW, XML isn’t OO, and I wondering where you get educated other than “Spring University”?

      Thats funny. Hopefully you read the article insteadof just seeing “XML” and “OO” and jumping on to comments.

      But your post is good example of how extreme most developers can be, and what separates good software engineer from the rest.

      Lets just look back into history:

      1. First it was just Java code and plain “main” classes.

      2. Then EJB and XML bandwagon came and almost everyone jumped on it and companies started rewriting their systems using EJB’s and doing XML from remote communication to application configurations.

      3. Then POJO’s came to light with frameworks like Spring and Hibernate, both still using XML configuration. And again most switched from EJB to Spring+Hibernate + XML. All yelling that EJB container does not buy you anything and is not cool anymore.

      4. Then annotation came to light and everyone assumed its Java code and is now in progress of moving so called XML hell into Java annotation hell, yelling that it was good idea to do everything in Java after all. Funny thing is that ironically this is still called EJB.

      Now most are back to square one, and worst of all they brought the annotation bloat along with them and I am not sure how long it will take for them to see it.

      Smart developers on other hand never chase latest and greatest but pick and choose what is best for their current needs. They evaluate and question the new technology (like its done in this article) before jumping on it. And again they don’t just read “XML” and “OO” and say “XML isn’t OO” or see “Annotation” and “plain Java” and assuming “will just write Java code”.

      BTW,

      The only problem I have with Spring is that Spring guys try to anything they can to avoid standard (I mean JCP spec), so if you are on the boat, you sink with the boat, before it sunk, they won’t tell you anything about it, I was using Spring before Mr. Johnson switching license back and force.

      JCP has never been anything worthy, and has become almost nothing, Dough Lea’s departure is another example.
      The only standard you will have from now on is Oracle’s standard.

  • Geoff

    Interesting discussion, but Gavin’s point about creating 2 subclasses of the Controller just to change the serializer is pretty weak…that is the LAST thing you would want to do, and it is exactly why we use a dependency injection framework in the first place.

  • Roy Nid

    Come on guys! This is just getting interesting…love the awesome flame war! This is waaaaaay better than what’s on TV tonight!

  • J Yu

    It looks to me that Tsolak’s question is how to create two global objects of the same type, but with one property set differently. This question sounds strange to people who are not on the DI wagon. Why not create two objects, and set the property differently on each object, in simple Java code? Tsolak and Gavin both agree on that solution.

    Suppose in a greater picture, DI is a required technique to solve this particular problem, then Tsolak has made legitimate critiques that some DI frameworks cannot solve it very well.

    Gavin’s first solution is to create two new types. I would say that the solution is an ugly hack bent to fit the framework, and I’m sure a lot of people agree. Gavin set the bar really high if anybody wants to argue against his solution. I can’t meet that bar; it’s just my gut feeling. But what good are frameworks if they can’t make programmers feel good? Different solutions are often of same intrinsic complexity, but the “superficial” differences do set them apart, and people’s subjective and subconscious judgments do matter.

    However, if in a greater picture, a framework is selected for its overall greatness, and within the framework this is the necessary hack to make things work, I wouldn’t think twice. Yeah, two new classes for frivolous reason, sue me.

  • Alex F

    It’s just so funny how Gavin lacks self-control and he dives into flame, using all dirty words from his vocabulary, spending so much time to write long posts full of hate :) And all this to prove your point to a complete stranger? Come one, how old are you? :)

  • Alex F

    BTW, CDI advocates are probably that evil, because they see how weak their point is. Spring for sure takes major market share and it is not going to change in the nearest future. CDI must be 5 times better than Spring just to slooowly get people back from Spring. And for now it gives at most 20% of what can be done just with Spring DI, not to mention other parts of Spring framework and how they are well integrated with each other.

    The solution with a subclass-by-dependency is obviously ugly and Tsolak made good arguments why. The second solution with CDI is better, but you still need to put these producer methods in some class, which leads you to the same style, as in Spring JavaConfig, but with more annotations and more verbose. So again no benefit over Spring or plain vanilla Java factory (like in one of Tsolak’s examples).

  • irreputable

    Just for the record, here’s a real person asking the exact same problem:

    http://stackoverflow.com/questions/6514697/java-ee-6-injection-to-create-different-strategies

    so the problem itself is not totally bogus, as Gavin imagined. (Whether DI is bogus is another question)

Leave a Reply

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>