71

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?

BrianP
  • 1,857
  • 6
  • 20
  • 27
  • 1
    This is definitely possible. The first thing to check is whether your external jar file is getting deployed to tomcat along with everything else. Sometimes it's down to the way you're deploying, rather than the spring autowiring. – Ashley Frieze Apr 10 '15 at 22:02
  • 1
    Is the package containing this bean scanned by Spring? Why don't you provide the relevant code and configuration? – JB Nizet Apr 10 '15 at 22:03
  • 1
    If these are the real names, you should follow the usual naming conventions, i.e. class names start with an upper case. – dunni Apr 11 '15 at 09:42
  • @AshleyFrieze - Good point. I'm successfully pulling it in as a dependency in my maven pom file, and the application compiles, however how do I go about determining that the util jar is also deployed along with the app? – BrianP Apr 11 '15 at 12:34
  • @JBNizet - Yes, it's being scanned by spring, or at least I assume it is. – BrianP Apr 11 '15 at 12:35
  • Don't assume. Check it. Once again, where is your Spring configuration code. Package scanning doesn't happen magically. – JB Nizet Apr 11 '15 at 12:36
  • @JBNizet - Well, this is a library that is pulled into a spring application. My spring application is set up and working (i.e. component scanning is working such that Autowired works, for beans within the app). I don't want to set the library up as a full blown spring application. So is there some minimum setup such that the beans from the lib are visible in the application that's using the lib? – BrianP Apr 11 '15 at 14:12
  • So, in your own spring configuration, have you configured spring to scan the package of the service located in the external library. You're saying that "component scanning is working such that Autowired works". But it doesn't work, otherwise you wouldn't ask this question. We can't help fixing it and finding the bug if you persist to tell us nothing about the package of the helper service, and nothing about your spring configuration, despite being asked to several times. Voting to close. – JB Nizet Apr 11 '15 at 14:17
  • @JBNizet - Edited the question. Hopefully that's the info you're looking for. – BrianP Apr 11 '15 at 14:43
  • What I mean is Autowired works for beans that are defined WITHIN the application, but for this question it's not working for the bean defined from the external library. – BrianP Apr 11 '15 at 14:45
  • Did you use Eclipse to generate the library jar file, or did you use Maven? Do you have a single Spring context, or do you have a root context and an MVC context? Maybe the permission service is used by a bean of the root context, and the package is only scanned by the web context. – JB Nizet Apr 11 '15 at 14:53
  • How are you deploying everything to tomcat? Are you poackaging it into a war? In Maven or eclipse? – Ashley Frieze Apr 11 '15 at 15:35
  • Packaging into a war, using Maven. My problem ended up being that I simply didn't instruct the application to scan the library code for beans. Actually in all honesty, I didn't know to do that as I'm still somewhat new to this realm. – BrianP Apr 11 '15 at 16:05

5 Answers5

86

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.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Benjamin Boutier
  • 1,093
  • 8
  • 6
  • 1
    This was actually my problem. Thanks for the answer (Accepting this as the answer). In my application that is pulling in the library, I had to make sure to include the package of the lib in the @ComponentScan(). I didn't quite have it right, and after double checking, I made it right. Thanks again! – BrianP Apr 11 '15 at 15:40
  • 2
    Actually, I added `@EntityScan` & `@ComponentScan` on my `@Configuration` class, with all the right packages names, but it seems that my external jar still can't autowire an interface service that is implementing a `@Service` class. Maybe the problem come from the external library itself that should annotate the interface as well ? – Alex Jan 25 '17 at 12:34
  • is this package where jar is located or package where class is located in jar – jayant mishra Jul 09 '18 at 08:02
  • @jayantmishra package where classes and beans are located in the jar. This answer still helped me in my Spring 5 project. – kojot Jul 16 '18 at 07:04
  • Thx for the sollution. May I ask, I have class Config.java annotated as @Service and it does not work. Do you know why it does not work? – vnkid Sep 18 '20 at 11:35
23

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.

Maleck13
  • 1,709
  • 15
  • 17
12

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.

TuGordoBello
  • 4,350
  • 9
  • 52
  • 78
Holgi P
  • 141
  • 1
  • 3
8

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.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Hany Sakr
  • 2,591
  • 28
  • 27
1

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.

s91g
  • 11
  • 1