|
SYS-CON.TV Webcasts
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
Top Links You Must Click On
Features Implementing RESTful Services
Using Multipart Data Content
By: Rizwan Ahmed
Oct. 1, 2009 07:00 PM
The RESTful architectural style [1], with its URL addressable, resource oriented approach allows you to define Web services which can have multiple runtime representation in a variety of different media types. You define a Web resource, encapsulating the desired functionality within a business method, accessible via a URI over the HTTP protocol and its different "verbs": GET, POST, PUT, DELETE [2]. The transferred content may be either HTML, XML, binary data or images, which, depending on the business use case often require to be embedded within the same message. The Multipurpose Internet Mail Extensions (MIME) is an internet standard that is frequently used for describing content type in communication protocols like HTTP and specifies standard formats for encapsulating multiple pieces of data into a single message. In this article, I demonstrate RESTful services created by the RESTEasy open source framework to work with multipart data content typical in a real-world service scenario. Introduction RESTEasy is an open source reference implementation of the JAX-RS specification [4] and provides a developer friendly API, with annotations that facilitate a declarative style of programming, to create RESTful information-driven Web resources [5]. RESTEasy includes a rich set of built-in providers that support content (un)marshalling on a variety of different representations (including XML, JSON, FastInfoSet, Multipart, XOP, ATOM) with the selection of the appropriate provider invisible to the developers. RESTEasy comes with an easy-to-use client framework that allows you to create/bind the entity body and invoke HTTP requests mapped to the server resource via an interface proxy. RESTEasy also supports the multipart/mixed, multipart/form-data and multipart/related MIME types that allows the RESTful resource to work with multipart messages. A Real-World Service Scenario Multipart Messages Through the use of the multipart type, as the name suggests, MIME allows messages to have multiple parts that consist of attachments arranged inline in a linear tree like structure with support for various media content such as application/xml, application/octet-stream, application/msword, image/jpg, audio/mp3, etc. A multipart message contains a boundary defined in the top level "Content-Type" header that is placed between the parts and at the beginning and end of the body of the message (refer to Example 1). (The code examples and listings can be downloaded here.)The top level "Content-Type" header for the multipart message indicates the media type of the message content and could be one of the following subtypes: multipart/mixed, multipart/form-data and multipart/related. Each part of a multipart message has its own unique identity consisting of a "Content-Type" header indicating its wrapped media type, the "Content-Disposition" header indicating presentational information, and finally the message body encapsulating the message content. The mixed subtype of the multipart MIME type is the most basic and arguably the easiest way of sending heterogeneous media content. Its intended for use when the individual body parts are independent of each other and do not need to be bundled in any particular order (see Example 1) [8]. Defining a JAX-RS Service to Work with Multipart/Mixed Listing 3 shows a RESTful Web resource that returns a multipart/mixed message wrapped within MultipartOutput. The multipart message being returned consists of product details: name, cost, description, the purchase order PDF form (represented as binary data) and customer information as JAXB annotated classes for automatic marshalling by the RESTEasy JAXB Providers. The ProductDetailType, Product and Customer objects are JAXB schema derived (annotated with @XmlType) classes representing the individual part entities. It's worthwhile to keep in mind that the JAXB implementation will create an ObjectFactory class that is used by the RESTEasy runtime JAXBXmlTypeProvider to create a JAXBElement represention of the ProductDetailType, Customer and Product entities [5]. A sample multipart/mixed output for the HTTP request GET /rest-services/multipart/mixed HTTP/1.1 is shown in Example 1. The Multipart/form-data MIME Format Defining a JAX-RS Service and Client to Work with Multipart/form-data An alternate method involves first creating a value class that maps to your multipart/form-data message content. In this example (refer to Listing 6), I have created a POJO annotated with @XmlRootElement that will encapsulate the multipart content returned by a JAX-RS Web resource. As before, the Customer and Product objects are JAXB schema-derived classes representing the individual part entities. If posting from an online HTML form whose action is mapped to the RESTful resource that can handle multipart form-data (similar to MultipartFormResponseType), the @FormParam annotation on each multipart element is used to inject individual form parameters from the request body into the method. You may, alternately, choose to have your web resource declaratively voice its parameter preference of application/x-www-form-urlencoded which unmarshalls to a MultivaluedMap<String, String> if the message parts are of uniform content. In this example, we're creating a resource that generates multipart/form-data (to be sent back for pre-filling the HTML or PDF form), therefore, the @FormParam is used to bind the values of form-field data onto the response. The @PartType annotation is used to represent the media type of the individual parts. Listing 7 is an example of a RESTful Web resource that returns a multipart/form-data message encapsulated within an instance of MultipartFormResponseType. The @MultipartForm annotation is used to tell RESTEasy that the returned entity has multiple parts annotated with @FormParam and therefore should be marshalled as such. JAX-RS allows for building custom responses using the javax.ws.rs.core.Response and ResponseBuilder classes. The javax.ws.rs.core.GenericEntity<T> class represents a response entity of a generic type T and is used by the Resource class to wrap the entity representing the multipart message. The javax.ws.rs.core.Response class's ok() convenience method builds the response containing an entity of generic type MultipartFormResponseType and returns an HTTP 200 OK. This generic type is available at runtime and is used by RESTEasy for selection of the appropriate MessageBodyWriter for marshalling. Once we have a RESTful Web resource defined that outputs multipart data, the next thing we need is a client that can parse out and understand it. RESTEasy has an easy-to-use client proxy framework. You create a Java class proxy that is a mirror interface of the resource class (refer to Listing 8). The client framework builds an HTTP request that is then used to invoke on the remote RESTful Web resource (see Listing 9) and leverages similar providers to unmarshal the response from the server resource. The org.jboss.resteasy.client.ClientResponse is the RESTEasy extension of the javax.ws.rs.core.Response and is typically used if your clients need access to the Response entity as well as status and header information. A sample output of the response to the following HTTP request GET /rest-services/multipart/form HTTP/1.1 is shown in Example 2. The Multipart/related MIME Format Defining a JAX-RS Service to Work with Multipart/related Messages Alternately, you could create a POJO (akin to Listing 6) consisting of JAXB annotated classes for XML media type content, byte array (or the more commonly used javax.activation.DataHandler) for binary content that wraps your multipart message. In Listing 12, I have created a JAX-RS resource that consumes a multipart/related message represented by the class MultipartRelatedType. RESTEasy enables multipart/related messages consisting of binary data to be packaged using the XOP (XML binary Optimized Packaging) mechanism. XOP optimizes the packaging of the binary content without encoding it within Base64 thereby resulting in a faster transport [11]. The @Consumes(MediaType.MULTIPART_RELATED) annotation informs RESTEasy about our intention to pass a multipart/related message as a parameter to the Web service. The annotation @XopWithMultipartRelated tells RESTEasy to unpack and process the message packaged using XOP (the same annotation on the client side interface tells the RESTEasy client framework to pack the message using XOP packaging). Conclusion References
Reader Feedback: Page 1 of 1
Enterprise Open Source Magazine Latest Stories . . .
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||