blob: 02e0dde4bc169a4977376e5ed2e55d7e291870ef [file] [log] [blame]
<!--
/***************************************************************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
***************************************************************************************************************************/
-->
Custom Serializers and Parsers
<p>
A very easy-to-use API is provided for defining your own serializers and parsers at both the servlet and
method levels.
</p>
<p>
The following examples show a custom serializer and parser defined at the method level.
It's the <l>PhotosResource</l> class pulled from the Samples project.
It shows an example of defining a serializer and parser to handle images.
</p>
<p class='bpcode w800'>
<jd>/**
* Sample resource that allows images to be uploaded and retrieved.
*/</jd>
<ja>@Rest</ja>(
path=<js>"/photos"</js>,
messages=<js>"nls/PhotosResource"</js>,
title=<js>"Photo REST service"</js>,
description=<js>"Use a tool like Poster to upload and retrieve jpeg and png images."</js>,
htmldoc=<ja>@HtmlDoc</ja>(
navlinks={
<js>"options: ?method=OPTIONS"</js>
}
)
)
<jk>public class</jk> PhotosResource <jk>extends</jk> BasicRestServlet {
<jc>// Our cache of photos</jc>
<jk>private</jk> Map&lt;Integer,Photo&gt; photos = <jk>new</jk> TreeMap&lt;Integer,Photo&gt;();
<jd>/** Bean class for storing photos */</jd>
<jk>public static class</jk> Photo {
<jk>private int</jk> <jf>id</jf>;
BufferedImage <jf>image</jf>;
Photo(int id, BufferedImage image) {
<jk>this</jk>.<jf>id</jf> = id;
<jk>this</jk>.<jf>image</jf> = image;
}
<jk>public</jk> URI getURI() <jk>throws</jk> URISyntaxException {
<jk>return new</jk> URI(<js>"photos/"</js>+<jf>id</jf>);
}
<jk>public int</jk> getID() {
<jk>return</jk> <jf>id</jf>;
}
}
<jd>/** GET request handler for list of all photos */</jd>
<ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/"</js>)
<jk>public</jk> Collection&lt;Photo&gt; getAllPhotos(RestRequest req, RestResponse res) <jk>throws</jk> Exception {
res.setPageTitle(<js>"Photo REST service"</js>);
res.setPageText(<js>"Use a tool like Poster to upload and retrieve jpeg and png images."</js>);
<jk>return</jk> photos.values();
}
<jd>/** GET request handler for single photo */</jd>
<ja>@RestMethod</ja>(name=<jsf>GET</jsf>, path=<js>"/{id}"</js>, serializers=ImageSerializer.<jk>class</jk>)
<jk>public</jk> BufferedImage getPhoto(RestRequest req, <ja>@Path</ja>(<js>"id"</js>) int id) <jk>throws</jk> Exception {
Photo p = photos.get(id);
if (p == <jk>null</jk>)
<jk>throw new</jk> RestException(<jsf>SC_NOT_FOUND</jsf>, <js>"Photo not found"</js>);
<jk>return</jk> p.image;
}
<jd>/** PUT request handler */</jd>
<ja>@RestMethod</ja>(name=<jsf>PUT</jsf>, path=<js>"/{id}"</js>, parsers=ImageParser.<jk>class</jk>)
<jk>public</jk> String addPhoto(RestRequest req, <ja>@Path</ja>(<js>"id"</js>) <jk>int</jk> id, <ja>@Body</ja> BufferedImage image) <jk>throws</jk> Exception {
photos.put(id, <jk>new</jk> Photo(id, image));
<jk>return</jk> <js>"OK"</js>;
}
<jd>/** POST request handler */</jd>
<ja>@RestMethod</ja>(name=<jsf>POST</jsf>, path=<js>"/"</js>, parsers=ImageParser.<jk>class</jk>)
<jk>public</jk> Photo setPhoto(RestRequest req, <ja>@Body</ja> BufferedImage image) <jk>throws</jk> Exception {
<jk>int</jk> id = photos.size();
Photo p = <jk>new</jk> Photo(id, image);
photos.put(id, p);
<jk>return</jk> p;
}
<jd>/** DELETE request handler */</jd>
<ja>@RestMethod</ja>(name=<jsf>DELETE</jsf>, path=<js>"/{id}"</js>)
<jk>public</jk> String deletePhoto(RestRequest req, <ja>@Path</ja>(<js>"id"</js>) <jk>int</jk> id) <jk>throws</jk> Exception {
Photo p = photos.remove(id);
if (p == <jk>null</jk>)
<jk>throw new</jk> RestException(<jsf>SC_NOT_FOUND</jsf>, <js>"Photo not found"</js>);
<jk>return</jk> <js>"OK"</js>;
}
<jd>/** OPTIONS request handler */</jd>
<ja>@RestMethod</ja>(name=<jsf>OPTIONS</jsf>, path=<js>"/*"</js>)
<jk>public</jk> Swagger getOptions(RestRequest req) {
<jk>return</jk> req.getSwagger();
}
<jd>/** Serializer for converting images to byte streams */</jd>
<ja>@Produces</ja>(<js>"image/png,image/jpeg"</js>)
<jk>public static class</jk> ImageSerializer <jk>extends</jk> OutputStreamSerializer {
<ja>@Override</ja> <jc>/* Serializer */</jc>
<jk>public void</jk> serialize(Object o, OutputStream out, SerializerSession session) <jk>throws</jk> IOException, SerializeException {
RenderedImage image = (RenderedImage)o;
String mediaType = ctx.getMediaType();
ImageIO.<jsm>write</jsm>(image, mediaType.substring(mediaType.indexOf(<js>'/'</js>)+1), out);
}
}
<jd>/** Parser for converting byte streams to images */</jd>
<ja>@Consumes</ja>(<js>"image/png,image/jpeg"</js>)
<jk>public static class</jk> ImageParser <jk>extends</jk> InputStreamParser {
<ja>@Override</ja> <jc>/* Parser */</jc>
<jk>public</jk> &lt;T&gt; T parse(InputStream in, ClassMeta&lt;T&gt; type, ParserSession session) <jk>throws</jk> ParseException, IOException {
BufferedImage image = ImageIO.<jsm>read</jsm>(in);
<jk>return</jk> (T)image;
}
}
}
</p>