1
votes

I have a problem with Spring Boot application:

spring.bat init --artifactId=dbproto4 --boot-version=2.1.7.RELEASE --dependencies=jdbc,data-rest,web,thymeleaf,devtools,lombok,configuration-processor,security,data-jpa,data-jdbc,postgresql,actuator --description=dbproto4 --groupId=com.test --java-version=11 --name=dbproto4 --package-name=com.test.dbproto4 --version=0.0.1-SNAPSHOT

It is an exception:

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'testService' available

All files are in application root

Dbproto4Application:

@SpringBootApplication public class Dbproto4Application {

public static void main(String[] args) {
    SpringApplication.run(Dbproto4Application.class, args);

    ApplicationContext javaConfigContext = new AnnotationConfigApplicationContext(SpringConfig.class);
    TestService testServiceObj = (TestService) javaConfigContext.getBean("testService");        
    testServiceObj.addNewUser();

SpringConfig:

@EnableJdbcRepositories(basePackages = "com.test.dbproto4.infrastructure.storage.jdbcrepos")
@Configuration
public class SpringConfig { }

User:

@Entity
@Table(name = "userstab")
public class User {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    private String name;

    private String email;

...

}

UserRepository:

public interface UserRepository extends CrudRepository<User, Integer> {

}

application properties:

server.port = 8082

## default connection pool
spring.datasource.hikari.connectionTimeout=20000
spring.datasource.hikari.maximumPoolSize=5


## PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/example_db4
spring.datasource.username=someuser
spring.datasource.password=123456

spring.jpa.hibernate.ddl-auto=update

http://localhost:8084/actuator/beans/:

"testService": {
"aliases": [],
"scope": "singleton",
"type": "com.test.dbproto4.TestService",
"resource": "file [E:\\Java\\JavaProjects\\dbproto4\\target\\classes\\com\\test\\dbproto4\\TestService.class]",
"dependencies": [
"userRepository"
]
}

"userRepository": {
"aliases": [],
"scope": "singleton",
"type": "com.test.dbproto4.UserRepository",
"resource": null,
"dependencies": [
"(inner bean)#667aba3e",
"(inner bean)#22b3117e",
"(inner bean)#2607b66f",
"jpaMappingContext"
]
}

Actuator shows the bean named "testService", but Spring doesn't see it. How can i get bean "testService" from ApplicationContext?

1

1 Answers

0
votes

Solution

Perform these changes to your Dbproto4Application class

ApplicationContext javaConfigContext = SpringApplication.run(Dbproto4Application.class, args); 

TestService testServiceObj = (TestService) javaConfigContext.getBean("testService");  

Problem

Inside your Spring boot application, you have configured 2 different spring application contexts.

// 1st application context and the one which Actuator endpoint is referring to
SpringApplication.run(Dbproto4Application.class, args); 

// 2nd application context which is created here from which you want testService bean
ApplicationContext javaConfigContext = new AnnotationConfigApplicationContext(SpringConfig.class);
TestService testServiceObj = (TestService) javaConfigContext.getBean("testService");  

Notice that the 2nd application context which you created is built from SpringConfig which only has access to beans which are defined inside com.test.dbproto4.infrastructure.storage.jdbcrepos package. It does not have access to testService bean.