Constructor vs. Field injection

I was interviewing a candidate the other day; we were talking about Spring, when I asked him if he preferred constructor or field injection. Typically people pick a side; either the first or the second one, so I was pretty surprised when the candidate told me that it depends on the context. And actually, this is the most awesome answer (in my opinion, of course) one can give to this question.

A lot has already been written about this topic. Most of the articles (and several people I know) state that not injecting all your dependencies through the constructors you are doing it all wrong, as you are hiding your dependencies (This makes perfect sense, but only up to a certain limit). Do these people then actually say that you have no way to write code of good quality based on the EJB technology? There you cannot use constructor injection at all – since you must provide a no-arg constructor that will be called by the container. Can anybody say that every each such system is rubbish and should be thrown away? I’m quite positive that we could find awesome EJB systems without an exhaustive search.

On the other hand, however, in Spring you are free to inject anything through your constructors. Is it than the only one right way to do dependency injection? Should the field based option just left out starting from the next releases of the framework and buried forever?I’d say no – and not only for backwards compatibility reasons. There are many cases when constructor injection produces better results than field injection; but not always. 

Let’s just take two examples. In the first one we are producing the most awesome BDD framework ever. There is only one thing left for us to do, develop a reporting module that is capable of producing test results in various formats (XML, HTM and plain text, for example).  We can come up with something like this:


public class ReportHandler {

  private Reporter reporter;

  public ReportHandler(Reporter reporter) {
    this.reporter = reporter;
  }

  public ReportContents produceOutput() {
    //...
    reporter.getReport()
    //...
  }

  public void dumpOutput() {
    //...
    reporter.persistReport();
    //...
  }
  //...
}

Constructor based injection is clearly the right choice here. With field-based injection we couldn’t even decide what kind of reporter to inject – that is an another level of abstraction.

Let’s now suppose that we are writing a simple text parser utility; it needs to replace placeholders of format #{…} with actual values, replace end of line characters to Linux style and remove all lines that start with three stars. In this case these three responsibilities may very well be factored out to different classes. Now, we have two possibilities:

Nr. 1

public class Parser {

 public Parser(PlaceholderResolver resolver, EndingsReplacer replacer, CommentsDeleter deleter) {
   this. resolver = resolver;
   this.replacer = replacer;
   this.deleter = deleter;
 }

 public Text resolveProperties(...) {
   //...
   Text text = resolver.resolve(...);
   //...
 }

 public Text deleteComments(...) {
   //...
   Text text =  deleter.removeComments(...);
   //...
  }

 public Text replaceEndings(...) {
   //...
   Text text = replacer.replaceEndings(...);
   //...
 }
}

or Nr. 2

public class Parser {

 @Inject
 PlaceholderResolver resolver;
 @Inject
 EndingsReplacer replacer;
 @Inject
 CommentsDeleter deleter;

 
 public Text resolveProperties(...) {
   //...
   Text text = resolver.resolve(...);
   //...
 }

 public Text deleteComments(...) {
   //...
   Text text = deleter.removeComments(...);
   //...
  }

 public Text replaceEndings(...) {
   //...
   Text text = replacer.replaceEndings(...);
   //...
 }
}

The problem with the first version is that we are injecting dependencies through the constructor which are not really dependencies for the whole Reporter object, but for different methods only. This way we are polluting the constructor with dependencies that will be used at only one or two places.

People overly into constructor injection, commonly come up with problems like:

The second version is untestable, as we have no control over the three dependencies. This, in my opinion, is hypocrisy; we’ve all learnt so far that putting in a protected setter just for a unit test is not an evil thing. Having everything tested thoroughly is worth a such a method or two.

“One could call those setters within the package” they argue further… Well, perhaps we should treat each other like professionals who know what they’re doing and not malicious code-monkeys, which try to make the biggest harm possible.

“@Inject, a Spring related dependency is spread in my application”. Well this is not true, as @Inject is in package javax.inject, so this is a javax dependency. Anyway, let’s pretend we have @Autowired instead of @Inject; I’ve never seen a mature application that was ported from Spring to some other IoC container; if you use Spring, you inevitably have it as a dependency. It is, perhaps, not worth the effort to keep Spring-related stuff in the config files only, as it can keep you from reinventing the wheel.

Single responsibility principle is a two ways street. As such, it can be violated two ways: you either create objects with way too many responsibilities, or none. That is, you create your objects so dummy that they have no real logic in them. It’s like someone was like: “Introduce yourself, say that your name is Steven”. Shouldn’t it rather be “Introduce yourself” only, with the responsibility of telling your name left to you? I think it should. Not to mention that in the case of excessive constructor-injection you will -pretty fast- face with monster config files (be it Java or XML) – objects putting together other objects in a long, ugly chain.

