'No adapter for endpoint' exception - apache-camel with spring-boot & spring-ws - spring

JVM 1.8.0_45
apache-camel 2.15.2
spring-ws 2.2.1
spring-boot 1.2.4
I am trying to use apache-camel (2.15.2) within a spring-boot application to handle incoming web service calls.
I created an initial working spring boot project (no camel) following the guidelines here http://spring.io/guides/gs/producing-web-service/
I then attempted to integrate the Camel: Spring Web Services component as a Consumer to handle incoming web service requests following guidelines in the 'Exposing Web Services' section here http://camel.apache.org/spring-web-services.html
WebServiceConfig.java
import org.apache.camel.component.spring.ws.bean.CamelEndpointMapping;
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
// default wsdl stuff here...
// exposing the endpoint mapping bean here rather than in spring-ws-servlet.xml (seems to work)
#Bean public CamelEndpointMapping endpointMapping() {
return new CamelEndpointMapping();
}
}
ClaimRouter.java
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.dataformat.JaxbDataFormat;
import org.springframework.stereotype.Component;
#Component
public class ClaimRouter extends RouteBuilder {
#Override
public void configure() throws Exception {
JaxbDataFormat jaxb = new JaxbDataFormat(false);
jaxb.setContextPath("uk.co.example.claim.ws.v2");
// comment #PayloadRoot annotation in ClaimEndpointV2.java to enable requests to be mapped to this camel route
from("spring-ws:rootqname:{http://example.co.uk/claim/ws/v2}getClaimRequest?endpointMapping=#endpointMapping")
.to("log:uk.co.example.claim.ws.v2?level=INFO")
.unmarshal(jaxb)
.process(new ClaimProcessor())
.marshal(jaxb);
}
}
According to the log (below) incoming requests are successfully mapped to my Camel Consumer, but then it fails with 'No adapter for endpoint'
[2015-06-24 13:22:03.981] boot - 6892 DEBUG [http-nio-8090-exec-6] --- WsdlDefinitionHandlerAdapter: Transforming [/ws] to [http://localhost:8090/ws]
[2015-06-24 13:22:03.983] boot - 6892 DEBUG [http-nio-8090-exec-6] --- MessageDispatcherServlet: Successfully completed request
[2015-06-24 13:22:13.544] boot - 6892 DEBUG [http-nio-8090-exec-7] --- WebServiceMessageReceiverHandlerAdapter: Accepting incoming [org.springframework.ws.transport.http.HttpServletConnection#70863933] at [http://localhost:8090/ws]
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- received: Received request [SaajSoapMessage {http://example.co.uk/claim/ws/v2}getClaimRequest]
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- PayloadRootAnnotationMethodEndpointMapping: Looking up endpoint for [{http://example.co.uk/claim/ws/v2}getClaimRequest]
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint mapping [org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping#5fdbde50] has no mapping for request
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapActionAnnotationMethodEndpointMapping: Looking up endpoint for []
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint mapping [org.springframework.ws.soap.server.endpoint.mapping.SoapActionAnnotationMethodEndpointMapping#50bf4dcb] has no mapping for request
[2015-06-24 13:22:13.547] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint mapping [org.springframework.ws.soap.addressing.server.AnnotationActionEndpointMapping#8b5028a] has no mapping for request
[2015-06-24 13:22:13.548] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint mapping [org.apache.camel.component.spring.ws.bean.CamelEndpointMapping#7a9ff5b1] maps request to endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]
[2015-06-24 13:22:13.548] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Testing endpoint adapter [org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter#5a1e093a]
[2015-06-24 13:22:13.549] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapFaultAnnotationExceptionResolver: Resolving exception from endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: java.lang.IllegalStateException: No adapter for endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: Is your endpoint annotated with #Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?
[2015-06-24 13:22:13.549] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SimpleSoapExceptionResolver: Resolving exception from endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: java.lang.IllegalStateException: No adapter for endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: Is your endpoint annotated with #Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?
[2015-06-24 13:22:13.549] boot - 6892 DEBUG [http-nio-8090-exec-7] --- SoapMessageDispatcher: Endpoint invocation resulted in exception - responding with Fault
java.lang.IllegalStateException: No adapter for endpoint [Consumer[spring-ws://rootqname:(http://example.co.uk/claim/ws/v2)getClaimRequest?endpointMapping=%23endpointMapping]]: Is your endpoint annotated with #Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?
at org.springframework.ws.server.MessageDispatcher.getEndpointAdapter(MessageDispatcher.java:302)
at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:235)
at org.springframework.ws.server.MessageDispatcher.reessageDispatcher.java:176)
at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:89)
at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:61)
at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:293)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catali.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
[2015-06-24 13:22:13.554] boot - 6892 DEBUG [http-nio-8090-exec-7] --- sent: Sent response [SaajSoapMessage {http://schemas.xmlsoap.org/soap/envelope/}Fault] for request [SaajSoapMessage {http://example.co.uk/claim/ws/v2}getClaimRequest]
[2015-06-24 13:22:13.556] boot - 6892 DEBUG [http-nio-8090-exec-7] --- MessageDispatcherServlet: Successfully completed request
My gradle dependencies are as follows:
dependencies {
compile("org.springframework.boot:spring-boot-starter-ws") {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
compile("org.springframework.boot:spring-boot-starter") {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
compile("org.springframework.boot:spring-boot-starter-log4j")
compile("org.springframework:spring-web")
compile("com.fasterxml.jackson.core:jackson-databind")
compile("org.apache.camel:camel-core:2.15.2")
compile("org.apache.camel:camel-spring-boot:2.15.2")
compile("org.apache.camel:camel-spring-ws:2.15.2")
compile("org.apache.camel:camel-jaxb:2.15.2")
testCompile("org.springframework.boot:spring-boot-starter-test")
compile 'org.slf4j:slf4j-log4j12:1.7.12'
compile("wsdl4j:wsdl4j:1.6.1")
jaxb("com.sun.xml.bind:jaxb-xjc:2.2.4-1")
compile sourceSets.generated.output
}
I've researched a large number of No adapter for endpoint problems and most of them seem to be caused by the return type of the endpoint. However, I'm just creating a camel route, so presumably the camel-spring-ws integration should be providing the actual endpoint.
Am I missing a key piece of configuration/annotation or is there a more fundamental problem (some version incompatibility, perhaps)? Any help or insights much appreciated.

When spring boot is used, it registers just DefaultMethodEndpointAdapter that configures annotation driven Spring WS programming model. This makes it possible to use the various annotations like #Endpoint, #Payload auto detected.
As in our case, spring-ws endpoint has to hand over ws requests to camel endpoint, DefaultMethodEndpointAdapter won't do that job for us.
Below is the part of the code in the spring framework that does the end point adapters registration,
private void initEndpointAdapters(ApplicationContext applicationContext) throws BeansException {
if (endpointAdapters == null) {
Map<String, EndpointAdapter> matchingBeans = BeanFactoryUtils
.beansOfTypeIncludingAncestors(applicationContext, EndpointAdapter.class, true, false);
if (!matchingBeans.isEmpty()) {
endpointAdapters = new ArrayList<EndpointAdapter>(matchingBeans.values());
Collections.sort(endpointAdapters, new OrderComparator());
}
else {
endpointAdapters =
defaultStrategiesHelper.getDefaultStrategies(EndpointAdapter.class, applicationContext);
if (logger.isDebugEnabled()) {
logger.debug("No EndpointAdapters found, using defaults");
}
}
}
}
When we use spring-boot, DefaultMethodEndpointAdapter gets registered and hence the first 'if block' runs and hence it doesn't register other adapters like MessageEndpointAdapter, PayloadEndpointAdapter etc.
What we need in this case is, other than DefaultMethodEndpointAdapter, have to register MessageEndpointAdapter as well to offload spring-ws to camel endpoints.
So in WebServiceConfig class, add the below code,
#Bean
public EndpointAdapter messageEndpointAdapter() {
return new MessageEndpointAdapter();
}
then the handover magic happens.
MessageEndpointAdapter is required for spring-ws and camel
handover.

Related

spring webflux - don't create session for specific paths

My spring webflux service exposes a health-check endpoint, which is called every few seconds. spring-security is configured, and currently each health-check call creates a new session, which fills the SessionStore quickly.
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
return http
.authorizeExchange()
.pathMatchers("/actuator/*").permitAll() // disable security for health-check
.anyExchange().authenticated()
...
.and().build();
}
logs:
2020-07-23 21:58:03.805 DEBUG 4722 --- [ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : [b185e815-1] HTTP GET "/actuator/health"
2020-07-23 21:58:03.845 DEBUG 4722 --- [ctor-http-nio-3] o.s.w.s.s.DefaultWebSessionManager : Created new WebSession.
Is it possible to configure spring-session or spring-security to not create sessions for specific paths?

Spring Boot azureAD filter autoconfiguration

I few days ago I was able to configure the integration with Azure AD and spring boot.
I'm usisng the following dependencies to achieve that:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-active-directory-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>msal4j</artifactId>
</dependency>
</dependencies>
It works so nice and I was able to get the expected result, but now the problem.
I have to Security configurations. Each one are configured with spring profiles, for example:
spring:
profiles:
active: DDBBSecurized, local
This one enables the sucurity with DDBB and it was configuired before the integration with AzureAD, It works perfect
I also have
spring:
profiles:
active: ADDSecurized, local
that enables the integration of azure AD.
Before configuring Azure AD integration if I use DDBBSecurized it works nice and I also had a option that if I dont configure anyThing. spring.profiles.active: local, for example, it disable the security:
the way to achive that is the following:
#EnableWebSecurity
#Profile( "DDBBSecurized" )
public class DDBBSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private RestAuthenticationExceptionHandler restAuthenticationExceptionHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS );
http.headers().frameOptions().disable();
//Filtro de autenticacion de peticiones
http.addFilterAfter( new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class );
//Filtros CORS
http.addFilterBefore( new CorsFilter(), ChannelProcessingFilter.class );
//Manejador de excpeciones de login
http.exceptionHandling().authenticationEntryPoint( restAuthenticationExceptionHandler );
//Configuracion Endpoints
http.authorizeRequests().antMatchers( HttpMethod.POST, "/auth/login**" ).permitAll()
.antMatchers( "/v2/api-docs", "/configuration/**","/swagger*/**","/webjars/**" ).permitAll()
.antMatchers( "/actuator/**" ).permitAll()
.anyRequest().authenticated();
}
}
I have my own JWT filter and login endpoint and I also had:
#EnableWebSecurity
#Profile( "!DDBBSecurized & !AzureAdSecurized" )
public class NonSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private RestAuthenticationExceptionHandler restAuthenticationExceptionHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS );
http.headers().frameOptions().disable();
//Filtros CORS
http.addFilterBefore( new CorsFilter(), ChannelProcessingFilter.class );
//Manejador de excpeciones de login
http.exceptionHandling().authenticationEntryPoint( restAuthenticationExceptionHandler );
//Configuracion Endpoints
http.authorizeRequests().anyRequest().permitAll();
}
}
That works Perfect.
Now If i use ADDSecurized everything works perfect.
#EnableWebSecurity
#Profile("AzureAdSecurized")
public class AzureSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private RestAuthenticationExceptionHandler restAuthenticationExceptionHandler;
#Autowired
private AADAppRoleStatelessAuthenticationFilter aadAuthenticationFilter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS );
http.headers().frameOptions().disable();
//Filtro de autenticacion de peticiones
http.addFilterAfter( aadAuthenticationFilter, UsernamePasswordAuthenticationFilter.class );
http.addFilterAfter( new AzureTokenGetFilter(), UsernamePasswordAuthenticationFilter.class );
//Filtros CORS
http.addFilterBefore( new CorsFilter(), ChannelProcessingFilter.class );
//Manejador de excpeciones de login
http.exceptionHandling().authenticationEntryPoint( restAuthenticationExceptionHandler );
//Configuracion Endpoints
http.authorizeRequests().antMatchers( HttpMethod.POST, "/auth/login**" ).permitAll()
.antMatchers( "/v2/api-docs", "/configuration/**", "/swagger*/**", "/webjars/**" ).permitAll()
.antMatchers( "/actuator/**" ).permitAll().anyRequest().authenticated();
}
}
But if I change to DDBBSecurized profile it is still passing the aadAuthenticationFilter filter of azure. even if this configuration is disable. It seems its autoconfigure and WebSecurityAdpater by its Own or something like That.
the properties I also have are:
security:
oauth2:
client:
registration:
azure:
client-id: XXXX-XXXX-XXXX-XXXX-XXXXXXXX
azure:
activedirectory:
tenant-id: XXXX-XXXX-XXXX-XXXX-XXXXXXXX
client-id: XXXX-XXXX-XXXX-XXXX-XXXXXXXX
scope: /User.Read
session-stateless: true
authority-url: https://login.microsoftonline.com/
Now for example I have configured DDBBSecurized And I can see in the log that the filter is being applied:
STARTUPLOG:
2020-03-26 20:10:02,279 INFO class=org.springframework.boot.StartupInfoLogger Starting Application on gggarrido10 with PID 8760 (D:\Proyectos\EvoSago\SOM-Back\admin-user\target\classes started by gggarrido in D:\Proyectos\EvoSago\SOM-Back)
2020-03-26 20:10:11,378 INFO class=org.springframework.boot.SpringApplication The following profiles are active: DDBBSecurized,local
2020-03-26 20:10:31,479 INFO class=org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$2e0e67bf] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-03-26 20:10:33,267 INFO class=org.springframework.boot.web.embedded.tomcat.TomcatWebServer Tomcat initialized with port(s): 8080 (http)
2020-03-26 20:10:34,434 INFO class=org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext Root WebApplicationContext: initialization completed in 22895 ms
2020-03-26 20:10:39,649 INFO class=org.springframework.boot.actuate.endpoint.web.ServletEndpointRegistrar Registered '/actuator/jolokia' to jolokia-actuator-endpoint
2020-03-26 20:10:42,925 INFO class=org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver Exposing 17 endpoint(s) beneath base path '/actuator'
2020-03-26 20:10:43,850 INFO class=org.springframework.security.web.DefaultSecurityFilterChain Creating filter chain: any request, [es.indra.som.common.utilities.CorsFilter#26f5e45d, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter#704c3bdf, org.springframework.security.web.context.SecurityContextPersistenceFilter#1e6d30c0, org.springframework.security.web.header.HeaderWriterFilter#5529522f, org.springframework.security.web.authentication.logout.LogoutFilter#4d2f9e3c, es.indra.som.security.filter.JWTAuthenticationFilter#37986daf, org.springframework.security.web.savedrequest.RequestCacheAwareFilter#69d667a5, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter#7ab1ad9, org.springframework.security.web.authentication.AnonymousAuthenticationFilter#c82d925, org.springframework.security.web.session.SessionManagementFilter#1b60d324, org.springframework.security.web.access.ExceptionTranslationFilter#43a59289, org.springframework.security.web.access.intercept.FilterSecurityInterceptor#61993d18]
2020-03-26 20:10:45,610 INFO class=org.springframework.scheduling.concurrent.ExecutorConfigurationSupport Initializing ExecutorService 'applicationTaskExecutor'
2020-03-26 20:10:48,503 INFO class=org.springframework.scheduling.concurrent.ExecutorConfigurationSupport Initializing ExecutorService
2020-03-26 20:10:51,398 INFO class=org.springframework.boot.web.embedded.tomcat.TomcatWebServer Tomcat started on port(s): 8080 (http) with context path ''
2020-03-26 20:10:51,407 INFO class=org.springframework.boot.StartupInfoLogger Started Application in 53.341 seconds (JVM running for 56.018)
ERROR LOG BECAUSE THE ADD FILTER IS BEING APPLIED WHEN IT SHOULD'T
2020-03-26 20:11:16,144 ERROR class=com.microsoft.azure.spring.autoconfigure.aad.AADAppRoleStatelessAuthenticationFilter Failed to initialize UserPrincipal.
com.nimbusds.jose.proc.BadJOSEException: Signed JWT rejected: Another algorithm expected, or no matching key(s) found
at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:384)
at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:330)
at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:321)
at com.microsoft.azure.spring.autoconfigure.aad.UserPrincipalManager.buildUserPrincipal(UserPrincipalManager.java:83)
at com.microsoft.azure.spring.autoconfigure.aad.AADAppRoleStatelessAuthenticationFilter.doFilterInternal(AADAppRoleStatelessAuthenticationFilter.java:58)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter
The point is that before only with DDBBSecurized and NoSecurity ot works perfect. Why for ADDfilter even if I disable it by profile is appliying the filter?
I also tried to
#SpringBootApplication(exclude = {SecurityAutoConfiguration.class , SecurityFilterAutoConfiguration.class,
AADAuthenticationFilterAutoConfiguration.class})
I also tried to delete the full AzureSecurityConfiguration.... but it didnt work, event if I delete the full class it pass the filter
But it did not work and also the app doesnt start because it need AADAuthenticationFilterAutoConfiguration to autoconfigure the filters provided by the library with the properties set in applicacion.yaml avoid the user to manually configure them.
Thanks in advance.

