I'm trying to create a library using Spring Boot that has a database and will be used in another Spring Boot Application. I don't know what I'm doing wrong but is not working. I guess the problem is related to the autoconfiguration or the bean scanning.
These are my current files: My library is called "demo-lib" and has the following files:
User Entity:
package com.example.demolib;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
// Constructor, getters and setters
}
UserRepository:
package com.example.demolib;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}
And finally I have a HelloWorldService with 3 basic methods:
package com.example.demolib;
import org.springframework.stereotype.Service;
@Service
public class HelloWorldService {
private final UserRepository userRepository;
public HelloWorldService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public String getHelloMessage() {
return "Hello World!";
}
public User storeUser() {
User user = new User("John", 30);
return userRepository.save(user);
}
public User getUser(Long id) {
return userRepository.findById(id).orElseThrow();
}
}
Now in my application project "timetreelib-integration" I have the following:
The main Spring Boot class with a @ComponentScan to been able to inject my library beans:
package com.artelys.timetreelibintegration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan({"com.example.demolib"})
public class TimetreelibIntegrationApplication {
public static void main(String[] args) {
SpringApplication.run(TimetreelibIntegrationApplication.class, args);
}
}
The demo-lib dependency in my pom.xml
<dependency>
<groupId>com.example</groupId>
<artifactId>demo-lib</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
An autoconfiguration registered in META-INF/spring.factories*
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.artelys.timetreelibintegration.autoconfiguration.HelloLibConfig
The configuration class were I'm defining the HelloWorldService bean that needs as parameter the UserRepository.
package com.artelys.timetreelibintegration.autoconfiguration;
import com.example.demolib.HelloWorldService;
import com.example.demolib.UserRepository;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HelloLibConfig {
private final UserRepository userRepository;
public HelloLibConfig(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Bean
@ConditionalOnBean(UserRepository.class)
public HelloWorldService helloWorldService() {
return new HelloWorldService(userRepository);
}
}
And a controller to with a simple endpoints to tests everything:
package com.artelys.timetreelibintegration.controller;
import com.example.demolib.HelloWorldService;
import org.springframework.web.bind.annotation.GetMapping;
public class HelloWorldController {
private final HelloWorldService helloWorldService;
public HelloWorldController(HelloWorldService helloWorldService) {
this.helloWorldService = helloWorldService;
}
@GetMapping("/hello")
public String timetreelib() {
return helloWorldService.getHelloMessage();
}
}
Now with this setup when I try to run the application project I get this error:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2024-01-31 16:13:36.950 ERROR 17696 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.demolib.HelloWorldService required a bean of type 'com.example.demolib.UserRepository' that could not be found.
Action:
Consider defining a bean of type 'com.example.demolib.UserRepository' in your configuration.
Process finished with exit code 1
I don't know if I'm doing something wrong...
I have to say that everything was working well when the library didn't have a Database.
I hope you can help me I can expand more on the information if needed.
Thanks in advance :)
Okay, I could find the solution. I will put it here in case this could be useful for someone.
I updated the TimetreelibIntegrationApplication main class and added 2 annotations.
@EnableJpaRepositories : To have access to the library repositories
@EntityScan : To have access to library entities (that are used by the library)
It seems to work fine :D This is how I have my application main class.
As an extra note, I have to say that the spring.factories file is not doing anything. I tried to remove this file and my autoconfiguration and everything is still working without problems.