Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Autowire Annotation on Abstract class: No unique bean is defined

I've got an abstract class:

@Component
public abstract class BaseReport {

  public void export() {
   ...
}

And a bunch of classes that extend it, and override the export() method (or not).

@Component
public final class Report1 extends BaseReport

@Component
public final class Report2 extends BaseReport

Most of my tests autowire concrete classes that extend BaseReport, with no problems:

public class Report1Test extends BaseTest {

    @Autowired
    Report1 _report;

public class Report2Test extends BaseTest {

    @Autowired
    Report2 _report;

This works fine for autowiring of all classes that extend BaseReport. But I also need to autowire the abstract class itself, BaseReport, to test the export() method.

public class BaseReportTest extends BaseTest {

  @Autowired
  BaseReport _report;

When I try to run it I get the infamous:

No unique bean of type BaseReport is defined: expected single matching bean but found 2 [Report1, Report2].

I've tried using @Qualifier but the problem with @Qualifier is that (as I understand it) you use it to tell Spring which class -- that implements an Interface or extends an Abstract class - you wish to use. But that's not my case. I want to use the abstract class itself.

I also tried using @Resource, like this:

public class BaseReportTest extends BaseTest {

  @Resource(name = "baseReport")
  BaseReport _report;

Spring tells me there is no bean with this name. :(

How can I do this?

Cheers.

like image 374
Robert Bowen Avatar asked Apr 12 '13 12:04

Robert Bowen


1 Answers

Abstract classes can't be instantiated, you need to use a concrete implementation. Same as in regular java, if you try to instantiate an abstract class, it tells you to implement the abstract methods within. When you do, an anonymous class is created. It's not an instatiation of the abstract class, but a new subclass of that abstract class.

Spring will look for classes which extend your base class, being Report1 and Report2, Spring sees it has multiple classes which match the requirements and doesn't know which one to choose. thus you get the error that there are multiple matching beans.

You can fix this by making an "adapter" basicly create a concrete class which extends your base-class, implements the abstract methods, but doesn't do anything them. Then you can autowire that implementation and test against it. However your abstract class should allready be tested due to the fact you are testing report 1 and 2. If errors still occur with your base class, it means logic you don't use is causing bugs, which is a bad practice anyway. also with a test coveage tool you could spot unused code that way.

like image 94
G-Man Avatar answered Oct 24 '22 12:10

G-Man