why can not get ${validatedValue} when using HibernateValidator - spring

I want get the invalid value in the validation message by using ${validatedValue} .
But I got an exception like this.
exception
java.lang.NumberFormatException: For input string: "validatedValue"
java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
java.lang.Integer.parseInt(Integer.java:580)
java.lang.Integer.parseInt(Integer.java:615)
java.text.MessageFormat.makeFormat(MessageFormat.java:1427)
java.text.MessageFormat.applyPattern(MessageFormat.java:479)
java.text.MessageFormat.<init>(MessageFormat.java:380)
org.springframework.context.support.MessageSourceSupport.createMessageFormat(MessageSourceSupport.java:159)
org.springframework.context.support.ResourceBundleMessageSource.getMessageFormat(ResourceBundleMessageSource.java:352)
org.springframework.context.support.ResourceBundleMessageSource.resolveCode(ResourceBundleMessageSource.java:175)
org.springframework.context.support.AbstractMessageSource.getMessageInternal(AbstractMessageSource.java:224)
org.springframework.context.support.AbstractMessageSource.getMessage(AbstractMessageSource.java:169)
org.springframework.context.support.DelegatingMessageSource.getMessage(DelegatingMessageSource.java:83)
org.springframework.context.support.AbstractApplicationContext.getMessage(AbstractApplicationContext.java:1320)
org.springframework.web.servlet.support.RequestContext.getMessage(RequestContext.java:725)
org.springframework.web.servlet.support.BindStatus.initErrorMessages(BindStatus.java:308)
org.springframework.web.servlet.support.BindStatus.getErrorMessages(BindStatus.java:278)
org.springframework.web.servlet.tags.form.ErrorsTag.exposeAttributes(ErrorsTag.java:321)
org.springframework.web.servlet.tags.form.AbstractHtmlElementBodyTag.writeTagContent(AbstractHtmlElementBodyTag.java:53)
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:87)
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:83)
org.apache.jsp.WEB_002dINF.jsp.basic.validation_005fand_005ferror_jsp._jspService(validation_005fand_005ferror_jsp.java:215)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:71)
javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:467)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:378)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:326)
javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:171)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
I use a validation annotation in java object like this.
#DateTimeFormat(pattern = "yyyy:MM:dd")
protected Date birthday;
The message definition in validation_err_message.properties like this.
typeMismatch.birthday=input value of birthday is not valid. ({0}: ${validatedValue} ).
#Override
#Bean("messageSource")
public MessageSource messageSource() {
final ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
resourceBundleMessageSource.setBasename("validation_err_message");
resourceBundleMessageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
resourceBundleMessageSource.setDefaultLocale(Locale.CHINA);
return resourceBundleMessageSource;
}
The Validator's Definition :
#Override
public Validator getValidator() {
final OptionalValidatorFactoryBean validatorFactoryBean = new OptionalValidatorFactoryBean();
validatorFactoryBean.setProviderClass(org.hibernate.validator.HibernateValidator.class);
validatorFactoryBean.setValidationMessageSource(this.messageSource);
return validatorFactoryBean;
}
MessageInterpolator will be
org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator
automatically.

Related

org.apache.catalina.connector.ClientAbortException: java.io.IOException: Key no longer registered

