Spring and Autowiring of Generic Types

Spring 4 brings some nice improvements to how autowiring of generic types are handled. Before going into details, let’s look into the current state of affairs.

Basics

Consider the following example where you have one generic interface:

And two concrete implementations of it:

Now, the task is to create a FooService that autowires an instance of the FooDao class. Using current Spring versions, i.e. versions 3.x, one can either tie the implementation of the FooService class to the FooDao class:

Or use the @Qualifer annotation:

However, the disadvantage of these implementations is that they both suffer from coupling. In the first example, the FooService implementation is tightly coupled to the FooDao class. The second example has less coupling in a way that the FooService does not know about the class that implements the GenericDao, but there is still some coupling present because the name of the FooDao bean is hardcoded in the FooService implementation.

As of Spring 4 RC1, the issue SPR-9965 has been solved, which allows us to do autowiring by generic type:

Subtle difference, the key difference is that the FooService implementation does not need any information about the implementing FooDao bean, they are completely decoupled from each other.

Side note, if you attempt to use this solution in a Spring 3.x environment, you will find that it works if your application context contains a single GenericDao bean. However, you will get an exception if the application context contains two or more beans. When the generic type is not acknowledged, Spring cannot determine which bean to use:

Inheritance

To further investigate the autowiring issue, one can also see how it affects inheritance. In a pre Spring 4 environment, there is a little ceremony to handle inheritance and generic types. First, a GenericService needs a constructor with the generic type:

Then we yet again have to tightly tie the implementation of a specific service to its specific dao:

Spring 4 also makes it possible to autowire generic class hierarchies. First, we can autowire a GenericDao instance to the GenericService:

Next, we can implement the concrete FooService by just extending the GenericService with the generic type:

Problem solved with less code and less coupling than before.

Spring 4 RC1

Spring Framework project lead Juergen Hoeller writes in a blog post:

Overall, this is the perfect time to give Spring Framework 4.0 an early try! We’ll make sure to incorporate your feedback in a timely fashion on our way to 4.0 GA in December.

Spring 4 RC1 is available in the Spring milestone repository. Add it to your list of Maven repositories:

Update your Spring dependencies to version 4.0.0.RC1 accordingly:

Update

Dec 4th, 2013: Phil Webb has published a blog post at the Spring blog titled Spring Framework 4.0 and Java Generics which further elaborates the topic.

Update 2

Dec 12th, 2013: Adrian Colyer announced the release of Spring 4.0 (which means that you should update the version number to 4.0.0.RELEASE, and that you can remove the declaration of the Spring Milestone Repository in case you used the 4.0.0.RC1 version).

Mattias Severson

Mattias is a senior software engineer specialized in backend architecture and development with experience of cloud based applications and scalable solutions. He is a clean code proponent who appreciates Agile methodologies and pragmatic Test Driven Development. Mattias has experience from many different environments, including everything between big international projects that last for years and solo, single day jobs. He is open-minded and curious about new technologies. Mattias believes in continuous improvement on a personal level as well as in the projects that he is working on. Additionally, Mattias is a frequent speaker at user groups, companies and conferences.

