0

I made a library project using Spring Boot that should be reused by other projects. In this library project I have an interface that needs to be implemented by the project that uses the library, something like:

public interface MyService {
    void doSomething();
}

I then autowire this interface in other beans in the library project like this:

@Service
public class AnotherLibraryService {
    @Autowired
    private MyService myService;
}

Obviously IntelliJ already tells me there is a problem: There is no bean for MyService. I want the project that uses the library to provide a bean for this interface like this:

@Service
public class MyServiceImplInOtherProject  implements MyService {
    @Override
    public void doSomething() {
    }
}

The library project is included in the concrete project as a Maven dependency. I want the library project to use the bean provided by the concrete project when I autowire MyService. Does anyone know how to configure this? Or is it not possible?

Btw: If I ignore the warning by IntelliJ and simply do it the way I described, the autowired MyService is null in the library project, even when there is a bean that implements it in the concrete project.

Philipp
  • 520
  • 3
  • 7
  • 1
    First, convert to constructor injection to eliminate the bug you have in your code (probably [using `new`](https://stackoverflow.com/questions/19896870)). Then it appears that you aren't actually adding a bean of `MyServiceImplInOtherProject` to the context. – chrylis -cautiouslyoptimistic- Sep 23 '21 at 16:08
  • @chrylis-cautiouslyoptimistic- Actually, I already use constructor injection in reality. I just wanted to make the examples as short as possible here. And I also forgot to add the Service annotation on MyServiceImplInOtherProject in the example (added it now). In reality I do that too. – Philipp Sep 23 '21 at 16:10
  • 1
    The autowired field _will not be null_ if you are not using `new`; you'll get a detailed Spring exception instead. – chrylis -cautiouslyoptimistic- Sep 23 '21 at 16:13
  • @chrylis-cautiouslyoptimistic- Damn it, you were right! There was one spot where I did not use constructor injection but simply injected it the way I wrote it in my question. Suddenly it works. You're a wizard! However, I don't understand why this happened. I never instantiated anything with "new ..." – Philipp Sep 23 '21 at 16:25
  • *Somebody* did, likely framework code of some variety. That's one of the major reasons to use constructor injection: If it fails, you get a noisy complaint from whatever framework indicating where the problem was instead of a delayed NPE time-bomb. – chrylis -cautiouslyoptimistic- Sep 23 '21 at 17:15

1 Answers1

0

I don't see any problem @Philipp, your approach is correct.

When your app starts to load all beans to the context regardless of what library come from

From the classes in your library, you can make use of any method defined in your interface. In the background, spring injects the bean (a specific class not an interface) in your service (which at the same time it is another bean)

As you pointed correctly, the "concrete" project MUST implement the interface that you provided in your library, otherwise you'll get an UnsatisfiedDependencyException

bipe15
  • 111
  • 1
  • 8