It is giving us this error right after updating and uploading the app changes. It stays that way, until we restart Tomcat.
We know what the error means. The connection between the client and the server has been closed. But it only happens when we deploy the app
29-07-2022#07:33:14 ERROR - Failed to invoke #ExceptionHandler method: public org.springframework.http.ResponseEntity<java.lang.Object> com.controller.ws.GlobalExceptionHandler.handleAllExceptions(java.lang.Exception,org.springframework.web.context.request.WebRequest)
org.apache.catalina.connector.ClientAbortException: java.io.IOException: Key no longer registered
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:309)
at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:272)
at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:118)
at com.fasterxml.jackson.core.json.UTF8JsonGenerator.flush(UTF8JsonGenerator.java:1042)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:2240)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:231)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:208)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:161)
at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:144)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:362)
at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:60)
at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:138)
at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1167)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1004)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:955)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
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:652)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.core.filters.AuthFilter.doFilter(AuthFilter.java:128)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: Key no longer registered
at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:87)
at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:152)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1253)
at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:764)
at org.apache.tomcat.util.net.SocketWrapperBase.flushBlocking(SocketWrapperBase.java:717)
at org.apache.tomcat.util.net.SocketWrapperBase.flush(SocketWrapperBase.java:707)
at org.apache.coyote.http11.Http11OutputBuffer$SocketOutputBuffer.flush(Http11OutputBuffer.java:572)
at org.apache.coyote.http11.filters.ChunkedOutputFilter.flush(ChunkedOutputFilter.java:157)
at org.apache.coyote.http11.Http11OutputBuffer.flush(Http11OutputBuffer.java:220)
at org.apache.coyote.http11.Http11Processor.flush(Http11Processor.java:1195)
at org.apache.coyote.AbstractProcessor.action(AbstractProcessor.java:399)
at org.apache.coyote.Response.action(Response.java:209)
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:305)
... 51 more
29-07-2022#08:32:12 ERROR - Failed to invoke #ExceptionHandler method: public org.springframework.http.ResponseEntity<java.lang.Object> com.controller.ws.GlobalExceptionHandler.handleAllExceptions(java.lang.Exception,org.springframework.web.context.request.WebRequest)
java.lang.NullPointerException
at org.springframework.web.util.UrlPathHelper.getServletPath(UrlPathHelper.java:315)
The controller class:
#Order(Ordered.HIGHEST_PRECEDENCE)
#ControllerAdvice
public class GlobalExceptionHandler {
#ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleAllExceptions(final Exception ex, final WebRequest request) {
return new ResponseEntity<Object>(new ErrorJsonObject(ApiResponseType.INVALID_ARGUMENT,
"Client specified an invalid argument, request body or query param"), HttpStatus.BAD_REQUEST);
}
#ExceptionHandler(MissingServletRequestParameterException.class)
protected ResponseEntity<Object> handleMethodArgumentNotValid(final Exception ex, final WebRequest request) {
return new ResponseEntity<Object>(new ErrorJsonObject(ApiResponseType.INVALID_ARGUMENT,
"Client specified an invalid argument, request body or query param"), HttpStatus.BAD_REQUEST);
}
}
Thank you very much in advance

Autowire doesn't work after enabling Hystrix

