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.
Comment From: HJK181
Please also consider https://github.com/spring-cloud/spring-cloud-netflix/issues/4177 as my comments there were ignored.
Comment From: dnlnfr
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.
Comment From: c4mpos
Same problem here, also with Spring boot 3.1.1 and Spring Cloud 2022.0.3
Comment From: abhayc77
Same problem here.. any solution
Comment From: Shapoval1van
Same problem
Comment From: Shapoval1van
@HJK181 are you sure that is ok to change @ConditionalOnMissingClass to @ConditionalOnClass
Comment From: HJK181
@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 ...
Comment From: Shapoval1van
@HJK181 I see that exist some Jersey3DiscoveryClientOptionalArgs here but I can not find a source.
Comment From: HJK181
@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
Comment From: HJK181
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?
Comment From: andytael
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: @.***>
Comment From: spencergibb
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.
Comment From: spring-cloud-issues
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.
Comment From: HJK181
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.
Comment From: andytael
Spring 3.2.1 and Spring Cloud 2023.0.0 still have the same problem
Comment From: ZIRAKrezovic
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
Comment From: weiro-9-w7
any update, the issue fixed ?
Comment From: zhangjunapk
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
Comment From: rvervaek
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();
}
}
Comment From: samuelfac
same error with spring boot 3.3.1 and spring cloud 2023.0.2
works with workaround proposed by @HJK181
Comment From: OlgaMaciaszek
@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?
Comment From: spencergibb
Yeah, that's fine