In summary, field and constructor injection are two complementary technologies. Using one does not rule out the other; one should, however, apply common sense when dealing with this issue, and should not be overly biased toward one or the another.

JavaEE dependency injection – common mistakes

In this post, I will cover some common mistakes people make when it comes about injection in enterprise environment.

1.) @EJB and the new keyword

I’ve seen dozens of forum posts, was asked the question so many times: “Instead of injecting my dependencies, the container throws a NullPointerException. Why?”

Most of the times, the answer to this question is really simple: because you are instantiating your EJB with the new operator, and don’t let the container do its job. For example, let’s consider the following piece of code:

@Stateless
public class Car {

  @EJB
  private Engine engine;

  //...

  public void startEngine() {
    engine.start();
  }

  //...
}

@Stateless
public class CarSalon {

  //...

  public void testDrive() {
    Car car = new Car();
    car.startEngine();
    // ...
  }
}

You see both classes here are stateless session beans; however, if you tried to run the code above, you’d get a big fat NullPointerException. The reason is that the object Car is not managed by the container, even if it’s a session bean. When you use the new keyword, you get in charge for managing that object. An object instantiated this way is outside the reach of the container, and it has no way of injecting dependencies. None of the @EJB, @Resource, @PersistenceContext etc. injections will have any effect. Simply put, using new you can only create POJOs, not Enterprise Java Beans.

In order to fix this error, you have to get the container take care of the Car object. Nothing easier than that, we just have to either look up the bean tgrough an instance of the InitialContext class:

@Stateless
public class CarSalon {

  //...

  public void testDrive() {
    InitialContext context;
    try {
		context = new InitialContext();
		Car car = (Car)context.lookup(CAR_JNDI_NAME);
		car.startEngine();
		//...
    } catch (NamingException e) {
        //...
    }
}

or, have the container inject the dependency:

@Stateless
public class CarSalon {

  @EJB
  private Car car;
  //...

  public void testDrive() {
    car.startEngine();
    //...
  }
}

Either way, the container will get you a fully initialized instance of the bean from the bean pool. And all the injections start working again.

2.) POJO injection

By POJO injection, we can mean two different things: injecting POJOs into Beans, or injecting Beans into POJOs.

Unless we are using CDI (which may be the topic of another post), we cannot inject a POJO into a session bean. You can only inject EJBs into EJBs. Intuitively, you cannot use the @EJB annotation to inject a POJO (as it is not an EJB), also, you can only look up EJBs using the InitialContext (as POJOs have no JNDI names). In one sentence, without CDI you cannot inject POJOs anywhere.

The other way around, is possible, though. You can use a fully initialized EJB in your POJO code. The @EJB annotation will not work, as only an EJB can be injected into another EJB using annotations. However, your object needs not be an EJB to be able to use the InitialContext.lookup() mechanism (provided that there actually is a container running under your application).

Note that starting from EJB 3.1, JNDI names are standardized. If (using the example above) we suppose that we have an EAR called Salon_EAR amd an EJB project, called Salon_EJB then the JNDI name for the object Car is:  java:global/Salon_EAR/Salon_EJB/Car.

3.) EJB injection and constructors

This one is related to Glassfish(3.1.1) application server and perhaps several others (some other app servers may support this, but Glassfish is the reference implementation, so…)

Let’s get back to the car salon example above. Given this piece of code:

@Stateless
public class CarSalon {

  @EJB
  Car car;

  public CarSalon() {
    car.startEngine();
  }

  // ...
}

Surprisingly enough, this code will throw a NullPointerException in deploy time. The Car object injected using the @EJB annotation is not available in the constructor. And no, it’s not because CarSalon is created first and Car second (you can even annotate the Car class with @Startup to be sure about the initialization sequence).

What is the solution then? Is there no way of using container managed objects in the object initialization process? There is, fo course. Let’s move all the logic from the constructor into a @PostConstruct method. The code now looks like this:

@Stateless
public class CarSalon {

  @EJB
  Car car;

  public CarSalon() {
    System.out.println("Constructor");
  }

  @PostConstruct
  public void init() {
    System.out.println("PostConstruct");
    car.startEngine();
  }

  // ...
}

And guess what, this actually gets deployed. The post construct block will run as part of the initialization process, but still outside the constructor. It even makes your code cleaner since we all know that it is not a good idea to place work in the constructor. Not to say that all the injected resources are available in such methods.