I'm encountering a issue, where autowiring doesn't work when I add Hystrix(EnableHystrix) in my microservice.
Controller class:
#RestController
#RequestMapping("/login")
#Slf4j
public class LoginController {
#Autowired
ILoginService loginService;
#ApiOperation(value = "Validate user credentials", response = LoginUser.class)
#PostMapping(value = "/validateCredentials")
private ResponseEntity<LoginUser> validateUserCredentials(#RequestBody LoginUser logginUser) {
LoginUser user=loginService.validateUser(logginUser);
......
.....
}
}
Autowiring of ILoginService works perfectively without Hystrix.
But when I add the dependency( Version 2.2.6 Release)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
And enable Hystrix as:
#EnableFeignClients("com.abcd")
#SpringBootApplication
#EnableHystrix
public class MyApplication{
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
The Autowire of ILoginService fails and NullPointerException is thrown when trying to access the autowired property.
I have this configuration working fine in other microservices, But fails in this particular microservice. What is going wrong here?
EDIT:
StackTrace is:
java.lang.NullPointerException
at com.demo.login.controller.LoginController.validateUserCredentials(LoginController.java:46)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
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.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
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.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
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.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
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.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)2021-01-28 17:09:12.999 DEBUG 1800 --- [nio-9200-exec-8] com.demo.login.ExceptionsHelper : Exception:
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
In the current form, its kind of hard to tell what exactly happens.
So I'll provide some thoughts that can lead to the solution:
You say,
The Autowire of ILoginService fails and NullPointerException is thrown when trying to access the autowired property.
Usually when its possible to autowire a bean because it doesn't exist or something, spring should throw an exception during the startup and it will be impossible to "access" the autowired property during the statrup because the system won't start, so this is confusing. Maybe if you could provide a stacktrace and the place where you're trying to access the property it could become more clear...
Its possible in theory (again the stacktrace could show that) that someone tries to access the property before the autowiring actually executes. Technically its implemented in spring via BeanPostProcessor with certain priority that might compete with other bean post processors.
Try to rewrite the controller to use constructor injection (so that spring would inject the ILoginService during the construction of the controller:
#RestController
public class LoginController {
// Note, no autowiring here
private final ILoginService loginService;
// If you are on old spring you need to mark this constructor with #Autowired,
// in the recent spring versions its not required anymore as long as this is the only
// constructor of your class
public LoginController(ILoginService loginService) {
this.loginService = loginService;
}
After you're doing this, try to place a breakpoint in the constructor and see what exactly gets injected (this is an advantage of constructor injection in this case)

Feign client throwing 401

I am trying to hit a third party API (Running in a different server - Not my micro-service) from my application (running on my local machine). The API, when executed on the postman, works perfectly.
curl --location --request POST 'https://myserver.com' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Accept: application/json' \
--data-urlencode 'client_id=12345****67890' \
--data-urlencode 'client_secret=123456&&&&&5678**90' \
--data-urlencode 'grant_type=abcd' \
--data-urlencode 'token_format=jwt'
But when I tried through Feign it fails.
#FeignClient( name = "test", url = "https://myserver.com", configuration = FeignSimpleEncoderConfig.class )
public interface AuthFeinClient {
#PostMapping( value = "/uaa/oauth/token", consumes = "application/json" )
#Headers( "Content-Type: application/x-www-form-urlencoded" )
ResponseEntity<String> getAuthToken( #RequestBody Map<String, String> formData );
}
Now I am calling the interface method
Map<String, String> formData = new HashMap<>();
formData.put("client_id", "12345****67890");
formData.put("client_secret", "123456&&&&&5678**90");
formData.put("grant_type", "abcd");
formData.put("token_format", "jwt");
ResponseEntity<String> authToken = feignClient.getAuthToken(formData);
I am sending the form data in a map. I also tried with MultiValueMap as well. But the same error is coming.
feign.FeignException$Unauthorized: [401] during [POST] to [https://oauth.eastus.cloudapp.azure.com:8443/uaa/oauth/token] [AuthFeinClient#getAuthToken(Map)]: []
at feign.FeignException.clientErrorStatus(FeignException.java:197) ~[feign-core-10.7.4.jar:na]
at feign.FeignException.errorStatus(FeignException.java:177) ~[feign-core-10.7.4.jar:na]
at feign.FeignException.errorStatus(FeignException.java:169) ~[feign-core-10.7.4.jar:na]
at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:92) ~[feign-core-10.7.4.jar:na]
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:156) ~[feign-core-10.7.4.jar:na]
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:80) ~[feign-core-10.7.4.jar:na]
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100) ~[feign-core-10.7.4.jar:na]
at com.sun.proxy.$Proxy107.getAuthToken(Unknown Source) ~[na:na]
at com.highpeak.tlp.ybanqauthmanager.service.AuthManagerServiceImpl.generateAuthTokenAndSaveInRedis(AuthManagerServiceImpl.java:64) ~[classes/:na]
at com.highpeak.tlp.ybanqauthmanager.controller.AuthController.getAuth(AuthController.java:28) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_232]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_232]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_232]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_232]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) [spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) [spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) [spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) [spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) [spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) [spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) [spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) [spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) [spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) [spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) [tomcat-embed-websocket-9.0.35.jar:9.0.35]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93) [spring-boot-actuator-2.3.0.RELEASE.jar:2.3.0.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) [tomcat-embed-core-9.0.35.jar:9.0.35]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.35.jar:9.0.35]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_232]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_232]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.35.jar:9.0.35]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_232]
I also set up the encoder to send form data.
#Configuration
public class FeignSimpleEncoderConfig {
#Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
#Bean
FormEncoder feignFormEncoder() {
return new FormEncoder(new SpringEncoder(this.messageConverters));
}
}
What am I doing wrong here?
I also encountered this problem before. I could use the OkHttpClient or curl request, but not FeignClient. This is my solution, and it's work for me, I hope it worked for you, too.
#Configuration
#ConditionalOnClass(Feign.class)
#AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {
#Bean
public okhttp3.OkHttpClient okHttpClient(){
return new okhttp3.OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool())
.build();
}
#Bean
#ConditionalOnMissingBean({Client.class})
public Client feignClient(okhttp3.OkHttpClient client) {
return new feign.okhttp.OkHttpClient(client);
}
#Bean
#ConditionalOnMissingBean({ConnectionPool.class})
public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties, OkHttpClientConnectionPoolFactory connectionPoolFactory) {
Integer maxTotalConnections = httpClientProperties.getMaxConnections();
Long timeToLive = httpClientProperties.getTimeToLive();
TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
}
#Bean
public OkHttpClient client(OkHttpClientFactory httpClientFactory, ConnectionPool connectionPool, FeignHttpClientProperties httpClientProperties) {
Boolean followRedirects = httpClientProperties.isFollowRedirects();
Integer connectTimeout = httpClientProperties.getConnectionTimeout();
Boolean disableSslValidation = httpClientProperties.isDisableSslValidation();
return httpClientFactory.createBuilder(disableSslValidation)
.connectTimeout((long)connectTimeout, TimeUnit.MILLISECONDS)
.followRedirects(followRedirects)
.connectionPool(connectionPool)
.build();
}
}
Through my debugging, by default, FeignClient's default-Client is called to initiate a request, so we can force it to use OkHttpClient with the above configuration.
Finally, please forgive my English is not very good.
The more important is springboot config code.
How about adding consumes = APPLICATION_FORM_URLENCODED_VALUE on #PostMapping()?
full code would be:
#FeignClient(
name = "test",
url = "https://myserver.com",
configuration = FeignSimpleEncoderConfig.class,
consumes = APPLICATION_FORM_URLENCODED_VALUE
)
public interface AuthFeinClient {
#PostMapping( value = "/uaa/oauth/token", consumes = "application/json" )
#Headers( "Content-Type: application/x-www-form-urlencoded" )
ResponseEntity<String> getAuthToken( #RequestBody Map<String, String> formData );
}
My requests worked with curl, but didn't with the feignClient (Err 401).
#FeignClient(value = "authentication-service", url = "http://localhost:1234/api/users")//<--wrong, should be /api/user
public interface AuthenticationServiceClient {
#PostMapping(value = "/register")
SomeResponseType register(User user);
}
In my case I used "users" instead of "user" in my url (inside the FeignClient annotation), which caused a 401 instead of 404 because only the url with "user" was excluded from csrf-protection (defined in my Spring Security config).
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic();
http.csrf().ignoringAntMatchers("/api/user/register"); //like here
http.authorizeRequests()
.antMatchers("/api/user/register") //and here
.permitAll()
.anyRequest()
.authenticated();
}

