20

I am developing a SpringBoot application (e.g. MyApp) with dependency to two data projects with different implementation:

data-jdbc.jar

  • built using the spring-boot-starter-jdbc which exposes JDBCDataService class that will be used by my application

Sample Code:

@Service 
public class JDBCDataServiceImpl implements JDBCDataService {

@Autowired
private JDBCDataRepository jdbcDataRepository;    
... 
}
  • with package my.data.jdbc
  • there is no SpringBoot main class. Spring configuration only created for the unit test classes
  • the repository classes are using JDBCTemplate

Sample Repository:

@Repository
public class JDBCDataRepositoryImpl implements JDBCDataRepository {

@Autowired
protected JdbcTemplate jdbcTemplate;
...
}

data-jpa.jar

  • built using the spring-boot-starter-data-jpa which also exposes JPADataService class that will also be used by my application

Sample Code:

@Service 
public class JPADataServiceImpl implements JPADataService {

@Autowired
private JPADataRepository jpaDataRepository;    
... 
}
  • with package my.data.jpa
  • there is no SpringBoot main class. Spring configuration only created for the unit test classes
  • repository classes extends the CrudRepository interface

Sample Repository:

@Repository
public interface JPADataRepository extends CrudRepository<MyObject, Integer{
...
}

In my SpringBoot project, I have the following SpringBoot main application:

@SpringBootApplication
public class MyApp extends SpringBootServletInitializer {
}

In my business service MainService class, I have the following injection

@Service
public class MainServiceImpl implements MainService {

@Autowired
private JDBCDataService jdbcDataService;

@Autowired
private JPADataService jpaDataService;

However, I have encountered the problem "Could not Autowire. No beans of 'JPADataService' type found" which only exists for the class JPADataService but working fine for JDBCService class.

I have tried the solution found in the following questions, but none of these work in my case:

Can't I @Autowire a Bean which is present in a dependent Library Jar?

@ComponentScan(basePackages = {"org.example.main", "package.of.user.class"})

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

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

I have now found the solution on my problem. I have to move up my main MyApp.java one package level higher in order to scan my data libraries.

Instead of putting my MyApp.java under my.app package, I have to move it under my in order to successfully scan my libraries with my.data.jpa and my.data.jdbc packages.

Community
  • 1
  • 1
Jown
  • 453
  • 1
  • 3
  • 17
  • `@ComponentScan` will only work if the `JPADataService` class is annotated with `@Component`. You need to add an `@Bean` annotated method in your `@Configuration` class. http://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html – Christopher Schneider Aug 05 '16 at 13:31
  • @Christopher Schneider ,both service classes in both jar files are actually annotated with `@Service`. AFAIK, `@ComponentScan` should also be able to read those classes. – Jown Aug 05 '16 at 13:59
  • @Service should take care of it. You say you have no main class, so where is the entry point to the application? – Christopher Schneider Aug 05 '16 at 14:39
  • The entry point is in my new SpringBoot app (MyApp) that I am developing, so I have those data as my dependency in my maven project. – Jown Aug 08 '16 at 06:59

4 Answers4

16

I have now found the solution on my problem. I have to move up my main MyApp.java one package level higher in order to scan my data libraries.

Instead of putting my MyApp.java under my.app package, I have to move it under my in order to successfully scan my libraries with my.data.jpa and my.data.jdbc packages.

Jown
  • 453
  • 1
  • 3
  • 17
  • Why did this happen? It's a bug or a spring-boot feature? – ajaristi Feb 22 '18 at 23:37
  • 2
    It's not a bug, @ComponentScan by default picks up from package where main class is defined and it's sub-directories – Gagandeep Kalra Apr 02 '18 at 10:39
  • 1
    You are a life savior @Jown. I spent almost a day to figure out the problem in my application. I added ComponentScan to my SpringBoot main application calls, it solved the actual problem, but that caused some other problem internal to my app. I have moved the SpringBoot main class, and it solved my problem. Literally you have saved my weekend.. kudos! – Satya P Feb 19 '21 at 15:56
12

Adding @ComponentScan won't work if the class you're attempting to Autowire isn't annotated with @Component. In order to get this to work, you'll have to annotate a method in your @Configuration class. Something like this should allow you to autowire the class:

@Configuration
public class ConfigClass{

    @Bean
    public JPADataService jpaDataService(){
        return new JPADataService();
    }
}
TuGordoBello
  • 4,350
  • 9
  • 52
  • 78
Christopher Schneider
  • 3,745
  • 2
  • 24
  • 38
  • I should add I'm not familiar with JPADataService. It may require some sort of configuration that I didn't account for. – Christopher Schneider Aug 05 '16 at 13:45
  • If this is the case, it should also not work in `JDBCService` object as I have not declared this class in any Java configuration file in my application which uses them. AFAIK, using `@SpringBootApplication` should do the magic for you :-) – Jown Aug 05 '16 at 14:06
  • anybody know why '@ComponentScan' wont work? I am facing the same issue, my repository is even annotated with '@Repository' and added a ComponentScan with base package value, which is one level up where spring could see all the beans even from jar libraries. The application only worked when I moved up one level the SpringBootApplication as @Jown said. – SHAKU Feb 07 '18 at 14:11
2

You need to config spring.factories at external jar:

external-jar-project
   |--java
   |--resources
        |-- META-INF
              |-- spring.factories

the contect of spring.factoires, like this:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx
ETO
  • 6,970
  • 1
  • 20
  • 37
Bond Zhou
  • 21
  • 1
-6

This problem has also bothered me for a long time. What I found is that springboot cannot scan the related classes under the jar package path you introduced.

You may need to use annotations like @EnableJpaRepositories ("cn.XXX") @EntityScan ("cn.XXX") to Scan your classes)

General Grievance
  • 4,555
  • 31
  • 31
  • 45
sweeter
  • 15
  • 1