During runtime, type erasure removes generic type information. For example an object of type List<Order> appears to contain a raw List<?> at runtime.
In JAX-RS, wrapping a response object (like List<Order>) in Response, removes the generic type information. Because of that, some MessageBodyWriter implementations cannot be selected without the generic information. Wrapping the entity in GenericEntity preserves the generic type. Let's see an example to understand the problem and then how to use GenericEntity.
Example
First, we will wrap our entity object directly in Response:
@Path("/")
public class OrderResource {
@Path("/orders")
@Produces(MediaType.APPLICATION_XML)
@GET
public Response handle() {
List<Order> orders = getOrders();
Response r = Response.ok(orders)
.header("someHeader", "someHeaderValue")
.build();
return r;
}
public List<Order> getOrders() {
Order o1 = new Order(1, new BigDecimal(15));
Order o2 = new Order(2, new BigDecimal(20));
return Arrays.asList(o1, o2);
}
.............
}
@XmlRootElement
public class Order {
private int id;
private BigDecimal amount;
.............
}
To try examples, run embedded tomcat (configured in pom.xml of example project below):
mvn tomcat7:run
public class MyClient1 {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080/orders");
String response = target.request()
.get(String.class);
System.out.println(response);
}
}Outputjavax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error at org.glassfish.jersey.client.JerseyInvocation.convertToException (JerseyInvocation.java:1032) at org.glassfish.jersey.client.JerseyInvocation.translate (JerseyInvocation.java:819) at org.glassfish.jersey.client.JerseyInvocation.access$700 (JerseyInvocation.java:92) at org.glassfish.jersey.client.JerseyInvocation$2.call (JerseyInvocation.java:701) 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:697) at org.glassfish.jersey.client.JerseyInvocation$Builder.method (JerseyInvocation.java:420) at org.glassfish.jersey.client.JerseyInvocation$Builder.get (JerseyInvocation.java:316) at com.logicbig.example.MyClient1.main (MyClient1.java:13) 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:498) at org.codehaus.mojo.exec.AbstractExecJavaBase.executeMainMethod (AbstractExecJavaBase.java:402) at org.codehaus.mojo.exec.AbstractExecJavaBase.doExecClassLoader (AbstractExecJavaBase.java:377) at org.codehaus.mojo.exec.AbstractExecJavaBase.lambda$execute$0 (AbstractExecJavaBase.java:287) at java.lang.Thread.run (Thread.java:748)
In the server console:
Oct 22, 2025 12:21:37 PM org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo
SEVERE: MessageBodyWriter not found for media type=application/xml, type=class java.util.Arrays$ArrayList, genericType=class java.util.Arrays$ArrayList.
Using GenericEntity
@Path("/")
public class OrderResource {
.............
@Path("/orders2")
@Produces(MediaType.APPLICATION_XML)
@GET
public Response handle2() {
List<Order> orders = getOrders();
GenericEntity<List<Order>> genericEntity = new GenericEntity<List<Order>>(orders) {
};//needs empty body to preserve generic type
Response r = Response.ok(genericEntity)
.header("someHeader", "someHeaderValue")
.build();
return r;
}
}
public class MyClient2 {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
WebTarget target = client.target("http://localhost:8080/orders2");
String s = target.request().get(String.class);
System.out.println(s);
}
}Output[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.6.2:java (default-cli) on project generic-entity-example: An exception occurred while executing the Java class. java.net.ConnectException: Connection refused: connect -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
Example ProjectDependencies and Technologies Used: - jersey-container-servlet 2.25.1 (Jersey core Servlet 3.x implementation)
- JDK 1.8
- Maven 3.3.9
|