Thanks for the quick response Sergey, I never intended my question to be a "Why haven't you don't this, this is stupid" type of question, you guys have done a great deal of work already with CXF and it is very much so appreciated. I will be doing an upgrade to 2.2.4 and will look to submitting a patch for the other fix so we can target it for 2.2.5, hopefully before you do :) Thanks again!
Mustafa -----Original Message----- From: Sergey Beryozkin [mailto:[email protected]] Sent: Friday, 6 November 2009 5:50 AM To: Sergey Beryozkin; [email protected] Subject: Re: NPE when doing a post with null content type MultipartProvider has been fixed to check the ContentLength, if 0 it will throw 400, sismilarly to what is requested from JAXB providers by JAXRS 1.1. JAXRS 1.1 actually says that only a JAXB provider should throw 400 in such cases but given that the support for Multiparts is not currently standardized and it's clearly a client bug in this case, I reckon it's appropriate to throw 400 too from MultipartProvider cheers, Sergey ----- Original Message ----- From: "Sergey Beryozkin" <[email protected]> To: <[email protected]> Sent: Thursday, November 05, 2009 10:16 AM Subject: Re: NPE when doing a post with null content type > Hi > >> >> This seems to related to the Content-Type list having a null object. The >> HttpHeaderImpl class seems to do the following on line 132 >> >> >> >> String[] ls = values.get(0).split(","); >> >> >> >> But because content type has a null object, the NPE is thrown. > > > This issue (HttpHeadersImpl throwing NPE if one of the headers's value is actually 'null' ) has been fixed in 2.2.3 or 2.2.4, > there's an extra check now in getListValues()... > >> >> >> I have also found another issue where the content-type is set to >> multipart/mixed but no post content exists... >> > <snip/> >> -------------------------------------- >> >> I get >> >> >> javax.ws.rs.WebApplicationException: >> java.lang.StringIndexOutOfBoundsException: String index out of range: -1 >> >> at >> org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java: >> 839) >> >> Now CXF may have deliberately not implemented these checks for some >> reason, and left these checks for us to implement via the use of an >> interceptor, but I would find that a bit odd. > > It is a CXF bug so I agreed it's odd a custom interceptor has to do these kinds of checks. JAX-RS 1.1 explicitly says what needs > to be done in case when request bodies are not available so this issue will be fixed for 2.2.3 and I'll try to fix it for the > incoming 2.2.5. > > I wish we started implementing with various possible issues like empty request bodies, etc, in mind from the get-go, but for a > while (and still in some cases today) the goal has been : to do it (a given feature, etc) asap, make sure the basic case work well > and enhance/improve over time. I'm hoping there're much fewer issues like the one you're reporting remain and we'll just continue > fixing the lurking bugs out there, if any... > >> Could the CXF developers provide some insight into these issues and if I >> should implement specific interceptors to perform these checks? > > Implementing blocking intercepters is only needed if you're hitting a CXF bug further down the chain > >> Our Rest >> services return XML error responses and we would like to also do that in >> these cases where the messages are not constructed properly.. > > Sure, there's a number of ways : > > - register a custom ExceptionMapper which captures RuntimeExceptions and return a custom XML response describing an exception > - register a custom ServletFiler and handle the original exceptions wrapped in ServletExceptions > - register a custom out fault interceptor with jaxrs:server, write details to the HttpServletResponse stream and abort the chain - > a test showing how to do it will be available shortly > > > thanks, Sergey > >> >> Thanks >> >> >> >> Mustafa > > > ----- Original Message ----- > From: "Mustafa Sezgin" <[email protected]> > To: <[email protected]> > Sent: Thursday, November 05, 2009 7:03 AM > Subject: NPE when doing a post with null content type > > >> Hi all, >> >> >> >> Im using CXF 2.2.2 and have come across an issue which I thought would >> raise with you guys to see if i should submit a patch..I am doing a POST >> request to a Rest service which accepts a multi part message. If i craft >> a message such that the following output is produced by CXF >> >> >> >> [2009-11-05 17:34:42,512 >> debug][haseinterceptorchain][12601...@qtp-288204-3 g1n57lim][127.0.0.1][] >> Chain org.apache.cxf.phase.phaseinterceptorch...@1bf6406 was created. >> Current flow: >> >> receive [LoggingInInterceptor] >> >> unmarshal [JAXRSInInterceptor] >> >> pre-logical [OneWayProcessorInterceptor] >> >> pre-invoke [MonitoringInterceptor, ExtAPIThrottlingInterceptor, >> EventOriginInterceptor] >> >> invoke [ServiceInvokerInterceptor] >> >> post-invoke [OutgoingChainInterceptor] >> >> >> >> [2009-11-05 17:34:42,512 >> debug][haseinterceptorchain][12601...@qtp-288204-3 g1n57lim][127.0.0.1][] >> Invoking handleMessage on interceptor >> org.apache.cxf.interceptor.logginginintercep...@1f6d4ab >> >> [2009-11-05 17:34:42,512 INFO >> ][loggingininterceptor][12601...@qtp-288204-3 g1n57lim][127.0.0.1][] >> Inbound Message >> >> ---------------------------- >> >> ID: 31 >> >> Address: /api/projects/107/mail >> >> Encoding: UTF-8 >> >> Content-Type: >> >> Headers: {connection=[Keep-Alive], Host=[localhost:8080], >> Content-Length=[0], User-Agent=[Apache-HttpClient/4.0-beta2 (java 1.5)], >> Content-Type=[null]} >> >> Payload: >> >> -------------------------------------- >> >> Then I get the following stacktrace >> >> >> >> javax.ws.rs.WebApplicationException: java.lang.NullPointerException >> >> at >> org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java: >> 839) >> >> at >> org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:470 >> ) >> >> at >> org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:43 >> 5) >> >> at >> org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSIn >> Interceptor.java:194) >> >> at >> org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInI >> nterceptor.java:65) >> >> at >> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorCha >> in.java:236) >> >> at >> org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiation >> Observer.java:89) >> >> at >> org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestinat >> ion.java:99) >> >> at >> org.apache.cxf.transport.servlet.ServletController.invokeDestination(Servl >> etController.java:368) >> >> at >> org.apache.cxf.transport.servlet.ServletController.invoke(ServletControlle >> r.java:146) >> >> at >> org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServ >> let.java:163) >> >> at >> org.apache.cxf.transport.servlet.AbstractCXFServlet.doPost(AbstractCXFServ >> let.java:141) >> >> at >> javax.servlet.http.HttpServlet.service(HttpServlet.java:727) >> >> at >> javax.servlet.http.HttpServlet.service(HttpServlet.java:820) >> >> at >> org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1166) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(Delega >> tingFilterProxy.java:236) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFi >> lterProxy.java:167) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(Delega >> tingFilterProxy.java:236) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFi >> lterProxy.java:167) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilte >> rInternal(OpenSessionInViewFilter.java:198) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(Delega >> tingFilterProxy.java:236) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFi >> lterProxy.java:167) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) >> >> at >> org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216 >> ) >> >> at >> org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) >> >> at >> org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) >> >> at >> org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) >> >> at >> org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCo >> llection.java:230) >> >> at >> org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java: >> 114) >> >> at >> org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) >> >> at org.mortbay.jetty.Server.handle(Server.java:326) >> >> at >> org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:536) >> >> at >> org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnect >> ion.java:915) >> >> at >> org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:539) >> >> at >> org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) >> >> at >> org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:405) >> >> at >> org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java: >> 228) >> >> at >> org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:5 >> 82) >> >> Caused by: java.lang.NullPointerException >> >> at >> org.apache.cxf.jaxrs.impl.HttpHeadersImpl.getListValues(HttpHeadersImpl.ja >> va:132) >> >> at >> org.apache.cxf.jaxrs.impl.HttpHeadersImpl.getRequestHeaders(HttpHeadersImp >> l.java:84) >> >> at >> org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java: >> 827) >> >> ... 55 more >> >> This seems to related to the Content-Type list having a null object. The >> HttpHeaderImpl class seems to do the following on line 132 >> >> >> >> String[] ls = values.get(0).split(","); >> >> >> >> But because content type has a null object, the NPE is thrown. >> >> >> >> I have also found another issue where the content-type is set to >> multipart/mixed but no post content exists... >> >> For a message such that >> >> [2009-11-05 17:34:51,695 INFO >> ][loggingininterceptor][12601...@qtp-288204-3 g1n57smk][127.0.0.1][] >> Inbound Message >> >> ---------------------------- >> >> ID: 32 >> >> Address: /api/projects/107/mail >> >> Encoding: UTF-8 >> >> Content-Type: multipart/mixed >> >> Headers: {content-type=[multipart/mixed], connection=[Keep-Alive], >> Host=[localhost:8080], Content-Length=[0], >> User-Agent=[Apache-HttpClient/4.0-beta2 (java 1.5)], >> Content-Type=[multipart/mixed]} >> >> Payload: >> >> -------------------------------------- >> >> I get >> >> >> >> javax.ws.rs.WebApplicationException: >> java.lang.StringIndexOutOfBoundsException: String index out of range: -1 >> >> at >> org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java: >> 839) >> >> at >> org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:470 >> ) >> >> at >> org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:43 >> 5) >> >> at >> org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSIn >> Interceptor.java:194) >> >> at >> org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInI >> nterceptor.java:65) >> >> at >> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorCha >> in.java:236) >> >> at >> org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiation >> Observer.java:89) >> >> at >> org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestinat >> ion.java:99) >> >> at >> org.apache.cxf.transport.servlet.ServletController.invokeDestination(Servl >> etController.java:368) >> >> at >> org.apache.cxf.transport.servlet.ServletController.invoke(ServletControlle >> r.java:146) >> >> at >> org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServ >> let.java:163) >> >> at >> org.apache.cxf.transport.servlet.AbstractCXFServlet.doPost(AbstractCXFServ >> let.java:141) >> >> at >> javax.servlet.http.HttpServlet.service(HttpServlet.java:727) >> >> at >> javax.servlet.http.HttpServlet.service(HttpServlet.java:820) >> >> at >> org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1166) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(Delega >> tingFilterProxy.java:236) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFi >> lterProxy.java:167) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(Delega >> tingFilterProxy.java:236) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFi >> lterProxy.java:167) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilte >> rInternal(OpenSessionInViewFilter.java:198) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(Delega >> tingFilterProxy.java:236) >> >> at >> org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFi >> lterProxy.java:167) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerReques >> tFilter.java:76) >> >> at >> org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandl >> er.java:1157) >> >> at >> org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) >> >> at >> org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216 >> ) >> >> at >> org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) >> >> at >> org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) >> >> at >> org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) >> >> at >> org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCo >> llection.java:230) >> >> at >> org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java: >> 114) >> >> at >> org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) >> >> at org.mortbay.jetty.Server.handle(Server.java:326) >> >> at >> org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:536) >> >> at >> org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnect >> ion.java:915) >> >> at >> org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:539) >> >> at >> org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) >> >> at >> org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:405) >> >> at >> org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java: >> 228) >> >> at >> org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:5 >> 82) >> >> Caused by: java.lang.StringIndexOutOfBoundsException: String index out of >> range: -1 >> >> at java.lang.String.checkBounds(String.java:398) >> >> at java.lang.String.<init>(String.java:443) >> >> at >> org.apache.cxf.helpers.IOUtils.newStringFromBytes(IOUtils.java:65) >> >> at >> org.apache.cxf.attachment.AttachmentDeserializer.findBoundaryFromInputStre >> am(AttachmentDeserializer.java:142) >> >> at >> org.apache.cxf.attachment.AttachmentDeserializer.initializeRootMessage(Att >> achmentDeserializer.java:105) >> >> at >> org.apache.cxf.attachment.AttachmentDeserializer.initializeAttachments(Att >> achmentDeserializer.java:85) >> >> at >> org.apache.cxf.interceptor.AttachmentInInterceptor.handleMessage(Attachmen >> tInInterceptor.java:60) >> >> at >> org.apache.cxf.jaxrs.ext.MessageContextImpl.createAttachments(MessageConte >> xtImpl.java:131) >> >> at >> org.apache.cxf.jaxrs.ext.MessageContextImpl.get(MessageContextImpl.java:58 >> ) >> >> at >> org.apache.cxf.jaxrs.impl.tl.ThreadLocalMessageContext.get(ThreadLocalMess >> ageContext.java:38) >> >> at >> org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils.getMultipartBody(Atta >> chmentUtils.java:81) >> >> at >> org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils.getAttachments(Attach >> mentUtils.java:86) >> >> at >> org.apache.cxf.jaxrs.provider.MultipartProvider.readFrom(MultipartProvider >> .java:76) >> >> at >> org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java: >> 827) >> >> ... 55 more >> >> Now CXF may have deliberately not implemented these checks for some >> reason, and left these checks for us to implement via the use of an >> interceptor, but I would find that a bit odd. >> >> Could the CXF developers provide some insight into these issues and if I >> should implement specific interceptors to perform these checks? Our Rest >> services return XML error responses and we would like to also do that in >> these cases where the messages are not constructed properly.. >> >> Thanks >> >> >> >> Mustafa >> >> >