SpringValidatorAdapter bug? Validating collection of Strings

Say that our http request data are:
{
"a": ["a", "b", "c"]
}
corresponding DTO could be:
#Data //lombok
public class DTO {
private List<String> a;
}
but we want to validate this as well, including elements in collection, which should be possible with Java Bean Validation 2.0 and (IIRC) from hibernate-validator 6.0.1. So lets add annotations:
#Data
public class DTO {
#NotEmpty
private List<#NotBlank String> a;
}
however, this does not work neither in our "2.2.2.RELEASE" nor in newest "2.3.0.RELEASE".
This method: org.springframework.validation.beanvalidation.SpringValidatorAdapter#processConstraintViolations will correctly receive ConstraintViolation(below is its toString):
ConstraintViolationImpl{interpolatedMessage='must not be blank', propertyPath=a[0].<list element>, rootBeanClass=class DTO, messageTemplate='{javax.validation.constraints.NotBlank.message}'}
so it means that hibernate-validator is OK, however it continues with with its logic, and calculates field related to this error to be: a[0]. When we drill deeper, we can find org.springframework.beans.CachedIntrospectionResults#getPropertyDescriptor trying to find propertyDescriptor named "a" or "A" failing to find it. I thought it might be caused by used lombok, so I added setters/getters manually, but no change. Full delombok did not help either, and this is all I can do to help with PropertyDescriptors. Everything what could be searched for is in the class declared.
Is it a bug? Do I have something set incorrectly? Does SpringBoot need some help to be able to process such bean validation?
Produced exception:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: JSR-303 validated property 'a[0]' does not have a corresponding accessor for Spring data binding - check your DataBinder's configuration (bean property versus direct field access)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at brave.servlet.TracingFilter.doFilter(TracingFilter.java:65)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:204)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
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.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
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.cloud.sleuth.instrument.web.ExceptionLoggingFilter.doFilter(ExceptionLoggingFilter.java:50)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at brave.servlet.TracingFilter.doFilter(TracingFilter.java:82)
at org.springframework.cloud.sleuth.instrument.web.LazyTracingFilter.doFilter(TraceWebServletAutoConfiguration.java:138)
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.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
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.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
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.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: JSR-303 validated property 'a[0]' does not have a corresponding accessor for Spring data binding - check your DataBinder's configuration (bean property versus direct field access)
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.processConstraintViolations(SpringValidatorAdapter.java:188)
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:109)
at org.springframework.validation.ValidationUtils.invokeValidator(ValidationUtils.java:89)
at org.springframework.validation.ValidationUtils.invokeValidator(ValidationUtils.java:56)
at ...our code...
at org.springframework.validation.DataBinder.validate(DataBinder.java:892)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.validateIfApplicable(AbstractMessageConverterMethodArgumentResolver.java:266)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:137)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
... 87 common frames omitted
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'a[0]' of bean class [java.util.ArrayList]: Bean property 'a[0]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:622)
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:612)
at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:104)
at org.springframework.validation.AbstractBindingResult.getRawFieldValue(AbstractBindingResult.java:284)
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.getRejectedValue(SpringValidatorAdapter.java:318)
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.processConstraintViolations(SpringValidatorAdapter.java:174)
... 104 common frames omitted
Expected behavior — as any other bean validation issue.
UPDATE — so definitely not a bug. I created "same" field in different DTO being processed via different, but equally annotated, controller, and it works. Placement into different modules also does not seem to produce different result. I'll retry lombok. So far I have no idea why it fails.
UPDATE — I think I found some clue:
if I have controller method defined as this:
public void accept(#RequestBody #Valid DTO dtos) {
it works just fine. However if I have it like this:
public void accept(#RequestBody #Valid List<DTO> dtos) {
if fails as described. By default this is not validated, sure. What we have here to enable this validations are these 2 classes:
#ControllerAdvice
public class ValidatorAdvice {
private final LocalValidatorFactoryBean validator;
#SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public ValidatorAdvice(LocalValidatorFactoryBean validator) {
this.validator = validator;
}
/**
* Adds the {#link CollectionValidator} to the supplied
* {#link WebDataBinder}
*
* #param binder web data binder.
*/
#InitBinder
public void initBinder(WebDataBinder binder) {
if (binder.getTarget() instanceof Collection) {
binder.addValidators(new CollectionValidator(validator));
}
}
}
and
import java.util.Collection;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
public class CollectionValidator implements Validator {
private final Validator validator;
public CollectionValidator(LocalValidatorFactoryBean validatorFactory) {
this.validator = validatorFactory;
}
#Override
public boolean supports(Class<?> clazz) {
return Collection.class.isAssignableFrom(clazz);
}
/**
* Validate each element inside the supplied {#link Collection}.
*
* The supplied errors instance is used to report the validation errors.
*
* #param target the collection that is to be validated
* #param errors contextual state about the validation process
*/
#Override
#SuppressWarnings("rawtypes")
public void validate(Object target, Errors errors) {
Collection collection = (Collection) target;
for (Object object : collection) {
ValidationUtils.invokeValidator(validator, object, errors);
}
}
}
these will do the validation of all DTO in dto list (#RequestBody #Valid List<DTO> dtos), but somehow it messes with the validation. Any ideas why is it like this, or how to do it correctly (if this is incorrect way)?

Calling microservice using feign client from Zuul gateway filter

I have a validation service which needs to be called before every request, and if the validation fails I want to return the result from gateway itselh,so I am trying to call it using feign-client from my Zuul gateway filter. It is giving me some exception and not able to make the call
I have tried creating a proxy of my service to be called and enabled it as a fegin client.
Run method of my Zuul filter. This filter is of type "pre"
#Autowired
private ValidationServiceProxy proxy;
public Object run() {
try {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request =ctx.getRequest();
ctx.addZuulRequestHeader("interaction_id", "1000");
String responseEntity= proxy.test(request);
logger.info("Response"+responseEntity);
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
My validation service proxy code
#FeignClient(name="validation-service")
public interface ValidationServiceProxy {
#GetMapping("/api/v1/test")
public String test(HttpServletRequest httpServletRequest);
}
My controller code on the validation service.
#GetMapping(value = "/test")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.TEXT_PLAIN)
public ResponseEntity<String> test(HttpServletRequest httpServletRequest) {
String result = "Hello World";
return ResponseEntity.ok().body(result);
}
feign.codec.EncodeException: Could not write JSON: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false); nested exception is com.fasterxml.jackson.databind.JsonMappingException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) (through reference chain: org.springframework.cloud.netflix.zuul.filters.pre.Servlet30RequestWrapper["request"]->org.apache.catalina.connector.RequestFacade["asyncContext"])
at feign.ReflectiveFeign$BuildEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:376)
at feign.ReflectiveFeign$BuildTemplateByResolvingArgs.create(ReflectiveFeign.java:224)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:74)
at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103)
at com.sun.proxy.$Proxy162.test(Unknown Source)
at com.in28minutes.microservices.netflixzuulapigatewayserver.ZuulLoggingFilter.run(ZuulLoggingFilter.java:48)
at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:117)
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193)
at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157)
at com.netflix.zuul.FilterProcessor.preRoute(FilterProcessor.java:133)
at com.netflix.zuul.ZuulRunner.preRoute(ZuulRunner.java:105)
at com.netflix.zuul.http.ZuulServlet.preRoute(ZuulServlet.java:125)
at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:74)
at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:165)
at org.springframework.cloud.netflix.zuul.web.ZuulController.handleRequest(ZuulController.java:45)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
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:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.cloud.sleuth.instrument.web.ExceptionLoggingFilter.doFilter(ExceptionLoggingFilter.java:50)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at brave.servlet.TracingFilter.doFilter(TracingFilter.java:99)
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.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false); nested exception is com.fasterxml.jackson.databind.JsonMappingException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) (through reference chain: org.springframework.cloud.netflix.zuul.filters.pre.Servlet30RequestWrapper["request"]->org.apache.catalina.connector.RequestFacade["asyncContext"])
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:296)
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.writeInternal(AbstractGenericHttpMessageConverter.java:112)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:227)
at org.springframework.cloud.openfeign.support.SpringEncoder.encode(SpringEncoder.java:112)
at feign.ReflectiveFeign$BuildEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:372)
... 74 more
Caused by: com.fasterxml.jackson.databind.JsonMappingException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) (through reference chain: org.springframework.cloud.netflix.zuul.filters.pre.Servlet30RequestWrapper["request"]->org.apache.catalina.connector.RequestFacade["asyncContext"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:394)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:353)
at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:316)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:727)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1396)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:913)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:287)
... 78 more
Caused by: java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
at org.apache.catalina.connector.Request.getAsyncContext(Request.java:1784)
at org.apache.catalina.connector.RequestFacade.getAsyncContext(RequestFacade.java:1068)
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:498)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:688)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
... 87 more
See the below code. after adding the zuul. uri becomes like this
http://zuul-service/your-service/uri
That how you need to change the proxy interface.
#FeignClient(name="zuul-service")
public interface ValidationServiceProxy {
#GetMapping("validation-service/api/v1/test")
public String test(HttpServletRequest httpServletRequest);
}

Resources