Bug 1163547 - [GSS](6.3.z) RESTEASY-1125 - JAXB MessageBodyReader providers not recognized when using generics in a complex inheritance structure
Summary: [GSS](6.3.z) RESTEASY-1125 - JAXB MessageBodyReader providers not recognized ...
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: CR1
: EAP 6.3.3
Assignee: Weinan Li
QA Contact: Katerina Odabasi
URL:
Whiteboard:
Depends On: 1156645
Blocks: eap633-payload 1164404
TreeView+ depends on / blocked
 
Reported: 2014-11-13 01:54 UTC by Kyle Lape
Modified: 2019-08-19 12:41 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of: 1156645
Environment:
Last Closed: 2019-08-19 12:41:42 UTC
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 2015-05-25 21:13:06 UTC

Description Kyle Lape 2014-11-13 01:54:36 UTC
+++ This bug was initially created as a clone of Bug #1156645 +++

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.

--- Additional comment from William Antônio on 2014-10-30 02:01:45 EDT ---

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 1 Weinan Li 2014-11-18 07:36:38 UTC
This will be included into the rebuild of 2.3.9-redhat-X.

Comment 2 Kyle Lape 2014-11-18 19:05:50 UTC
@Weinan, can this also be included in another SP release of 2.3.8 (for EAP 6.3.3)?

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

Comment 5 Katerina Odabasi 2015-01-20 09:14:30 UTC
Verified in EAP 6.3.3.CP.CR1. (RESTEASY-1125 test)


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