Close

JAX-RS - Returning GenericEntity to preserve generic type

[Last Updated: Oct 29, 2025]

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);
  }
}

Output

javax.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 Project

Dependencies and Technologies Used:

  • jersey-container-servlet 2.25.1 (Jersey core Servlet 3.x implementation)
  • JDK 1.8
  • Maven 3.3.9

Generic Entity Example Select All Download
  • generic-entity-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • OrderResource.java

    See Also