Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-6463

AbstractHTTPDestination.cacheInput() throws NullPointerException if HttpServletRequest returns null for getInputStream()

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 3.1.1
    • 3.0.10, 3.1.7, 3.2.0
    • JAX-RS
    • None
    • Unknown

    Description

      I am writing a unit test executing inside Spring 4.0's @WebApplicationContext unit test framework that invokes CXFServlet. Spring's framework provides a MockHttpServletRequest object that you can construct as input to a servlet request/response dispatch call.

      If the incoming message body of the MockHttpServletRequest is empty, then when you call getInputStream() on it, MockHttpServletRequest will return null instead of returning a ServletInputStream that contains no data.

      The code under the CXFServlet doesn't appear to like this behavior and crashes with a pretty mysterious stack trace:

      2015-06-15 17:29:39,399 DEBUG [main] org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleMessage on interceptor org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor@3118ed2c
      2015-06-15 17:29:39,400 DEBUG [main] org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor - Response content type is: text/plain
      2015-06-15 17:29:39,400 DEBUG [main] org.apache.cxf.ws.addressing.ContextUtils - retrieving MAPs from context property javax.xml.ws.addressing.context.inbound
      2015-06-15 17:29:39,400 DEBUG [main] org.apache.cxf.ws.addressing.ContextUtils - WS-Addressing - failed to retrieve Message Addressing Properties from context
      2015-06-15 17:29:39,401 ERROR [main] org.apache.cxf.jaxrs.utils.JAXRSUtils - Problem with writing the data, class java.lang.String, ContentType: text/plain
      2015-06-15 17:29:39,402 DEBUG [main] org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleFault on interceptor org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor@3118ed2c
      2015-06-15 17:29:39,402 DEBUG [main] org.apache.cxf.phase.PhaseInterceptorChain - Invoking handleFault on interceptor org.apache.cxf.interceptor.MessageSenderInterceptor@1b6824c1
      2015-06-15 17:29:39,403 WARN [main] org.apache.cxf.phase.PhaseInterceptorChain - Interceptor for {http://rest.web.opennms.org/}AcknowledgmentRestService has thrown exception, unwinding now
      org.apache.cxf.interceptor.Fault
      	at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.handleWriteException(JAXRSOutInterceptor.java:371)
      	at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRSOutInterceptor.java:272)
      	at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.processResponse(JAXRSOutInterceptor.java:118)
      	at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.handleMessage(JAXRSOutInterceptor.java:81)
      	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
      	at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:83)
      	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
      	at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
      	at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:251)
      	at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:234)
      	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:208)
      	at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:160)
      	at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:171)
      	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:293)
      	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:217)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:735)
      	at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:268)
      	at org.opennms.core.test.rest.AbstractSpringJerseyRestTestCase$1.doFilter(AbstractSpringJerseyRestTestCase.java:240)
      	at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:232)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      	at org.opennms.core.test.rest.AbstractSpringJerseyRestTestCase.dispatch(AbstractSpringJerseyRestTestCase.java:244)
      	at org.opennms.core.test.rest.AbstractSpringJerseyRestTestCase.sendRequest(AbstractSpringJerseyRestTestCase.java:482)
      	at org.opennms.core.test.rest.AbstractSpringJerseyRestTestCase.sendRequest(AbstractSpringJerseyRestTestCase.java:477)
      	at org.opennms.core.test.rest.AbstractSpringJerseyRestTestCase.sendRequest(AbstractSpringJerseyRestTestCase.java:473)
      	at org.opennms.web.rest.MinionRestServiceTest.testGetProperty(MinionRestServiceTest.java:116)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:497)
      	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
      	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
      	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
      	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
      	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
      	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
      	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
      	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
      	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:233)
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
      	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
      	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
      	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
      	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
      	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
      	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
      	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
      	at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
      	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176)
      	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
      	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
      Caused by: java.lang.NullPointerException
      	at org.apache.cxf.helpers.IOUtils.copy(IOUtils.java:182)
      	at org.apache.cxf.helpers.IOUtils.copy(IOUtils.java:141)
      	at org.apache.cxf.io.DelegatingInputStream.cacheInput(DelegatingInputStream.java:54)
      	at org.apache.cxf.transport.http.AbstractHTTPDestination$1.cacheInput(AbstractHTTPDestination.java:308)
      	at org.apache.cxf.transport.http.AbstractHTTPDestination.cacheInput(AbstractHTTPDestination.java:582)
      	at org.apache.cxf.transport.http.AbstractHTTPDestination.flushHeaders(AbstractHTTPDestination.java:604)
      	at org.apache.cxf.transport.http.AbstractHTTPDestination.flushHeaders(AbstractHTTPDestination.java:597)
      	at org.apache.cxf.transport.http.AbstractHTTPDestination$WrappedOutputStream.onFirstWrite(AbstractHTTPDestination.java:782)
      	at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
      	at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:60)
      	at org.apache.cxf.jaxrs.provider.StringTextProvider.writeTo(StringTextProvider.java:72)
      	at org.apache.cxf.jaxrs.provider.StringTextProvider.writeTo(StringTextProvider.java:35)
      	at org.apache.cxf.jaxrs.utils.JAXRSUtils.writeMessageBody(JAXRSUtils.java:1375)
      	at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRSOutInterceptor.java:250)
      	... 53 more
      

      If I subclass MockHttpServletRequest and have it return an empty ServletInputStream instead of null, then CXF works without throwing the NPE.

      Just to be defensive, you might want to check for null return values from HttpServletRequest.getInputStream(). It seems like several people have run into issues with this, like this mailing list post:

      http://mail-archives.apache.org/mod_mbox/cxf-users/201104.mbox/%3C1303876123106-4342671.post@n5.nabble.com%3E

      Attachments

        Activity

          People

            sergey_beryozkin Sergey Beryozkin
            soleger Seth Leger
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: