Bug 1156645 - [GSS](6.4.0) RESTEASY-1125: JAXB MessageBodyReader providers not recognized when using generics in a complex inheritance structure
Summary: [GSS](6.4.0) RESTEASY-1125: JAXB MessageBodyReader providers not recognized w...
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: JBoss Enterprise Application Platform 6
Classification: JBoss
Component: RESTEasy
Version: 6.2.4
Hardware: Unspecified
OS: Unspecified
unspecified
high
Target Milestone: DR11
: EAP 6.4.0
Assignee: Weinan Li
QA Contact: Katerina Odabasi
URL:
Whiteboard:
Depends On:
Blocks: 1118891 1163547 1164401
TreeView+ depends on / blocked
 
Reported: 2014-10-24 22:08 UTC by William Antônio
Modified: 2019-08-19 12:46 UTC (History)
4 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Cause: The isReadable method is not implemented properly in EAP 6.4 Consequence: JAXB MessageBodyReader providers are not recognized when using generics in a complex inheritance structure. For the class that works, it returns the correct type of the class. For the class that is not working, it returns the type TypeVariable. Thus displaying an error message. Fix: This issue is now fixed in this version of JBoss EAP 6. The version of RESTEasy is now upgraded from 2.3.8 to 2.3.9. Result: JAXB MessageBodyReader providers is recognized when using generics in a complex inheritance structure
Clone Of:
: 1163547 (view as bug list)
Environment:
Last Closed:
Type: Bug
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker RESTEASY-1125 0 Critical Resolved RESTEASY-1125: JAXB MessageBodyReader providers not recognized when using generics in a complex inheritance structure 2016-02-15 23:12:17 UTC

Description William Antônio 2014-10-24 22:08:56 UTC
Description of problem:

I have the abstract resource:

public class AbstractResource<T> {

	@POST
	@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
	public Response createEntity(T entity) {
		return Response.ok("Success!").build();
	}

}

Then an intermediary class:

public class OtherAbstractResource<T> extends AbstractResource<T>{}

And two resources test(doesn't work) and test2(will work in any scenario):

@Path("test2")
@Stateless
public class ConcreteClassThatWorks extends AbstractResource<Model>{

}

@Stateless
@Path("/test")
public class ConcreteResource extends OtherAbstractResource<Model> {

}

I deploy my application and test both resources for XML, see:

[wsiqueir@wsiqueir secured-servlet]$ curl -X POST --data '<model></model>' -H 'content-type: application/xml' http://localhost:8080/generics-resteasy/test
<html><head><title>JBoss Web/7.2.2.Final-redhat-1 - JBWEB000064: Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>JBWEB000065: HTTP Status 400 - Could not find message body reader for type: T of content type: application/xml</h1><HR size="1" noshade="noshade"><p><b>JBWEB000309: type</b> JBWEB000067: Status report</p><p><b>JBWEB000068: message</b> <u>Could not find message body reader for type: T of content type: application/xml</u></p><p><b>JBWEB000069: description</b> <u>JBWEB000120: The request sent by the client was syntactically incorrect.</u></p><HR size="1" noshade="noshade"><h3>JBoss Web/7.2.2.Final-redhat-1</h3></body></html>


[wsiqueir@wsiqueir secured-servlet]$ curl -X POST --data '<model></model>' -H 'content-type: application/xml' http://localhost:8080/generics-resteasy/test2
Success!


Both will work for JSON, see:

[wsiqueir@wsiqueir secured-servlet]$ curl -X POST --data '{}' -H 'content-type: application/json' http://localhost:8080/generics-resteasy/test2
Success!

[wsiqueir@wsiqueir secured-servlet]$ curl -X POST --data '{}' -H 'content-type: application/json' http://localhost:8080/generics-resteasy/test
Success!


Everything works fine in Wildfly 8.1.

Comment 1 William Antônio 2014-10-30 06:01:45 UTC
After a few debugging and analysis, I found that the issue is in Types class. A utility class to find more about the actual type of a given parameter.

At the MethodInjectorImpl class, we have the type retrieving:

      Type[] genericParameterTypes = actualMethod.getGenericParameterTypes();
      for (int i = 0; i < actualMethod.getParameterTypes().length; i++)
      {
         Class<?> type;
         Type genericType;

         // the parameter type might be a type variable defined in a superclass
         if (actualMethod.getGenericParameterTypes()[i] instanceof TypeVariable<?>)
         {
            // try to find out the value of the type variable
            genericType = Types.getActualValueOfTypeVariable(root, (TypeVariable<?>) genericParameterTypes[i]);
            type = Types.getRawType(genericType);
         }
         else
         {
            type = actualMethod.getParameterTypes()[i];
            genericType = genericParameterTypes[i];
         }

         Annotation[] annotations = method.getParameterAnnotations()[i];
         params[i] = factory.getInjectorFactory().createParameterExtractor(root, method, type, genericType, annotations);
      }


And at the following line is were we can observe the bug:

            // try to find out the value of the type variable
            genericType = Types.getActualValueOfTypeVariable(root, (TypeVariable<?>) genericParameterTypes[i]);

For the class that works, it will return the correct type of the class. For the class that is not working, it returns the type TypeVariable, leading to the mentioned error.

Now, the question is why it works with JSON? I believe that the answer is how the MessageBodyReader from jackson implemented the isReadable method.

The JAXB implementation is as follow:


      return type.isAnnotationPresent(XmlRootElement.class) && (FindAnnotation.findAnnotation(type, annotations, DoNotUseJAXBProvider.class) == null) && !IgnoredMediaTypes.ignored(type, annotations, mediaType);


It means that it trusts on the type that was passed. 


After this debugging, I went to upstream source to see how is they type retrieved, since the fix could be on the type retrieving because the MessageBodyReader for JAXB didn't change its isReadable implementation. The problem is that the Types class changed a lot:

https://github.com/resteasy/Resteasy/blob/master/jaxrs/resteasy-jaxrs/src/main/java/org/jboss/resteasy/util/Types.java


Probably due some spec change, since upstream resteasy implements JAX-RS 2.0. Basically I meant that we don't have the fix yet. The fix will probably be change the method Types.getActualValueOfTypeVariable to make it works with the ConcreteResource scenario and return the correct type.

Comment 2 JBoss JIRA Server 2014-11-19 09:56:10 UTC
Weinan Li <weli> updated the status of jira RESTEASY-1125 to Resolved

Comment 3 Kabir Khan 2014-11-21 15:29:28 UTC
Setting to MODIFIED from the following mail thread:
- - - -
Yes they are all included.

--
Weinan Li / JBoss

On Nov 20, 2014, at 8:44 PM, Kabir Khan <kabir.khan> wrote:

Are either https://bugzilla.redhat.com/show_bug.cgi?id=1156645 or https://bugzilla.redhat.com/show_bug.cgi?id=1165332 fixed by today’s RestEasy upgrade https://bugzilla.redhat.com/show_bug.cgi?id=1118891?

Comment 4 Katerina Odabasi 2014-11-27 15:09:55 UTC
Verified in EAP 6.4.0.DR11 with RESTEASY-1125 test.


Note You need to log in before you can comment on or make changes to this bug.