1

I have a spring-boot application (Java8, spring-boot 2.1.4-RELEASE).

One of the services in the business layer need to @Autowire a bean from a certain jars in my classpath. In order to achieve that i had to add @ComponentScan({"package.to.my.bean.inside.the.jar"}) and it was magically scanned and wired successfully (this was added to the main spring-boot class which declare the main method).

However, since then my controllers aren't scanned hence the DispatcherServlet is returning 404 for every request i trigger (default dispatcher). Actually my entire spring-boot app annotations is being ignored - no scan is performed. Just to emphasis - the application worked perfectly before adding the @ComponentScan.

Main spring-boot app class:

package com.liav.ezer;

// This is the problematic addition that cause the endpoints to stop
// inside a jar in the classpath, in com.internal.jar package resides an 
// object which i need to wire at run time
@ComponentScan({"com.internal.jar"})
@SpringBootApplication
public class JobsApplication {
    public static void main(String[] args) {
        SpringApplication.run(JobsApplication .class, args);
        }
}

Controller example:

package com.liav.ezer.controller;

@RestController
@EnableAutoConfiguration
@RequestMapping(path = "/jobs")
public class JobController {

    @GetMapping(path="/create", produces = "application/json")
    @ResponseStatus(HttpStatus.OK)
    String createJob(@RequestParam() String jobName) String jobName){       
        return "job created...";
    }
}

I tried adding my spring-boot app base package to the list of packages in the @ComponentScan with no luck. I tried narrowing down the scope of the package declaration to be only on the class which i need with no luck. Here is the code

Liav Ezer
  • 29
  • 5
  • Add you controller package to @ComponentScan: `@ComponentScan({"com.internal.jar", "com.liav.ezer.controller"}) – Bor Laze May 31 '19 at 19:10
  • 3
    You told it to *only* scan `com.internal.jar`. Specifying a value *replaces* the default (package of containing class), it doesn't add to it. Please **read the documentation**, i.e. the javadoc of [`ComponentScan`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html): *"If specific packages **are not defined**, scanning will occur from the package of the class that declares this annotation."* – Andreas May 31 '19 at 19:14
  • Hi Andreas and Bor. As i wrote in the question - i did tried to add my base package to the list of scan (e.g @ComponentScan("com.internal.jar", "com.liav.ezer")) with no success. My controllers are still ignored – Liav Ezer May 31 '19 at 19:20
  • When adding my base package to the @CompoentScan my container fails to start and i get: *************************** APPLICATION FAILED TO START *************************** Description: Field jobManager in com.liav.ezer.service.JobNotifier required a bean of type 'com.internal.jar.JobManager' that could not be found. The injection point has the following annotations: - @org.springframework.beans.factory.annotation.Autowired(required=true) Action: Consider defining a bean of type 'com.internal.jar.JobManager' in your configuration. – Liav Ezer May 31 '19 at 19:27

2 Answers2

2

According to Spring documentation

Configures component scanning directives for use with @Configuration classes. Provides support parallel with Spring XML's element. Either basePackageClasses() or basePackages() (or its alias value()) may be specified to define specific packages to scan. If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.

In your case when you are adding

@ComponentScan({"com.internal.jar"}) you are disabling scanning of com.liav.ezer.controller

To fix it you can do the following configuration

@ComponentScan(basePackages = {"com.internal.jar", "com.liav.ezer.controller"})

Peter Gyschuk
  • 919
  • 8
  • 12
  • Actualy this is a more correct answer than the accepted one. – Alexander Petrov May 31 '19 at 19:48
  • @ComponentScan(basePackages = {"com.internal.jar", "com.liav.ezer.controller"}) this is the solution. – Alexander Petrov May 31 '19 at 19:49
  • As i stated above in the comments this approach (list of packages) which i tried after reading the doc's hasn't worked. Not only that it didn't progressed me i made a regression that my internal jar bean hasn't been wired. – Liav Ezer May 31 '19 at 20:21
  • @LiavEzer is you class in com.internal.jar package annotated as Component or any other Spring stereotype? If no Spring can not create instance of this class with ComponentScan – Peter Gyschuk May 31 '19 at 20:42
0

If so, remove @ComponentScan, can declare that bean in yourself configuration. try below

@SpringBootApplication
public class JobsApplication {
    public static void main(String[] args) {
        SpringApplication.run(JobsApplication .class, args);
        }
     @Bean
     public BeanInOtherJar xxBean(){
        return new com.internal.jar.XXX();
     }
}
Qingfei Yuan
  • 1,196
  • 1
  • 8
  • 12