This Post Has 21 Comments

  1. Good post, thanks!

  2. Thanks, nice post

  3. It took me a a few seconds to realise that the realise that concrete service saves specifying a constructor by having an Autowired type on the superclass. It takes a second to see but it’s good and a good use of Generics.

    1. @Phil: Thanks for pointing this out. I guess I was more concerned about the coupling when I wrote the blog post (i.e. in the old days, the FooService needs to autowire the concrete Dao implementation FooDao, as opposed to the Spring 4 way, where a generic Dao of type Foo GenericDao<Foo> can be used).

  4. I tried a sample but it seems generic types don’t work with spring 4. Probably I am missing something.

    Below code fails with an exception “NoSuchBeanDefinitionException: No qualifying bean of type [spring.generics.UserDao] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=userdao)}”

    @Component
    public class UserService {
    @Autowired
    private UserDao userDao;

    public void someService() {
    userDao.performDBOperation();
    }
    }

    @Component
    public class UserDao {

    public void performDBOperation() {
    System.out.println(“Executing db operation”);
    }
    }

    Any suggestions?

      1. On further troubleshooting I realized that the exception comes when I use generics (extends) in the class declaration. Sorry I missed it in my earlier comment.

        public interface Cacheable {
        }

        public class TimeUnit implements Cacheable {
        }

        @Component
        public class UserDao {

        public void performDBOperation() {
        System.out.println(“Executing db operation”);
        }
        }

        @Component
        public class UserService {
        @Autowired
        private UserDao timeUnitUserDao;

        public void someService() {
        timeUnitUserDao.performDBOperation();
        }
        }

        If I replace the UserDao to remove the extends keyword, the application starts as expected.

        Looking into the source code I realized that ResolvableType class checks if TimeUnit.class.isAssignableFrom(Cacheable.class) and since this check fails the application start up fails.

        Any inputs on why it worked in spring 3.2 and not in spring 4? How to make it work?

        1. @Amit: No, sorry, I have not experienced that. If you believe it is a bug, I suggest that you submit an issue to the Spring Framework project in the SpringSource Jira. Meanwhile, perhaps you can implement a workaround using the abstract class pattern described in the “Inheritance” paragraph above.

  5. I can’t make it work with Generic Type, always facing problem: NoUniqueBeanDefinitionException: No qualifying bean of type [GenericDao] is defined:
    expected single matching bean but found 2: barDao,fooDao

    There’s special in XML or anything else? Do you have a complete working example?

    1. @Hoai: Make sure that you use Spring version 4 or above, and that your repositories have the correct generic type, GenericDao<Foo> and GenericDao<Bar> respectively. Also verify that your service autowire the correct type.
      There is no magic in how your put your application context together. Component scanning of your repository packages should suffice regardless if you have an XML based or Java based application context.

      1. Sorry for very late reply but I lost this site. I think Spring come with other library in Appfuse that could make this cannot Autowired the Generic. I update Spring 3.2 to 4.0.0 (change spring.version only) and see it downloads other libs but I dont update this in pom/classpath. The source come with 4.0.0 work good. Maybe the JPA.
        I don’t have enough time to test because production has run.

  6. from last one week i was getting issue with the generic implementation issue of spring ,but now i got confidence after reading this blog.

    thanks for good explanation of generic issue.

    great post

  7. Nice Demo

  8. Great post.

    This is a feature I’ve wanted for a very long time. I’ve adopted the practice of specifying Service layer interfaces to Controllers via generic types (similar for Daos being wired into Services, etc.)

    public class BaseController {…}

    But prior to this feature, the service couldn’t be autowired into the BaseController class due to the limitation this removes. You had to @Autowire the service in the concrete class, create an abstract getService() method in the base class, that is implemented (identically) in every concrete service.

    In short, I viewed that as “boilerplate” code in the concrete classes that can now be eliminated. Specify the type of your Service as the generic parameter in your concrete class and that causes the base class to autowire it, provide a getService() implementation, and also allows you to USE the service in base class method implementations (such as common CRUD implementation methods).

    public class CurrencyController extends BaseController {…}

    1. @Dave: Thank you for your comment. It seems like we both have encountered (and solved) Java generics and Spring related issues in the past that Spring 4 brings a nicer solution to.

  9. when i use spring boot jersey, this feature doesn’t work.

    1. @kent: I am sorry to hear that. I suggest that you post a question on Stack Overflow with some more details, perhaps someone there is able to help you.

  10. Hi,

    Say you want to go extreme:
    inter
    public interface SimpleRepository extends CrudRepository{}
    public interface SimpleService {
    List findAll();
    T findById(int id);
    T add(T t);
    void deleteById(int id);
    void delete(T t);
    }
    public abstract class SimpleServiceManager implements SimpleService{
    @Autowired
    SimpleRepository repository;

    @Override
    public List findAll() {
    return new DaoUtilities().iterableToList(repository.findAll());
    }

    @Override
    public T findById(int id) {
    return repository.findOne(id);
    }

    @Override
    public T add(T t) {
    return repository.save(t);
    }

    @Override
    public void deleteById(int id) {
    repository.delete(id);
    }

    @Override
    public void delete(T t) {
    repository.delete(t);
    }
    }

    and the implementation of the manager would be something like
    public class FooManager extends SimpleServiceManager {}

    If I try to run something like that (eg, with a unit test )

    public class FooServiceTest {
    @Autowired
    SimpleService service;

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void testInitializaion(){
    log.info(“tesing initialization”);
    assertNotNull(service);
    }
    }

    I get an exception that states that Spring cannot deal with the un-managed type Object :
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘simpleRepository’: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class java.lang.Object

    Using spring 4.3.6 Release.
    Any hint would greatly be appreciated

    1. @Marco: I have not experienced this problem. However, I noticed one thing that may (or may not) be related to your problem. The SimpleRepository extends the CrudRepository interface without neither defining what kind of entities are being stored, nor what kind of ID is being used. You do that by providing the generic T and ID type arguments respectively, e.g. public interface SimpleRepository extends CrudRepository<User, Long>. Without them being defined, the Spring Data “magic” has no idea what kind of objects are being stored in the repository.

Leave a Reply

Close Menu