Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-13620

webjars resource handling may run into NPE in JarURLInputStream

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Complete
    • Affects Version/s: 4.1.8, 4.2.2
    • Fix Version/s: 4.1.9, 4.2.3
    • Component/s: Web
    • Labels:
      None
    • Last commented by a User:
      true

      Description

      Project setup:

      • Spring Boot 1.2.7.RELEASE
      • Spring MVC 4.1.8.RELEASE
      • Embedded Tomcat 8.0.28
      • JDK 1.8.0_51
      • Default Spring Boot mvc autoconfiguration
      • Added jQuery 2.1.3 webjar maven dependency

      Run application from IDE by executing main method or by maven spring-boot:run command

      Request to webjars/jquery/2.1.3/ or webjars/jquery/ ends up in a HTTP 500:

      java.lang.NullPointerException: null
      	at java.io.FilterInputStream.read(FilterInputStream.java:133)
      	at java.io.FilterInputStream.read(FilterInputStream.java:107)
      	at org.springframework.util.StreamUtils.copy(StreamUtils.java:123)
      	at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.writeContent(ResourceHttpRequestHandler.java:411)
      	at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:242)
      	at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:51)
      	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:967)
      	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
      	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
      	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.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
      	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:85)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.access.channel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:144)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at com.intrasoft.mysafety.config.security.custom.CorsFilter.doFilter(CorsFilter.java:24)
      	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
      	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
      	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      	at org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83)
      	at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:364)
      	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.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
      	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
      	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
      	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
      	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:673)
      	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
      	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
      	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)
      

      I set debug breakpoint on org.springframework.web.servlet.resource.ResourceHttpRequestHandler.writeContent(ResourceHttpRequestHandler.java:411)

      protected void writeContent(HttpServletResponse response, Resource resource) throws IOException {
      		try {
      			InputStream in = resource.getInputStream();
      			try {
      				StreamUtils.copy(in, response.getOutputStream());// debug breakpoint
      			}
      			finally {
      				try {
      					in.close();
      				}
      				catch (Throwable ex) {
      					// ignore, see SPR-12999
      				}
      			}
      		}
      		catch (FileNotFoundException ex) {
      			// ignore, see SPR-12999
      		}
      	}
      

      Variables state:

      Error is caused by calling read method of JarURLInputStream which delegates to null when resource is a directory inside another JAR file on classpath.

      Additionally when application is run by executing java -jar (all jars are packed inside Spring Boot jar), request to webjars/jquery/2.1.3/ or webjars/jquery/ ends up in a HTTP 200.
      This time inner class DataInputStream of org.springframework.boot.loader.data.RandomAccessDataFile is used, not inner class JarURLInputStream of sun.net.www.protocol.jar.JarURLConnection

        Attachments

          Activity

            People

            • Assignee:
              bclozel Brian Clozel
              Reporter:
              darnok1234 Konrad Lubianka
              Last updater:
              St├ęphane Nicoll
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Days since last comment:
                2 years, 42 weeks, 3 days ago