JAX-RS - Injecting Providers instance with @Context annotation

[Updated: Dec 1, 2017, Created: Nov 30, 2017]

Providers interface allows runtime lookup of registered provider instances. Following is its declaration:

package javax.ws.rs.ext;
 ....
public interface Providers {
    <T> MessageBodyReader<T> getMessageBodyReader(Class<T> type, Type genericType,
                                        Annotation[] annotations, MediaType mediaType);

    <T> MessageBodyWriter<T> getMessageBodyWriter(Class<T> type, Type genericType,
                                        Annotation[] annotations, MediaType mediaType);

    <T extends Throwable> ExceptionMapper<T> getExceptionMapper(Class<T> type);

    <T> ContextResolver<T> getContextResolver(Class<T> contextType, MediaType mediaType);
}

The instance of this interface can be injected with @Context annotation. It is injectable in both client and server providers.

This interface typically meant to be injected in a provider class wishing to use other provider to delegate some functionality.

We have already seen an example of Providers.getContextResolver() here. In the following example we are going to use Providers.getMessageBodyWriter().

Example

Following example resource is meant to return the response in CSV format:

@Path("/persons")
public class PersonsResource {

  @GET
  @Produces("text/csv")
  public List<Person> getPersons() {
      return Arrays.asList(
              new Person("Tina", 35),
              new Person("Charlie", 40));
  }
}
public class Person {
  private String name;
  private int age;
    .............
}

Injecting Providers instance

To convert POJOs to CSV format, we are going to implement MessageBodyWriter:

@Provider
@Produces("text/csv")
public class CsvWriter<T> implements MessageBodyWriter<List<T>> {
  @Context
  Providers providers;

  @Override
  public void writeTo(List<T> ts, Class<?> type, Type genericType, Annotation[] annotations,
                      MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
                      OutputStream entityStream) throws IOException, WebApplicationException {
      String response = "";
      for (T t : ts) {
          try {
              Class<?> c = t.getClass();
              //using Java Bean API to access property values
              BeanInfo beanInfo = Introspector.getBeanInfo(c);
              String temp = "";
              for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
                  if (pd.getName().equals("class")) {//skip getClass()
                      continue;
                  }
                  Object o = pd.getReadMethod().invoke(t);
                  temp += "," + o;
              }
              if (temp.length() > 0) {
                  temp = temp.substring(1);
                  response += temp + "\n";
              }
          } catch (Exception e) {
              throw new WebApplicationException(e);
          }
      }
      //using Providers instance
      MessageBodyWriter<String> plainTextWriter = providers.getMessageBodyWriter(String.class,
              genericType, annotations, MediaType.TEXT_PLAIN_TYPE);
      plainTextWriter.writeTo(response, String.class, genericType, annotations, mediaType,
              httpHeaders, entityStream);
  }

  @Override
  public boolean isWriteable(Class<?> type, Type genericType,
                             Annotation[] annotations, MediaType mediaType) {
      return true;
  }

  @Override
  public long getSize(List<T> ts, Class<?> type, Type genericType,
                      Annotation[] annotations, MediaType mediaType) {
      return -1;
  }
}

As seen above, the actual responsibility of writing response to output stream is delegated to the default writer which handles plain text.

To try examples, run embedded tomcat (configured in pom.xml of example project below):

mvn tomcat7:run-war

The JAX-RS client

public class ExampleClient {
  public static void main(String[] args) {
      Client client = ClientBuilder.newClient();
      WebTarget target =
              client.target("http://localhost:8080/persons");
      Response response = target.request()
                                .get();
      System.out.printf("status: %s%n", response.getStatus());
      System.out.printf("-- response body --%n%s%n", response.readEntity(String.class));
  }
}

Output

status: 200
-- response body --
35,Tina
40,Charlie

Example Project

Dependencies and Technologies Used :

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

@Context Providers Example Select All Download
  • injecting-providers-example
    • src
      • main
        • java
          • com
            • logicbig
              • example

See Also