1) Empty array causes NPE in Spring Cloud config
2) Spring cloud config does not log the exception.
We use config-service. Spring Cloud version 2.1 used to work well. When we updated Spring Cloud version 2.2, it stopped working.
I use Spring profile native and fetch configuration from local file on dev machine
(not from git repository).
This is an example of a configuration file in spring config. python-service.yml
resources:
- resource1
- resource2
newResources: []
The problem is caused by newResources: []. However, it worked in Spring Cloud v 2.1.
Examples, I used curl and Postman.
HTTP http://localhost:8888/python-service/dev
Accept: application/vnd.spring-cloud.config-server.v2+json
returns fail result 1).
{
"timestamp": "2020-04-24T08:38:19.803+0000",
"status": 500,
"error": "Internal Server Error",
"message": "Could not construct context for config=python-service profile=dev label=null includeOrigin=true; nested exception is java.lang.NullPointerException",
"path": "/python-service/dev"
}
Next, without the Accept header, it works.
HTTP http://localhost:8888/python-service/dev
Returns success result 2).
{
"name": "python-service",
"profiles": [
"dev"
],
"label": null,
"version": null,
"state": null,
"propertySources": [
{
"name": "file:/configuration/python-service.yml",
"source": {
"resources[0]": "resource1",
"resources[1]": "resource2",
"newResources": ""
}
}
]
}
By the way, why "newResources": "" is an empty String, if it was an array.
However, the header Accept: application/vnd.spring-cloud.config-server.v2+json is sent by Spring Cloud config client (unfortunately, I had to debug it!).
In the version 2.1, there is
Accept: application/json
As you see, different value for Accept header.
Next, when I down-graded Spring Cloud 2.1
It works
http://localhost:8888/python-service/dev
Accept: application/json
Success result 2).
When I use Spring Cloud config-service version 2.2 and remove empty array from python-service.yml on local machine, it works as well.
http://localhost:8888/python-service/dev
returns success result 3)
{
"name": "python-service",
"profiles": [
"dev"
],
"label": null,
"version": null,
"state": null,
"propertySources": [
{
"name": "file:/configuration/python-service.yml",
"source": {
"resources[0]": {
"value": "resource1",
"origin": "2:5"
},
"resources[1]": {
"value": "resource2",
"origin": "3:5"
}
}
}
]
}
I do not know what origin: "3.5" is though.
Please, advise.
How to support empty array in the configuration. It breaks our services.
Links https://github.com/spring-cloud/spring-cloud-config/issues/866 https://github.com/spring-projects/spring-boot/issues/12965 https://github.com/spring-projects/spring-framework/issues/21310
Comment From: spencergibb
Please provide the stack trace
Comment From: yan-khonski-it
I do not have stack trace. The problem is that when config-service fails, there are not logs in the config service. I have not debugged config-service; I debugged config service client.
Comment From: spencergibb
can you look on the config server?
Comment From: yan-khonski-it
please, give me one hour. I will check...
Comment From: yan-khonski-it
2020-04-24 15:10:58.756 DEBUG 1 --- [io-8888-exec-10] o.s.web.servlet.DispatcherServlet : GET "/python-service/dev", parameters={}
2020-04-24 15:10:58.761 DEBUG 1 --- [io-8888-exec-10] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.cloud.config.server.environment.EnvironmentController#defaultLabelIncludeOrigin(String, String)
2020-04-24 15:10:59.123 DEBUG 1 --- [io-8888-exec-10] .m.m.a.ExceptionHandlerExceptionResolver : Using @ExceptionHandler org.springframework.cloud.config.server.environment.EnvironmentController#environmentException(HttpServletResponse, EnvironmentException)
2020-04-24 15:10:59.126 DEBUG 1 --- [io-8888-exec-10] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.cloud.config.server.environment.FailedToConstructEnvironmentException: Could not construct context for config=python-service profile=dev label=null includeOrigin=true; nested exception is java.lang.NullPointerException]
2020-04-24 15:10:59.138 DEBUG 1 --- [io-8888-exec-10] o.s.web.servlet.DispatcherServlet : Completed 500 INTERNAL_SERVER_ERROR
2020-04-24 15:10:59.140 DEBUG 1 --- [io-8888-exec-10] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for GET "/error", parameters={}
This a debug log.
Comment From: spencergibb
I'm unable to reproduce the issue.
Can you provide a complete, minimal, verifiable sample that reproduces the problem? It should be available as a GitHub (or similar) project or attached to this issue as a zip file.
Comment From: yan-khonski-it
Yes, I can make an example, but later.
For now, the NPE was caused by org.springframework.cloud.config.server.environment.FailedToConstructEnvironmentException
Comment From: yan-khonski-it
More stack trace
org.springframework.cloud.config.server.environment.FailedToConstructEnvironmentException: Could not construct context for config=python-service profile=dev label=null includeOrigin=true; nested exception is java.lang.NullPointerException
at org.springframework.cloud.config.server.environment.NativeEnvironmentRepository.findOne(NativeEnvironmentRepository.java:161)
at org.springframework.cloud.config.server.environment.FailedToConstructEnvironmentException.<init>(FailedToConstructEnvironmentException.java:31)
at org.springframework.cloud.config.server.environment.NativeEnvironmentRepository.findOne(NativeEnvironmentRepository.java:161)
at org.springframework.cloud.config.server.environment.CompositeEnvironmentRepository.findOne(CompositeEnvironmentRepository.java:58)
at org.springframework.cloud.config.server.environment.EnvironmentEncryptorEnvironmentRepository.findOne(EnvironmentEncryptorEnvironmentRepository.java:61)
at org.springframework.cloud.config.server.environment.EnvironmentController.getEnvironment(EnvironmentController.java:144)
at org.springframework.cloud.config.server.environment.EnvironmentController.defaultLabelIncludeOrigin(EnvironmentController.java:115)
at jdk.internal.reflect.GeneratedMethodAccessor65.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
at org.springframework.cloud.context.scope.GenericScope$LockedScopedProxyFactoryBean.invoke(GenericScope.java:499)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at org.springframework.cloud.config.server.environment.EnvironmentController$$EnhancerBySpringCGLIB$$38d99eeb.defaultLabelIncludeOrigin(<generated>)
at jdk.internal.reflect.GeneratedMethodAccessor65.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
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:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
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)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
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 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:108)
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:367)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.NullPointerException
at org.springframework.cloud.config.server.environment.PassthruEnvironmentRepository.getMap(PassthruEnvironmentRepository.java:101)
at org.springframework.cloud.config.server.environment.PassthruEnvironmentRepository.findOne(PassthruEnvironmentRepository.java:80)
at org.springframework.cloud.config.server.environment.NativeEnvironmentRepository.findOne(NativeEnvironmentRepository.java:152)
... 68 more
Comment From: yan-khonski-it
Comment From: yan-khonski-it
As I promised, I added logs. Next week, I will make a docker compose example for you to reproduce. Have a good weekend for now!@
Comment From: yan-khonski-it
Hi Please, check this repository https://github.com/yan-khonski-it/spring-cloud-config-demo
README.md file explains how to start the example. Use maven and Java 11 to build the project. Use docker to run it.
Comment From: ryanjbaxter
Why do we need to use docker compose to reproduce this? Does the JDK version make a difference? Why are you not using the Spring Cloud BOM?
Comment From: spencergibb
Duplicates #1572