Workaround for the slowness of the WebClient first request

I am using WebClient in a Spring Boot MVC 2.1 project and found that the first request made by the client takes up to 6 seconds. Subsequent requests are way faster (~30ms).
There's a closed issue in Spring's JIRA that advices using Jetty as the WebClient Http connector. I have tried that approach, improving the figures, with a ~800ms first request. This time is an improvement but it's still far from RestTemplate which usally takes <200ms.
Netty approach (5s first request):
Conf:
#Bean
public WebClient webClient() {
return WebClient.create();
}
Usage:
private final WebClient webClient;
#GetMapping(value="/wc", produces = APPLICATION_JSON_UTF8_VALUE)
public Mono<String> findWc() throws URISyntaxException {
URI uri = new URI("http://xxx");
final Mono<String> response = webClient.get().uri(uri).retrieve().bodyToMono(String.class);
return response;
}
Jetty approach (800ms first request):
Conf:
#Bean
public JettyResourceFactory resourceFactory() {
return new JettyResourceFactory();
}
#Bean
public WebClient webClient() {
ClientHttpConnector connector = new JettyClientHttpConnector(resourceFactory(), null);
return WebClient.builder().clientConnector(connector).build();
}
Usage: same as before.
There's another "problem" with the Jetty approach. On server shutdown it always produces the following exception:
27-Dec-2018 11:24:20.463 INFO [jetty-http#74305db9-65] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load [org.eclipse.jetty.io.ManagedSelector$StopSelector]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [org.eclipse.jetty.io.ManagedSelector$StopSelector]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1348)
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1336)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1195)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1157)
at java.lang.Class.getDeclaringClass0(Native Method)
at java.lang.Class.getDeclaringClass(Class.java:1235)
at java.lang.Class.getEnclosingClass(Class.java:1277)
at java.lang.Class.getSimpleBinaryName(Class.java:1443)
at java.lang.Class.getSimpleName(Class.java:1309)
at org.eclipse.jetty.io.ManagedSelector$SelectorProducer.toString(ManagedSelector.java:534)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.getString(EatWhatYouKill.java:458)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.toStringLocked(EatWhatYouKill.java:447)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.toString(EatWhatYouKill.java:440)
at org.slf4j.helpers.MessageFormatter.safeObjectAppend(MessageFormatter.java:299)
at org.slf4j.helpers.MessageFormatter.deeplyAppendParameter(MessageFormatter.java:271)
at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:233)
at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:173)
at org.eclipse.jetty.util.log.JettyAwareLogger.log(JettyAwareLogger.java:680)
at org.eclipse.jetty.util.log.JettyAwareLogger.debug(JettyAwareLogger.java:224)
at org.eclipse.jetty.util.log.Slf4jLog.debug(Slf4jLog.java:97)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:288)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.lang.Thread.run(Thread.java:748)
SLF4J: Failed toString() invocation on an object of type [org.eclipse.jetty.util.thread.strategy.EatWhatYouKill]
Reported exception:
java.lang.NoClassDefFoundError: org/eclipse/jetty/io/ManagedSelector$StopSelector
at java.lang.Class.getDeclaringClass0(Native Method)
at java.lang.Class.getDeclaringClass(Class.java:1235)
at java.lang.Class.getEnclosingClass(Class.java:1277)
at java.lang.Class.getSimpleBinaryName(Class.java:1443)
at java.lang.Class.getSimpleName(Class.java:1309)
at org.eclipse.jetty.io.ManagedSelector$SelectorProducer.toString(ManagedSelector.java:534)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.getString(EatWhatYouKill.java:458)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.toStringLocked(EatWhatYouKill.java:447)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.toString(EatWhatYouKill.java:440)
at org.slf4j.helpers.MessageFormatter.safeObjectAppend(MessageFormatter.java:299)
at org.slf4j.helpers.MessageFormatter.deeplyAppendParameter(MessageFormatter.java:271)
at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:233)
at org.slf4j.helpers.MessageFormatter.arrayFormat(MessageFormatter.java:173)
at org.eclipse.jetty.util.log.JettyAwareLogger.log(JettyAwareLogger.java:680)
at org.eclipse.jetty.util.log.JettyAwareLogger.debug(JettyAwareLogger.java:224)
at org.eclipse.jetty.util.log.Slf4jLog.debug(Slf4jLog.java:97)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:288)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: Illegal access: this web application instance has been stopped already. Could not load [org.eclipse.jetty.io.ManagedSelector$StopSelector]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1338)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1195)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1157)
... 25 more
Caused by: java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [org.eclipse.jetty.io.ManagedSelector$StopSelector]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1348)
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1336)
... 27 more
27-Dec-2018 11:24:20.467 INFO [jetty-http#74305db9-65] org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading Illegal access: this web application instance has been stopped already. Could not load [ch.qos.logback.classic.spi.ThrowableProxy]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
java.lang.IllegalStateException: Illegal access: this web application instance has been stopped already. Could not load [ch.qos.logback.classic.spi.ThrowableProxy]. The following stack trace is thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access.
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForResourceLoading(WebappClassLoaderBase.java:1348)
at org.apache.catalina.loader.WebappClassLoaderBase.checkStateForClassLoading(WebappClassLoaderBase.java:1336)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1195)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1157)
at ch.qos.logback.classic.spi.LoggingEvent.<init>(LoggingEvent.java:119)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:419)
at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:383)
at ch.qos.logback.classic.Logger.log(Logger.java:765)
at org.eclipse.jetty.util.log.JettyAwareLogger.log(JettyAwareLogger.java:668)
at org.eclipse.jetty.util.log.JettyAwareLogger.warn(JettyAwareLogger.java:474)
at org.eclipse.jetty.util.log.Slf4jLog.warn(Slf4jLog.java:73)
at org.eclipse.jetty.util.log.Slf4jLog.warn(Slf4jLog.java:67)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.execute(EatWhatYouKill.java:375)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:305)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.lang.Thread.run(Thread.java:748)
Exception in thread "jetty-http#74305db9-65" java.lang.NoClassDefFoundError: ch/qos/logback/classic/spi/ThrowableProxy
at ch.qos.logback.classic.spi.LoggingEvent.<init>(LoggingEvent.java:119)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:419)
at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:383)
at ch.qos.logback.classic.Logger.log(Logger.java:765)
at org.eclipse.jetty.util.log.JettyAwareLogger.log(JettyAwareLogger.java:668)
at org.eclipse.jetty.util.log.JettyAwareLogger.warn(JettyAwareLogger.java:474)
at org.eclipse.jetty.util.log.Slf4jLog.warn(Slf4jLog.java:73)
at org.eclipse.jetty.util.log.Slf4jLog.warn(Slf4jLog.java:67)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:740)
at java.lang.Thread.run(Thread.java:748)
How can I avoid this exception?
Is there any other way we can use to improve the WebClient first request slowness?
I went through the same problem and managed to solve it by changing the connector used by the WebClient.
Below the configuration file with the appropriate imports
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.JettyClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
The class
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
HttpClient httpClient = new HttpClient(sslContextFactory);
httpClient.setFollowRedirects(false);
httpClient.setConnectTimeout(TIMEOUT);
httpClient.start();
final ClientHttpConnector connector = new JettyClientHttpConnector(httpClient);
final WebClient webClient = WebClient.builder()
.clientConnector(connector)
.baseUrl(BASE_URL)
.build();
It is important to know how to add the right libs to your project, so below is how I managed to import using gradle:
implementation 'org.eclipse.jetty:jetty-client'
implementation 'org.eclipse.jetty:jetty-reactive-httpclient'
We upgraded Spring Boot to 2.4.2 with reactor-netty 1.0.3 but still encounter this issue.
Here is our upgraded configuration:
#Bean
public WebClient createWebClient(WebClient.Builder webClientBuilder) {
log.info("Initializing WebClient Bean");
final int timeoutInMillis = Long.valueOf(TimeUnit.SECONDS.toMillis(timeout)).intValue();
final HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, timeoutInMillis)
.responseTimeout(Duration.ofMillis(timeoutInMillis))
.doOnConnected(conn ->
conn.addHandlerLast(new ReadTimeoutHandler(timeoutInMillis, TimeUnit.MILLISECONDS))
.addHandlerLast(new WriteTimeoutHandler(timeoutInMillis, TimeUnit.MILLISECONDS)));
final ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
final WebClient webClient = webClientBuilder
.clientConnector(connector)
.defaultHeader("x-clientname", clientname)
.build();
httpClient.warmup().block();
log.info("WebClient initialized");
return webClient;
}
Our call with WebClient:
ResoponseObject doCall() {
return this.webClient
.get()
.uri("http://***.de/api/rest/***")
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(ResponseObject.class)
.block();
}
With debugging enabled via application.yaml:
logging.level.reactor.netty: debug
We now see this during application startup:
2021-02-10 17:02:31,922 INFO d.t.e.b.c.c.WebClientAutoConfiguration - Initializing WebClient Bean
2021-02-10 17:02:31,959 DEBUG r.n.r.DefaultLoopIOUring - Default io_uring support : false
2021-02-10 17:02:31,967 DEBUG r.n.r.DefaultLoopEpoll - Default Epoll support : true
2021-02-10 17:02:31,997 INFO d.t.e.b.c.c.WebClientAutoConfiguration - WebClient initialized
This should be an indication that the warmup works as expected?
But on first request this happens:
2021-02-10 17:05:16,045 DEBUG o.s.w.r.f.c.ExchangeFunctions - [73d400c8] HTTP GET http://***.de/api/rest/***
2021-02-10 17:05:16,050 DEBUG r.n.r.PooledConnectionProvider - Creating a new [http] client pool [PoolFactory{evictionInterval=PT0S, leasingStrategy=fifo, maxConnections=500, maxIdleTime=-1, maxLifeTime=-1, metricsEnabled=false, pendingAcquireMaxCount=1000, pendingAcquireTimeout=45000}] for [***.de/<unresolved>:80]
2021-02-10 17:05:29,619 DEBUG r.n.r.DefaultPooledConnectionProvider - [id: 0x71b840f4] Created a new pooled channel, now 1 active connections and 0 inactive connections
2021-02-10 17:05:29,635 DEBUG r.n.t.TransportConfig - [id: 0x71b840f4] Initialized pipeline DefaultChannelPipeline{(reactor.left.httpCodec = io.netty.handler.codec.http.HttpClientCodec), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
...
In our case, creating the client pool is the problem. On a decent machine, it takes about 13 seconds.
Can you give us any comment on that? This is very this is very frustrating for us.
Thanks a lot!

Resilience4j circuit breaker used with reactive Flux never changes to OPEN on errors

I am evaluating resilience4j to include it in our reactive APIs, so far I am using mock Fluxes.
The service below always fails as I want to test if the circuit OPENs on multiple errors:
#Service
class GamesRepositoryImpl : GamesRepository {
override fun findAll(): Flux<Game> {
return if (Math.random() <= 1.0) {
Flux.error(RuntimeException("fail"))
} else {
Flux.just(
Game("The Secret of Monkey Island"),
Game("Loom"),
Game("Maniac Mansion"),
Game("Day of the Tentacle")).log()
}
}
}
This is the handler that uses the repository, printing the state of the circuit:
#Component
class ApiHandlers(private val gamesRepository: GamesRepository) {
var circuitBreaker : CircuitBreaker = CircuitBreaker.ofDefaults("gamesCircuitBreaker")
fun getGames(serverRequest: ServerRequest) : Mono<ServerResponse> {
println("*********${circuitBreaker.state}")
return ok().body(gamesRepository.findAll().transform(CircuitBreakerOperator.of(circuitBreaker)), Game::class.java)
}
}
I invoke the API endpoint many times, always getting this stacktrace:
*********CLOSED
2018-03-14 12:02:28.153 ERROR 1658 --- [ctor-http-nio-3] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request [GET http://localhost:8081/api/v1/games]
java.lang.RuntimeException: FAIL
at com.codependent.reactivegames.repository.GamesRepositoryImpl.findAll(GamesRepositoryImpl.kt:12) ~[classes/:na]
at com.codependent.reactivegames.web.handler.ApiHandlers.getGames(ApiHandlers.kt:20) ~[classes/:na]
...
2018-03-14 12:05:48.973 DEBUG 1671 --- [ctor-http-nio-2] i.g.r.c.i.CircuitBreakerStateMachine : No Consumers: Event ERROR not published
2018-03-14 12:05:48.975 ERROR 1671 --- [ctor-http-nio-2] .a.w.r.e.DefaultErrorWebExceptionHandler : Failed to handle request [GET http://localhost:8081/api/v1/games]
java.lang.RuntimeException: fail
at com.codependent.reactivegames.repository.GamesRepositoryImpl.findAll(GamesRepositoryImpl.kt:12) ~[classes/:na]
at com.codependent.reactivegames.web.handler.ApiHandlers.getGames(ApiHandlers.kt:20) ~[classes/:na]
at com.codependent.reactivegames.web.route.ApiRoutes$apiRouter$1$1$1.invoke(ApiRoutes.kt:14) ~[classes/:na]
As you see the circuit is always CLOSED. I don't know if it has anything to do but notice this message No Consumers: Event ERROR not published.
Why isn't this working?
The problem was the default ringBufferSizeInClosedState which is 100 requests and I never made so many manual requests.
I setup my own CircuitBreakerConfig for my tests and now the circuit opens right away:
val circuitBreakerConfig : CircuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(50f)
.waitDurationInOpenState(Duration.ofMillis(10000))
.ringBufferSizeInHalfOpenState(5)
.ringBufferSizeInClosedState(5)
.build()
var circuitBreaker: CircuitBreaker = CircuitBreaker.of("gamesCircuitBreaker", circuitBreakerConfig)

Ribbon with Spring Cloud and Eureka: java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local

I am working on Spring Boot Eureka Client Application with Ribbon Load Balancer.
I have two instances of the server registered with Eureka with the name "TEST". On the client side, I have the following code to fetch the server from Eureka.
#Configuration
#ComponentScan
#EnableAutoConfiguration
#EnableEurekaClient
#RestController
public class EurekaConsumerApplication {
#Autowired
DiscoveryClient discoveryClient;
#Autowired
RestTemplate restTemplate;
#RequestMapping(value = "/",method = RequestMethod.GET)
String consumer(){
InstanceInfo instance = discoveryClient.getNextServerFromEureka("TEST", false);
URI uri = UriComponentsBuilder.fromUriString(instance.getHomePageUrl() + "baseDir")
.build()
.toUri();
String baseDir = restTemplate.getForObject(uri, String.class);
return baseDir;
}
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
}
application.yml
spring:
application:
name: consumer
info:
component: Consumer to fetch configuration
server:
port: 8090
eureka:
instance:
leaseRenewalIntervalInSeconds: 3
metadataMap:
instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${random.value}}}
client:
# Default values comes from org.springframework.cloud.netflix.eurek.EurekaClientConfigBean
region: default
registryFetchIntervalSeconds: 5
instanceInfoReplicationIntervalSeconds: 5
initialInstanceInfoReplicationIntervalSeconds: 5
serviceUrl:
defaultZone: http://localhost:8761/eureka/
availabilityZones:
default: ${APPLICATION_DOMAIN:${DOMAIN:defaultZone}}
However, when I hit the restful endpoint by using the following command, it gives an error:
curl http://localhost:8090/
This is the error:
{"exception":"java.lang.IllegalStateException","message":"org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local","path":"/"}
Stacktrace:
2015-07-22 14:37:35.005 INFO 13841 --- [tp1334391583-19] c.netflix.loadbalancer.BaseLoadBalancer : Client:Samarths-MacBook-Pro.local instantiated a LoadBalancer:DynamicServerListLoadBalancer:{NFLoadBalancer:name=Samarths-MacBook-Pro.local,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2015-07-22 14:37:35.009 INFO 13841 --- [tp1334391583-19] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client Samarths-MacBook-Pro.local initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=Samarths-MacBook-Pro.local,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList#681eda37
2015-07-22 14:37:35.029 WARN 13841 --- [tp1334391583-19] o.eclipse.jetty.servlet.ServletHandler :
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:808)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:295)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:102)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty..ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:68)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:499)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local
at org.springframework.cloud.netflix.ribbon.RibbonClientHttpRequestFactory.createRequest(RibbonClientHttpRequestFactory.java:64)
at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:76)
at org.springframework.web.client.Rlate.doExecute(RestTemplate.java:565)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:253)
at com.securityscorecard.eureka.consumer.EurekaConsumerApplication.consumer(EurekaConsumerApplication.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
... 38 common frames omitted
Looks like my server list is empty.
The RestTemplate you autowired is already connected to Ribbon. So you do a lookup by hand and then RestTemplate is trying to lookup the hostname passed in to ribbon. You have two options: 1) Don't use the netflix DiscoveryClient and pass the serviceId as a logical hostname to ribbon (http://TEST/myservice), 2) Don't use the autowired RestTemplate, create a new one for your class. My choice would be #1.
I got this working. The only change I had to make was in the way I was using RestTemplate api.
Error Code:
#Autowired
RestTemplate restTemplate;
#RequestMapping(value = "/",method = RequestMethod.GET)
String consumer(){
String baseDir = restTemplate.getForObject("TEST", String.class);
return baseDir;
}
Working Code:
#Autowired
RestTemplate restTemplate;
#RequestMapping(value = "/",method = RequestMethod.GET)
String consumer(){
String baseDir = restTemplate.getForObject("http://TEST", String.class);
return baseDir;
}
Solution:
The first parameter to restTemplate.getForObject should have the format of a URL. And the domain name should be the name of the service you want to discover.
Ex: http://TEST. Here, TEST is the name of my server registered to eureka registry
The question is already answered, but I found a workaround that seems neat and fixed our problem.
First declare a new #Component class and in it create a method that returns RestTemplate:
#Component
public class RestTemplateComponentFix{
#Autowired
SomeConfigurationYouNeed someConfiguration;
#LoadBalanced
public RestTemplate getRestTemplate() {
// TODO set up your restTemplate
rt.setRequestFactory( new HttpComponentsClientHttpRequestFactory() );
return rt;
}
}
After that just Autowire the restTemplateComponentFix in your class and when when you need the rest template call the restTemplate() method. Something like this:
#Service
public class someClass{
#Autowired
RestTemplateComponentFix restTemplateComponentFix;
public void methodUsingRestTemplate(){
// Some code...
RestTemplate rt = restTemplateComponentFix.getRestTemplate();
// Some code...
}
}
After that you can unit test with something like:
RestTemplate rt = Mockito.mock(RestTemplate.class)
when(restTemplateComponentFix.getRestTemplate()).thenReturn(rt);
when(rt.someMethod()).thenReturn(something);
Removing #LoadBalanced Annotation from RestTemplate works for me.
P.S: #LoadAnnotation is supposed to be applied only to Eureka Server which is your discovery server.
The question is already answered by #spencergibb, after trying #spencergibb way if you are still struggling with no instance avialable for ..MS... make sure that in pom.xml if you are using Netflix Eureka then avoid adding dependency for Netflix ribbon as Eureka itself internally uses ribbon.
This was causing problems for me.
RestTemplateBuilder works for me. As below-
#Service
public class someClass{
#Autowired
RestTemplateBuilder restTemplateBuilder;
public void methodUsingRestTemplate(){
restTemplateBuilder.build().getForObject("http://TEST", String.class);
}
}
Can be due to outdated release used in dependencies.
I was using a project from GitHub blog to understand the working of Microservices registry and discovery.
The dependency of netflix in that project was outdated,
spring-cloud-starter-netflix-eureka-server', version: '2.0.1.RELEASE'
After removing version, issue was solved as latest version would be used.

Resources