LibraryToggle FramesPrintFeedback

Custom entity readers are responsible for mapping incoming HTTP requests into a Java type that a service's implementation can manipulate. They implement the javax.ws.rs.ext.MessageBodyReader interface.

The interface, shown in Example 7.1, has two methods that need implementing:


isReadable()

The isReadable() method determines if the reader is capable of reading the data stream and creating the proper type of entity representation. If the reader can create the proper type of entity the method returns true.

Table 7.2 describes the isReadable() method's parameters.


readFrom()

The readFrom() method reads the HTTP entity and coverts it into the desired Java object. If the reading is successful the method returns the created Java object containing the entity. If an error occurs when reading the input stream the method should throw an IOException exception. If an error occurs that requires an HTTP error response, an WebApplicationException with the HTTP response should be thrown.

Table 7.3 describes the readFrom() method's parameters.


[Important]Important

This method should not close the input stream.

Before an MessageBodyReader implementation can be used as an entity reader, it must be decorated with the javax.ws.rs.ext.Provider annotation. The @Provider annotation alerts the runtime that the supplied implementation provides additional functionality. The implementation must also be registered with the runtime as described in Registering readers and writers.

By default a custom entity provider handles all MIME types. You can limit the MIME types that a custom entity reader will handle using the javax.ws.rs.Consumes annotation. The @Consumes annotation specifies a comma separated list of MIME types that the custom entity provider reads. If an entity is not of a specified MIME type, the entity provider will not be selected as a possible reader.

Example 7.2 shows an entity reader the consumes XML entities and stores them in a Source object.

Example 7.2. XML source entity reader

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;
import org.apache.cxf.jaxrs.ext.xml.XMLSource;

@Provider
@Consumes({"application/xml", "application/*+xml", "text/xml", "text/html" })
public class SourceProvider implements MessageBodyReader<Object>
{
  public boolean isReadable(Class<?> type,
                            Type genericType,
                            Annotation[] annotations,
                            MediaType mt)
  {
    return Source.class.isAssignableFrom(type) || XMLSource.class.isAssignableFrom(type);
  }

  public Object readFrom(Class<Object> source,
                         Type genericType,
                         Annotation[] annotations,
                         MediaType mediaType, 
                         MultivaluedMap<String, String> httpHeaders,
                         InputStream is)
  throws IOException
  {
    if (DOMSource.class.isAssignableFrom(source))
    {
      Document doc = null;
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      DocumentBuilder builder;
      try
      {
        builder = factory.newDocumentBuilder();
        doc = builder.parse(is);
      }
      catch (Exception e)
      {
        IOException ioex = new IOException("Problem creating a Source object");
        ioex.setStackTrace(e.getStackTrace());
        throw ioex;
       }

       return new DOMSource(doc);
    }
    else if (StreamSource.class.isAssignableFrom(source) || Source.class.isAssignableFrom(source))
    {
      return new StreamSource(is);
    }
    else if (XMLSource.class.isAssignableFrom(source))
    {
      return new XMLSource(is);
    }

    throw new IOException("Unrecognized source");
  }
}

Custom entity writers are responsible for mapping Java types into HTTP entities. They implement the javax.ws.rs.ext.MessageBodyWriter interface.

The interface, shown in Example 7.3, has three methods that need implementing:


isWriteable()

The isWriteable() method determines if the entity writer can map the Java type to the proper entity type. If the writer can do the mapping, the method returns true.

Table 7.4 describes the isWritable() method's parameters.


getSize()

The getSize() method is called before the writeTo(). It returns the length, in bytes, of the entity being written. If a positive value is returned the value is written into the HTTP message's Content-Length header.

Table 7.5 describes the getSize() method's parameters.


writeTo()

The writeTo() method converts a Java object into the desired entity type and writes the entity to the output stream. If an error occurs when writing the entity to the output stream the method should throw an IOException exception. If an error occurs that requires an HTTP error response, an WebApplicationException with the HTTP response should be thrown.

Table 7.6 describes the writeTo() method's parameters.


Before a MessageBodyWriter implementation can be used as an entity writer, it must be decorated with the javax.ws.rs.ext.Provider annotation. The @Provider annotation alerts the runtime that the supplied implementation provides additional functionality. The implementation must also be registered with the runtime as described in Registering readers and writers.

By default a custom entity provider handles all MIME types. You can limit the MIME types that a custom entity writer will handle using the javax.ws.rs.Produces annotation. The @Produces annotation specifies a comma separated list of MIME types that the custom entity provider generates. If an entity is not of a specified MIME type, the entity provider will not be selected as a possible writer.

Example 7.4 shows an entity writer that takes Source objects and produces XML entities.

Example 7.4. XML source entity writer

import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import org.apache.cxf.jaxrs.ext.xml.XMLSource;

@Provider
@Produces({"application/xml", "application/*+xml", "text/xml" })
public class SourceProvider implements MessageBodyWriter<Source>
{

  public boolean isWriteable(Class<?> type,
                             Type genericType,
                             Annotation[] annotations,
                             MediaType mt)
  {
    return Source.class.isAssignableFrom(type);
  }

  public void writeTo(Source source,
                      Class<?> clazz,
                      Type genericType,
                      Annotation[] annotations,
                      MediaType mediatype,
                      MultivaluedMap<String, Object> httpHeaders,
                      OutputStream os)
  throws IOException
  {
    StreamResult result = new StreamResult(os);
    TransformerFactory tf = TransformerFactory.newInstance();
    try
    {
      Transformer t = tf.newTransformer();
      t.transform(source, result);
    }
    catch (TransformerException te)
    {
      te.printStackTrace();
      throw new WebApplicationException(te);
    }
  }

  public long getSize(Source source,
                      Class<?> type, 
                      Type genericType, 
                      Annotation[] annotations,
                      MediaType mt)
  {
    return -1;
  }
}

Comments powered by Disqus