Marshaling CSV representation to Java objects with MessageBodyReader

In the previous section, we discussed the entity provider that supports the marshaling of the Java object to media types. In this section, we will see the entity provider that does the reverse process, unmarshaling of the input stream to the Java types.

The JAX-RS framework uses MessageBodyReader to deserialize the message body into the Java type. The JAX-RS runtimes natively supports the deserialization of input stream to the commonly used Java types. You can use the custom MessageBodyReader implementation to control the deserialization of the input stream, which is not supported by JAX-RS, by default.

A javax.ws.rs.ext.MessageBodyReader<T> provider should implement the following methods and contracts:

  • isReadable(): This method checks whether the MessageBodyReader interface can produce an instance of a particular Java type. This method is invoked when the framework tries to find a matching MessageBodyReader interface for reading the input stream into a Java type parameter present in the resource method.
  • readFrom(): This method reads the input stream into the designated Java type.

Keep a note of the following points when building a MessageBodyReader interface:

  • A MessageBodyReader implementation may be annotated with @Consumes to restrict the media types for which it will be considered suitable
  • A MessageBodyReader provider implementation must be either programmatically registered in the JAX-RS runtime or must be annotated with the @Provider annotation

The following example illustrates a custom MessageBodyReader implementation, which converts the CSV representation of the department items present in the input stream to list the Department Java objects:

//Other imports are omitted for brevity 
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 org.supercsv.cellprocessor.ift.CellProcessor; 
import org.supercsv.io.CsvBeanReader; 
import org.supercsv.io.ICsvBeanReader; 
import org.supercsv.prefs.CsvPreference; 
 
@Provider 
@Consumes("application/csv") 
public class CSVMessageBodyReader implements MessageBodyReader<List<Department>> { 
 
    /** 
     * Ascertain if the MessageBodyReader can produce  
     * an instance of a particular type. 
     */ 
    @Override 
    public boolean isReadable(Class<?> type, Type genericType,  
        Annotation[] annotations, MediaType mediaType) { 
        return Collection.class.isAssignableFrom(type); 
    } 
 
    /** 
     * Read a type from InputStream.  
     */ 
    @Override 
    public List readFrom(Class<List<Department>> type, Type  
        genericType, Annotation[] annotations,  
        MediaType mediaType,  
        MultivaluedMap<String, String> httpHeaders, 
        InputStream entityStream)  
        throws IOException, WebApplicationException { 
 
        ArrayList list = new ArrayList(); 
        //Following code uses Super CSV lib for reading CSV data 
        //Define the type for each column in CSV 
        final CellProcessor[] processors = new CellProcessor[]{ 
            new NotNull(new ParseShort()), // departmentId 
            new NotNull(), // departmentName 
            new NotNull(new ParseShort()), // locationId 
            new Optional(new ParseInt()) //managerId 
        }; 
        //Reads CSV input stream 
        ICsvBeanReader beanReader = new CsvBeanReader(new  
            InputStreamReader(entityStream),  
            CsvPreference.STANDARD_PREFERENCE); 
        //Start building object from CVS 
        String[] header = beanReader.getHeader(false); 
        Object obj = null; 
        while ((obj = beanReader.read(Department.class,  
       header, processors)) != null) { 
            list.add(obj); 
            logger.log(Level.INFO, obj.toString()); 
        } 
 
        return list; 
    } 
} 

The following RESTful web service call illustrates how a JAX-RS application can use CSVMessageBodyReader for taking input in CSV format:

POST /api/hr/departments HTTP/1.1 
Host: localhost:8080 
Content-Type: application/csv 
 
departmentId,departmentName,locationId,managerId 
1001,"Finance",1700,101 
1002,"Office Administration",1500,205 
You can download this example from the Packt website link mentioned at the beginning of this book, in the Preface. See the CSVMessageBodyReader.java and CSVMessageBodyWriter.java files in the <rest-chapter4-service> project.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.251.57