Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullPointerException for yml configuration files with empty list ([]) #1572

Closed
copa2 opened this issue Mar 11, 2020 · 6 comments
Closed

NullPointerException for yml configuration files with empty list ([]) #1572

copa2 opened this issue Mar 11, 2020 · 6 comments
Labels
Milestone

Comments

@copa2
Copy link
Contributor

copa2 commented Mar 11, 2020

Requesting config-server for config of a service will throw a NullPointException when using yml configuration which contains an empty list([]).
This only occurs when using accept header application/vnd.spring-cloud.config-server.v2+json which is the new default when using a config-client.

Problem is that the origin is null at https://github.com/spring-cloud/spring-cloud-config/blob/v2.2.2.RELEASE/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/PassthruEnvironmentRepository.java#L101

Reproduction
Create spring-config-server from https://start.spring.io/ and setup a local repo.
(Using Spring Boot 2.2.5)
Add following sample (demo-client.yml) into repo and commit

foo: bar
# Emptylist will throw NullPointerException 
emptylist: []

Start config-server and try to access this configuration file.

Working (old without accept header)
curl http://localhost:8888/demo-client/default

{
  "name": "demo-client",
  "profiles": [
    "default"
  ],
  "label": null,
  "version": "91e04f01593514508554c85eb42f6b000dd10411",
  "state": null,
  "propertySources": [
    {
      "name": "D:/temp/configserver-repo/demo-client.yml",
      "source": {
        "foo": "bar",
        "list": ""
      }
    }
  ]
}

Exception
curl -H "accept: application/vnd.spring-cloud.config-server.v2+json" http://localhost:8888/demo-client/default

{
  "timestamp": "2020-03-11T13:26:01.485+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "Could not construct context for config=demo-client profile=default label= includeOrigin=true; nested exception is java.lang.NullPointerException",
  "path": "/demo-client/default"
}

Newer config-clients are accessing this through the new media-type (config-sever.v2).
See https://github.com/spring-cloud/spring-cloud-config/blob/v2.2.2.RELEASE/spring-cloud-config-client/src/main/java/org/springframework/cloud/config/client/ConfigServicePropertySourceLocator.java#L254

@copa2
Copy link
Contributor Author

copa2 commented Mar 12, 2020

Problem is in org.springframework.boot.envOriginTrackedYamlLoader which is in spring-boot. Opened issue there and closing this one.

@copa2 copa2 closed this as completed Mar 12, 2020
@wilkinsona
Copy link
Contributor

Without a stack trace, I don't know exactly where the NPE is occurring, but if it's due to a missing origin then I think an investigation here is warranted. A property isn't guaranteed to have an origin so its absence needs to be tolerated.

@wilkinsona
Copy link
Contributor

wilkinsona commented Mar 12, 2020

Here's the exception that's thrown when using Spring Cloud Commons 2.2.2.RELEASE:

org.springframework.cloud.config.server.environment.FailedToConstructEnvironmentException: Could not construct context for config=demo-client profile=default label= 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.AbstractScmEnvironmentRepository.findOne(AbstractScmEnvironmentRepository.java:59)
	at org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.findOne(MultipleJGitEnvironmentRepository.java:187)
	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:136)
	at org.springframework.cloud.config.server.environment.EnvironmentController.defaultLabelIncludeOrigin(EnvironmentController.java:115)
	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 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$$71033f6d.defaultLabelIncludeOrigin(<generated>)
	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 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: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)
	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:109)
	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:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1639)
	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.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)
	... 70 more

PassthruEnvironmentRepository is assuming that OriginLookup.getOrigin(Object, K) will not return null but its javadoc notes that it can do so:

Attempt to lookup the origin from the given source. If the source is not a OriginLookup or if an exception occurs during lookup then null is returned.

@yan-khonski-it
Copy link

Related and a duplicate
#1599

@yan-khonski-it
Copy link

Problem is in org.springframework.boot.envOriginTrackedYamlLoader which is in spring-boot. Opened issue there and closing this one.

Where is the ticked to Spring Boot issue? Please, provide.

@wilkinsona
Copy link
Contributor

wilkinsona commented Apr 28, 2020

@yan-khonski-it There's a link to it above. spring-projects/spring-boot#20506 was opened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants