spring-cloud / spring-cloud-netflix

Integration with Netflix OSS components
http://cloud.spring.io/spring-cloud-netflix/
Apache License 2.0
4.85k stars 2.43k forks source link

NullPointerException in EurekaClient when jeresey-client lib is found on the class path #4256

Closed ZIRAKrezovic closed 4 months ago

ZIRAKrezovic commented 4 months ago

Describe the bug

Version: Spring Cloud Starter 2023.0.0

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
ZIRAKrezovic commented 4 months ago

Duplicate: #4185