You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/01 17:30:11 UTC
[22/53] [partial] incubator-juneau git commit: Merge changes from
GitHub repo.
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/package.html
----------------------------------------------------------------------
diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/package.html b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/package.html
new file mode 100755
index 0000000..a498e78
--- /dev/null
+++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/package.html
@@ -0,0 +1,3600 @@
+<!DOCTYPE HTML>
+<!--
+/***************************************************************************************************************************
+ * 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.
+ *
+ ***************************************************************************************************************************/
+ -->
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+ /* For viewing in Page Designer */
+ @IMPORT url("../../../../../javadoc.css");
+
+ /* For viewing in REST interface */
+ @IMPORT url("../htdocs/javadoc.css");
+ body {
+ margin: 20px;
+ }
+ </style>
+ <script>
+ /* Replace all @code and @link tags. */
+ window.onload = function() {
+ document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
+ document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>');
+ }
+ </script>
+</head>
+<body>
+<p>REST Servlet API</p>
+
+<script>
+ function toggle(x) {
+ var div = x.nextSibling;
+ while (div != null && div.nodeType != 1)
+ div = div.nextSibling;
+ if (div != null) {
+ var d = div.style.display;
+ if (d == 'block' || d == '') {
+ div.style.display = 'none';
+ x.className += " closed";
+ } else {
+ div.style.display = 'block';
+ x.className = x.className.replace(/(?:^|\s)closed(?!\S)/g , '' );
+ }
+ }
+ }
+</script>
+
+<p>
+ Defines an API for defining REST resources as servlets.
+</p>
+
+<a name='TOC'></a><h5 class='toc'>Table of Contents</h5>
+<ol class='toc'>
+ <li><p><a class='doclink' href='#Intro'>Introduction</a></p>
+ <li><p><a class='doclink' href='#HelloWorldResource'>Hello World Example</a></p>
+ <li><p><a class='doclink' href='#ClassHierarchy'>Class Hierarchy</a></p>
+ <li><p><a class='doclink' href='#RestServlets'>REST Servlets</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#RestServlets.MethodSignature'>REST Java Method Signature</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#RestServlets.MethodSignature.Path'>Path</a></p>
+ <li><p><a class='doclink' href='#RestServlets.MethodSignature.Matchers'>Matchers</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#RestServlets.RequestContent'>Request Content</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#RestServlets.RequestContent.FormPosts'>Form Posts</a></p>
+ <li><p><a class='doclink' href='#RestServlets.RequestContent'>Multipart Form Posts</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#RestServlets.ResponseContent'>Response Content</a></p>
+ <li><p><a class='doclink' href='#RestServlets.OptionsPages'>OPTIONS Pages</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Serializers'>Serializers</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Parsers'>Parsers</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Properties'>Properties</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Transforms'>Transforms</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Guards'>Guards</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Converters'>Converters</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Children'>Child Resources</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Labels'>Localized Messages</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Encoders'>Encoders</a></p>
+ <li><p><a class='doclink' href='#RestServlets.SvlVars'>SVL Vars</a></p>
+ <li><p><a class='doclink' href='#RestServlets.StaticFiles'>Static Files</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Listeners'>Listener Methods</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Stylesheet'>Stylesheet</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Headers'>Default Headers</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Errors'>Handling Errors / Logging</a></p>
+ <li><p><a class='doclink' href='#RestServlets.ConfigFile'>Configuration Files</a></p>
+ <li><p><a class='doclink' href='#RestServlets.Inheritence'>Annotation Inheritence</a></p>
+ <li><p><a class='doclink' href='#RestServlets.HttpStatusCodes'>HTTP Status Codes</a></p>
+ <li><p><a class='doclink' href='#RestServlets.OverloadedHttpMethods'>Overloaded HTTP Methods</a></p>
+ <li><p><a class='doclink' href='#RestServlets.BuildInParams'>Built-In Parameters</a></p>
+ <li><p><a class='doclink' href='#RestServlets.CustomSerializersParsers'>Defining your own serializers/parsers</a></p>
+ <li><p><a class='doclink' href='#RestServlets.ResponseHandlers'>Response Handlers</a></p>
+ <li><p><a class='doclink' href='#RestServlets.OtherNotes'>Other Notes</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#Osgi'>Using with OSGi</a></p>
+ <li><p><a class='doclink' href='#PojosConvertableFromString'>POJOs Convertable From Strings</a></p>
+ <li><p><a class='doclink' href='#AddressBookResource'>Address Book Resource</a></p>
+</ol>
+
+<!-- ======================================================================================================== -->
+<a name="Intro"></a>
+<h2 class='topic' onclick='toggle(this)'>1 - Introduction</h2>
+<div class='topic'>
+ <p>
+ The <l>juneau-server.jar</l> library allows you to quickly wrap POJOs and expose them as full-fledged REST resources served up in a servlet container using a bare-minimum amount of code.
+ The primary goal for Juneau was to make it as easy as possible to implement easy-to-read and self-documenting REST resources using very little code.
+ </p>
+ <p>
+ One of the biggest advantages of the Juneau REST framework over similar architectures is that it hides the serialization layer from the developer.
+ The developer can work entirely with POJOs and let the Juneau framework handle all the serialization and parsing work.
+ The developer need never know what the <l>Accept</l> or <l>Content-Type</l> or <l>Accept-Encoding</l> (etc...) header values are because those details are all handled by the framework.
+ </p>
+ <p>
+ The API builds upon the existing JEE Servlet API.
+ The root class, {@link org.apache.juneau.server.RestServlet} is nothing but a specialized {@link javax.servlet.http.HttpServlet}, and the
+ {@link org.apache.juneau.server.RestRequest} and {@link org.apache.juneau.server.RestResponse} classes are nothing more than specialized {@link javax.servlet.http.HttpServletRequest} and
+ {@link javax.servlet.http.HttpServletResponse} objects.
+ This allows maximum flexibility for the developer since you can let Juneau handle operations such as serialization, or you can revert
+ to the existing servlet APIs to do low-level processing of requests yourself.
+ It also means you need nothing more than a Servlet container such as Jetty to use the REST framework.
+ </p>
+ <h6 class='topic'>Features</h6>
+ <ul class='spaced-list'>
+ <li>Serializes POJOs to JSON, XML, HTML, URL-Encoding, UON, RDF/XML, N-Triple, Turtle, N3, SOAP, or Java-serialized-object based on
+ value of <l>Accept</l> header. <br>
+ No user code is required to handle these types.
+ <br>
+ <ul>
+ <li>Extensible design that provides ability to override existing content type handlers, or add the ability to handle other kinds of content types.
+ </ul>
+ <br>
+ <li>Parses content of POST/PUT request bodies to POJOs.
+ <br><br>
+ <li>Automatic built-in ability to serialize POJO metadata to JSON+SCHEMA, XML+SCHEMA, or HTML+SCHEMA based on <l>Accept</l> header.
+ <br><br>
+ <li>Automatic negotiation of output Writer based on HTTP headers.
+ <br>
+ <ul>
+ <li>Automatic handling of <l>Accept-Charset</l> header for all character sets supported by the JVM.
+ <li>Automatic handling of <l>Accept-Encoding</l> header with registered encoders.
+ </ul>
+ <br>
+ <li>Automatic error handling.
+ <br>
+ <ul>
+ <li>Automatic 401 errors (Unauthorized) on failed guards.
+ <li>Automatic 404 errors (Not Found) on unmatched path patterns.
+ <li>Automatic 405 errors (Method Not Implemented) on unimplemented methods.
+ <li>Automatic 406 errors (Not Acceptable) when no matching serializer was found to handle the <l>Accept</l> header.
+ <li>Automatic 412 errors (Precondition Failed) when all matchers failed to match.
+ <li>Automatic 415 errors (Unsupported Media Type) when no matching parser was found was found to handle the <l>Content-Type</l> header.
+ <li>Automatic 500 errors on uncaught exceptions.
+ </ul>
+ <br>
+ <li>Self-documenting REST interfaces.
+ <br>
+ <li>Various useful debugging features that make debugging using a browser extremely simple...
+ <br>
+ <ul>
+ <li>Ability to pass HTTP header values as URL GET parameters (e.g. <l>&Accept=text/xml</l>).
+ <li>Ability to pass HTTP content on PUT/POST requests as a URL GET parameter (e.g. <l>&content={foo:"bar"}</l>).
+ <li>Ability to simulate non-GET requests using a <l>&method</l> GET parameter (e.g. <l>&method=POST</l>).
+ <li>Ability to force <ss>"text/plain"</ss> on response using GET parameter <l>&plainText=true</l>.
+ </ul>
+ <br>
+ <li>Ability to implement overloaded HTTP methods through the use of the <l>&method</l> attribute (e.g. <l>&method=FOO</l>).
+ <br><br>
+ <li>Ability to match URL patterns (e.g. <l>/foo/{fooId}/bar/{barId}</l>) against URLs (e.g. <l>/foo/123/bar/456/bing</l>).
+ <br><br>
+ <li>Ability to associate guards at the resource or method levels through annotations.<br>
+ Typically useful for security, but can be used for a variety of purposes.
+ <br><br>
+ <li>Ability to associate converters at the resource or method levels through annotations.<br>
+ Typically useful for performing conversions on input and output, such as for supporting older input and output formats.
+ </ul>
+ <p>
+ Many of the examples in this document are pulled directly from the <l>microservice-samples-project.zip</l> project.
+ </p>
+</div>
+
+<!-- ======================================================================================================== -->
+<a name="HelloWorldResource"></a>
+<h2 class='topic' onclick='toggle(this)'>2 - Hello World Example</h2>
+<div class='topic'>
+ <p>
+ A REST resource is an implementation of {@link org.apache.juneau.server.RestServlet}, which itself is simply an extension of {@link javax.servlet.http.HttpServlet}.
+ </p>
+ <p>
+ In this example, we define a resource called <l>HelloWorldResource</l>.
+ This example is located in the <l>microservice-samples-project.zip</l> project.
+ It's assumed the reader is familiar with defining servlets in web applications.
+ </p>
+ <p>
+ Like any servlet, we could define our resource in the <l>web.xml</l> file of the web application like so...
+ </p>
+ <p class='bcode'>
+ <xt><?xml</xt> <xa>version</xa>=<xs>"1.0"</xs> <xa>encoding</xa>=<xs>"UTF-8"</xs><xt>?></xt>
+ <xt><web-app</xt> <xa>version</xa>=<xs>"2.3"</xs><xt>></xt>
+ <xt><servlet></xt>
+ <xt><servlet-name></xt>HelloWorldResource<xt></servlet-name></xt>
+ <xt><servlet-class></xt>com.ibm.sample.HelloWorldResource<xt></servlet-class></xt>
+ <xt></servlet></xt>
+ <xt><servlet-mapping></xt>
+ <xt><servlet-name></xt>HelloWorldResource<xt></servlet-name></xt>
+ <xt><url-pattern></xt>/*<xt></url-pattern></xt>
+ <xt></servlet-mapping></xt>
+ <xt></web-app></xt>
+ </p>
+ <p>
+ Our servlet code is shown below:
+ </p>
+ <p class='bcode'>
+ <jd>/**
+ * Sample REST resource that prints out a simple "Hello world!" message.
+ */</jd>
+ <ja>@RestResource</ja>(
+ messages=<js>"nls/HelloWorldResource"</js>,
+ properties={
+ <ja>@Property</ja>(name=<jsf>HTMLDOC_links</jsf>, value=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>)
+ }
+ )
+ <jk>public class</jk> HelloWorldResource <jk>extends</jk> Resource {
+
+ <jd>/** GET request handler */</jd>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>)
+ <jk>public</jk> String sayHello() {
+ <jk>return</jk> <js>"Hello world!"</js>;
+ }
+ }
+ </p>
+ <p>
+ The <l>messages</l> annotation points to a properties file on the classpath whose contents are shown below:
+ </p>
+ <p class='bcode'>
+ <cc>#--------------------------------------------------------------------------------
+ # HelloWorldResource labels
+ #--------------------------------------------------------------------------------</cc>
+ <ck>label</ck> = <cv>Hello World sample resource</cv>
+ <ck>description</ck> = <cv>Simplest possible resource</cv>
+ <ck>sayHello</ck> = <cv>Responds with "Hello world!"</cv>
+ </p>
+ <p>
+ It doesn't much simpler than that.
+ In this case, we're simply returning a string that will be converted to any of the supported languages (e.g. JSON, XML, HTML, ...).
+ However, we could have returned any POJO consisting of beans, maps, collections, etc...
+ </p>
+ <p>
+ The {@link org.apache.juneau.server.RestServletDefault} class that we're using here is a subclass of {@link org.apache.juneau.server.RestServlet} that provides default support for a variety of content types.
+ Implementers can choose to use this class, or create their own subclass of {@link org.apache.juneau.server.RestServlet} with their own specialized serializers and parsers.
+ </p>
+ <p>
+ If you were to start up this servlet and view it with a browser, you would see this:
+ </p>
+ <img class='bordered' src="doc-files/HelloWorldResource1.png">
+ <p>
+ The Juneau REST interface is designed to make it easy to interact with resources using nothing but a browser.
+ Therefore, several built-in features are provided for making it easy to do so.
+ Specifically, we'll be using these available URL parameters...
+ </p>
+ <ul class='normal'>
+ <li><l>&plainText=true</l> - If specified, then the <l>Content-Type</l> on the response is always <l>"text/plain"</l> regardless of the data format.
+ <br><br>
+ <li><l>&Accept=X</l> - Specify the content type of the response.
+ In a browser, <l>"text/html"</l> is the default content type, but this parameter can be used to override the content type on the response.<br>
+ Note: The behavior is identical to setting the <l>Accept</l> header on the request.
+ In fact, Juneau allows ANY HTTP request headers to be specified as URL parameters for debugging purposes.
+ </ul>
+ <p>
+ Using the <l>plainText</l> parameter, we can view the HTML as plain text...
+ </p>
+ <img class='bordered' src="doc-files/HelloWorldResource2.png">
+ <p>
+ You'll notice that the HTML view has a simple stylesheet associated with it to improve the look of the interface.
+ It is possible to specify your own stylesheet, but the default styles will usually suffice for most purposes.
+ </p>
+ <p>
+ When accessed through a browser, the content type will default to HTML (based on the value of the <l>Accept</l> HTTP header).
+ </p>
+ <p>
+ Let's use the <l>&Accept</l> URL paramter to override the <l>Accept</l> HTTP header to view this servlet in other formats...
+ </p>
+ <p>
+ In the case of <l>JSON</l>, we're serialize a single string, so it gets rendered as a JSON fragment....
+ </p>
+ <img class='bordered' src="doc-files/HelloWorldResource3.png">
+ <p>
+ ...or as <l>XML</l>...
+ </p>
+ <img class='bordered' src="doc-files/HelloWorldResource4.png">
+ <p>
+ ...or any of the other supported languages.
+ </p>
+ <p>
+ If you click the OPTIONS link on the page, you'll see the results from an <l>HTTP OPTIONS</l> request:
+ </p>
+ <img class='bordered' src="doc-files/HelloWorldResourceOptions.png">
+ <p>
+ The OPTIONS page is generated automatically by introspection of the class itself combined with
+ labels in the messages properties file.
+ It's composed of a POJO that gets serialized just like any other POJO.
+ Therefore, the POJO can be searialized to any of the supported languages, like JSON.
+ </p>
+ <img class='bordered' src="doc-files/HelloWorldResourceOptionsJson.png">
+</div>
+
+<!-- ======================================================================================================== -->
+<a name="ClassHierarchy"></a>
+<h2 class='topic' onclick='toggle(this)'>3 - Class Hierarchy</h2>
+<div class='topic'>
+ <p>
+ The class hierarchy for the REST servlet class is shown below:
+ </p>
+ <ul class='javahierarchy'>
+ <li class='a'>{@link javax.servlet.http.HttpServlet javax.servlet.http.HttpServlet}
+ <ul>
+ <li class='a'>{@link org.apache.juneau.server.RestServlet org.apache.juneau.server.RestServlet}
+ <br>Contains all the main logic.
+ <ul>
+ <li class='a'>{@link org.apache.juneau.server.RestServletDefault org.apache.juneau.server.RestServletDefault}
+ <br>Provides a default set of serializers, parsers, options page, stylesheet, and other common settings.
+ <br><b>Developers will typically subclass this when creating REST resources in JEE environments.</b>
+ <ul>
+ <li class='a'>{@link org.apache.juneau.microservice.Resource org.apache.juneau.microservice.Resource}
+ <br>Subclass intented to be used in REST microservices.
+ <br><b>Developers will typically subclass this when creating microservices.</b>
+ <li class='a'>{@link org.apache.juneau.server.RestServletGroupDefault org.apache.juneau.server.RestServletGroupDefault}
+ <br>A default implementation for "router" pages.
+ <ul>
+ <li class='a'>{@link org.apache.juneau.microservice.ResourceGroup org.apache.juneau.microservice.ResourceGroup}
+ <br>Subclass intented to be used in REST microservices.
+ </ul>
+ <li class='c'>{@link org.apache.juneau.server.remoteable.RemoteableServlet org.apache.juneau.server.remoteable.RemoteableServlet}
+ <br>REST servlet for implementing remoteable proxy interfaces.
+ </ul>
+ <li class='a'>{@link org.apache.juneau.server.jena.RestServletJenaDefault org.apache.juneau.server.jena.RestServletJenaDefault}
+ <br>Same as {@link org.apache.juneau.server.RestServletDefault}, but adds RDF support.
+ <ul>
+ <li class='a'>{@link org.apache.juneau.microservice.ResourceJena org.apache.juneau.microservice.ResourceJena}
+ <br>Subclass intented to be used in REST microservices.
+ <li class='a'>{@link org.apache.juneau.server.jena.RestServletJenaGroupDefault org.apache.juneau.server.jena.RestServletJenaGroupDefault}
+ <br>Same as {@link org.apache.juneau.server.RestServletGroupDefault}, but adds RDF support.
+ </ul>
+ <li class='a'><code>com.ibm.team.repository.service.JazzRestResource</code>
+ <br>Parent class in Jazz Foundation for REST-based services.
+ <ul>
+ <li class='a'><code>com.ibm.team.repository.service.JazzDefaultRestResource</code>
+ <br>Provides a default set of serializers, parsers, options page, stylesheet, and other common settings.
+ </ul>
+ </ul>
+ </ul>
+ </ul>
+ <p>
+ The servlets with RDF support require Jena on the classpath.
+ All other serializers and parsers do not have any external library dependencies.
+ For this reason, we have separate servlets for supporting RDF so that you don't need Jena if you don't need to support RDF.
+ </p>
+ <p>
+ The {@link org.apache.juneau.server.RestRequest} and {@link org.apache.juneau.server.RestResponse} classes described later also extend from their servlet equivalents:
+ </p>
+ <ul class='javahierarchy'>
+ <li class='i'>{@link javax.servlet.http.HttpServletRequest javax.servlet.http.HttpServletRequest}
+ <ul>
+ <li class='c'>{@link org.apache.juneau.server.RestRequest org.apache.juneau.server.RestRequest} - Augmented with specialized REST methods.
+ </ul>
+ <li class='i'>{@link javax.servlet.http.HttpServletResponse javax.servlet.http.HttpServletResponse}
+ <ul>
+ <li class='c'>{@link org.apache.juneau.server.RestResponse org.apache.juneau.server.RestResponse} - Augmented with specialized REST methods.
+ </ul>
+ </ul>
+</div>
+
+ <!-- ======================================================================================================== -->
+<a name="RestResources"></a>
+<h2 class='topic' onclick='toggle(this)'>4 - REST Servlets</h2>
+ <div class='topic'>
+ <p>
+ Since REST servlets are subclasses of <l>HttpServlet</l>, they can be deployed in a J2EE
+ container like any other servlet, typically inside a <l>web.xml</l> file.
+ The REST servlet framework does not depend on any classloader scanning or external setup
+ other than registering the servlet with the J2EE container.
+ </p>
+ <p>
+ REST servlets can also be deployed by declaring them as children of other REST servlets (described later).
+ </p>
+ <p>
+ A REST servlet consists of an instance of {@link org.apache.juneau.server.RestServlet}
+ annotated with {@link org.apache.juneau.server.annotation.RestResource @RestResource} containing
+ public Java methods annotated with {@link org.apache.juneau.server.annotation.RestMethod @RestMethod}.
+ </p>
+ <p>
+ Developers will typically subclass directly from {@link org.apache.juneau.server.RestServletDefault}
+ since it provides a default set of serializers and parsers for a variety of
+ <l>Accept</l> and <l>Content-Type</l> types.
+ </p>
+ <h6 class='figure'>Valid Accept headers for RestServletDefault</h6>
+ <table class='styled'>
+ <tr>
+ <th>Accept</th>
+ <th>Content-Type</th>
+ <th>Serializer</th>
+ </tr>
+ <tr>
+ <td class='code'>application/json<br>text/json</td>
+ <td class='code'>application/json</td>
+ <td>{@link org.apache.juneau.json.JsonSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>application/json+simple<br>text/json+simple</td>
+ <td class='code'>application/json</td>
+ <td>{@link org.apache.juneau.json.JsonSerializer.Simple}</td>
+ </tr>
+ <td class='code'>application/json+schema<br>text/json+schema</td>
+ <td class='code'>application/json</td>
+ <td>{@link org.apache.juneau.json.JsonSchemaSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/xml</td>
+ <td class='code'>text/xml</td>
+ <td>{@link org.apache.juneau.xml.XmlDocSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/xml+schema</td>
+ <td class='code'>text/xml</td>
+ <td>{@link org.apache.juneau.xml.XmlSchemaDocSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/html</td>
+ <td class='code'>text/html</td>
+ <td>{@link org.apache.juneau.html.HtmlDocSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/html+stripped</td>
+ <td class='code'>text/html</td>
+ <td>{@link org.apache.juneau.html.HtmlStrippedDocSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/uon</td>
+ <td class='code'>text/uon</td>
+ <td>{@link org.apache.juneau.urlencoding.UonSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/uon-simple</td>
+ <td class='code'>text/uon</td>
+ <td>{@link org.apache.juneau.urlencoding.UonSerializer.Simple}</td>
+ </tr>
+ <tr>
+ <td class='code'>application/x-www-form-urlencoded</td>
+ <td class='code'>application/x-www-form-urlencoded</td>
+ <td>{@link org.apache.juneau.urlencoding.UrlEncodingSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>application/x-www-form-urlencoded-simple</td>
+ <td class='code'>application/x-www-form-urlencoded</td>
+ <td>{@link org.apache.juneau.urlencoding.UrlEncodingSerializer.Simple}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/xml+soap</td>
+ <td class='code'>text/xml</td>
+ <td>{@link org.apache.juneau.soap.SoapXmlSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/plain</td>
+ <td class='code'>text/plain</td>
+ <td>{@link org.apache.juneau.plaintext.PlainTextSerializer}</td>
+ </tr>
+ <tr>
+ <td class='code'>application/x-java-serialized-object</td>
+ <td class='code'>application/x-java-serialized-object</td>
+ <td>{@link org.apache.juneau.jso.JavaSerializedObjectSerializer}</td>
+ </tr>
+ </table>
+ <h6 class='figure'>Valid Content-Type headers for RestServletDefault</h6>
+ <table class='styled'>
+ <tr>
+ <th>Content-Type</th>
+ <th>Parser</th>
+ </tr>
+ <tr>
+ <td class='code'>application/json<br>text/json</td>
+ <td>{@link org.apache.juneau.json.JsonParser}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/xml<br>application/xml</td>
+ <td>{@link org.apache.juneau.xml.XmlParser}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/html<br>text/html+stripped</td>
+ <td>{@link org.apache.juneau.html.HtmlParser}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/uon</td>
+ <td>{@link org.apache.juneau.urlencoding.UonParser}</td>
+ </tr>
+ <tr>
+ <td class='code'>application/x-www-form-urlencoded</td>
+ <td>{@link org.apache.juneau.urlencoding.UrlEncodingParser}</td>
+ </tr>
+ <tr>
+ <td class='code'>text/plain</td>
+ <td>{@link org.apache.juneau.plaintext.PlainTextParser}</td>
+ </tr>
+ </table>
+ <p>
+ {@link org.apache.juneau.server.RestServletDefault} also provides a default OPTIONS page by implementing
+ a {@link org.apache.juneau.server.RestServletDefault#getOptions(RestRequest)} method that returns a POJO consisting
+ of beans describing the class.
+ This is what produces the output for the OPTIONS page on the Hello World sample above.
+ </p>
+
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='javahierarchy'>
+ <li class='a'>{@link org.apache.juneau.server.RestServletDefault}
+ <li class='a'>{@link org.apache.juneau.server.jena.RestServletJenaDefault}
+ </ul>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.MethodSignature"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.1 - REST Java Method Signature</h3>
+ <div class='topic'>
+ <p>
+ REST Java methods are identified on REST servlets using the {@link org.apache.juneau.server.annotation.RestMethod @RestMethod} annotation.
+ The annotation allows the framework to identify the available REST methods through reflection.
+ </p>
+ <p class='bcode'>
+ <jd>/** GET request handler */</jd>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/"</js>)
+ <jk>public</jk> String sayHello() {
+ <jk>return</jk> <js>"Hello world!"</js>;
+ }
+ </p>
+ <h6 class='topic'>Method Name</h6>
+ <p>
+ There are no restrictions on the name of the Java method. However, if you plan on making use of the
+ {@link org.apache.juneau.server.annotation.RestResource#messages() @RestResource.messages()}
+ annotation (described later), the method names must be unique to make it possible to identify unique keys for labels in the resource bundle.
+ Therefore, you should not define two identically-named <l>doFoo(...)</l> methods that differ only by parameters.
+ If you're not using messages for NLS support, then name them whatever you want!
+ </p>
+ <h6 class='topic'>Method Return Type</h6>
+ <p>
+ The return type can be any serializable POJO as defined in <a class='doclink' href='../../../../overview-summary.html#Core.PojoCategories'>POJO Categories</a>.
+ It can also be <jk>void</jk> if the method is not sending any output (e.g. a request redirect) or
+ is setting the output using the {@link org.apache.juneau.server.RestResponse#setOutput(Object)} method.
+ Calling the {@link org.apache.juneau.server.RestResponse#setOutput(Object)} method is functionally equivalent to returning a value.
+ </p>
+ <p class='bcode'>
+ <jc>// Equivalent method 1</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>)
+ <jk>public void</jk> doGet(RestResponse res) {
+ res.setOutput(<js>"Hello World!"</js>);
+ }
+
+ <jc>// Equivalent method 2</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>)
+ <jk>public</jk> String doGet() {
+ <jk>return</jk> <js>"Hello World!"</js>;
+ }
+ </p>
+ <p>
+ The return type can also be any of the following special object types:
+ </p>
+ <ul class='javahierarchy'>
+ <li class='c'>{@link java.io.InputStream}
+ <br>The contents are simply piped to the output stream returned by {@link org.apache.juneau.server.RestResponse#getNegotiatedOutputStream()}.
+ <br>Note that you should call {@link org.apache.juneau.server.RestResponse#setContentType(String)} to set the <l>Content-Type</l> header if you use this object type.
+ <li class='c'>{@link java.io.Reader}
+ <br>The contents are simply piped to the output stream returned by {@link org.apache.juneau.server.RestResponse#getNegotiatedWriter()}.
+ <br>Note that you should call {@link org.apache.juneau.server.RestResponse#setContentType(String)} to set the <l>Content-Type</l> header if you use this object type.
+ <li class='c'>{@link org.apache.juneau.server.Redirect}
+ <br>Represents an HTTP redirect response.
+ <li class='i'>{@link org.apache.juneau.Streamable}
+ <br>Interface that identifies that an object can be serialized directly to an output stream.
+ <li class='i'>{@link org.apache.juneau.Writable}
+ <br>Interface that identifies that an object can be serialized directly to a writer.
+ <li class='c'>{@link org.apache.juneau.utils.ZipFileList}
+ <br>Special interface for sending zip files as responses.
+ </ul>
+ <p>
+ Additional "special types" can be defined through the {@link org.apache.juneau.server.ResponseHandler} interface (described later).
+ </p>
+ <h6 class='topic'>Method Parameters</h6>
+ <p>
+ The method can contain any of the following parameters in any order:
+ </p>
+ <ul class='spaced-list'>
+ <li>Parameter of type {@link org.apache.juneau.server.RestRequest}
+ <li>Parameter of type {@link javax.servlet.http.HttpServletRequest}
+ <li>Parameter of type {@link org.apache.juneau.server.RestResponse}
+ <li>Parameter of type {@link javax.servlet.http.HttpServletResponse}
+ <li>Parameters annotated with {@link org.apache.juneau.server.annotation.Attr @Attr}
+ <br>These match variables in matched URL path patterns.
+ <li>Parameters annotated with with {@link org.apache.juneau.server.annotation.Param @Param}
+ <br>These denote query parameter values.
+ <li>Parameters annotated with {@link org.apache.juneau.server.annotation.HasParam @HasParam}
+ <br>Similar to <ja>@Param</ja>, but resolves to a simple boolean <jk>true/false</jk> denoting whether the query parameter exists.
+ <li>Parameters annotated with {@link org.apache.juneau.server.annotation.QParam @QParam}
+ <br>Same as <ja>@Param</ja>, but only looks for actual query parameters, not form post query parameters.
+ <br>Using this prevents the HTTP body from being processed as a URL-Encoded form post.
+ <li>Parameters annotated with {@link org.apache.juneau.server.annotation.HasQParam @HasQParam}
+ <br>Similar to <ja>@QParam</ja>, but resolves to a simple boolean <jk>true/false</jk> denoting whether the query parameter exists.
+ <li>Parameters annotated with {@link org.apache.juneau.server.annotation.Header @Header}
+ <br>These denote header values.
+ <li>Parameter annotated with {@link org.apache.juneau.server.annotation.Method @Method}
+ <br>This denotes the HTTP method name.
+ <li>Parameter annotated with {@link org.apache.juneau.server.annotation.PathRemainder @PathRemainder}
+ <br>This denotes the path remainder value after path pattern match.
+ <li>Parameter annotated with {@link org.apache.juneau.server.annotation.Content @Content}
+ <br>This denotes the HTTP content parsed as a POJO.
+ <br>The type can be any parsable POJO type as defined in <a class='doclink' href='../../../../overview-summary.html#Core.PojoCategories'>POJO Categories</a>
+ <li>Parameter annotated with {@link org.apache.juneau.server.annotation.Messages @Messages}
+ <br>This gives you access to the resource bundle for the servlet localized to the language on the request.
+ <li>Parameter annotated with {@link org.apache.juneau.server.annotation.Properties @Properties}
+ <br>This gives you access to the serializer/parser/servlet properties so they can be read or altered on the request.
+ </ul>
+ <p class='bcode'>
+ <jc>// Example GET request using annotated attributes</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/example1/{a1}/{a2}/{a3}/*"</js>)
+ <jk>public</jk> String doGetExample1(
+ RestRequest req,
+ RestResponse res,
+ <ja>@Method</ja> String method,
+ <ja>@Attr</ja> String a1,
+ <ja>@Attr</ja> <jk>int</jk> a2,
+ <ja>@Attr</ja> UUID a3,
+ <ja>@Param</ja>(<js>"p1"</js>) <jk>int</jk> p1,
+ <ja>@Param</ja>(<js>"p2"</js>) String p2,
+ <ja>@Param</ja>(<js>"p3"</js>) UUID p3,
+ <ja>@HasParam</ja>(<js>"p3"</js>) boolean hasP3,
+ <ja>@PathRemainder</ja> String remainder,
+ <ja>@Header</ja>(<js>"Accept-Language"</js>) String lang,
+ <ja>@Header</ja>(<js>"Accept"</js>) String accept,
+ <ja>@Header</ja>(<js>"DNT"</js>) <jk>int</jk> doNotTrack,
+ <ja>@Properties</ja> ObjectMap properties,
+ <ja>@Messages</ja> ResourceBundle nls
+ ) {
+ <jc>// Do something with all of those</jc>
+ }
+ </p>
+ <p>
+ All the annotated parameters (with the exception of <l>@Content</l>) can be any POJO type convertable from a <l>String</l>.
+ (See <a class='doclink' href='#PojosConvertableFromString'>POJOs Convertable From String</a>)
+ </p>
+ <p>
+ For example, headers can be accessed as Strings or UUIDs...
+ </p>
+ <p class='bcode'>
+ <jc>// Example GET with access to HTTP headers</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>)
+ <jk>public</jk> String doGet(<ja>@Header</ja>(<js>"Accept-Language"</js>) String lang, <ja>@Header</ja>(<js>"ETag"</js>) UUID eTag) <jk>throws</jk> Exception {
+ ...
+ }
+ </p>
+ <p>
+ All annotations have programmatic equivalents on the {@link org.apache.juneau.server.RestRequest} class:
+ </p>
+ <ul class='javahierarchy'>
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getAttribute(String,Class)}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getParameter(String,Class)}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#hasParameter(String)}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getQueryParameter(String,Class)}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#hasQueryParameter(String)}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getInput(Class)}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getHeader(String,Class)}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getMethod()}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getPathRemainder()}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getMessage(String,Object[])}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getProperties()}
+ </ul>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.MethodSignature.Path"></a>
+ <h4 class='topic' onclick='toggle(this)'>4.1.1 - Path</h4>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.server.annotation.RestMethod#path() @RestMethod.path()} annotation
+ allows you to define URL path patterns to match against.
+ These patterns can contain variables of the form <l>"{xxx}"</l> that can be passed in directly to the
+ Java methods as extra parameters.
+ </p>
+ <p>
+ In the following example, 3 separate GET request handlers are defined with different path patterns.
+ Note how the variables are passed in as additional arguments on the method, and how those arguments are automatically
+ converted to the specified class type...
+ </p>
+ <p class='bcode'>
+ <jc>// Default method</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>)
+ <jk>public void</jk> doGetDefault() {
+ ...
+ }
+
+ <jc>// Method with path pattern</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/xxx"</js>)
+ <jk>public void</jk> doGetNoArgs(...) {
+ ...
+ }
+
+ <jc>// Method with path pattern with arguments</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/xxx/{foo}/{bar}/{baz}/{bing}"</js>)
+ <jk>public void</jk> doGetWithArgs(<ja>@Attr</ja> String foo, <ja>@Attr</ja> <jk>int</jk> bar, <ja>@Attr</ja> MyEnum baz, <ja>@Attr</ja> UUID bing) {
+ ...
+ }
+ </p>
+ <p>
+ By default, path patterns are matched using a best-match heuristic.
+ When overlaps occur, URLs are matched from most-specific to most-general order:
+ </p>
+ <p class='bcode'>
+ <jc>// Try first </jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo/bar"</js>)
+ <jk>public void</jk> method1() {
+ ...
+ }
+
+ <jc>// Try second</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo/{bar}"</js>)
+ <jk>public void</jk> method2(...) {
+ ...
+ }
+
+ <jc>// Try third</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo/*"</js>)
+ <jk>public void</jk> method3(...) {
+ ...
+ }
+
+ <jc>// Try last</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>)
+ <jk>public void</jk> method4(...) {
+ ...
+ }
+ </p>
+ <p>
+ The match heuristic behavior can be overridden by the {@link org.apache.juneau.server.annotation.RestMethod#priority() @RestMethod.priority()} annotation property.
+ However, in practice this is almost never needed.
+ </p>
+ <p>
+ Paths that end with <js>"/*"</js> will do a prefix match on the incoming URL.
+ Any remainder after the match can be accessed through {@link org.apache.juneau.server.RestRequest#getPathRemainder()}
+ or parameters with the {@link org.apache.juneau.server.annotation.PathRemainder @PathRemainder} annotation.
+ On the other hand, paths that don't end with <js>"/*"</js> (e.g. <js>"/"</js> or <js>"/foo"</js>) will require
+ an exact URL match, and if any remainder exists, a 404 (not found) error will be thrown.
+ </p>
+ <p>
+ The following example shows the distinction.
+ </p>
+ <p class='bcode'>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>)
+ <jk>public void</jk> doGet(<ja>@PathRemainder</ja> String remainder) {
+ <jc>// URL path pattern can have remainder accessible through req.getRemainder().</jc>
+ }
+
+ <ja>@RestMethod</ja>(name=<js>"PUT"</js>, path=<js>"/"</js>)
+ <jk>public void</jk> doPut() {
+ <jc>// URL path pattern must match exactly and will cause a 404 error if a remainder exists.</jc>
+ }
+ </p>
+ <p>
+ Annotations are provided for easy access to URL parameters with automatic conversion to any parsable object type.
+ For example, the following example can process the URL <l>"/urlWithParams?foo=foo&bar=[1,2,3]&baz=067e6162-3b6f-4ae2-a171-2470b63dff00"</l>...
+ </p>
+ <p class='bcode'>
+ <jc>// Example GET request with access to query parameters</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/urlWithParams"</js>)
+ <jk>public</jk> String doGetWithParams(<ja>@Param</ja>(<js>"foo"</js>) String foo, <ja>@Param</ja>(<js>"bar"</js>) <jk>int</jk> bar, <ja>@Param</ja>(<js>"baz"</js>) UUID baz) <jk>throws</jk> Exception {
+ <jk>return</jk> <js>"GET /urlWithParams?foo="</js>+foo+<js>"&bar="</js>+bar+<js>"&baz="</js>+baz);
+ }
+ </p>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.MethodSignature.Matchers"></a>
+ <h4 class='topic' onclick='toggle(this)'>4.1.2 - Matchers</h4>
+ <div class='topic'>
+ <p>
+ {@link org.apache.juneau.server.RestMatcher RestMatchers} are used to allow multiple Java methods to be tied to the same HTTP method and path, but
+ differentiated by some request attribute such as a specific header value.
+ <p class='bcode'>
+ <jc>// GET method that gets invoked for administrators</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>, matchers=IsAdminMatcher.<jk>class</jk>)
+ <jk>public</jk> Object doGetForAdmin() {
+ ...
+ }
+
+ <jc>// GET method that gets invoked for everyone else</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>)
+ <jk>public</jk> Object doGetForEveryoneElse() {
+ ...
+ }
+ </p>
+ <p>
+ The interface for matchers is simple:
+ </p>
+ <p class='bcode'>
+ <jk>public class</jk> IsAdminMatcher <jk>extends</jk> RestMatcher {
+ <ja>@Override</ja>
+ <jk>public boolean</jk> matches(RestRequest req) {
+ <jk>return</jk> req.isUserInRole(<js>"ADMINS_GROUP"</js>);
+ }
+ }
+ </p>
+ <h6 class='topic'>Other Notes</h6>
+ <ul class='spaced-list'>
+ <li>If no methods are found with a matching matcher, a <l>412 Precondition Failed</l> status is returned.
+ <li>If multiple matchers are specified on the same method, ONLY ONE matcher needs to match for the method to be invoked.
+ <li>Note that you CANNOT define identical paths on different methods UNLESS you use matchers.
+ <br>That includes paths that are only different in variable names (e.g. <l>"/foo/{bar}"</l> and <l>"/foo/{baz}"</l>).
+ <br>If you try to do so, a <l>ServletException</l> will be thrown on startup.
+ <li>Methods with matchers take precedence over methods without.
+ <br>Otherwise, methods are attempted in the order they appear in the class.
+ </ul>
+ </div>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.RequestContent"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.2 - Request Content</h3>
+ <div class='topic'>
+ <p>
+ Annotations are provided for easy access to HTTP body content as any parsable POJO type
+ (See <a class='doclink' href='../../../../overview-summary.html#Core.PojoCategories'>POJO Categories</a>).
+ In the example below, we're POSTing beans.
+ </p>
+ <p class='bcode'>
+ <jc>// Example POST of a bean</jc>
+ <ja>@RestMethod</ja>(name=<js>"POST"</js>, path=<js>"/"</js>)
+ <jk>public void</jk> doPost(<ja>@Content</ja> Person person) <jk>throws</jk> Exception {
+ <jc>// Do something with person.</jc>
+ }
+ </p>
+ <p>
+ The HTTP body of a request can be retrieved as a parsed POJO using either the
+ {@link org.apache.juneau.server.RestRequest#getInput(Class)} method, or a parameter
+ annotated with {@link org.apache.juneau.server.annotation.Content @Content}.
+ </p>
+ <p class='bcode'>
+ <jc>// Equivalent method 1</jc>
+ <ja>@RestMethod</ja>(name=<js>"POST"</js>, path=<js>"/example1"</js>)
+ <jk>public void</jk> doPost1(<ja>@Content</ja> Person p) {
+ <jc>// Do something with p.</jc>
+ }
+
+ <jc>// Equivalent method 2</jc>
+ <ja>@RestMethod</ja>(name=<js>"POST"</js>, path=<js>"/example2"</js>)
+ <jk>public void</jk> doPost2(RestRequest req) {
+ Person p = req.getInput(Person.<jk>class</jk>);
+ <jc>// Do something with p.</jc>
+ }
+ </p>
+ <p>
+ The Juneau framework will automatically determine the appropriate <l>Parser</l> to use based on the
+ <l>Content-Type</l> HTTP header. So the body content could be JSON or XML or any other supported parsing types.
+ </p>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.RequestContent.FormPosts"></a>
+ <h4 class='topic' onclick='toggle(this)'>4.2.1 - Form Posts</h4>
+ <div class='topic'>
+ <p>
+ URL-Encoded form posts require their own topic since they can be handled in multiple ways.
+ </p>
+ <p>
+ The best way to handle a form post is by using an input bean.
+ The samples include a <l>UrlEncodedFormResource</l> class that takes in URL-Encoded
+ form post of the form <l>"aString=foo&aNumber=123&aDate=2001-07-04T15:30:45Z"</l>.
+ The code is shown here:
+ </p>
+ <p class='bcode'>
+ <ja>@RestResource</ja>(
+ path=<js>"/urlEncodedForm"</js>
+ )
+ <jk>public class</jk> UrlEncodedFormResource <jk>extends</jk> Resource {
+
+ <jd>/** POST request handler */</jd>
+ <ja>@RestMethod</ja>(name=<js>"POST"</js>, path=<js>"/"</js>)
+ <jk>public</jk> Object doPost(<ja>@Content</ja> FormInputBean input) <jk>throws</jk> Exception {
+ <jc>// Just mirror back the request</jc>
+ <jk>return</jk> input;
+ }
+
+ <jk>public static class</jk> FormInputBean {
+ <jk>public</jk> String <jf>aString</jf>;
+ <jk>public int</jk> <jf>aNumber</jf>;
+ <ja>@BeanProperty</ja>(transform=CalendarTransform.<jsf>ISO8601DT</jsf>.<jk>class</jk>)
+ <jk>public</jk> Calendar <jf>aDate</jf>;
+ }
+ }
+ </p>
+ <p>
+ Another possibility is to access the form parameters individually:
+ </p>
+ <p class='bcode'>
+ <jd>/** POST request handler */</jd>
+ <ja>@RestMethod</ja>(name=<js>"POST"</js>, path=<js>"/"</js>)
+ <jk>public</jk> Object doPost(<ja>@Param</ja>(<js>"aString"</js>) String aString, <ja>@Param</ja>(<js>"aNumber"</js>) <jk>int</jk> aNumber, <ja>@Param</ja>(<js>"aDate"</js>) Calendar aDate) <jk>throws</jk> Exception {
+ ...
+ }
+ </p>
+ <p>
+ The advantage to the form input bean is that it can handle any of the parsable types (e.g. JSON, XML...)
+ in addition to URL-Encoding. The latter approach only supports URL-Encoding.
+ </p>
+ <p class='severe'>
+ If you're using form input beans, DO NOT use the <l>@Param</l> attribute
+ or {@link org.apache.juneau.server.RestRequest#getParameter(String)} method since this will
+ cause the underlying JEE servlet to parse the HTTP body as a form post.
+ Your input bean will end up being null since there won't be any content left
+ after the servlet has parsed the body of the request.
+ This applies to WHENEVER you use <l>@Content</l> or {@link org.apache.juneau.server.RestRequest#getInput(Class)}.
+ </p>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.RequestContent"></a>
+ <h4 class='topic' onclick='toggle(this)'>4.2.2 - Multipart Form Posts</h4>
+ <div class='topic'>
+ <p>
+ The Juneau framework does not natively support multipart form posts.
+ However, it can be used in conjunction wih the Apache Commons File Upload library to do so.
+ </p>
+ <p>
+ The samples include a <l>TempDirResource</l> class that uses the File Upload library
+ to allow files to be uploaded as multipart form posts.
+ </p>
+ <p class='bcode'>
+ <ja>@RestResource</ja>(
+ path=<js>"/tempDir"</js>
+ )
+ <jk>public class</jk> TempDirResource <jk>extends</jk> DirectoryResource {
+
+ <jd>/**
+ * [POST /upload] - Upload a file as a multipart form post.
+ * Shows how to use the Apache Commons ServletFileUpload class for handling multi-part form posts.
+ */</jd>
+ <ja>@RestMethod</ja>(name=<js>"POST"</js>, path=<js>"/upload"</js>, matchers=TempDirResource.MultipartFormDataMatcher.<jk>class</jk>)
+ <jk>public</jk> Redirect uploadFile(RestRequest req) <jk>throws</jk> Exception {
+ ServletFileUpload upload = <jk>new</jk> ServletFileUpload();
+ FileItemIterator iter = upload.getItemIterator(req);
+ <jk>while</jk> (iter.hasNext()) {
+ FileItemStream item = iter.next();
+ <jk>if</jk> (item.getFieldName().equals(<js>"contents"</js>)) {
+ File f = <jk>new</jk> File(getRootDir(), item.getName());
+ IOPipe.<jsm>create</jsm>(item.openStream(), <jk>new</jk> FileOutputStream(f)).closeOut().run();
+ }
+ }
+ <jk>return new</jk> Redirect(); <jc>// Redirect to the servlet root.</jc>
+ }
+
+ <jd>/** Causes a 404 if POST isn't multipart/form-data */</jd>
+ <jk>public static class</jk> MultipartFormDataMatcher <jk>extends</jk> RestMatcher {
+ <ja>@Override</ja> <jc>/* RestMatcher */</jc>
+ <jk>public boolean</jk> matches(RestRequest req) {
+ String contentType = req.getContentType();
+ <jk>return</jk> contentType != <jk>null</jk> && contentType.startsWith(<js>"multipart/form-data"</js>);
+ }
+ }
+ </p>
+ </div>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.ResponseContent"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.3 - Response Content</h3>
+ <div class='topic'>
+ <p>
+ REST Java methods can generate output in any of the following ways:
+ </p>
+ <ul class='spaced-list'>
+ <li>By returning a serializable POJO, or any of the following:
+ <br>{@link java.io.Reader}, {@link java.io.InputStream}, {@link org.apache.juneau.Streamable}, {@link org.apache.juneau.Writable}
+ <li>By calling {@link org.apache.juneau.server.RestResponse#setOutput(Object)} with any of the types above.
+ <li>By accessing the {@link java.io.Writer} directly by calling {@link org.apache.juneau.server.RestResponse#getNegotiatedWriter()} and writing the output
+ yourself.
+ </ul>
+ <p class='bcode'>
+ <jc>// Equivalent method 1</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/example1/{personId}"</js>)
+ <jk>public</jk> Person doGet1(<ja>@Attr</ja> UUID personId) {
+ Person p = getPersonById(personId);
+ <jk>return</jk> p;
+ }
+
+ <jc>// Equivalent method 2</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/example2/{personId}"</js>)
+ <jk>public void</jk> doGet2(RestResponse res, <ja>@Attr</ja> UUID personId) {
+ Person p = getPersonById(personId);
+ res.setOutput(p);
+ }
+
+ <jc>// (Sorta) Equivalent method 3</jc>
+ <jc>// (Ignores any converters or method-level properties)</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/example3/{personId}"</js>)
+ <jk>public void</jk> doGet3(RestRequest req, RestResponse res, <ja>@Attr</ja> UUID personId) {
+ Person p = getPersonById(personId);
+ String accept = req.getHeader(<js>"Accept"</js>, <js>"text/json"</js>);
+ WriterSerializer s = res.getSerializerGroup().getWriterSerializer(accept);
+ res.setContentType(s.getResponseContentType());
+ s.serialize(p, res.getNegotiatedWriter());
+ }
+ </p>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.OptionsPages"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.4 - OPTIONS Pages</h3>
+ <div class='topic'>
+ <p>
+ One of the most useful features of Juneau is that it can produce OPTIONS pages for self-documenting designs (i.e. REST interfaces that document themselves).
+ </p>
+ <h6 class='figure'>OPTIONS page for HelloWorld sample resource</h6>
+ <img class='bordered' src='doc-files/OptionsPage.png'>
+ <p>
+ To facilitate this, the {@link org.apache.juneau.server.labels.ResourceOptions} class is provided that
+ inspects a <l>RestServlet</l> and its methods, and returns a serializable POJO data structure
+ that describes the options for that resource and pulling localized strings from the resource
+ bundle associated with the servlet.
+ </p>
+ <p>
+ {@link org.apache.juneau.server.RestServletDefault} provides a default OPTIONS page by implementing
+ a {@link org.apache.juneau.server.RestServletDefault#getOptions(RestRequest)} method that returns a POJO consisting
+ of beans describing the class.
+ </p>
+ <p class='bcode'>
+ <jd>/**
+ * [OPTIONS /*] - Show resource options.
+ *
+ * <ja>@param</ja> req The HTTP request.
+ * <ja>@return</ja> A bean containing the contents for the OPTIONS page.
+ */</jd>
+ <ja>@RestMethod</ja>(name=<js>"OPTIONS"</js>, path=<js>"/*"</js>,
+ properties={
+ <ja>@Property</ja>(name=<jsf>HTMLDOC_links</jsf>, value=<js>"{back:'$R{servletURI}'}"</js>),
+ <ja>@Property</ja>(name=<jsf>HTMLDOC_description</jsf>, value=<js>"Resource options"</js>)
+ },
+ description=<js>"Resource options"</js>
+ )
+ <jk>public</jk> ResourceOptions getOptions(RestRequest req) {
+ <jk>return new</jk> ResourceOptions(<jk>this</jk>, req);
+ }
+ </p>
+ <p>
+ The <l>AddressBookResource</l> class in the samples shows an example of augmenting the existing
+ {@link org.apache.juneau.server.labels.ResourceOptions} bean with some additional information.
+ </p>
+ <p class='bcode'>
+ <jd>/** OPTIONS request handler */</jd>
+ <ja>@Override</ja> <jc>/* RestServletJenaDefault */</jc>
+ <ja>@RestMethod</ja>(name=<js>"OPTIONS"</js>, path=<js>"/*"</js>)
+ <jk>public</jk> ResourceOptions getOptions(RestRequest req) {
+ <jk>return new</jk> Options(req);
+ }
+
+ <jd>/**
+ * Output POJO for OPTIONS requests.
+ * Note that we're extending the existing ResourceOptions class.
+ */</jd>
+ <jk>public class</jk> Options <jk>extends</jk> ResourceOptions {
+ <jk>public</jk> ParamDescription[] queryableParameters;
+ <jk>public</jk> String[] otherNotes;
+
+ <jk>public</jk> Options(RestRequest req) {
+ <jk>super</jk>(AddressBookResource.<jk>this</jk>, req);
+ Locale locale = req.getLocale();
+ queryableParameters = getQueryableParamDescriptions(locale);
+ otherNotes = getMessage(locale, <js>"otherNotes"</js>).split(<js>"\\.\\s*"</js>);
+ }
+ }
+ </p>
+ <p>
+ Refer to <a class='doclink' href='#AddressBookResource'>Address Book Resource</a> for a complete example.
+ </p>
+ <h6 class='topic'>Label and Description</h6>
+ <p>
+ The label and description can be defined in two ways.
+ </p>
+ <p>
+ If you don't care about internationalization, then the easiest way is to use annotations on the servlet.
+ </p>
+ <p class='bcode'>
+ <ja>@RestResource</ja>(
+ path=<js>"/example"</js>,
+ label=<js>"Example Resource"</js>,
+ description=<js>"This shows how to use labels and descriptions."</js>
+ )
+ <jk>public class</jk> ExampleResource <jk>extends</jk> RestServletDefault {
+ </p>
+ <p>
+ The second approach which supports internationalization is to use the
+ {@link org.apache.juneau.server.annotation.RestResource#messages() @RestResource.messages()}
+ annotation to point to a resource bundle, and then use predefined properties
+ that identify the label and description.
+ </p>
+ <p class='bcode'>
+ <ja>@RestResource</ja>(
+ messages=<js>"nls/Messages"</js>
+ )
+ <jk>public class</jk> ExampleResource <jk>extends</jk> RestServletDefault {
+ </p>
+ <p>
+ The label and description are specified as special properties in the resource bundle:
+ </p>
+ <p class='bcode'>
+ <cc>#--------------------------------------------------------------------------------
+ # Contents of Messages.properties
+ #--------------------------------------------------------------------------------</cc>
+ <ck>label</ck> = <cv>Example Resource</cv>
+ <ck>description</ck> = <cv>This shows how to use labels and descriptions.</cv>
+ </p>
+ <p>
+ Message keys can optionally be prefixed by the short class name if the resource bundle is shared by multiple servlets:
+ </p>
+ <p class='bcode'>
+ <cc>#--------------------------------------------------------------------------------
+ # Contents of Messages.properties
+ #--------------------------------------------------------------------------------</cc>
+ <ck>ExampleResource.label</ck> = <cv>Example Resource</cv>
+ <ck>ExampleResource.description</ck> = <cv>This shows how to use labels and descriptions.</cv>
+ </p>
+ <p>
+ When both annotations and properties are used, annotations take precedence.
+ </p>
+ <p>
+ The localized label and description are also available through the following methods:
+ </p>
+ <ul class='javahierarchy'>
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getServletLabel()}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getServletDescription()}
+ </ul>
+ <p>
+ They are also made available as the request string variables <js>"$R{servletLabel}"</js> and <js>"$R{servletDescription}"</js>.
+ These variable facilitate the localized label and descriptions on the HTML pages when using {@link org.apache.juneau.server.RestServletDefault}:
+ </p>
+ <p class='bcode'>
+ <ja>@RestResource</ja>(
+ properties={
+ <jc>// Provide a default title on HTML pages.</jc>
+ <ja>@Property</ja>(name=<jsf>HTMLDOC_title</jsf>, value=<js>"$R{servletLabel}"</js>),
+ <jc>// Provide a default description on HTML pages.</jc>
+ <ja>@Property</ja>(name=<jsf>HTMLDOC_description</jsf>, value=<js>"$R{servletDescription}"</js>)
+ }
+ )
+ <jk>public abstract class</jk> RestServletDefault <jk>extends</jk> RestServlet {
+ </p>
+ <p>
+ The label and description annotations support string variables.
+ So in theory, you could also provide localized messages using <js>"$L"</js> variables pointing to your own resource bundle properties:
+ </p>
+ <p class='bcode'>
+ <ja>@RestResource</ja>(
+ path=<js>"/example"</js>,
+ messages=<js>"nls/Messages"</js>
+ label=<js>"$L{my.resource.label}"</js>,
+ description=<js>"$L{my.resource.description}"</js>
+ )
+ <jk>public class</jk> ExampleResource <jk>extends</jk> RestServletDefault {
+ </p>
+ <p>
+ Another option is to override the {@link org.apache.juneau.server.RestServlet#getLabel(RestRequest)}
+ and {@link org.apache.juneau.server.RestServlet#getDescription(RestRequest)} methods.
+ </p>
+ <h6 class='topic'>Method Description, Input, and Responses</h6>
+ <p>
+ The <l>methods</l> field in the OPTIONS page is mostly populated through reflection.
+ However, the description, input, and responses field can be specified through either
+ annotations or resource properties.
+ </p>
+ <p>
+ For example, the <l>AddressBookResource</l> has a <l>getPerson()</l> method
+ that gets rendered in the OPTIONS page like so...
+ </p>
+ <img class='bordered' src='doc-files/Options2.png'>
+ <p>
+ This method is described through the {@link org.apache.juneau.server.annotation.RestMethod#description() @RestMethod.description()},
+ {@link org.apache.juneau.server.annotation.RestMethod#input() @RestMethod.input()},
+ and {@link org.apache.juneau.server.annotation.RestMethod#responses() @RestMethod.responses()} annotations.
+ </p>
+ <p class='bcode'>
+ <ja>@RestMethod</ja>(
+ name=<js>"GET"</js>,
+ path=<js>"/people/{id}/*"</js>,
+ converters={Traversable.<jk>class</jk>,Queryable.<jk>class</jk>,Introspectable.<jk>class</jk>},
+ description=<js>"Get a person by id in the address book"</js>,
+ input={
+ <ja>@Var</ja>(category=VarCategory.<jsf>ATTR</jsf>, name=<js>"id"</js>, description=<js>"Person UUID"</js>)
+ },
+ responses={
+ <ja>@Response</ja>(
+ value=200,
+ output={
+ <ja>@Var</ja>(category=VarCategory.<jsf>CONTENT</jsf>, description=<js>"Person bean"</js>)
+ }
+ ),
+ <ja>@Response</ja>(value=404, description=<js>"Person with specified id not found"</js>)
+ }
+ )
+ <jk>public</jk> Person getPerson(<ja>@Attr</ja> <jk>int</jk> id) throws Exception {
+ <jk>return</jk> findPerson(id);
+ }
+ </p>
+ <p>
+ These labels can also be localized by instead specifying them in the servlet properties file:
+ </p>
+ <p class='bcode'>
+ <ja>@RestMethod</ja>(
+ name=<js>"GET"</js>,
+ path=<js>"/people/{id}/*"</js>,
+ converters={Traversable.<jk>class</jk>,Queryable.<jk>class</jk>,Introspectable.<jk>class</jk>}
+ <jc>// Don't specify annotations for labels...they'll be detected in resource bundle.</jc>
+ )
+ <jk>public</jk> Person getPerson(<ja>@Attr</ja> <jk>int</jk> id) throws Exception {
+ <jk>return</jk> findPerson(id);
+ }
+ </p>
+ <p class='bcode'>
+ <cc>#--------------------------------------------------------------------------------
+ # Contents of AddressBookResource.properties
+ #--------------------------------------------------------------------------------</cc>
+ <ck>getPerson</ck> = <cv>Get a person by id in the address book</cv>
+ <ck>getPerson.req.attr.id</ck> = <cv>Person UUID</cv>
+ <ck>getPerson.res.200</ck> = <cv>Person found</cv>
+ <ck>getPerson.res.404</ck> = <cv>Person with specified id not found</cv>
+ </p>
+ <p>
+ The following table shows the predefined resource bundle message property names:
+ </p>
+ <table class='styled'>
+ <tr>
+ <th>Property</th>
+ <th>Description</th>
+ <th>Equivalent Annotation</th>
+ <th>Equivalent Method</th>
+ </tr>
+ <tr>
+ <td><ck>label</ck></td>
+ <td>Servlet label</td>
+ <td>{@link org.apache.juneau.server.annotation.RestResource#label() @RestResource.label()}</td>
+ <td>{@link org.apache.juneau.server.RestServlet#getLabel(RestRequest)}</td>
+ </tr>
+ <tr>
+ <td><ck>description</ck></td>
+ <td>Servlet description</td>
+ <td>{@link org.apache.juneau.server.annotation.RestResource#description() @RestResource.description()}</td>
+ <td>{@link org.apache.juneau.server.RestServlet#getDescription(RestRequest)}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName]</ck></td>
+ <td>Java method description</td>
+ <td>{@link org.apache.juneau.server.annotation.RestMethod#description() @RestMethod.description()}</td>
+ <td>{@link org.apache.juneau.server.RestServlet#getMethodDescriptions(RestRequest)}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].req.content</ck></td>
+ <td>
+ A description of the HTTP request content.
+ </td>
+ <td>{@link org.apache.juneau.server.annotation.RestMethod#input() @RestMethod.input()}</td>
+ <td>{@link org.apache.juneau.server.RestServlet#getMethodDescriptions(RestRequest)}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].req.[category].[name]</ck></td>
+ <td>
+ A request input variable.
+ <br>Categories: <l>ATTR, PARAM, HEADER</l>
+ </td>
+ <td>{@link org.apache.juneau.server.annotation.RestMethod#input() @RestMethod.input()}</td>
+ <td>{@link org.apache.juneau.server.RestServlet#getMethodDescriptions(RestRequest)}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].res.[code]</ck></td>
+ <td>
+ A possible HTTP response code and description.
+ </td>
+ <td>{@link org.apache.juneau.server.annotation.RestMethod#responses() @RestMethod.responses()}</td>
+ <td>{@link org.apache.juneau.server.RestServlet#getMethodDescriptions(RestRequest)}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].res.[code].content</ck></td>
+ <td>
+ A description of response content for the specified HTTP response.
+ </td>
+ <td>{@link org.apache.juneau.server.annotation.RestMethod#responses() @RestMethod.responses()}</td>
+ <td>{@link org.apache.juneau.server.RestServlet#getMethodDescriptions(RestRequest)}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].res.[code].[category].[name]</ck></td>
+ <td>
+ A response output variable.
+ <br>Categories: <l>ATTR, PARAM, HEADER</l>
+ </td>
+ <td>{@link org.apache.juneau.server.annotation.RestMethod#responses() @RestMethod.responses()}</td>
+ <td>{@link org.apache.juneau.server.RestServlet#getMethodDescriptions(RestRequest)}</td>
+ </tr>
+ </table>
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='javahierarchy'>
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#description() @RestMethod.description()}
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#input() @RestMethod.input()}
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#responses() @RestMethod.responses()}
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#rc() @RestMethod.rc()}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getServletLabel()}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getServletDescription()}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getMethodDescription()}
+ <li class='m'>{@link org.apache.juneau.server.RestRequest#getMethodDescriptions()}
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.Serializers"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.5 - Serializers</h3>
+ <div class='topic'>
+ <p>
+ REST servlets use the {@link org.apache.juneau.serializer.Serializer} API for defining serializers for serializing response POJOs.
+ </p>
+ <p>
+ The servlet will pick which serializer to use by matching the request <l>Accept</l> header with the
+ media types defined through the {@link org.apache.juneau.serializer.Serializer#getMediaTypes()} method
+ (which itself usually comes from the {@link org.apache.juneau.annotation.Produces @Produces} annotation).
+ </p>
+ <p>
+ Serializers can be associated with REST servlets in the following ways:
+ </p>
+ <ul class='javahierarchy'>
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestResource#serializers() @RestResource.serializers()} - Annotation on servlet class.
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#serializers() @RestMethod.serializers()} - Annotation on individual servlet methods.
+ <li class='m'>{@link org.apache.juneau.server.RestServlet#createSerializers(ObjectMap,Class[])} - Override method to set the serializers programmatically.
+ </ul>
+ <p>
+ The following are equivalent ways of defining serializers used by a servlet...
+ </p>
+ <p class='bcode'>
+ <jc>// Example #1 - Serializers defined on servlet through annotation</jc>
+ <ja>@RestResource</ja>(
+ serializers={JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>}
+ )
+ <jk>public</jk> MyRestServlet <jk>extends</jk> RestServlet {
+ ...
+ }
+
+ <jc>// Example #2 - Serializers defined on method through annotation</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>
+ serializers={JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>}
+ )
+ <jk>public</jk> Object doGet() {
+ ...
+ }
+
+ <jc>// Example #3 - Serializers defined on servlet by overriding the createSerializers(ObjectMap,Class[]) method</jc>
+ <ja>@Override</ja>
+ <jk>public</jk> SerializerGroup createSerializers(ObjectMap,Class[]) {
+
+ SerializerGroup g = <jk>new</jk> SerializerGroup()
+ .append(JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>);
+
+ <jk>return</jk> g;
+ }
+ </p>
+ <p class='info'>
+ When debugging the output from REST servlets, it's almost always easier to bypass the REST servlet and try to serialize
+ the POJOs using the serializers directly using the {@link org.apache.juneau.serializer.WriterSerializer#toString(Object)} method.
+ </p>
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='javahierarchy'>
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#serializersInherit() @RestMethod.serializersInherit()}
+ <br>Controls how serializers are inherited from the servlet class.
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.Parsers"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.6 - Parsers</h3>
+ <div class='topic'>
+ <p>
+ REST servlets use the {@link org.apache.juneau.parser.Parser} API for defining parsers for parsing request body content and converting them into POJOs.
+ </p>
+ <p>
+ The servlet will pick which parser to use by matching the request <l>Content-Type</l> header with the
+ media types defined through the {@link org.apache.juneau.parser.Parser#getMediaTypes()} method (which itself
+ usually comes from the {@link org.apache.juneau.annotation.Consumes @Consumes} annotation).
+ </p>
+ <p>
+ Parsers can be associated with REST servlets in the following ways:
+ </p>
+ <ul class='javahierarchy'>
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestResource#parsers() @RestResource.parsers()} - Annotation on servlet class.
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#parsers() @RestMethod.parsers()} - Annotation on individual servlet methods.
+ <li class='m'>{@link org.apache.juneau.server.RestServlet#createParsers(ObjectMap,Class[])} - Override method to set the parsers programmatically.
+ </ul>
+ <p>
+ The following are equivalent ways of defining parsers used by a servlet...
+ </p>
+ <p class='bcode'>
+ <jc>// Example #1 - Parsers defined on servlet through annotation</jc>
+ <ja>@RestResource</ja>(
+ parsers={JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>}
+ )
+ <jk>public</jk> MyRestServlet <jk>extends</jk> RestServlet {
+ ...
+ }
+
+ <jc>// Example #2 - Parsers defined on method through annotation</jc>
+ <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>
+ parsers={JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>}
+ )
+ <jk>public void</jk> doPut(<ja>@Content</ja> Foo input) {
+ ...
+ }
+
+ <jc>// Example #3 - Parsers defined on servlet by overriding the getParserGroup method</jc>
+ <ja>@Override</ja>
+ <jk>public</jk> ParserGroup getParserGroup() {
+
+ ParserGroup g = <jk>new</jk> ParserGroup()
+ .append(JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>);
+
+ <jk>return</jk> g;
+ }
+ </p>
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='javahierarchy'>
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#parsersInherit() @RestMethod.parsersInherit()}
+ <br>Controls how parsers are inherited from the servlet class.
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.Properties"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.7 - Properties</h3>
+ <div class='topic'>
+ <p>
+ The Juneau serializers and parsers are highly-configurable through properties.
+ (See <a class='doclink' href='../../../../overview-summary.html#Core.ConfigurableProperties'>Configurable Properties</a>)
+ </p>
+ <p>
+ There are several ways of defining properties in the REST API.
+ The most common way is going to be through the {@link org.apache.juneau.server.annotation.RestResource#properties() @RestResource.properties()}
+ and {@link org.apache.juneau.server.annotation.RestMethod#properties() @RestMethod.properties()} annotations.
+ </p>
+ <p>
+ The {@link org.apache.juneau.server.annotation.RestResource#properties() @RestResource.properties()} annotation
+ can be used as a convenient way to set various serializer and parser
+ properties to all serializers and parsers registered with the servlet.
+ </p>
+ <p class='bcode'>
+ <jk>import static</jk> org.apache.juneau.SerializerContext.*;
+ <jk>import static</jk> org.apache.juneau.xml.XmlSerializerContext.*;
+ <jk>import static</jk> org.apache.juneau.server.serializers.HtmlSerializerContext.*;
+
+ <jc>// Servlet with properties applied</jc>
+ <ja>@RestResource</ja>(
+ properties={
+ <jc>// Nulls should not be serialized</jc>
+ <ja>@Property</ja>(name=<jsf>TRIM_NULLS</jsf>, value=<js>"true"</js>),
+
+ <jc>// Empty lists should not be serialized</jc>
+ <ja>@Property</ja>(name=<jsf>SERIALIZER_trimEmptyLists</jsf>, value=<js>"true"</js>),
+
+ <jc>// Specify the default namespaces for the XML serializer</jc>
+ <ja>@Property</ja>(name=<jsf>XML_defaultNamespaceUriS</jsf>,
+ value=<js>"{jp06:'http://jazz.net/xmlns/prod/jazz/process/0.6/',jp:'http://jazz.net/xmlns/prod/jazz/process/1.0/'}"</js>),
+
+ <jc>// Specify a default title for the HtmlSerializer serializer</jc>
+ <ja>@Property</ja>(name=<jsf>HTMLDOC_title</jsf>, value=<js>"My resource"</js>)
+ }
+ )
+ <jk>public</jk> MyRestServlet <jk>extends</jk> RestServlet {
+ ...
+ }
+ </p>
+ <p>
+ The {@link org.apache.juneau.server.annotation.RestMethod#properties() @RestMethod.properties()} annotation
+ can be used to define method-level properties that can alter the behavior of serializers and parsers at the method level only.
+ </p>
+ <p class='bcode'>
+ <jc>// GET method with method-level properties</jc>
+ <ja>@RestMethod</ja>(
+ name=<js>"GET"</js>, path=<js>"/*"</js>,
+ properties={
+ <jc>// Nulls should not be serialized</jc>
+ <ja>@Property</ja>(name=<jsf>TRIM_NULLS</jsf>, value=<js>"true"</js>),
+
+ <jc>// Empty lists should not be serialized</jc>
+ <ja>@Property</ja>(name=<jsf>SERIALIZER_trimEmptyLists</jsf>, value=<js>"true"</js>),
+
+ <jc>// Specify the default namespaces for the XML serializer</jc>
+ <ja>@Property</ja>(name=<jsf>XML_defaultNamespaceUriS</jsf>,
+ value=<js>"{jp06:'http://jazz.net/xmlns/prod/jazz/process/0.6/',jp:'http://jazz.net/xmlns/prod/jazz/process/1.0/'}"</js>),
+
+ <jc>// Specify a default title for the HtmlSerializer serializer</jc>
+ <ja>@Property</ja>(name=<jsf>HTMLDOC_title</jsf>, value=<js>"My resource"</js>)
+ }
+ <jk>public</jk> Object doGet() {
+ ...
+ }
+ </p>
+ <p>
+ In particular, the {@link org.apache.juneau.server.RestServletContext} class has a variety of properties
+ for controlling the behavior of the {@link org.apache.juneau.server.RestServlet} class itself.
+ </p>
+ <p>
+ There are also ways to provide properties programmatically.
+ </p>
+ <ul class='spaced-list'>
+ <li>By overriding the {@link org.apache.juneau.server.RestServlet#createProperties()} method.
+ <li>By overriding the {@link org.apache.juneau.server.RestServlet#createSerializers(ObjectMap,Class[])} and
+ {@link org.apache.juneau.server.RestServlet#createParsers(ObjectMap,Class[])} methods and setting properties on the
+ serializers and parsers directly.
+
+ </ul>
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='javahierarchy'>
+ <li class='c'>{@link org.apache.juneau.server.RestServletContext}
+ <br>Properties associated with the {@link org.apache.juneau.server.RestServlet} class.
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#serializersInherit @RestMethod.serializersInherit()}
+ <br>Controls how serializers inherit properties from the servlet class.
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#parsersInherit @RestMethod.parsersInheritInherit()}
+ <br>Controls how parsers inherit properties from the servlet class.
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.Transforms"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.8 - Transforms</h3>
+ <div class='topic'>
+ <p>
+ The Juneau serializers and parsers can be configured on how to handle POJOs through the use of Transforms.
+ (See <a class='doclink' href='../../../../overview-summary.html#Core.Transforms'>Transforms</a>)
+ </p>
+ <p>
+ The {@link org.apache.juneau.server.annotation.RestResource#transforms() @RestResource.transforms()} annotation
+ can be used as a convenient way to add POJO transforms to the serializers and parsers
+ registered with the servlet.
+ </p>
+ <p class='bcode'>
+ <jc>// Servlet with transforms applied</jc>
+ <ja>@RestResource</ja>(
+ transforms={
+ <jc>// Calendars should be serialized/parsed as ISO8601 date-time strings</jc>
+ CalendarTransform.<jsf>DEFAULT_ISO8601DT</jsf>.<jk>class</jk>,
+
+ <jc>// Byte arrays should be serialized/parsed as BASE64-encoded strings</jc>
+ ByteArrayBase64Transform.<jk>class</jk>,
+
+ <jc>// Subclasses of MyInterface will be treated as MyInterface objects.</jc>
+ <jc>// Bean properties not defined on that interface will be ignored.</jc>
+ MyInterface.<jk>class</jk>
+ }
+ )
+ <jk>public</jk> MyRestServlet <jk>extends</jk> RestServlet {
+ ...
+ }
+ </p>
+ <p>
+ {@link org.apache.juneau.server.annotation.RestMethod#transforms() @RestMethod.transforms()}
+ is the equivalent annotation for individual Java methods.
+ </p>
+ <p>
+ Transforms can also be defined programmatically through the following:
+ </p>
+ <ul class='spaced-list'>
+ <li>By overriding the {@link org.apache.juneau.server.RestServlet#createTransforms()} method.
+ <li>By overriding the {@link org.apache.juneau.server.RestServlet#createSerializers(ObjectMap,Class[])} and
+ {@link org.apache.juneau.server.RestServlet#createParsers(ObjectMap,Class[])} methods and setting transforms on the
+ serializers and parsers directly.
+
+ </ul>
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='javahierarchy'>
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#serializersInherit @RestMethod.serializersInherit()}
+ <br>Controls how serializers inherit transforms from the servlet class.
+ <li class='n'>{@link org.apache.juneau.server.annotation.RestMethod#parsersInherit @RestMethod.parsersInherit()}
+ <br>Controls how parsers inherit transforms from the servlet class.
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.Guards"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.9 - Guards</h3>
+ <div class='topic'>
+ <p>
+ Guards are classes that control access to REST servlets and methods.
+ </p>
+ <p>
+ The {@link org.apache.juneau.server.annotation.RestResource#guards @RestResource.guards()} annotation
+ can be used to associate one or more class-level {@link org.apache.juneau.server.RestGuard RestGuards} with a servlet.
+ </p>
+ <p class='bcode'>
+ <jc>// Servlet with class-level guard applied</jc>
+ <ja>@RestResource</ja>(guards=BillyGuard.<jk>class</jk>)
+ <jk>public</jk> MyRestServlet <jk>extends</jk> RestServlet {
+
+ <jc>// Delete method that only Billy is allowed to call.</jc>
+ <jk>public</jk> doDelete(RestRequest req, RestResponse res) <jk>throws</jk> Exception {...}
+ }
+
+ <jc>// Define a guard that only lets Billy make a request</jc>
+ <jk>public</jk> BillyGuard <jk>extends</jk> RestGuard {
+
+ <ja>@Override</ja>
+ <jk>public boolean</jk> isRequestAllowed(RestRequest req) {
+ return req.getUserPrincipal().getName().equals(<js>"Billy"</js>);
+ }
+ }
+ </p>
+ <p>
+ A common use for guards is to only allow admin access to certain Java methods...
+ </p>
+ <p class='bcode'>
+ <jc>// DELETE method</jc>
+ <ja>@RestMethod</ja>(name=<js>"DELETE"</js>, guards={AdminGuard.<jk>class</jk>})
+ <jk>public void</jk> doDelete(RestRequest req, RestResponse res) <jk>throws</jk> Exception {
+ ...
+ </p>
+ <p class='bcode'>
+ <jk>public class</jk> AdminGuard <jk>extends</jk> RestGuard {
+ <ja>@Override</ja>
+ <jk>public boolean</jk> isRequestAllowed(RestRequest req) {
+ <jk>return</jk> req.getUserPrincipal().isUserInRole(<js>"ADMIN"</js>);
+ }
+ }
+ </p>
+ <p>
+ A guard failure results in an <l>HTTP 401 Unauthorized</l> response.
+ However, this can be configured by overriding the {@link org.apache.juneau.server.RestGuard#guard(RestRequest,RestResponse)}
+ and processing the response yourself.
+ </p>
+ <p>
+ When guards are associated at the class-level, it's equivalent to associating guards on all Java methods on the servlet.
+ </p>
+ <p>
+ Class-level guards can also be created programmatically by overriding the {@link org.apache.juneau.server.RestServlet#createGuards(ObjectMap)} method.
+ </p>
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='javahierarchy'>
+ <li class='a'>{@link org.apache.juneau.server.RestGuard}
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.Converters"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.10 - Converters</h3>
+ <div class='topic'>
+ <p>
+ Converters can be thought of as a "post-processor" for POJOs before they get passed to the serializers.
+ </p>
+ <p>
+ The {@link org.apache.juneau.server.annotation.RestResource#converters @RestResource.converters()} annotation
+ can be used as a convenient way to add {@link org.apache.juneau.server.RestConverter RestConverters} to
+ all Java REST methods on a servlet.
+ </p>
+ <p class='bcode'>
+ <jc>// Associate the Traversable converter to all Java REST methods in this servlet</jc>
+ <ja>@RestResource</ja>(converters=Traversable.<jk>class</jk>)
+ <jk>public</jk> MyRestServlet <jk>extends</jk> RestServlet {
+ ...
+ }
+ </p>
+ <p>
+ The {@link org.apache.juneau.server.annotation.RestMethod#converters() @RestMethod.converters()} annotation
+ can be used to associate converters on individual methods.
+ </p>
+ <p class='bcode'>
+ <jc>// GET person request handler.</jc>
+ <jc>// Traversable conversion enabled to allow nodes in returned POJO tree to be addressed.</jc>
+ <jc>// Queryable conversion enabled to allow returned POJO to be searched/viewed/sorted.</jc>
+ <ja>@RestMethod</ja>(
+ name=<js>"GET"</js>, path=<js>"/people/{id}/*"</js>,
+ converters={Traversable.<jk>class</jk>,Queryable.<jk>class</jk>}
+ )
+ <jk>public</jk> Person getPerson(<ja>@Attr</ja> <jk>int</jk> id) {
+ <jk>return</jk> findPerson(id);
+ }
+ </p>
+ <p>
+ The following converter is used to provide support for addressing child nodes in a POJO tree with
+ URL path remainders.
+ <br>In this code, the 3rd parameter is the object that was returned by the Java method (or set through <l>request.setObject(o);</l>).
+ <br>The converter uses the {@link org.apache.juneau.utils.PojoRest} wrapper class to address nodes in the tree.
+ </p>
+ <p class='bcode'>
+ <jd>/**
+ * Converter for enablement of PojoRest support on response objects returned by a @RestMethod method.
+ * When enabled, objects in a POJO tree returned by the REST method can be addressed through additional URL path information.
+ */</jd>
+ <jk>public class</jk> Traversable <jk>implements</jk> RestConverter {
+
+ <ja>@Override</ja>
+ <jk>public</jk> Object convert(RestServlet resource, RestRequest req, Object o) {
+ if (o == <jk>null</jk>)
+ <jk>return null</jk>;
+
+ BeanContext beanContext = resource.getBeanContext();
+
+ <jk>if</jk> (req.getRemainder() != <jk>null</jk>) {
+ PojoRest p = <jk>new</jk> PojoRest(o, beanContext);
+ <jk>try</jk> {
+ o = p.get(req.getRemainder());
+ } <jk>catch</jk> (PojoRestException e) {
+ <jk>throw new</jk> RestException(e.getStatus(), e.getMessage(), e);
+ }
+ }
+
+ <jk>return</jk> o;
+ }
+ }
+ </p>
+ <p>
+ Juneau defines the following converters out-of-the-box:
+ </p>
+ <ul class='javahierarchy'>
+ <li class='i'>{@link org.apache.juneau.server.RestConverter}
+ <ul>
+ <li class='c'>{@link org.apache.juneau.server.converters.Queryable}
+ <br>Provides query parameters that can be used to transform the response (i.e. search/view/sort the POJO response before being serialized).
+ <li class='c'>{@link org.apache.juneau.server.converters.Traversable}
+ <br>Allows nodes in the POJO response tree to be individually accessed through additional path info on the request.
+ <li class='c'>{@link org.apache.juneau.server.converters.Introspectable}
+ <br>Allows method calls to be made on the response POJO, and for the result of that method call to be serialized as the response.
+ </ul>
+ </ul>
+ <p>
+ Class-level converters can be created programmatically by overriding the {@link org.apache.juneau.server.RestServlet#createConverters(ObjectMap)} method.
+ </p>
+ <p>
+ Note that from the example above, you can specify more than one converter.
+ When multiple converters are used, they're executed in the order they're specified in the annotation
+ (e.g. first the results will be traversed, then the resulting node will be searched/sorted).
+
+ </p>
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='javahierarchy'>
+ <li class='i'>{@link org.apache.juneau.server.RestConverter}
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a name="RestResources.Children"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.11 - Child Resources</h3>
+ <div class='topic'>
+ <p>
+ Child Resources are REST servlets that are linked to parent servlets through the
+ {@link org.apache.juneau.server.annotation.RestResource#children() @RestResource.children()} annnotation.
+ </p>
+ <p class='bcode'>
+ <jd>/** Parent Resource */</jd>
+ <ja>@RestResource</ja>(
+ path=<js>"/parent"</js>,
+ children={Foo.<jk>class</jk>}
+ )
+ <jk>public</jk> MyResource <jk>extends</jk> RestServlet {
+ ...
+ </p>
+ <p class='bcode'>
+ <jd>/** Child Resource */</jd>
+ <ja>@RestResource</ja>(
+ path=<js>"/foo"</js> // Path relative to parent resource.
+ )
+ <jk>public</jk> FooResource <jk>extends</jk> RestServlet {
+ ...
+ </p>
+ <p>
+ A HUGE advantage of using child resources is that they do not need to be declared in the JEE <l>web.xml</l> file.
+ Initialization of and access to the child resources occurs through the parent resource.
+ Children can be nested arbitrary deep to create complex REST interfaces with a single top-level REST servlet.
+ </p>
+ <p>
+ The path of the child resource gets appended to the path of the parent resource.
+ So in the example above, the child resource is accessed through the URL <l>/parent/foo</l>.
+ </p>
+ <p>
+ The {@link org.apache.juneau.server.RestServletGroupDefault} class provides a default "router" page for
+ child resources when a parent resource is nothing more than a grouping of child resources.
+ </p>
+ <p>
+ The <l>RootResources</l> class in the Samples project is an example of a router page:
+ </p>
+ <p class='bcode'>
+ <jd>/**
+ * Sample REST resource showing how to implement a "router" resource page.
+ */</jd>
+ <ja>@RestResource</ja>(
+ path=<js>"/"</js>,
+ messages=<js>"nls/RootResources"</js>,
+ properties={
+ <ja>@Property</ja>(name=HTMLDOC_links, value=<js>"{options:'$R{servletURI}?method=OPTIONS',source:'$R{servletURI}/source?classes=(org.apache.juneau.server.samples.RootResources)'}"</js>)
+ },
+ children={
+ HelloWorldResource.<jk>class</jk>,
+ MethodExampleResource.<jk>class</jk>,
+ RequestEchoResource.<jk>class</jk>,
+ TempDirResource.<jk>class</jk>,
+ AddressBookResource.<jk>class</jk>,
+ SampleRemoteableServlet.<jk>class</jk>,
+ PhotosResource.<jk>class</jk>,
+ AtomFeedResource.<jk>class</jk>,
+ JsonSchemaResource.<jk>class</jk>,
+ SqlQueryResource.<jk>class</jk>,
+ TumblrParserResource.<jk>class</jk>,
+ CodeFormatterResource.<jk>class</jk>,
+ UrlEncodedFormResource.<jk>class</jk>,
+ SourceResource.<jk>class</jk>,
+ ConfigResource.<jk>class</jk>,
+ LogsResource.<jk>class</jk>,
+ DockerRegistryResource.<jk>class</jk>,
+ ShutdownResource.<jk>class</jk>
+ }
+ )
+ <jk>public class</jk> RootResources <jk>extends</jk> ResourceGroup {
+ <jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L;
+ }
+ </p>
+ <p>
+ When you bring up this resource in a browser, you see the following:
+ </p>
+ <img class='bordered' src="doc-files/Samples_RootResources.png"/>
+ <p>
+ The <l>RestServletGroupDef
<TRUNCATED>