20.12. XML-binary Optimized Packaging (Xop)
RESTEasy supports packaging XOP (XML-binary Optimized Packaging) messages as
multipart/related
. This means that if you have a JAXB-annotated POJO that also holds some binary content, you can send it without needing to encode the binary in any other way. This results in faster transport while retaining the convenience of the POJO. (You can read more about XOP at the W3C web page.)
Take the following JAXB-annotated POJO as an example.
@XmlMimeType
tells JAXB the MIME type of the binary content. (This is not required, but it is recommended.)
@XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public static class Xop { private Customer bill; private Customer monica; @XmlMimeType(MediaType.APPLICATION_OCTET_STREAM) private byte[] myBinary; @XmlMimeType(MediaType.APPLICATION_OCTET_STREAM) private DataHandler myDataHandler; // methods, other fields ... }
Here,
myBinary
and myDataHandler
are processed as binary attachments, while the XOP object will be sent as XML. javax.activation.DataHandler
is the most common supported type, so if you need a java.io.InputStream
or a javax.activation.DataSource
, you must use the DataHandler
. java.awt.Image
and javax.xml.transform.Source
are also supported. We assume, in the previous example, that Customer
is a JAXB-friendly POJO. The following is an example Java client to send the previous example:
// our client interface: @Path("mime") public static interface MultipartClient { @Path("xop") @PUT @Consumes(MediaType.MULTIPART_RELATED) public void putXop(@XopWithMultipartRelated Xop bean); } // Somewhere using it: { MultipartClient client = ProxyFactory.create(MultipartClient.class, "http://www.example.org"); Xop xop = new Xop(new Customer("bill"), new Customer("monica"), "Hello Xop World!".getBytes("UTF-8"), new DataHandler(new ByteArrayDataSource("Hello Xop World!".getBytes("UTF-8"), MediaType.APPLICATION_OCTET_STREAM))); client.putXop(xop); }
@Consumes(MediaType.MULTIPART_RELATED)
tells RESTEasy that we want to send multipart/related
packages, a format that will hold our XOP message. @XopWithMultipartRelated
tells RESTEasy that we want to create XOP messages. Now that we have a POJO and a client service capable of sending it, we need a server capable of reading it:
@Path("/mime") public class XopService { @PUT @Path("xop") @Consumes(MediaType.MULTIPART_RELATED) public void putXopWithMultipartRelated(@XopWithMultipartRelated Xop xop) { // do very important things here } }
@Consumes(MediaType.MULTIPART_RELATED)
tells RESTEasy that we want to read multipart/related
packages. @XopWithMultipartRelated
tells RESTEasy that we want to read XOP messages. We could also produce XOP return values by annotating them with @Produce
.