How can I @Autowire a spring bean that was created from an external jar?

JavaSpringMavenSpring Mvc

Java Problem Overview


I have a module/jar that I've created and am using as a util library. I created a service in there like so:

@Service
public class PermissionsService { ... }

... where this resides in a package here: com.inin.architect.permissions and in my main application, I'm referencing/loading this jar (i.e. set as a dependency in the maven POM.xml file for the app) like so:

<dependency>
        <groupId>com.inin.architect</groupId>
        <artifactId>permissions</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

and within the application I want to use that service like:

@Autowired
PermissionsService permissions

In the application's spring setup, I've got this:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.inin.generator", "com.inin.architect.permissions" })
public class WebConfig extends WebMvcConfigurerAdapter implements ServletContextAware { }

However when I run my application under tomcat, it complains that there isn't a bean for the PermissionsService: "org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ..."

So, how can I bring over the bean from the lib into my application? Surely there's a way. Do you have to set the library up as a full blown spring MVC application so that this can work? i.e. do you have to have @Configuration and @ComponentScan setup in the lib as well?

Java Solutions


Solution 1 - Java

You have to scan at least the package containing the class you want to inject. For example, with Spring 4 annotation:

@Configuration
@ComponentScan("com.package.where.my.class.is")
class Config {
...
}

It is the same principle for XML configuration.

Solution 2 - Java

Just a note on this, but you could decouple your dependency from spring. In your @Configuration class create

@Bean public PermissionsService  permissionsService(){
   return new PermissionsService()
}

This will also allow it to be injected. Not that you have to remove your spring annotation, just an option making it potentially usable outside of spring.

Solution 3 - Java

Ok - i had exactly the same problem - i wanted to autowire a mongo db repository interface from an external jar.

  • I could autowire every bean from that jar with using

    @SpringBootApplication(scanBasePackages = {"com.myrootpackage"})

  • However - autowiring the interface always failed with "Could not find blablabla..."

But the interface was in the same package as the beans i could import. It turned out that searching for the mongo db interfaces is NOT taking the scanBasePackages from the @SpringBootApplication into consideration!

It has to be explicitly configured via

@EnableMongoRepositories(basePackages = {"com.myrootpackage"})

Or you could move the main class "up" so the default searching works also for the mongo interfaces. So i understood the problem and found a solution. But i am still a bit unhappy because i need to configure the same lookup path twice. I find it stupid honestly.

Solution 4 - Java

I faced the same issue while scanning other classes from other project dependencies, The scanning solution depends on the type of classes you need to scan as follows:

if they are normal @Component, @Service annotations use

@ComponentScan({"com.mypackge1","com.mypackage2"})

If the type of classes are domain objects based on entities use

@EntityScan("com.mypackge1.domain")

If JPA repository classes

@EnableJpaRepositories(basePackages = {"com.mypackage.repository"})

If Redis repository classes use

@EnableRedisRepositories(basePackages = {"com.mypackage.repository"})

Same for Mongo, etc.

Solution 5 - Java

You can import application-context.xml for com.inin.architect.permissions in the following manner inside your main application.

<import resource="classpath:/permissionApplicationContext.xml" />

This will enable you to autowire beans from com.inin.architect.permissions that you have defined.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrianPView Question on Stackoverflow
Solution 1 - JavaBenjamin BoutierView Answer on Stackoverflow
Solution 2 - JavaMaleck13View Answer on Stackoverflow
Solution 3 - JavaHolgi PView Answer on Stackoverflow
Solution 4 - JavaHany SakrView Answer on Stackoverflow
Solution 5 - Javas91gView Answer on Stackoverflow