Springboot upgrade 1.5.8 to 2.0 release getting exception "org.springframework.beans.factory.NoSuchBeanDefinitionException" - spring-boot

Gradle dependency related to kubernetes:
"io.fabric8:spring-cloud-kubernetes-core:0.1.6",
"io.fabric8:spring-cloud-starter-kubernetes:0.1.6",
"org.springframework.cloud:spring-cloud-starter-sleuth:1.2.4.RELEASE",
Getting the below exception while upgrading springboot 1.5.6 to 2.0.0.Release
Parameter 2 of method configurationUpdateStrategy in
io.fabric8.spring.cloud.kubernetes.reload.ConfigReloadAutoConfiguration$ConfigReloadAutoConfigurationBeans required a bean of type 'org.springframework.cloud.context.restart.RestartEndpoint' that could not be found.
Bean method 'restartEndpoint' not loaded because #ConditionalOnClass did not find required class 'org.springframework.integration.monitor.IntegrationMBeanExporter'
Bean method 'restartEndpointWithoutIntegration' in 'RestartEndpointWithoutIntegrationConfiguration' not loaded because #ConditionalOnEnabledEndpoint found property management.endpoint.restart.enabled with value false

You can do either of following, depending on your requirements:
Disable ConfigReloadAutoConfiguration if you don't need it:
#SpringBootApplication(exclude = ConfigReloadAutoConfiguration.class)
public class SomeApplication {
...
}
Add the following into your application.properties, just as the error message says:
management.endpoint.restart.enabled = true

Related

kotlin, spring boot and data classes for configuration

I've implemented several projects with spring boot and java. Now I'm evaluating, if I could do it with kotlin.
I am struggling with #ConfigurationProperties and data classes.
Simple example:
api:
clientId: client123
url: https://api.url.com
key: api-access-key
Data class:
#ConfigurationProperties("api")
#ConstructorBinding
data class ApiConfiguration(
val clientId: String,
val url: String,
val key: String
)
Starter class:
#EnableConfigurationProperties(ApiConfiguration::class)
#SpringBootApplication
class SpringdemoApplication
fun main(args: Array<String>) {
runApplication<SpringdemoApplication>(*args)
}
If I'm running a test, I get the following message:
s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'apiConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
...
Description:
ApiConfiguration is annotated with #ConstructorBinding but it is defined as a regular bean which caused dependency injection to fail.
Action:
Update your configuration so that ApiConfiguration is defined via #ConfigurationPropertiesScan or #EnableConfigurationProperties.
The following post doesn't help me: Kotlin & Spring Boot #ConfigurationProperties
Environment:
spring boot 2.7.8
kotlin 1.6.21
Can someone help me to understand and solve the problem?

#ConditionalOnBean not work for spring boot test

