Open jerseyrobot opened 8 years ago
@glassfishrobot Commented Reported by puce
@glassfishrobot Commented puce said: I don't seem to have enough rights to fix the typos...
@glassfishrobot Commented puce said: OK, according to the Javadoc, the readFrom method of a MessageBodyReader may throw a WebApplicationException, which seems strange as this seems only to make sense on the server side when parsing request messages.
But the same classes are also used on client side to parse response messages, which happens after the webservice has been called (which might be successful or not) and thus readFrom method should not affect the HTTP status code in this case.
@glassfishrobot Commented puce said: You should be able to reproduce this issue by writing a JAX-RS client which calls a GET request and tries to unmarshal the response with JAXB using: https://docs.oracle.com/javaee/7/api/javax/ws/rs/client/SyncInvoker.html#get-java.lang.Class-
and
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>${jersey.version}</version>
</dependency>
where the response provided by the server does contain a different content than expected -> call was successful, but unmarshalling fails -> should throw a ResponseProcessingException not a WebApplicationException
@glassfishrobot Commented puce said: The same issue also happens if you call: response.readEntity(MyJaxbClass.class)
javax.ws.rs.BadRequestException: HTTP 400 Bad Request
at org.glassfish.jersey.jaxb.internal.AbstractRootElementJaxbProvider.readFrom(AbstractRootElementJaxbProvider.java:136)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:256)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:235)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:808)
at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:326)
at org.glassfish.jersey.client.InboundJaxrsResponse$1.call(InboundJaxrsResponse.java:115)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:419)
at org.glassfish.jersey.client.InboundJaxrsResponse.runInScopeIfPossible(InboundJaxrsResponse.java:267)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:112)
at <some class>
at <some class>
at <some class>
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:94)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:619)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at com.github.tomakehurst.wiremock.junit.WireMockStaticRule$1.evaluate(WireMockStaticRule.java:55)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:110)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[Exception [EclipseLink-25008] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor with default root element foo was not found in the project]
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.handleXMLMarshalException(JAXBUnmarshaller.java:1072)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:326)
at org.glassfish.jersey.jaxb.internal.XmlRootElementJaxbProvider.readFrom(XmlRootElementJaxbProvider.java:140)
at org.glassfish.jersey.jaxb.internal.AbstractRootElementJaxbProvider.readFrom(AbstractRootElementJaxbProvider.java:134)
... 41 more
Caused by: Exception [EclipseLink-25008] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor with default root element foo was not found in the project
at org.eclipse.persistence.exceptions.XMLMarshalException.noDescriptorWithMatchingRootElement(XMLMarshalException.java:162)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshallerHandler.startElement(SAXUnmarshallerHandler.java:305)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.eclipse.persistence.internal.oxm.record.XMLReader.parse(XMLReader.java:243)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:401)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:654)
at org.eclipse.persistence.internal.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:581)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:323)
... 43 more
A ProcessException would be expected in this case.
@glassfishrobot Commented puce said: Here is the stack trace of the first case, where readEntity gets called by JerseyInvocation$Builder.get :
javax.ws.rs.BadRequestException: HTTP 400 Bad Request
at org.glassfish.jersey.jaxb.internal.AbstractRootElementJaxbProvider.readFrom(AbstractRootElementJaxbProvider.java:136)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:256)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:235)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:808)
at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:326)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:803)
at org.glassfish.jersey.client.JerseyInvocation.access$700(JerseyInvocation.java:92)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:700)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:696)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:420)
at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:316)
at <some class>
at <some class>
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:94)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:619)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at com.github.tomakehurst.wiremock.junit.WireMockStaticRule$1.evaluate(WireMockStaticRule.java:55)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:110)
at com.intellij.junit4.JUnit4TestRunnerUtil$IgnoreIgnoredTestJUnit4ClassRunner.runChild(JUnit4TestRunnerUtil.java:341)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:94)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:619)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[Exception [EclipseLink-25008] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor with default root element foo was not found in the project]
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.handleXMLMarshalException(JAXBUnmarshaller.java:1072)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:326)
at org.glassfish.jersey.jaxb.internal.XmlRootElementJaxbProvider.readFrom(XmlRootElementJaxbProvider.java:140)
at org.glassfish.jersey.jaxb.internal.AbstractRootElementJaxbProvider.readFrom(AbstractRootElementJaxbProvider.java:134)
... 47 more
Caused by: Exception [EclipseLink-25008] (Eclipse Persistence Services - 2.6.0.v20150309-bf26070): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor with default root element foo was not found in the project
at org.eclipse.persistence.exceptions.XMLMarshalException.noDescriptorWithMatchingRootElement(XMLMarshalException.java:162)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshallerHandler.startElement(SAXUnmarshallerHandler.java:305)
at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.eclipse.persistence.internal.oxm.record.XMLReader.parse(XMLReader.java:243)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:401)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:654)
at org.eclipse.persistence.internal.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:581)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:323)
... 49 more
In this case a ResponseProcessingException would be expected containing the response object with the correct status code.
@glassfishrobot Commented puce said: Related issue: #2740
@glassfishrobot Commented Issue-Links: is duplicated by JERSEY-2468
@glassfishrobot Commented This issue was imported from java.net JIRA JERSEY-3005
@zetlan Commented I've also been bitten by this issue – I had a JAXRS serialization error resulting from an unknown property that wasn't ignored. That caused an error whose stacktrace was only visible during debug. Somewhere in the processResponse() logic it would be helpful if the exception is re-thrown – would have saved me a couple hours of debugging.
I see this has been open quite a while – any thoughts about timing of a fix/change?
My analysis so far is as following: AbstractRootElementJaxbProvider throws subclasses of WebApplicationException instead of an IOException: https://jersey.java.net/project-info/2.22.1/jersey/project/jersey-media-jaxb/xref/org/glassfish/jersey/jaxb/internal/AbstractRootElementJaxbProvider.html
At least in the latest version this handled somewhat in JerseyInvocation, where WebApplicationException gets catched and wrapped by a ResponseProcessingException.
https://github.com/jersey/jersey/blob/master/core-client/src/main/java/org/glassfish/jersey/client/JerseyInvocation.java#L858
This is wakwards since the nested exception provides a wrong HTTP status code (eg. "HTTP 400 Bad Request", where the request itself was succesful.
In the end the nested WebApplicationException gets unwrapped again: https://github.com/jersey/jersey/blob/master/core-client/src/main/java/org/glassfish/jersey/client/JerseyInvocation.java#L690
So I think the best thing would be if the AbstractRootElementJaxbProvider class would throw IOException.
The case of a thrown WebApplicationException should never arise when calling response.readEntity (translate method). So the catch clause should be removed and it should be made sure this case never arises (otherwise it would still be catched by the Exception catch statement).
The unwrapping of the cause of the ProcessingException in the translate method also seems wrong in some cases (e.g. when there is no cause). Why not just set the ProcessingException itself as cause?
The IllegalStateException is not handled specially while ProcessingException is. Seems inconsistent.
And last but not least the WebApplicationException should not be unwrapped in the invoke method. Again, I think WebApplicationException should never be the cause of a ProcessingException anyway.
Affected Versions
[2.22.1]