spring-cloud-netflix
spring-cloud-netflix copied to clipboard
Application fails to start due to missing AbstractDiscoveryClientOptionalArgs bean
After updating Spring-Cloud from 2022.0.2 to 2022.0.3, our application failed to start:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field optionalArgs in org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration required a bean of type 'com.netflix.discovery.AbstractDiscoveryClientOptionalArgs' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.netflix.discovery.AbstractDiscoveryClientOptionalArgs' in your configuration.
Our application is a mix of spring-boot web application and our internal core that relies on Grizzly and therefore ships org.glassfish.jersey.client.JerseyClient
as a dependency. Besides the fact that this is a regression, I'm wondering what's the proper way to configure the eureka client if a JerseyClient is on the classpath?
As a workaround I created the following configuration class
@Profile("dev")
@Configuration
public class DiscoveryClientOptionalArgConfiguration {
@Bean
@ConditionalOnClass(name = { "org.springframework.web.client.RestTemplate", "org.glassfish.jersey.client.JerseyClient" })
@ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class }, search = SearchStrategy.CURRENT)
public RestTemplateDiscoveryClientOptionalArgs restTemplateDiscoveryClientOptionalArgs(EurekaClientHttpRequestFactorySupplier eurekaClientHttpRequestFactorySupplier) {
return new RestTemplateDiscoveryClientOptionalArgs(eurekaClientHttpRequestFactorySupplier);
}
@Bean
@ConditionalOnClass(name = { "org.springframework.web.client.RestTemplate", "org.glassfish.jersey.client.JerseyClient" })
@ConditionalOnMissingBean(value = { TransportClientFactories.class }, search = SearchStrategy.CURRENT)
public RestTemplateTransportClientFactories restTemplateTransportClientFactories(RestTemplateDiscoveryClientOptionalArgs optionalArgs) {
return new RestTemplateTransportClientFactories(optionalArgs);
}
}
However, this should work out of the box with auto-configuration as it did before.
Please also consider https://github.com/spring-cloud/spring-cloud-netflix/issues/4177 as my comments there were ignored.
Same problem with SpringBoot 3.1.1 and SpringCloud 2022.0.3
***************************
APPLICATION FAILED TO START
***************************
Description:
Field optionalArgs in org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration required a bean of type 'com.netflix.discovery.AbstractDiscoveryClientOptionalArgs' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.netflix.discovery.AbstractDiscoveryClientOptionalArgs' in your configuration.
However i tried this eureka client cloned from here: repository The service registers correctly and works. The versions are the same.
Same problem here, also with Spring boot 3.1.1 and Spring Cloud 2022.0.3
Same problem here.. any solution
Same problem
@HJK181 are you sure that is ok to change @ConditionalOnMissingClass to @ConditionalOnClass
@Shapoval1van For our purpose as both classes are on the classpath it's enough. However, we only use Eureka for local development ... I doubt that this is a reasonable general-purpose fix ...
@HJK181 I see that exist some Jersey3DiscoveryClientOptionalArgs here but I can not find a source.
@Shapoval1van The auto-configuration happens inside the spring-cloud-netflix-eureka-client: https://github.com/spring-cloud/spring-cloud-netflix/blob/v4.0.3/spring-cloud-netflix-eureka-client/src/main/java/org/springframework/cloud/netflix/eureka/config/DiscoveryClientOptionalArgsConfiguration.java#L67
There you can see that the default RestTemplateDiscoveryClientOptionalArgs
is not configured when you have org.glassfish.jersey.client.JerseyClient
on the classpath. My workaround above configures the default behavior even though JerseyClient is on the classpath, as I didn't want a discovery client based on Jersey but on RestTemplate
. However, if you want a Jersey discovery client, there is Jersey3DiscoveryClientOptionalArgs
which is shipped as part of com.netflix.eureka:eureka-client-jersey3
dependency. However, that dependency is only shipped as part of spring-cloud-starter-netflix-server
and not when you actually need it in spring-cloud-starter-netflix-eureka-client
I have nothing more than what I’ve posted in the issue description. What is the exact error you get?
My workaround only works if you have JerseyClient and RestTemplate on your classpath. Are you sure the letter is on the classpath as well?
My bad,I did a rookie mistake. ThanksOn Sep 4, 2023, at 11:44 AM, HJK181 @.***> wrote: I have nothing more than what I’ve posted in the issue description. What is the exact error you get? My workaround only works if you have JerseyClient and RestTemplate on your classpath. Are you sure the letter is on the classpath as well?
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>
We long have assumed that if you have jersey on the classpath then that is what you want to use for eureka since that is the default from Netflix and spring cloud changed our default to RestTemplate.
Maybe adding some documentation to https://docs.spring.io/spring-cloud-netflix/docs/current/reference/html/#eurekaclient-with-jersey
Not sure what else to do.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
I don’t know what more feedback I could provide. Everything is described in the ticket, even a necessary workaround. For me the better solution on a clash of the two classes would be to have a property that when set, ignores Jersey on the classpath for every auto configuration checking it class presents.
Spring 3.2.1 and Spring Cloud 2023.0.0 still have the same problem
Adding my findings from another bug that I created, missing this one
Related: https://github.com/spring-cloud/spring-cloud-netflix/issues/4177
When jeresey-client lib is present on the class path, in my case via spring-boot-starter-jeresey, application startup will fail with
Caused by: org.springframework.context.ApplicationContextException: Failed to start bean 'eurekaAutoServiceRegistration'
...
Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.cloud.netflix.eureka.CloudEurekaClient.getApplications()" because the return value of "org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration.getEurekaClient()" is null
at org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry.maybeInitializeClient(EurekaServiceRegistry.java:54) ~[spring-cloud-netflix-eureka-client-4.1.0.jar:4.1.0]
at org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry.register(EurekaServiceRegistry.java:38) ~[spring-cloud-netflix-eureka-client-4.1.0.jar:4.1.0]
Auto configuration report for DiscoveryClientOptionalArgsConfiguration
DiscoveryClientOptionalArgsConfiguration#defaultEurekaClientHttpRequestFactorySupplier matched:
- @ConditionalOnClass found required class 'org.springframework.web.client.RestTemplate' (OnClassCondition)
- @ConditionalOnMissingBean (types: org.springframework.cloud.netflix.eureka.http.EurekaClientHttpRequestFactorySupplier; SearchStrategy: all) did not find any beans (OnBeanCondition)
DiscoveryClientOptionalArgsConfiguration#restTemplateDiscoveryClientOptionalArgs:
Did not match:
- @ConditionalOnMissingClass found unwanted class 'org.glassfish.jersey.client.JerseyClient' (OnClassCondition)
DiscoveryClientOptionalArgsConfiguration#restTemplateTransportClientFactories:
Did not match:
- @ConditionalOnMissingClass found unwanted class 'org.glassfish.jersey.client.JerseyClient' (OnClassCondition)
DiscoveryClientOptionalArgsConfiguration.DiscoveryClientOptionalArgsTlsConfiguration:
Did not match:
- @ConditionalOnBean (types: com.netflix.discovery.AbstractDiscoveryClientOptionalArgs; SearchStrategy: current) did not find any beans of type com.netflix.discovery.AbstractDiscoveryClientOptionalArgs (OnBeanCondition)
Matched:
- @ConditionalOnClass found required class 'org.glassfish.jersey.client.JerseyClient' (OnClassCondition)
DiscoveryClientOptionalArgsConfiguration.WebClientConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.web.reactive.function.client.WebClient' (OnClassCondition)
DiscoveryClientOptionalArgsConfiguration.WebClientNotFoundConfiguration:
Did not match:
- @ConditionalOnMissingClass found unwanted class 'org.glassfish.jersey.client.JerseyClient' (OnClassCondition)
Further analysis
To use JereseyClient with eureka, the eureka-client-jeresey3 library must be present on the class path. Suggestion: change conditionals from org.glassfish.jersey.client.JerseyClient
to, for example,
com.netflix.discovery.shared.transport.jersey3.EurekaJersey3Client
Eureka Server, which depends on the eureka-client-jeresey3 publishes two beans
import com.netflix.discovery.AbstractDiscoveryClientOptionalArgs;
import com.netflix.discovery.Jersey3DiscoveryClientOptionalArgs;
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
import com.netflix.discovery.shared.transport.jersey3.Jersey3TransportClientFactories;
@Bean
@ConditionalOnMissingBean(AbstractDiscoveryClientOptionalArgs.class)
public Jersey3DiscoveryClientOptionalArgs jersey3DiscoveryClientOptionalArgs() {
return new Jersey3DiscoveryClientOptionalArgs();
}
@Bean
@ConditionalOnMissingBean(TransportClientFactories.class)
public Jersey3TransportClientFactories jersey3TransportClientFactories() {
return Jersey3TransportClientFactories.getInstance();
}
So even if eureka-client-jeresey3 and jeresey-client are present, application will still fail to start unless those two beans are also published.
Sample
https://github.com/ZIRAKrezovic/eureka-reproducer
./mvnw clean package spring-boot:run
any update, the issue fixed ?
Same problem
Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.cloud.netflix.eureka.CloudEurekaClient.getApplications()" because the return value of "org.springframework.cloud.netflix.eureka.serviceregistry.EurekaRegistration.getEurekaClient()" is null at org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry.maybeInitializeClient(EurekaServiceRegistry.java:83) ~[spring-cloud-netflix-eureka-client-4.1.1.jar:4.1.1] at org.springframework.cloud.netflix.eureka.serviceregistry.EurekaServiceRegistry.register(EurekaServiceRegistry.java:66) ~[spring-cloud-netflix-eureka-client-4.1.1.jar:4.1.1] at org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration.start(EurekaAutoServiceRegistration.java:89) ~[spring-cloud-netflix-eureka-client-4.1.1.jar:4.1.1] at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:288) ~[spring-context-6.1.6.jar:6.1.6] ... 13 common frames omitted
I'm having the same issue.
As I understand, the issue seems to be a lack of a com.netflix.discovery.shared.transport.jersey.TransportClientFactories
bean and com.netflix.discovery.Jersey3DiscoveryClientOptionalArgs
bean, when org.glassfish.jersey.client.JerseyClient
is on the classpath. Can the solution simply be to declare these in org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration
?
Something along these lines:
@ConditionalOnClass(name = "org.glassfish.jersey.client.JerseyClient")
protected static class Jersey3ClientConfiguration {
@Bean
@ConditionalOnMissingBean(value = { AbstractDiscoveryClientOptionalArgs.class }, search = SearchStrategy.CURRENT)
public Jersey3DiscoveryClientOptionalArgs jersey3DiscoveryClientOptionalArgs() {
return new Jersey3DiscoveryClientOptionalArgs();
}
@Bean
@ConditionalOnMissingBean(value = TransportClientFactories.class, search = SearchStrategy.CURRENT)
public Jersey3TransportClientFactories jersey3TransportClientFactories() {
return Jersey3TransportClientFactories.getInstance();
}
}
same error with spring boot 3.3.1
and spring cloud 2023.0.2
works with workaround proposed by @HJK181
@spencergibb I'm thinking we could add an opt-in flag (true
by default) that the users could use to disable using JerseyClient
even if it's on the classpath. wdyt?
Yeah, that's fine