Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to autowire a component in a dependency/external jar in Spring? [duplicate]

I have a Spring Boot project and I can't get components from an external jar to be autowired. When I try to, I got a org.springframework.beans.factory.NoSuchBeanDefinitionException saying that can't find a bean with that name available.

I tried some solutions found in similar questions, like these ones:

How to autowire @service from external Jar in Spring

Spring Boot @autowired does not work, classes in different package

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

..but still can't managed it to work.

Here is an example of what I'm trying to accomplish:

enter image description here

Here is boot class in the Spring Boot project spring-project-example

package com.springdi.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import com.dependency.example.DependencyBasePackageClass;
import com.dependency.example.somepackage.SomeBean;

@SpringBootApplication
@ComponentScan(basePackages = {"com.springdi.example"}, basePackageClasses = DependencyBasePackageClass.class)
public class SpringProjectExampleApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SpringProjectExampleApplication.class, args);

        String beanName = SomeBean.class.getName();
        System.out.printf("%s can be autowired: %s\n", beanName, String.valueOf(context.containsBean(beanName)).toUpperCase());
    }
}

It's just a simple Spring Boot project checking if it is possible to autowire a component present in the dependency jar.

Here is the component in the jar (dependency-example-1.0.0.jar)

package com.dependency.example.somepackage;

import org.springframework.stereotype.Component;

@Component
public class SomeBean {

    public void someMethod() {
        System.out.println("Some process...");
    }
}

And here is the base package class of this same jar

package com.dependency.example;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * Just a class to serve as the root for component
 * scanning in "com.dependency.example" and its sub-packages
 */
@Configuration
@ComponentScan
public class DependencyBasePackageClass {

}

I've already tried @Import(DependencyBasePackageClass.class) in SpringProjectExampleApplication and @ComponentScan with basePackages and basePackageClasses, but no success.

I also tried using @SpringBootApplication(scanBasePackageClasses = {SpringProjectExampleApplication.class, DependencyBasePackageClass.class})

and the not type safe @SpringBootApplication(scanBasePackages = {"com.springdi.example", "com.dependency.example"}).

@Configuration @ComponentScan({"com.dependency.example"}) also fails, context.containsBean("com.dependency.example.somepackage.SomeBean") still returns false.

This jar is included in classpath and in the pom.xml as a dependency

<dependencies>
    <!-- other dependencies -->

    <dependency>
        <groupId>com.rbaggio</groupId>
        <artifactId>dependency-example</artifactId>
        <version>1.0.0</version>
        <scope>system</scope>
        <systemPath>${basedir}/lib/dependency-example-1.0.0.jar</systemPath>
    </dependency>
</dependencies>

Could it be the location of the jar, the way it is included or some extra configuration needed?

I'd appreciate any help! Thanks in advance.

like image 394
Renan Baggio Avatar asked Jun 14 '19 00:06

Renan Baggio


Video Answer


1 Answers

Okey some basic things, you have mixed up your packages a bit.

@SpringBootApplication will scan all classes in packages below the class this is annotated on. This annotation is an alias for @EnableAutoConfiguration, @Configuration and @ComponentScan means that @ComponentScan(basePackages = {"com.springdi.example"}, basePackageClasses = DependencyBasePackageClass.class) is not needed.

com.springdi.example     // class with @SpringBootApplication annotation
         |
         |
         |
com.springdi.example.*    // Will find all @Service, @Component, @Configuration
                          // in subpackages below the @SpringBootApplication 
                          // annotation

You can read more about the annotation here SpringBootApplication

Since your other annotated classes are NOT in the same package structure as the @SpringBootApplication you need to define all the places you want to scan for annotations.

@SpringBootApplication(scanBasePackages = {"com.springdi.example", "com.dependency.example"})

will probably include all the packages that you want to scan through.

like image 105
Toerktumlare Avatar answered Sep 30 '22 20:09

Toerktumlare