mscharhag, Programming and Stuff;

A blog about programming and software development topics, mostly focused on Java technologies including Java EE, Spring and Grails.

Saturday, 12 April, 2014

The Grails depedency injection inheritance pitfall

This blog post is about a small pitfall you should be aware of when combining dependency injection in Grails with inheritance.

I think the problem is best explained with a piece of example code. So let's look at the following two definitions of Grails controllers.

class FooController {
  TestService testService

  def foo() {
    // do something with testService
  }
}
class BarController extends FooController {
  TestService testService

  def bar() {
    // do something with testService
  }
}

Both controllers look nearly identical. The only difference is that BarController extends FooController. Now assume we have an instance of BarController and we want to call the methods bar() and foo() on it. Guess what happens?

The call of bar() works fine while the call of foo() throws a NullPointerException because testService is null.

testService is a standard Groovy property. This means that the testService fields will become private and getter / setter methods are generated for both controllers. The getter / setter of BarController override the getter / setter of FooController. So whenever the dependency is injected using setTestService() only BarController retrieves the TestService instance. This is nothing special about Grails controllers, it works the same for services and other Groovy classes.

The solution is easy: Remove the testService dependency from BarController. Whenever testService is accessed in BarController, it will use the appropriate getter of FooController and everything works.

In this simple example the problem is quite obvious and can be easily solved. However, if your classes become larger this can be a bit tricky to debug. Assume you have a base class with multiple sub classes. Whenever you want to add a new dependency to your base class, you have to check all the subclasses. If one of the sub classes already defines the same dependency you have to remove it or it will not be available in your base class.

Comments

  • moaxcp (2015-04-17 21:37) - Monday, 17 August, 2015

    Isn't inheritance in grails controllers used more for code reuse than polymorphism. In that case does it really make sense to re-declare the dependency ever?

  • Randy Jones - Friday, 29 April, 2016

    Thanks, ran into this with a service, had been using inheritance with a controller but the service was a refactor and the injection was repeated in subclass.

  • Nina - Tuesday, 29 August, 2017

    Three years later I ran into this exact pitfall. Thanks for your post!

Leave a reply