Hy everyone! I'm trying to solve the problem for a very long time.
There is very simple spring boot test
public class ApplicationTest {
#Test
void testContext() {
SpringApplication.run(Application.class);
}
}
And several beans...
#Service
#ConditionalOnBean(CommonService.class)
#RequiredArgsConstructor
public class SimpleHelper {
...
#Service
#RequiredArgsConstructor
#ConditionalOnBean(CommonFeignClient.class)
public class CommonService {
...
#FeignClient(
name = "CommonClient",
url = "localhost:8080"
)
public interface CommonFeignClient {
And the main class look as
#SpringBootApplication
#EnableFeignClients(clients = AnotherFeignClient.class)
public class Application {
When the spring application starts everything works ok. SimpleHelper does not created.
But in the spring boot test throw the exception:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'simpleHelper' defined in URL [...]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'foo.bar.CommonService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Please help, I don't understand what's going on anymore =)
Spring boot version is 2.3.0.RELEASE.
To use #ConditionalOnBean correctly, CommonService needs to be an auto-configuration class or defined as a bean by an auto-configured class rather than a service that's found by component scanning. This ensures that the bean on which CommonService is conditional has been defined before the condition is evaluated. The need for this is described in the annotation's javadoc:
The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.

Upgrade from Spring 4 to Spring 5 and run into #Autowired enforcement issue. Any workaround please?

I am upgrading our app from spring 4 to spring 5. The app has a third party dependency library that we can not touch. This library is using spring 4 and one of its beans is autowiring a null bean instance. This works fine in spring 4 but I got the following exception in spring 5:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'LibraryService': Unsatisfied dependency expressed through field '_beanDoesntExist'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'x.y.z.LibraryService$BeanDoesntExist' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
The following is a demo of such a #Autowired usage in the library that would trigger the exception above in spring 5(but worked fine in spring 4):
#Service
public class LibraryService
{
#Autowired
private BeanDoesntExist _beanDoesntExist;
static class BeanDoesntExist {
}
#Configuration
static class Config {
#Bean
public BeanDoesntExist beanDoesntExist() {
return null;
}
}
}
It seems in spring 5, a check is added: https://github.com/spring-projects/spring-framework/blob/master/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java#L1293-L1296
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
This check would enforce #Autowired to always get not null instance back if required=true which is the default.
By comparision, in spring 4, there is no such enforcement check and the following code would simply return null in my case: https://github.com/spring-projects/spring-framework/blob/4.3.x/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java#L1131-L1132
return (instanceCandidate instanceof Class ?
descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
Since I can't touch the library code, I wonder how can I get around the #Autowired enforcement in spring 5? My app can't be started up with this enforcement in place.
It is a breaking change in Spring 5 and has been covered here:
Change in how Spring 5 handles null Beans?
Using Optional or ObjectProvider seems to be a viable workaround.

Spring Boot 2.0.0.M2 and Spring Data Elasticsearch configuration

I'm trying to move my project to Spring Boot 2.0.0.M2.
This is my old Spring Data Elasticsearch configuration:
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
#Profile("production")
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.example.domain.repository.elasticsearch")
public class ElasticsearchConfig {
#Value("${elasticsearch.host}")
private String host;
#Value("${elasticsearch.port}")
private int port;
#Bean
public Client client() throws Exception {
return TransportClient.builder().build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host), port));
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() throws Exception {
return new ElasticsearchTemplate(client());
}
}
Right now I faced a following issue:
1. The method builder() is undefined for the type TransportClient
2. InetSocketTransportAddress cannot be resolved to a type
On the Maven classpath I have Spring Data Elasticsearch 3.0.0.M4:
How to properly configure current version of Spring Data Elasticsearch ?
UPDATED
For my tests I use Embedded Elasticsearch with a following application.properties:
#Elasticsearch
spring.data.elasticsearch.properties.http.enabled=true
spring.data.elasticsearch.properties.http.port=9250
spring.data.elasticsearch.properties.path.home=target/test-elasticsearch-db
spring.data.elasticsearch.properties.transport.tcp.connect_timeout=60s
This is my ES test config:
#Profile("test")
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.example.domain.repository.elasticsearch")
public class ElasticsearchTestConfig {
}
Right now the test fails with a following error:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'elasticsearchTemplate' defined in class path resource [org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchDataAutoConfiguration.class]: Unsatisfied dependency expressed through method 'elasticsearchTemplate' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.elasticsearch.client.Client' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:726) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:458) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
and
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.elasticsearch.client.Client' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1478) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1089) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
What is wrong here and how to fix this ?
Spring Boot 2.0 uses Elasticsearch 5 which includes some breaking API changes. You would be shielded from those changes if you used Spring Boot's auto-configuration rather than trying to write your own.
All that's needed is a value for the spring.data.elasticsearch.cluster-nodes property. With that in place, Spring Boot will auto-configure both a TransportClient and an ElasticsearchTemplate.
Had similar issue when migrating from spring-boot 1.5.6 to 2.0.0. The reason seems to be previous support for embedded elasticsearch is not more supported and the same is reflected in spring-boot.
Previously leaving the following property empty
spring.data.elasticsearch.cluster-nodes
put the following into use
spring.data.elasticsearch.properties.path.home
and spring-boot created given directory in the target folder for embedded mode to run. With spring-boot 2.0.0 (spring-boot-autoconfigure-2.0.0.RELEASE.jar to be precise) cluster-nodes has become asserted for non-null value causing elasticsearchTemplate bean not to be created under the hood.
That is the reason why your app stop working so suddenly.

"No qualifying bean of type [play.cache.CachedAction] is defined" error in Play Framework with Spring configuration

I have a Play Framework 2.3 project that configure to use Spring as DI library. When i use #Cached on my controller i encountered the following error:
`No qualifying bean of type [play.cache.CachedAction] is defined`
How can i fix this problem?
I add CachedAction bean to Spring configuration as a bean and now everything is ok.
#Configuration
#ComponentScan({"controllers","services", "daos"})
public class AppConfig {
#Bean
public CachedAction getCachedAction() {
return new CachedAction();
}
}

Resources