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 2017/09/08 23:25:37 UTC
svn commit: r21540 [20/27] - in /release/incubator/juneau:
juneau-rest-client/ juneau-rest-client/.settings/ juneau-rest-client/bin/
juneau-rest-client/src/ juneau-rest-client/src/main/
juneau-rest-client/src/main/java/ juneau-rest-client/src/main/java...
Added: release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
==============================================================================
--- release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html (added)
+++ release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html Fri Sep 8 23:25:34 2017
@@ -0,0 +1,3860 @@
+<!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 id='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='#RestResources'>REST Servlets</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#RestResources.MethodSignature'>REST Java Method Signature</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#RestResources.MethodSignature.Path'>Path</a></p>
+ <li><p><a class='doclink' href='#RestResources.MethodSignature.Matchers'>Matchers</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#RestResources.RequestContent'>Request Content</a></p>
+ <ol>
+ <li><p><a class='doclink' href='#RestResources.RequestContent.FormPosts'>Form Posts</a></p>
+ <li><p><a class='doclink' href='#RestResources.RequestContent'>Multipart Form Posts</a></p>
+ </ol>
+ <li><p><a class='doclink' href='#RestResources.ResponseContent'>Response Content</a></p>
+ <li><p><a class='doclink' href='#RestResources.RestHooks'>Lifecycle Hooks</a></p>
+ <li><p><a class='doclink' href='#RestResources.OptionsPages'>OPTIONS Pages</a></p>
+ <li><p><a class='doclink' href='#RestResources.Serializers'>Serializers</a></p>
+ <li><p><a class='doclink' href='#RestResources.Parsers'>Parsers</a></p>
+ <li><p><a class='doclink' href='#RestResources.Properties'>Properties</a></p>
+ <li><p><a class='doclink' href='#RestResources.Transforms'>Transforms</a></p>
+ <li><p><a class='doclink' href='#RestResources.Guards'>Guards</a></p>
+ <li><p><a class='doclink' href='#RestResources.Converters'>Converters</a></p>
+ <li><p><a class='doclink' href='#RestResources.Children'>Child Resources</a></p>
+ <li><p><a class='doclink' href='#RestResources.Labels'>Localized Messages</a></p>
+ <li><p><a class='doclink' href='#RestResources.Encoders'>Encoders</a></p>
+ <li><p><a class='doclink' href='#RestResources.SvlVars'>SVL Vars</a></p>
+ <li><p><a class='doclink' href='#RestResources.StaticFiles'>Static Files</a></p>
+ <li><p><a class='doclink' href='#RestResources.Listeners'>Listener Methods</a></p>
+ <li><p><a class='doclink' href='#RestResources.Stylesheet'>Stylesheet</a></p>
+ <li><p><a class='doclink' href='#RestResources.Headers'>Default Headers</a></p>
+ <li><p><a class='doclink' href='#RestResources.Errors'>Handling Errors / Logging</a></p>
+ <li><p><a class='doclink' href='#RestResources.ConfigFile'>Configuration Files</a></p>
+ <li><p><a class='doclink' href='#RestResources.Inheritence'>Annotation Inheritance</a></p>
+ <li><p><a class='doclink' href='#RestResources.HttpStatusCodes'>HTTP Status Codes</a></p>
+ <li><p><a class='doclink' href='#RestResources.OverloadedHttpMethods'>Overloaded HTTP Methods</a></p>
+ <li><p><a class='doclink' href='#RestResources.BuildInParams'>Built-In Parameters</a></p>
+ <li><p><a class='doclink' href='#RestResources.CustomSerializersParsers'>Defining your own serializers/parsers</a></p>
+ <li><p><a class='doclink' href='#RestResources.ResponseHandlers'>Response Handlers</a></p>
+ <li><p><a class='doclink' href='#RestResources.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 Convertible From Strings</a></p>
+ <li><p><a class='doclink' href='#AddressBookResource'>Address Book Resource</a></p>
+</ol>
+
+<!-- ======================================================================================================== -->
+<a id="Intro"></a>
+<h2 class='topic' onclick='toggle(this)'>1 - Introduction</h2>
+<div class='topic'>
+ <p>
+ The <l>juneau-rest.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.rest.RestServlet} is nothing but a specialized
+ {@link javax.servlet.http.HttpServlet}, and the {@link org.apache.juneau.rest.RestRequest} and
+ {@link org.apache.juneau.rest.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.
+ <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>
+ <li>
+ Parses content of POST/PUT request bodies to POJOs.
+ <li>
+ Automatic built-in ability to serialize POJO metadata to JSON+SCHEMA, XML+SCHEMA, or HTML+SCHEMA based on
+ <l>Accept</l> header.
+ <li>
+ Automatic negotiation of output Writer based on HTTP headers.
+ <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>
+ <li>
+ Automatic error handling.
+ <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>
+ <li>
+ Self-documenting REST interfaces.
+ <li>
+ Various useful debugging features that make debugging using a browser extremely simple...
+ <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 <js>"text/plain"</js> on response using GET parameter <l>&plainText=true</l>.
+ </ul>
+ <li>
+ Ability to implement overloaded HTTP methods through the use of the <l>&method</l> attribute
+ (e.g. <l>&method=FOO</l>).
+ <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>).
+ <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.
+ <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 id="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.rest.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.foo.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>,
+ htmldoc=<ja>@HtmlDoc</ja>(
+ links={
+ <js>"up: request:/.."</js>,
+ <js>"options: servlet:/?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.rest.RestServletDefault} class that we're using here is a subclass of
+ {@link org.apache.juneau.rest.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.rest.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='spaced-list'>
+ <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.
+ <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 parameter 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 a serialized Swagger DTO bean populated by introspection of the class itself combined with
+ labels in the messages properties file and annotations.
+ It's composed of a POJO that gets serialized just like any other POJO.
+ Therefore, the POJO can be serialized to any of the supported languages, like Swagger JSON.
+ </p>
+ <img class='bordered' src="doc-files/HelloWorldResourceOptionsJson.png">
+</div>
+
+<!-- ======================================================================================================== -->
+<a id="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='doctree'>
+ <li class='jac'>
+ {@link javax.servlet.http.HttpServlet javax.servlet.http.HttpServlet}
+ <ul>
+ <li class='jac'>
+ {@link org.apache.juneau.rest.RestServlet org.apache.juneau.rest.RestServlet}
+ <br>Contains all the main logic.
+ <ul>
+ <li class='jac'>
+ {@link org.apache.juneau.rest.RestServletDefault org.apache.juneau.rest.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='jac'>
+ {@link org.apache.juneau.microservice.Resource org.apache.juneau.microservice.Resource}
+ <br>Subclass intended to be used in REST microservices.
+ <br><b>Developers will typically subclass this when creating microservices.</b>
+ <li class='jac'>
+ {@link org.apache.juneau.rest.RestServletGroupDefault org.apache.juneau.rest.RestServletGroupDefault}
+ <br>A default implementation for "router" pages.
+ <ul>
+ <li class='jac'>
+ {@link org.apache.juneau.microservice.ResourceGroup org.apache.juneau.microservice.ResourceGroup}
+ <br>Subclass intended to be used in REST microservices.
+ </ul>
+ </li>
+ <li class='jc'>
+ {@link org.apache.juneau.rest.remoteable.RemoteableServlet org.apache.juneau.rest.remoteable.RemoteableServlet}
+ <br>REST servlet for implementing remoteable proxy interfaces.
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </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.rest.RestRequest} and {@link org.apache.juneau.rest.RestResponse} classes
+ described later also extend from their servlet equivalents:
+ </p>
+ <ul class='doctree'>
+ <li class='jic'>
+ {@link javax.servlet.http.HttpServletRequest javax.servlet.http.HttpServletRequest}
+ <ul>
+ <li class='jc'>
+ {@link org.apache.juneau.rest.RestRequest org.apache.juneau.rest.RestRequest}
+ - Augmented with specialized REST methods.
+ </ul>
+ </li>
+ <li class='jic'>
+ {@link javax.servlet.http.HttpServletResponse javax.servlet.http.HttpServletResponse}
+ <ul>
+ <li class='jc'>
+ {@link org.apache.juneau.rest.RestResponse org.apache.juneau.rest.RestResponse}
+ - Augmented with specialized REST methods.
+ </ul>
+ </li>
+ </ul>
+</div>
+
+<!-- ======================================================================================================== -->
+<a id="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.rest.RestServlet} annotated with
+ {@link org.apache.juneau.rest.annotation.RestResource @RestResource} containing public Java methods
+ annotated with {@link org.apache.juneau.rest.annotation.RestMethod @RestMethod}.
+ </p>
+ <p>
+ Developers will typically subclass directly from {@link org.apache.juneau.rest.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>
+ <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.uon.UonSerializer}</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'>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.JsoSerializer}</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.uon.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.rest.RestServletDefault} also provides a default OPTIONS page by implementing
+ a {@link org.apache.juneau.rest.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='doctree'>
+ <li class='jac'>
+ {@link org.apache.juneau.rest.RestServletDefault}
+ </ul>
+
+ <!-- ======================================================================================================== -->
+ <a id="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.rest.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.rest.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.rest.RestResponse#setOutput(Object)} method.
+ Calling the {@link org.apache.juneau.rest.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='doctree'>
+ <li class='jc'>
+ {@link java.io.InputStream}
+ <br>The contents are simply piped to the output stream returned by
+ {@link org.apache.juneau.rest.RestResponse#getNegotiatedOutputStream()}.
+ <br>Note that you should call {@link org.apache.juneau.rest.RestResponse#setContentType(String)} to set
+ the <l>Content-Type</l> header if you use this object type.
+ <li class='jc'>
+ {@link java.io.Reader}
+ <br>The contents are simply piped to the output stream returned by
+ {@link org.apache.juneau.rest.RestResponse#getNegotiatedWriter()}.
+ <br>Note that you should call {@link org.apache.juneau.rest.RestResponse#setContentType(String)} to set
+ the <l>Content-Type</l> header if you use this object type.
+ <li class='jc'>
+ {@link org.apache.juneau.rest.Redirect}
+ <br>Represents an HTTP redirect response.
+ <li class='jic'>
+ {@link org.apache.juneau.Streamable}
+ <br>Interface that identifies that an object can be serialized directly to an output stream.
+ <li class='jic'>
+ {@link org.apache.juneau.Writable}
+ <br>Interface that identifies that an object can be serialized directly to a writer.
+ <li class='jc'>
+ {@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.rest.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>
+ Parameters of the following class types:
+ <ul>
+ <li>Request/response objects:
+ <ul>
+ <li>{@link org.apache.juneau.rest.RestRequest} - The request object.
+ <li>{@link javax.servlet.http.HttpServletRequest} - The superclass of <code>RestRequest</code>.
+ <li>{@link org.apache.juneau.rest.RestResponse} - The response object.
+ <li>{@link javax.servlet.http.HttpServletResponse} - The superclass of <code>RestResponse</code>.
+ </ul>
+ <li>Parsed request header values:
+ <ul>
+ <li>{@link org.apache.juneau.http.Accept}
+ <li>{@link org.apache.juneau.http.AcceptCharset}
+ <li>{@link org.apache.juneau.http.AcceptEncoding}
+ <li>{@link org.apache.juneau.http.AcceptLanguage}
+ <li>{@link org.apache.juneau.http.Authorization}
+ <li>{@link org.apache.juneau.http.CacheControl}
+ <li>{@link org.apache.juneau.http.Connection}
+ <li>{@link org.apache.juneau.http.ContentLength}
+ <li>{@link org.apache.juneau.http.ContentType}
+ <li>{@link org.apache.juneau.http.Date}
+ <li>{@link org.apache.juneau.http.Expect}
+ <li>{@link org.apache.juneau.http.From}
+ <li>{@link org.apache.juneau.http.Host}
+ <li>{@link org.apache.juneau.http.IfMatch}
+ <li>{@link org.apache.juneau.http.IfModifiedSince}
+ <li>{@link org.apache.juneau.http.IfNoneMatch}
+ <li>{@link org.apache.juneau.http.IfRange}
+ <li>{@link org.apache.juneau.http.IfUnmodifiedSince}
+ <li>{@link org.apache.juneau.http.MaxForwards}
+ <li>{@link org.apache.juneau.http.Pragma}
+ <li>{@link org.apache.juneau.http.ProxyAuthorization}
+ <li>{@link org.apache.juneau.http.Range}
+ <li>{@link org.apache.juneau.http.Referer}
+ <li>{@link org.apache.juneau.http.TE}
+ <li>{@link org.apache.juneau.http.UserAgent}
+ <li>{@link org.apache.juneau.http.Upgrade}
+ <li>{@link org.apache.juneau.http.Via}
+ <li>{@link org.apache.juneau.http.Warning}
+ <li>{@link java.util.TimeZone}
+ </ul>
+ <li>Direct streams on request/response:
+ <ul>
+ <li>{@link java.io.InputStream}
+ <li>{@link javax.servlet.ServletInputStream}
+ <li>{@link java.io.Reader}
+ <li>{@link java.io.OutputStream}
+ <li>{@link javax.servlet.ServletOutputStream}
+ <li>{@link java.io.Writer}
+ </ul>
+ <li>Localization:
+ <ul>
+ <li>{@link java.util.ResourceBundle} - Client-localized resource bundle.
+ <li>{@link org.apache.juneau.utils.MessageBundle} - A resource bundle with additional features.
+ <li>{@link java.util.Locale} - Client locale.
+ </ul>
+ <li>Request APIs:
+ <ul>
+ <li>{@link org.apache.juneau.rest.RequestHeaders} - API for accessing request headers.
+ <li>{@link org.apache.juneau.rest.RequestQuery} - API for accessing request query parameters.
+ <li>{@link org.apache.juneau.rest.RequestFormData} - API for accessing request form data.
+ <li>{@link org.apache.juneau.rest.RequestPathMatch} - API for accessing path variables.
+ <li>{@link org.apache.juneau.rest.RequestBody} - API for accessing request body.
+ </ul>
+ <li>Other:
+ <ul>
+ <li>{@link org.apache.juneau.http.HttpMethod} - The method name matched (when using <code><ja>@RestMethod</ja>(name=<js>"*"</js>)</code>)
+ <li>{@link java.util.logging.Logger} - The logger to use for logging.
+ <li>{@link org.apache.juneau.internal.JuneauLogger} - Logger with additional features.
+ <li>{@link org.apache.juneau.rest.RestContext} - The resource read-only context.
+ <li>{@link org.apache.juneau.parser.Parser} - The parser matching the request content type.
+ <li>{@link org.apache.juneau.dto.swagger.Swagger} - The auto-generated Swagger doc.
+ <li>{@link org.apache.juneau.ini.ConfigFile} - The external config file for the resource.
+ </ul>
+ </ul>
+ <li>
+ Annotated parameters:
+ <ul>
+ <li>{@link org.apache.juneau.rest.annotation.Path @Path} - Variables in matched URL path patterns.
+ <li>{@link org.apache.juneau.rest.annotation.FormData @FormData} - Multipart form post parameter values.
+ <li>{@link org.apache.juneau.rest.annotation.HasFormData @HasFormData} - Denotes whether the form data parameter exists.
+ <li>{@link org.apache.juneau.rest.annotation.Query @Query} - Query parameters. Using this prevents the HTTP body from being processed as a URL-Encoded form post.
+ <li>{@link org.apache.juneau.rest.annotation.HasQuery @HasQuery} - Denotes whether the query parameter exists.
+ <li>{@link org.apache.juneau.rest.annotation.Header @Header} - A header value.
+ <li>{@link org.apache.juneau.rest.annotation.Method @Method} - The HTTP method name.
+ <li>{@link org.apache.juneau.rest.annotation.PathRemainder @PathRemainder} - The remainder value after path pattern match.
+ <li>{@link org.apache.juneau.rest.annotation.Body @Body} - The HTTP content parsed as a POJO.
+ <li>{@link org.apache.juneau.rest.annotation.Messages @Messages} - The resource bundle for the servlet localized to the language on the request.
+ <li>{@link org.apache.juneau.rest.annotation.Properties @Properties} - The serializer/parser/servlet properties so they can be read or altered on the request.
+ </ul>
+ </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>@Path</ja> String a1,
+ <ja>@Path</ja> <jk>int</jk> a2,
+ <ja>@Path</ja> UUID a3,
+ <ja>@Query</ja>(<js>"p1"</js>) <jk>int</jk> p1,
+ <ja>@Query</ja>(<js>"p2"</js>) String p2,
+ <ja>@Query</ja>(<js>"p3"</js>) UUID p3,
+ <ja>@HasQuery</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>@Body</l>) can be any POJO type convertible from a
+ <l>String</l>.
+ (See <a class='doclink' href='#PojosConvertableFromString'>POJOs Convertible 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.rest.RestRequest} class.
+ </p>
+
+ <!-- ======================================================================================================== -->
+ <a id="RestResources.MethodSignature.Path"></a>
+ <h4 class='topic' onclick='toggle(this)'>4.1.1 - Path</h4>
+ <div class='topic'>
+ <p>
+ The {@link org.apache.juneau.rest.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>@Path</ja> String foo, <ja>@Path</ja> <jk>int</jk> bar, <ja>@Path</ja> MyEnum baz, <ja>@Path</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.rest.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.rest.RequestPathMatch#getRemainder()} or parameters with the
+ {@link org.apache.juneau.rest.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>@Query</ja>(<js>"foo"</js>) String foo, <ja>@Query</ja>(<js>"bar"</js>) <jk>int</jk> bar, <ja>@Query</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 id="RestResources.MethodSignature.Matchers"></a>
+ <h4 class='topic' onclick='toggle(this)'>4.1.2 - Matchers</h4>
+ <div class='topic'>
+ <p>
+ {@link org.apache.juneau.rest.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>
+ <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 id="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>@Body</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.rest.RestRequest#getBody()} method, or a parameter annotated with
+ {@link org.apache.juneau.rest.annotation.Body @Body}.
+ </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>@Body</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.getBody).asType(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 id="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>@Body</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>(pojoSwaps=CalendarSwap.<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>@FormData</ja>(<js>"aString"</js>) String aString, <ja>@FormData</ja>(<js>"aNumber"</js>) <jk>int</jk> aNumber, <ja>@FormData</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>
+ <ul class='doctree'>
+ <li class='severe'>
+ If you're using form input beans, DO NOT use the <l>@FormData</l> attribute or
+ {@link org.apache.juneau.rest.RestRequest#getParameter(String)} method since this will cause the
+ underlying JEE servlet to parse the HTTP body as a form post.
+ <br>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.
+ <br>This applies to WHENEVER you use <l>@Body</l> or {@link org.apache.juneau.rest.RestRequest#getBody()}
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="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 with 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 id="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.rest.RestResponse#setOutput(Object)} with any of the types above.
+ <li>
+ By accessing the {@link java.io.Writer} directly by calling
+ {@link org.apache.juneau.rest.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>@Path</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>@Path</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>@Path</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 id="RestResources.RestHooks"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.4 - Lifecycle Hooks</h3>
+ <div class='topic'>
+ <p>
+ Lifecycle hooks allow you to hook into lifecycle events of the servlet or REST call.
+ Like <ja>@RestMethod</ja> methods, the list of parameters are specified by the developer.
+ </p>
+ <p>
+ For example, if you want to add an initialization method to your resource:
+ </p>
+ <p class='bcode'>
+ <ja>@RestResource</ja>(...)
+ <jk>public class</jk> MyResource {
+
+ <jc>// Our database.</jc>
+ <jk>private</jk> Map<Integer,Object> <jf>myDatabase</jf>;
+
+ <ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ <jk>public void</jk> initMyDatabase(RestConfig config) <jk>throws</jk> Exception {
+ <jf>myDatabase</jf> = <jk>new</jk> LinkedHashMap<>();
+ }
+ }
+ </p>
+ <p>
+ Or if you want to intercept REST calls:
+ </p>
+ <p class='bcode'>
+ <ja>@RestResource</ja>(...)
+ <jk>public class</jk> MyResource {
+
+ <jc>// Add a request attribute to all incoming requests.</jc>
+ <ja>@RestHook</ja>(<jsf>PRE_CALL</jsf>)
+ <jk>public void</jk> onPreCall(RestRequest req) {
+ req.setAttribute(<js>"foo"</js>, <js>"bar"</js>);
+ }
+ }
+ </p>
+ <p>
+ The hook events can be broken down into two categories:
+ </p>
+ <ul class='spaced-list'>
+ <li>Resource lifecycle events:
+ <ul>
+ <li>{@link org.apache.juneau.rest.annotation.HookEvent#INIT INIT} - Right before initialization.
+ <li>{@link org.apache.juneau.rest.annotation.HookEvent#POST_INIT POST_INIT} - Right after initialization.
+ <li>{@link org.apache.juneau.rest.annotation.HookEvent#POST_INIT_CHILD_FIRST POST_INIT_CHILD_FIRST} - Right after initialization, but run child methods first.
+ <li>{@link org.apache.juneau.rest.annotation.HookEvent#DESTROY DESTROY} - Right before servlet destroy.
+ </ul>
+ <li>REST call lifecycle events:
+ <ul>
+ <li>{@link org.apache.juneau.rest.annotation.HookEvent#START_CALL START_CALL} - At the beginning of a REST call.
+ <li>{@link org.apache.juneau.rest.annotation.HookEvent#PRE_CALL PRE_CALL} - Right before the <ja>@RestMethod</ja> method is invoked.
+ <li>{@link org.apache.juneau.rest.annotation.HookEvent#POST_CALL POST_CALL} - Right after the <ja>@RestMethod</ja> method is invoked.
+ <li>{@link org.apache.juneau.rest.annotation.HookEvent#END_CALL END_CALL} - At the end of the REST call after the response has been flushed.
+ </ul>
+ </ul>
+
+
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='doctree'>
+ <li class='jp'>
+ {@link org.apache.juneau.rest.annotation.RestHook @RestHook}
+ </ul>
+ </div>
+
+
+ <!-- ======================================================================================================== -->
+ <a id="RestResources.OptionsPages"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.5 - 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/HelloWorldResourceOptions.png'>
+ <p>
+ This page is constructed through reflection on the servlet class and it's methods, combined with
+ information provided in the following locations:
+ </p>
+ <ul>
+ <li>Annotations (i.e. {@link org.apache.juneau.rest.annotation.RestResource @RestResource} and
+ {@link org.apache.juneau.rest.annotation.RestMethod @RestMethod}).
+ <li>Resource bundle properties.
+ <li>Swagger JSON files.
+ </ul>
+ <p>
+ Swagger JSON files are specified with the same name as the servlet
+ (e.g. <code>MyResource.java</code> -> <code>MyResource.json</code>).
+ Localized versions of Swagger JSON files can be specified by appending the locale to the file name
+ (e.g. <code>MyResource_ja_JP.json</code>).
+ The existence of Swagger JSON files will override any auto-generation of the OPTIONS pages.
+ This allows you to fully control the contents of the OPTIONS page with your own Swagger spec.
+ </p>
+ <p>
+ The framework takes the information above and populates a {@link org.apache.juneau.dto.swagger.Swagger} bean.
+ This bean is then serialized just like any other POJO to produce the page shown above.
+ </p>
+ <p>
+ {@link org.apache.juneau.rest.RestServletDefault} provides a default OPTIONS page by implementing
+ a {@link org.apache.juneau.rest.RestServletDefault#getOptions(RestRequest)} method that returns a POJO
+ consisting of beans describing the class.
+ It uses the {@link org.apache.juneau.rest.RestRequest#getSwagger()} method that returns a localized swagger
+ bean.
+ </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>,
+ summary=<js>"Resource options"</js>,
+ htmldoc=<ja>@HtmlDoc</ja>(
+ links={
+ <js>"back: servlet:/,"</js>,
+ <js>"json: servlet:/?method=OPTIONS&Accept=text/json&plainText=true"</js>
+ }
+ )
+ )
+ <jk>public</jk> Swagger getOptions(RestRequest req) {
+ <jk>return</jk> req.getSwagger();
+ }
+ </p>
+
+ <h6 class='topic'>Title and Description</h6>
+ <p>
+ The title and description can be defined in the following ways.
+ </p>
+ <ul>
+ <li>Annotations: {@link org.apache.juneau.rest.annotation.RestResource#title()},
+ {@link org.apache.juneau.rest.annotation.RestResource#description()}
+ <li>By overriding methods on the servlet class:
+ {@link org.apache.juneau.rest.RestInfoProvider#getTitle(RestRequest)},
+ {@link org.apache.juneau.rest.RestInfoProvider#getDescription(RestRequest)}
+ <li>By defining properties in the resource bundle.
+ <li>By specifying them in a Swagger JSON file.
+ </ul>
+ <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>,
+ title=<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.rest.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 title and description are specified as special properties in the resource bundle:
+ </p>
+ <p class='bcode'>
+ <cc>#--------------------------------------------------------------------------------
+ # Contents of Messages.properties
+ #--------------------------------------------------------------------------------</cc>
+ <ck>title</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.title</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='doctree'>
+ <li class='jm'>
+ {@link org.apache.juneau.rest.RestRequest#getServletTitle()}
+ <li class='jm'>
+ {@link org.apache.juneau.rest.RestRequest#getServletDescription()}
+ </ul>
+ <p>
+ They are also made available as the request string variables <js>"$R{servletTitle}"</js> and
+ <js>"$R{servletDescription}"</js>.
+ These variable facilitate the localized label and descriptions on the HTML pages when using
+ {@link org.apache.juneau.rest.RestServletDefault}:
+ </p>
+ <p class='bcode'>
+ <ja>@RestResource</ja>(
+ pageTitle=<js>"The title for this page is $R{servletTitle}"</js>,
+ pageText=<js>"The description for this page is $R{servletDescription}"</js>
+ )
+ <jk>public abstract class</jk> RestServletDefault <jk>extends</jk> RestServlet {
+ </p>
+ <p>
+ The title 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>
+ title=<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.rest.RestInfoProvider#getTitle(RestRequest)}
+ and {@link org.apache.juneau.rest.RestInfoProvider#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.rest.annotation.RestMethod#description() @RestMethod.description()},
+ {@link org.apache.juneau.rest.annotation.RestMethod#swagger() @RestMethod.swagger()},
+ and {@link org.apache.juneau.rest.annotation.MethodSwagger @MethodSwagger} 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>,
+ parameters={
+ <ja>@Parameter</ja>(in=<js>"path"</js>, name=<js>"id"</js>, description=<js>"Person UUID"</js>)
+ },
+ responses={
+ <ja>@Response</ja>(value=200, description="Person bean"),
+ <ja>@Response</ja>(value=404, description=<js>"Person with specified id not found"</js>)
+ }
+ )
+ <jk>public</jk> Person getPerson(<ja>@Path</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>@Path</ja> <jk>int</jk> id) throws Exception {
+ <jk>return</jk> findPerson(id);
+ }
+ </p>
+ <p class='bcode'>
+ <cc>#--------------------------------------------------------------------------------
+ # Contents of AddressBookResource.properties
+ #--------------------------------------------------------------------------------</cc>
+ <ck>getPerson.summary</ck> = <cv>Get a person by id in the address book</cv>
+ <ck>getPerson.req.path.id.description</ck> = <cv>Person UUID</cv>
+ <ck>getPerson.res.200.description</ck> = <cv>Person found</cv>
+ <ck>getPerson.res.404.description</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.rest.annotation.RestResource#title() @RestResource.title()}</td>
+ <td>{@link org.apache.juneau.rest.RestInfoProvider#getTitle(RestRequest)}</td>
+ </tr>
+ <tr>
+ <td><ck>description</ck></td>
+ <td>Servlet description</td>
+ <td>{@link org.apache.juneau.rest.annotation.RestResource#description() @RestResource.description()}</td>
+ <td>{@link org.apache.juneau.rest.RestInfoProvider#getDescription(RestRequest)}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].summary</ck></td>
+ <td>Java method summary</td>
+ <td>{@link org.apache.juneau.rest.annotation.RestMethod#summary() @RestMethod.summary()}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].description</ck></td>
+ <td>Java method description</td>
+ <td>{@link org.apache.juneau.rest.annotation.RestMethod#description() @RestMethod.description()}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].req.body.description</ck></td>
+ <td>
+ A description of the HTTP request body.
+ </td>
+ <td>{@link org.apache.juneau.rest.annotation.MethodSwagger#parameters() @MethodSwagger.parameters()}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].req.[category].[name].description</ck></td>
+ <td>
+ A request input variable.
+ <br>Categories: <l>path, query, formData, header</l>
+ </td>
+ <td>{@link org.apache.juneau.rest.annotation.MethodSwagger#parameters() @MethodSwagger.parameters()}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].res.[code].description</ck></td>
+ <td>
+ A possible HTTP response code and description.
+ </td>
+ <td>{@link org.apache.juneau.rest.annotation.MethodSwagger#responses() @MethodSwagger.responses()}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].res.[code].body.description</ck></td>
+ <td>
+ A description of response content for the specified HTTP response.
+ </td>
+ <td>{@link org.apache.juneau.rest.annotation.MethodSwagger#responses() @MethodSwagger.responses()}</td>
+ </tr>
+ <tr>
+ <td><ck>[javaMethodName].res.[code].header.[name].description</ck></td>
+ <td>
+ A response header.
+ </td>
+ <td>{@link org.apache.juneau.rest.annotation.MethodSwagger#responses() @MethodSwagger.responses()}</td>
+ </tr>
+ </table>
+
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='doctree'>
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestMethod#description() @RestMethod.description()}
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.MethodSwagger#parameters() @MethodSwagger.parameters()}
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.MethodSwagger#responses() @MethodSwagger.responses()}
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="RestResources.Serializers"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.6 - 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.
+ </p>
+ <p>
+ Serializers can be associated with REST servlets in the following ways:
+ </p>
+ <ul class='doctree'>
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestResource#serializers() @RestResource.serializers()}
+ - Annotation on servlet class.
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestMethod#serializers() @RestMethod.serializers()}
+ - Annotation on individual servlet methods.
+ <li class='jm'>
+ {@link org.apache.juneau.rest.RestConfig#addSerializers(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[],Class[]) method</jc>
+ <ja>@Override</ja>
+ <jk>public</jk> SerializerGroupBuilder createSerializers(ObjectMap,Class[],Class[]) {
+
+ <jk>return new</jk> SerializerGroupBuilder()
+ .append(JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>);
+ }
+ </p>
+ <ul class='doctree'>
+ <li 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.
+ </ul>
+
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='doctree'>
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestMethod#serializersInherit() @RestMethod.serializersInherit()}
+ <br>Controls how serializers are inherited from the servlet class.
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="RestResources.Parsers"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.7 - 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.
+ </p>
+ <p>
+ Parsers can be associated with REST servlets in the following ways:
+ </p>
+ <ul class='doctree'>
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestResource#parsers() @RestResource.parsers()}
+ - Annotation on servlet class.
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestMethod#parsers() @RestMethod.parsers()}
+ - Annotation on individual servlet methods.
+ <li class='jm'>
+ {@link org.apache.juneau.rest.RestConfig#addParsers(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>@Body</ja> Foo input) {
+ ...
+ }
+
+ <jc>// Example #3 - Parsers defined on servlet by overriding the getParserGroup method</jc>
+ <ja>@Override</ja>
+ <jk>public</jk> ParserGroupBuilder getParserGroup() {
+
+ <jk>return new</jk> ParserGroupBuilder()
+ .append(JsonParser.<jk>class</jk>, XmlParser.<jk>class</jk>);
+ }
+ </p>
+
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='doctree'>
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestMethod#parsersInherit() @RestMethod.parsersInherit()}
+ <br>Controls how parsers are inherited from the servlet class.
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="RestResources.Properties"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.8 - 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.rest.annotation.RestResource#properties() @RestResource.properties()}
+ and {@link org.apache.juneau.rest.annotation.RestMethod#properties() @RestMethod.properties()} annotations.
+ </p>
+ <p>
+ The {@link org.apache.juneau.rest.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.rest.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>
+ <jc>// This is equivalent to @RestResource(title/pageTitle)</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.rest.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>
+ <jc>// This is equivalent to @RestMethod(pageTitle)</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.rest.RestContext} class has a variety of properties for
+ controlling the behavior of the {@link org.apache.juneau.rest.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.rest.RestConfig#setProperties(Map)} method.
+ <li>
+ By overriding the {@link org.apache.juneau.rest.RestConfig#addSerializers(Class[])} and
+ {@link org.apache.juneau.rest.RestConfig#addParsers(Class[])} methods and setting properties on the
+ serializers and parsers directly.
+
+ </ul>
+
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='doctree'>
+ <li class='jc'>
+ {@link org.apache.juneau.rest.RestContext}
+ <br>Properties associated with the {@link org.apache.juneau.rest.RestServlet} class.
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestMethod#serializersInherit @RestMethod.serializersInherit()}
+ <br>Controls how serializers inherit properties from the servlet class.
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestMethod#parsersInherit @RestMethod.parsersInheritInherit()}
+ <br>Controls how parsers inherit properties from the servlet class.
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="RestResources.Transforms"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.9 - 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.rest.annotation.RestResource#beanFilters() @RestResource.beanFilters()}
+ and {@link org.apache.juneau.rest.annotation.RestResource#pojoSwaps() @RestResource.pojoSwaps()} annotations
+ can be used as a convenient way to add bean filters and POJO swaps to the serializers and parsers
+ registered with the servlet.
+ </p>
+ <p class='bcode'>
+ <jc>// Servlet with transforms applied</jc>
+ <ja>@RestResource</ja>(
+ pojoSwaps={
+ <jc>// Calendars should be serialized/parsed as ISO8601 date-time strings</jc>
+ CalendarSwap.<jsf>DEFAULT_ISO8601DT</jsf>.<jk>class</jk>,
+
+ <jc>// Byte arrays should be serialized/parsed as BASE64-encoded strings</jc>
+ ByteArrayBase64Swap.<jk>class</jk>,
+ },
+ beanFilters={
+ <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.rest.annotation.RestMethod#beanFilters() @RestMethod.beanFilters()} and
+ {@link org.apache.juneau.rest.annotation.RestMethod#pojoSwaps() @RestMethod.pojoSwaps()}
+ are the equivalent annotations 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.rest.RestConfig#addBeanFilters(Class[])} and
+ {@link org.apache.juneau.rest.RestConfig#addPojoSwaps(Class[])} methods.
+ <li>
+ By overriding the {@link org.apache.juneau.rest.RestConfig#addSerializers(Class[])} and
+ {@link org.apache.juneau.rest.RestConfig#addParsers(Class[])} methods and setting transforms on the
+ serializers and parsers directly.
+
+ </ul>
+
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='doctree'>
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestMethod#serializersInherit @RestMethod.serializersInherit()}
+ <br>Controls how serializers inherit transforms (bean filters and POJO swaps) from the servlet class.
+ <li class='ja'>
+ {@link org.apache.juneau.rest.annotation.RestMethod#parsersInherit @RestMethod.parsersInherit()}
+ <br>Controls how parsers inherit transforms from the servlet class.
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="RestResources.Guards"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.10 - Guards</h3>
+ <div class='topic'>
+ <p>
+ Guards are classes that control access to REST servlets and methods.
+ </p>
+ <p>
+ The {@link org.apache.juneau.rest.annotation.RestResource#guards @RestResource.guards()} annotation
+ can be used to associate one or more class-level {@link org.apache.juneau.rest.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.rest.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.rest.RestConfig#addGuards(Class[])} method.
+ </p>
+
+ <h6 class='topic'>Additional Information</h6>
+ <ul class='doctree'>
+ <li class='jac'>
+ {@link org.apache.juneau.rest.RestGuard}
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="RestResources.Converters"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.11 - 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.rest.annotation.RestResource#converters @RestResource.converters()} annotation
+ can be used as a convenient way to add {@link org.apache.juneau.rest.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.rest.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>@Path</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='doctree'>
+ <li class='jic'>
+ {@link org.apache.juneau.rest.RestConverter}
+ <ul>
+ <li class='jc'>
+ {@link org.apache.juneau.rest.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='jc'>
+ {@link org.apache.juneau.rest.converters.Traversable}
+ <br>Allows nodes in the POJO response tree to be individually accessed through additional path info on
+ the request.
+ <li class='jc'>
+ {@link org.apache.juneau.rest.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.rest.RestConfig#addConverters(Class[])} 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='doctree'>
+ <li class='jic'>
+ {@link org.apache.juneau.rest.RestConverter}
+ </ul>
+ </div>
+
+ <!-- ======================================================================================================== -->
+ <a id="RestResources.Children"></a>
+ <h3 class='topic' onclick='toggle(this)'>4.12 - Child Resources</h3>
+ <div class='topic'>
+ <p>
+ Child Resources are REST servlets that are linked to parent servlets through the
+ {@link org.apache.juneau.rest.annotation.RestResource#children() @RestResource.children()} annotation.
+ </p>
+ <p class='bcode'>
+ <jd>/** Parent Resource */</jd>
+ <ja>@RestResource</ja>(
+ path=<js>"/parent"</js>,
[... 1876 lines stripped ...]
Re: svn commit: r21540 [20/27] - in /release/incubator/juneau:
juneau-rest-client/ juneau-rest-client/.settings/ juneau-rest-client/bin/
juneau-rest-client/src/ juneau-rest-client/src/main/ juneau-rest-client/src/main/java/
juneau-rest-client/src/main/java...
Posted by James Bognar <ja...@apache.org>.
oops...yes. Those were supposed to go into Git.
On Fri, Sep 8, 2017 at 9:10 PM, John D. Ament <jo...@apache.org> wrote:
> James,
>
> Did you check these in by mistake?
>
> John
>
> On Fri, Sep 8, 2017 at 7:25 PM <ja...@apache.org> wrote:
>
> > Added:
> > release/incubator/juneau/juneau-rest-server/src/main/
> java/org/apache/juneau/rest/package.html
> >
> > ============================================================
> ==================
> > ---
> > release/incubator/juneau/juneau-rest-server/src/main/
> java/org/apache/juneau/rest/package.html
> > (added)
> > +++
> > release/incubator/juneau/juneau-rest-server/src/main/
> java/org/apache/juneau/rest/package.html
> > Fri Sep 8 23:25:34 2017
> > @@ -0,0 +1,3860 @@
> > +<!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 id='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='#RestResources'>REST
> > Servlets</a></p>
> > + <ol>
> > + <li><p><a class='doclink'
> > href='#RestResources.MethodSignature'>REST Java Method Signature</a></p>
> > + <ol>
> > + <li><p><a class='doclink'
> > href='#RestResources.MethodSignature.Path'>Path</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.MethodSignature.Matchers'>Matchers</a></p>
> > + </ol>
> > + <li><p><a class='doclink'
> > href='#RestResources.RequestContent'>Request Content</a></p>
> > + <ol>
> > + <li><p><a class='doclink'
> > href='#RestResources.RequestContent.FormPosts'>Form Posts</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.RequestContent'>Multipart Form Posts</a></p>
> > + </ol>
> > + <li><p><a class='doclink'
> > href='#RestResources.ResponseContent'>Response Content</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.RestHooks'>Lifecycle Hooks</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.OptionsPages'>OPTIONS Pages</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Serializers'>Serializers</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Parsers'>Parsers</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Properties'>Properties</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Transforms'>Transforms</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Guards'>Guards</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Converters'>Converters</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Children'>Child Resources</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Labels'>Localized Messages</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Encoders'>Encoders</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.SvlVars'>SVL Vars</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.StaticFiles'>Static Files</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Listeners'>Listener Methods</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Stylesheet'>Stylesheet</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Headers'>Default Headers</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Errors'>Handling Errors / Logging</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.ConfigFile'>Configuration Files</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.Inheritence'>Annotation Inheritance</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.HttpStatusCodes'>HTTP Status Codes</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.OverloadedHttpMethods'>Overloaded HTTP
> Methods</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.BuildInParams'>Built-In Parameters</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.CustomSerializersParsers'>Defining your own
> > serializers/parsers</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.ResponseHandlers'>Response Handlers</a></p>
> > + <li><p><a class='doclink'
> > href='#RestResources.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
> > Convertible From Strings</a></p>
> > + <li><p><a class='doclink' href='#AddressBookResource'>Address
> Book
> > Resource</a></p>
> > +</ol>
> > +
> > +<!--
> > ============================================================
> ============================================
> > -->
> > +<a id="Intro"></a>
> > +<h2 class='topic' onclick='toggle(this)'>1 - Introduction</h2>
> > +<div class='topic'>
> > + <p>
> > + The <l>juneau-rest.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.rest.
> RestServlet}
> > is nothing but a specialized
> > + {@link javax.servlet.http.HttpServlet}, and the {@link
> > org.apache.juneau.rest.RestRequest} and
> > + {@link org.apache.juneau.rest.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.
> > + <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>
> > + <li>
> > + Parses content of POST/PUT request bodies to
> POJOs.
> > + <li>
> > + Automatic built-in ability to serialize POJO
> > metadata to JSON+SCHEMA, XML+SCHEMA, or HTML+SCHEMA based on
> > + <l>Accept</l> header.
> > + <li>
> > + Automatic negotiation of output Writer based on
> > HTTP headers.
> > + <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>
> > + <li>
> > + Automatic error handling.
> > + <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>
> > + <li>
> > + Self-documenting REST interfaces.
> > + <li>
> > + Various useful debugging features that make
> > debugging using a browser extremely simple...
> > + <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
> <js>"text/plain"</js>
> > on response using GET parameter <l>&plainText=true</l>.
> > + </ul>
> > + <li>
> > + Ability to implement overloaded HTTP methods
> > through the use of the <l>&method</l> attribute
> > + (e.g. <l>&method=FOO</l>).
> > + <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>).
> > + <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.
> > + <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 id="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.rest.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.foo.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>,
> > + htmldoc=<ja>@HtmlDoc</ja>(
> > + links={
> > + <js>"up: request:/.."</js>,
> > + <js>"options:
> > servlet:/?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.rest.RestServletDefault}
> > class that we're using here is a subclass of
> > + {@link org.apache.juneau.rest.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.rest.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='spaced-list'>
> > + <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.
> > + <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 parameter 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 a serialized Swagger DTO bean
> > populated by introspection of the class itself combined with
> > + labels in the messages properties file and
> > annotations.
> > + It's composed of a POJO that gets serialized just like
> any
> > other POJO.
> > + Therefore, the POJO can be serialized to any of the
> > supported languages, like Swagger JSON.
> > + </p>
> > + <img class='bordered'
> > src="doc-files/HelloWorldResourceOptionsJson.png">
> > +</div>
> > +
> > +<!--
> > ============================================================
> ============================================
> > -->
> > +<a id="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='doctree'>
> > + <li class='jac'>
> > + {@link javax.servlet.http.HttpServlet
> > javax.servlet.http.HttpServlet}
> > + <ul>
> > + <li class='jac'>
> > + {@link
> > org.apache.juneau.rest.RestServlet org.apache.juneau.rest.RestServlet}
> > + <br>Contains all the main logic.
> > + <ul>
> > + <li class='jac'>
> > + {@link
> > org.apache.juneau.rest.RestServletDefault
> > org.apache.juneau.rest.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='jac'>
> > +
> > {@link org.apache.juneau.microservice.Resource
> > org.apache.juneau.microservice.Resource}
> > +
> > <br>Subclass intended to be used in REST microservices.
> > +
> > <br><b>Developers will typically subclass this when creating
> > microservices.</b>
> > + <li
> > class='jac'>
> > +
> > {@link org.apache.juneau.rest.RestServletGroupDefault
> > org.apache.juneau.rest.RestServletGroupDefault}
> > +
> > <br>A default implementation for "router" pages.
> > +
> > <ul>
> > +
> > <li class='jac'>
> > +
> > {@link org.apache.juneau.microservice.ResourceGroup
> > org.apache.juneau.microservice.ResourceGroup}
> > +
> > <br>Subclass intended to be used in REST microservices.
> > +
> > </ul>
> > + </li>
> > + <li
> > class='jc'>
> > +
> > {@link org.apache.juneau.rest.remoteable.RemoteableServlet
> > org.apache.juneau.rest.remoteable.RemoteableServlet}
> > +
> > <br>REST servlet for implementing remoteable proxy interfaces.
> > + </ul>
> > + </li>
> > + </ul>
> > + </li>
> > + </ul>
> > + </li>
> > + </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.rest.RestRequest} and
> {@link
> > org.apache.juneau.rest.RestResponse} classes
> > + described later also extend from their servlet
> equivalents:
> > + </p>
> > + <ul class='doctree'>
> > + <li class='jic'>
> > + {@link javax.servlet.http.HttpServletRequest
> > javax.servlet.http.HttpServletRequest}
> > + <ul>
> > + <li class='jc'>
> > + {@link
> > org.apache.juneau.rest.RestRequest org.apache.juneau.rest.RestRequest}
> > + - Augmented with specialized REST
> > methods.
> > + </ul>
> > + </li>
> > + <li class='jic'>
> > + {@link javax.servlet.http.HttpServletResponse
> > javax.servlet.http.HttpServletResponse}
> > + <ul>
> > + <li class='jc'>
> > + {@link
> > org.apache.juneau.rest.RestResponse org.apache.juneau.rest.RestResponse}
> > + - Augmented with specialized REST
> > methods.
> > + </ul>
> > + </li>
> > + </ul>
> > +</div>
> > +
> > +<!--
> > ============================================================
> ============================================
> > -->
> > +<a id="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.rest.RestServlet} annotated with
> > + {@link org.apache.juneau.rest.annotation.RestResource
> > @RestResource} containing public Java methods
> > + annotated with {@link
> > org.apache.juneau.rest.annotation.RestMethod @RestMethod}.
> > + </p>
> > + <p>
> > + Developers will typically subclass directly from {@link
> > org.apache.juneau.rest.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>
> > + <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.uon.UonSerializer}</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'>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.JsoSerializer}</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.uon.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.rest.RestServletDefault} also
> > provides a default OPTIONS page by implementing
> > + a {@link
> > org.apache.juneau.rest.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='doctree'>
> > + <li class='jac'>
> > + {@link org.apache.juneau.rest.
> RestServletDefault}
> > + </ul>
> > +
> > + <!--
> > ============================================================
> ============================================
> > -->
> > + <a id="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.rest.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.rest.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.rest.RestResponse#setOutput(Object)} method.
> > + Calling the {@link
> > org.apache.juneau.rest.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='doctree'>
> > + <li class='jc'>
> > + {@link java.io.InputStream}
> > + <br>The contents are simply piped to the
> > output stream returned by
> > + {@link
> > org.apache.juneau.rest.RestResponse#getNegotiatedOutputStream()}.
> > + <br>Note that you should call {@link
> > org.apache.juneau.rest.RestResponse#setContentType(String)} to set
> > + the <l>Content-Type</l> header if you use
> > this object type.
> > + <li class='jc'>
> > + {@link java.io.Reader}
> > + <br>The contents are simply piped to the
> > output stream returned by
> > + {@link
> > org.apache.juneau.rest.RestResponse#getNegotiatedWriter()}.
> > + <br>Note that you should call {@link
> > org.apache.juneau.rest.RestResponse#setContentType(String)} to set
> > + the <l>Content-Type</l> header if you use
> > this object type.
> > + <li class='jc'>
> > + {@link org.apache.juneau.rest.Redirect}
> > + <br>Represents an HTTP redirect response.
> > + <li class='jic'>
> > + {@link org.apache.juneau.Streamable}
> > + <br>Interface that identifies that an
> > object can be serialized directly to an output stream.
> > + <li class='jic'>
> > + {@link org.apache.juneau.Writable}
> > + <br>Interface that identifies that an
> > object can be serialized directly to a writer.
> > + <li class='jc'>
> > + {@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.rest.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>
> > + Parameters of the following class types:
> > + <ul>
> > + <li>Request/response objects:
> > + <ul>
> > + <li>{@link
> > org.apache.juneau.rest.RestRequest} - The request object.
> > + <li>{@link
> > javax.servlet.http.HttpServletRequest} - The superclass of
> > <code>RestRequest</code>.
> > + <li>{@link
> > org.apache.juneau.rest.RestResponse} - The response object.
> > + <li>{@link
> > javax.servlet.http.HttpServletResponse} - The superclass of
> > <code>RestResponse</code>.
> > + </ul>
> > + <li>Parsed request header values:
> > + <ul>
> > + <li>{@link
> > org.apache.juneau.http.Accept}
> > + <li>{@link
> > org.apache.juneau.http.AcceptCharset}
> > + <li>{@link
> > org.apache.juneau.http.AcceptEncoding}
> > + <li>{@link
> > org.apache.juneau.http.AcceptLanguage}
> > + <li>{@link
> > org.apache.juneau.http.Authorization}
> > + <li>{@link
> > org.apache.juneau.http.CacheControl}
> > + <li>{@link
> > org.apache.juneau.http.Connection}
> > + <li>{@link
> > org.apache.juneau.http.ContentLength}
> > + <li>{@link
> > org.apache.juneau.http.ContentType}
> > + <li>{@link
> > org.apache.juneau.http.Date}
> > + <li>{@link
> > org.apache.juneau.http.Expect}
> > + <li>{@link
> > org.apache.juneau.http.From}
> > + <li>{@link
> > org.apache.juneau.http.Host}
> > + <li>{@link
> > org.apache.juneau.http.IfMatch}
> > + <li>{@link
> > org.apache.juneau.http.IfModifiedSince}
> > + <li>{@link
> > org.apache.juneau.http.IfNoneMatch}
> > + <li>{@link
> > org.apache.juneau.http.IfRange}
> > + <li>{@link
> > org.apache.juneau.http.IfUnmodifiedSince}
> > + <li>{@link
> > org.apache.juneau.http.MaxForwards}
> > + <li>{@link
> > org.apache.juneau.http.Pragma}
> > + <li>{@link
> > org.apache.juneau.http.ProxyAuthorization}
> > + <li>{@link
> > org.apache.juneau.http.Range}
> > + <li>{@link
> > org.apache.juneau.http.Referer}
> > + <li>{@link
> > org.apache.juneau.http.TE}
> > + <li>{@link
> > org.apache.juneau.http.UserAgent}
> > + <li>{@link
> > org.apache.juneau.http.Upgrade}
> > + <li>{@link
> > org.apache.juneau.http.Via}
> > + <li>{@link
> > org.apache.juneau.http.Warning}
> > + <li>{@link
> > java.util.TimeZone}
> > + </ul>
> > + <li>Direct streams on
> > request/response:
> > + <ul>
> > + <li>{@link
> > java.io.InputStream}
> > + <li>{@link
> > javax.servlet.ServletInputStream}
> > + <li>{@link
> > java.io.Reader}
> > + <li>{@link
> > java.io.OutputStream}
> > + <li>{@link
> > javax.servlet.ServletOutputStream}
> > + <li>{@link
> > java.io.Writer}
> > + </ul>
> > + <li>Localization:
> > + <ul>
> > + <li>{@link
> > java.util.ResourceBundle} - Client-localized resource bundle.
> > + <li>{@link
> > org.apache.juneau.utils.MessageBundle} - A resource bundle with
> additional
> > features.
> > + <li>{@link
> > java.util.Locale} - Client locale.
> > + </ul>
> > + <li>Request APIs:
> > + <ul>
> > + <li>{@link
> > org.apache.juneau.rest.RequestHeaders} - API for accessing request
> headers.
> > + <li>{@link
> > org.apache.juneau.rest.RequestQuery} - API for accessing request query
> > parameters.
> > + <li>{@link
> > org.apache.juneau.rest.RequestFormData} - API for accessing request form
> > data.
> > + <li>{@link
> > org.apache.juneau.rest.RequestPathMatch} - API for accessing path
> variables.
> > + <li>{@link
> > org.apache.juneau.rest.RequestBody} - API for accessing request body.
> > + </ul>
> > + <li>Other:
> > + <ul>
> > + <li>{@link
> > org.apache.juneau.http.HttpMethod} - The method name matched (when using
> > <code><ja>@RestMethod</ja>(name=<js>"*"</js>)</code>)
> > + <li>{@link
> > java.util.logging.Logger} - The logger to use for logging.
> > + <li>{@link
> > org.apache.juneau.internal.JuneauLogger} - Logger with additional
> features.
> > + <li>{@link
> > org.apache.juneau.rest.RestContext} - The resource read-only context.
> > + <li>{@link
> > org.apache.juneau.parser.Parser} - The parser matching the request
> content
> > type.
> > + <li>{@link
> > org.apache.juneau.dto.swagger.Swagger} - The auto-generated Swagger doc.
> > + <li>{@link
> > org.apache.juneau.ini.ConfigFile} - The external config file for the
> > resource.
> > + </ul>
> > + </ul>
> > + <li>
> > + Annotated parameters:
> > + <ul>
> > + <li>{@link
> > org.apache.juneau.rest.annotation.Path @Path} - Variables in matched URL
> > path patterns.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.FormData @FormData} - Multipart form
> post
> > parameter values.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.HasFormData @HasFormData} - Denotes
> > whether the form data parameter exists.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.Query @Query} - Query parameters.
> Using
> > this prevents the HTTP body from being processed as a URL-Encoded form
> post.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.HasQuery @HasQuery} - Denotes whether
> the
> > query parameter exists.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.Header @Header} - A header value.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.Method @Method} - The HTTP method
> name.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.PathRemainder @PathRemainder} - The
> > remainder value after path pattern match.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.Body @Body} - The HTTP content parsed
> as
> > a POJO.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.Messages @Messages} - The resource
> bundle
> > for the servlet localized to the language on the request.
> > + <li>{@link
> > org.apache.juneau.rest.annotation.Properties @Properties} - The
> > serializer/parser/servlet properties so they can be read or altered on
> the
> > request.
> > + </ul>
> > + </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}/*
>
Re: svn commit: r21540 [20/27] - in /release/incubator/juneau:
juneau-rest-client/ juneau-rest-client/.settings/ juneau-rest-client/bin/
juneau-rest-client/src/ juneau-rest-client/src/main/ juneau-rest-client/src/main/java/
juneau-rest-client/src/main/java...
Posted by "John D. Ament" <jo...@apache.org>.
James,
Did you check these in by mistake?
John
On Fri, Sep 8, 2017 at 7:25 PM <ja...@apache.org> wrote:
> Added:
> release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
>
> ==============================================================================
> ---
> release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
> (added)
> +++
> release/incubator/juneau/juneau-rest-server/src/main/java/org/apache/juneau/rest/package.html
> Fri Sep 8 23:25:34 2017
> @@ -0,0 +1,3860 @@
> +<!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 id='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='#RestResources'>REST
> Servlets</a></p>
> + <ol>
> + <li><p><a class='doclink'
> href='#RestResources.MethodSignature'>REST Java Method Signature</a></p>
> + <ol>
> + <li><p><a class='doclink'
> href='#RestResources.MethodSignature.Path'>Path</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.MethodSignature.Matchers'>Matchers</a></p>
> + </ol>
> + <li><p><a class='doclink'
> href='#RestResources.RequestContent'>Request Content</a></p>
> + <ol>
> + <li><p><a class='doclink'
> href='#RestResources.RequestContent.FormPosts'>Form Posts</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.RequestContent'>Multipart Form Posts</a></p>
> + </ol>
> + <li><p><a class='doclink'
> href='#RestResources.ResponseContent'>Response Content</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.RestHooks'>Lifecycle Hooks</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.OptionsPages'>OPTIONS Pages</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Serializers'>Serializers</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Parsers'>Parsers</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Properties'>Properties</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Transforms'>Transforms</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Guards'>Guards</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Converters'>Converters</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Children'>Child Resources</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Labels'>Localized Messages</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Encoders'>Encoders</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.SvlVars'>SVL Vars</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.StaticFiles'>Static Files</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Listeners'>Listener Methods</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Stylesheet'>Stylesheet</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Headers'>Default Headers</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Errors'>Handling Errors / Logging</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.ConfigFile'>Configuration Files</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.Inheritence'>Annotation Inheritance</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.HttpStatusCodes'>HTTP Status Codes</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.OverloadedHttpMethods'>Overloaded HTTP Methods</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.BuildInParams'>Built-In Parameters</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.CustomSerializersParsers'>Defining your own
> serializers/parsers</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.ResponseHandlers'>Response Handlers</a></p>
> + <li><p><a class='doclink'
> href='#RestResources.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
> Convertible From Strings</a></p>
> + <li><p><a class='doclink' href='#AddressBookResource'>Address Book
> Resource</a></p>
> +</ol>
> +
> +<!--
> ========================================================================================================
> -->
> +<a id="Intro"></a>
> +<h2 class='topic' onclick='toggle(this)'>1 - Introduction</h2>
> +<div class='topic'>
> + <p>
> + The <l>juneau-rest.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.rest.RestServlet}
> is nothing but a specialized
> + {@link javax.servlet.http.HttpServlet}, and the {@link
> org.apache.juneau.rest.RestRequest} and
> + {@link org.apache.juneau.rest.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.
> + <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>
> + <li>
> + Parses content of POST/PUT request bodies to POJOs.
> + <li>
> + Automatic built-in ability to serialize POJO
> metadata to JSON+SCHEMA, XML+SCHEMA, or HTML+SCHEMA based on
> + <l>Accept</l> header.
> + <li>
> + Automatic negotiation of output Writer based on
> HTTP headers.
> + <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>
> + <li>
> + Automatic error handling.
> + <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>
> + <li>
> + Self-documenting REST interfaces.
> + <li>
> + Various useful debugging features that make
> debugging using a browser extremely simple...
> + <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 <js>"text/plain"</js>
> on response using GET parameter <l>&plainText=true</l>.
> + </ul>
> + <li>
> + Ability to implement overloaded HTTP methods
> through the use of the <l>&method</l> attribute
> + (e.g. <l>&method=FOO</l>).
> + <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>).
> + <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.
> + <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 id="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.rest.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.foo.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>,
> + htmldoc=<ja>@HtmlDoc</ja>(
> + links={
> + <js>"up: request:/.."</js>,
> + <js>"options:
> servlet:/?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.rest.RestServletDefault}
> class that we're using here is a subclass of
> + {@link org.apache.juneau.rest.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.rest.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='spaced-list'>
> + <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.
> + <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 parameter 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 a serialized Swagger DTO bean
> populated by introspection of the class itself combined with
> + labels in the messages properties file and
> annotations.
> + It's composed of a POJO that gets serialized just like any
> other POJO.
> + Therefore, the POJO can be serialized to any of the
> supported languages, like Swagger JSON.
> + </p>
> + <img class='bordered'
> src="doc-files/HelloWorldResourceOptionsJson.png">
> +</div>
> +
> +<!--
> ========================================================================================================
> -->
> +<a id="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='doctree'>
> + <li class='jac'>
> + {@link javax.servlet.http.HttpServlet
> javax.servlet.http.HttpServlet}
> + <ul>
> + <li class='jac'>
> + {@link
> org.apache.juneau.rest.RestServlet org.apache.juneau.rest.RestServlet}
> + <br>Contains all the main logic.
> + <ul>
> + <li class='jac'>
> + {@link
> org.apache.juneau.rest.RestServletDefault
> org.apache.juneau.rest.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='jac'>
> +
> {@link org.apache.juneau.microservice.Resource
> org.apache.juneau.microservice.Resource}
> +
> <br>Subclass intended to be used in REST microservices.
> +
> <br><b>Developers will typically subclass this when creating
> microservices.</b>
> + <li
> class='jac'>
> +
> {@link org.apache.juneau.rest.RestServletGroupDefault
> org.apache.juneau.rest.RestServletGroupDefault}
> +
> <br>A default implementation for "router" pages.
> +
> <ul>
> +
> <li class='jac'>
> +
> {@link org.apache.juneau.microservice.ResourceGroup
> org.apache.juneau.microservice.ResourceGroup}
> +
> <br>Subclass intended to be used in REST microservices.
> +
> </ul>
> + </li>
> + <li
> class='jc'>
> +
> {@link org.apache.juneau.rest.remoteable.RemoteableServlet
> org.apache.juneau.rest.remoteable.RemoteableServlet}
> +
> <br>REST servlet for implementing remoteable proxy interfaces.
> + </ul>
> + </li>
> + </ul>
> + </li>
> + </ul>
> + </li>
> + </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.rest.RestRequest} and {@link
> org.apache.juneau.rest.RestResponse} classes
> + described later also extend from their servlet equivalents:
> + </p>
> + <ul class='doctree'>
> + <li class='jic'>
> + {@link javax.servlet.http.HttpServletRequest
> javax.servlet.http.HttpServletRequest}
> + <ul>
> + <li class='jc'>
> + {@link
> org.apache.juneau.rest.RestRequest org.apache.juneau.rest.RestRequest}
> + - Augmented with specialized REST
> methods.
> + </ul>
> + </li>
> + <li class='jic'>
> + {@link javax.servlet.http.HttpServletResponse
> javax.servlet.http.HttpServletResponse}
> + <ul>
> + <li class='jc'>
> + {@link
> org.apache.juneau.rest.RestResponse org.apache.juneau.rest.RestResponse}
> + - Augmented with specialized REST
> methods.
> + </ul>
> + </li>
> + </ul>
> +</div>
> +
> +<!--
> ========================================================================================================
> -->
> +<a id="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.rest.RestServlet} annotated with
> + {@link org.apache.juneau.rest.annotation.RestResource
> @RestResource} containing public Java methods
> + annotated with {@link
> org.apache.juneau.rest.annotation.RestMethod @RestMethod}.
> + </p>
> + <p>
> + Developers will typically subclass directly from {@link
> org.apache.juneau.rest.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>
> + <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.uon.UonSerializer}</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'>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.JsoSerializer}</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.uon.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.rest.RestServletDefault} also
> provides a default OPTIONS page by implementing
> + a {@link
> org.apache.juneau.rest.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='doctree'>
> + <li class='jac'>
> + {@link org.apache.juneau.rest.RestServletDefault}
> + </ul>
> +
> + <!--
> ========================================================================================================
> -->
> + <a id="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.rest.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.rest.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.rest.RestResponse#setOutput(Object)} method.
> + Calling the {@link
> org.apache.juneau.rest.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='doctree'>
> + <li class='jc'>
> + {@link java.io.InputStream}
> + <br>The contents are simply piped to the
> output stream returned by
> + {@link
> org.apache.juneau.rest.RestResponse#getNegotiatedOutputStream()}.
> + <br>Note that you should call {@link
> org.apache.juneau.rest.RestResponse#setContentType(String)} to set
> + the <l>Content-Type</l> header if you use
> this object type.
> + <li class='jc'>
> + {@link java.io.Reader}
> + <br>The contents are simply piped to the
> output stream returned by
> + {@link
> org.apache.juneau.rest.RestResponse#getNegotiatedWriter()}.
> + <br>Note that you should call {@link
> org.apache.juneau.rest.RestResponse#setContentType(String)} to set
> + the <l>Content-Type</l> header if you use
> this object type.
> + <li class='jc'>
> + {@link org.apache.juneau.rest.Redirect}
> + <br>Represents an HTTP redirect response.
> + <li class='jic'>
> + {@link org.apache.juneau.Streamable}
> + <br>Interface that identifies that an
> object can be serialized directly to an output stream.
> + <li class='jic'>
> + {@link org.apache.juneau.Writable}
> + <br>Interface that identifies that an
> object can be serialized directly to a writer.
> + <li class='jc'>
> + {@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.rest.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>
> + Parameters of the following class types:
> + <ul>
> + <li>Request/response objects:
> + <ul>
> + <li>{@link
> org.apache.juneau.rest.RestRequest} - The request object.
> + <li>{@link
> javax.servlet.http.HttpServletRequest} - The superclass of
> <code>RestRequest</code>.
> + <li>{@link
> org.apache.juneau.rest.RestResponse} - The response object.
> + <li>{@link
> javax.servlet.http.HttpServletResponse} - The superclass of
> <code>RestResponse</code>.
> + </ul>
> + <li>Parsed request header values:
> + <ul>
> + <li>{@link
> org.apache.juneau.http.Accept}
> + <li>{@link
> org.apache.juneau.http.AcceptCharset}
> + <li>{@link
> org.apache.juneau.http.AcceptEncoding}
> + <li>{@link
> org.apache.juneau.http.AcceptLanguage}
> + <li>{@link
> org.apache.juneau.http.Authorization}
> + <li>{@link
> org.apache.juneau.http.CacheControl}
> + <li>{@link
> org.apache.juneau.http.Connection}
> + <li>{@link
> org.apache.juneau.http.ContentLength}
> + <li>{@link
> org.apache.juneau.http.ContentType}
> + <li>{@link
> org.apache.juneau.http.Date}
> + <li>{@link
> org.apache.juneau.http.Expect}
> + <li>{@link
> org.apache.juneau.http.From}
> + <li>{@link
> org.apache.juneau.http.Host}
> + <li>{@link
> org.apache.juneau.http.IfMatch}
> + <li>{@link
> org.apache.juneau.http.IfModifiedSince}
> + <li>{@link
> org.apache.juneau.http.IfNoneMatch}
> + <li>{@link
> org.apache.juneau.http.IfRange}
> + <li>{@link
> org.apache.juneau.http.IfUnmodifiedSince}
> + <li>{@link
> org.apache.juneau.http.MaxForwards}
> + <li>{@link
> org.apache.juneau.http.Pragma}
> + <li>{@link
> org.apache.juneau.http.ProxyAuthorization}
> + <li>{@link
> org.apache.juneau.http.Range}
> + <li>{@link
> org.apache.juneau.http.Referer}
> + <li>{@link
> org.apache.juneau.http.TE}
> + <li>{@link
> org.apache.juneau.http.UserAgent}
> + <li>{@link
> org.apache.juneau.http.Upgrade}
> + <li>{@link
> org.apache.juneau.http.Via}
> + <li>{@link
> org.apache.juneau.http.Warning}
> + <li>{@link
> java.util.TimeZone}
> + </ul>
> + <li>Direct streams on
> request/response:
> + <ul>
> + <li>{@link
> java.io.InputStream}
> + <li>{@link
> javax.servlet.ServletInputStream}
> + <li>{@link
> java.io.Reader}
> + <li>{@link
> java.io.OutputStream}
> + <li>{@link
> javax.servlet.ServletOutputStream}
> + <li>{@link
> java.io.Writer}
> + </ul>
> + <li>Localization:
> + <ul>
> + <li>{@link
> java.util.ResourceBundle} - Client-localized resource bundle.
> + <li>{@link
> org.apache.juneau.utils.MessageBundle} - A resource bundle with additional
> features.
> + <li>{@link
> java.util.Locale} - Client locale.
> + </ul>
> + <li>Request APIs:
> + <ul>
> + <li>{@link
> org.apache.juneau.rest.RequestHeaders} - API for accessing request headers.
> + <li>{@link
> org.apache.juneau.rest.RequestQuery} - API for accessing request query
> parameters.
> + <li>{@link
> org.apache.juneau.rest.RequestFormData} - API for accessing request form
> data.
> + <li>{@link
> org.apache.juneau.rest.RequestPathMatch} - API for accessing path variables.
> + <li>{@link
> org.apache.juneau.rest.RequestBody} - API for accessing request body.
> + </ul>
> + <li>Other:
> + <ul>
> + <li>{@link
> org.apache.juneau.http.HttpMethod} - The method name matched (when using
> <code><ja>@RestMethod</ja>(name=<js>"*"</js>)</code>)
> + <li>{@link
> java.util.logging.Logger} - The logger to use for logging.
> + <li>{@link
> org.apache.juneau.internal.JuneauLogger} - Logger with additional features.
> + <li>{@link
> org.apache.juneau.rest.RestContext} - The resource read-only context.
> + <li>{@link
> org.apache.juneau.parser.Parser} - The parser matching the request content
> type.
> + <li>{@link
> org.apache.juneau.dto.swagger.Swagger} - The auto-generated Swagger doc.
> + <li>{@link
> org.apache.juneau.ini.ConfigFile} - The external config file for the
> resource.
> + </ul>
> + </ul>
> + <li>
> + Annotated parameters:
> + <ul>
> + <li>{@link
> org.apache.juneau.rest.annotation.Path @Path} - Variables in matched URL
> path patterns.
> + <li>{@link
> org.apache.juneau.rest.annotation.FormData @FormData} - Multipart form post
> parameter values.
> + <li>{@link
> org.apache.juneau.rest.annotation.HasFormData @HasFormData} - Denotes
> whether the form data parameter exists.
> + <li>{@link
> org.apache.juneau.rest.annotation.Query @Query} - Query parameters. Using
> this prevents the HTTP body from being processed as a URL-Encoded form post.
> + <li>{@link
> org.apache.juneau.rest.annotation.HasQuery @HasQuery} - Denotes whether the
> query parameter exists.
> + <li>{@link
> org.apache.juneau.rest.annotation.Header @Header} - A header value.
> + <li>{@link
> org.apache.juneau.rest.annotation.Method @Method} - The HTTP method name.
> + <li>{@link
> org.apache.juneau.rest.annotation.PathRemainder @PathRemainder} - The
> remainder value after path pattern match.
> + <li>{@link
> org.apache.juneau.rest.annotation.Body @Body} - The HTTP content parsed as
> a POJO.
> + <li>{@link
> org.apache.juneau.rest.annotation.Messages @Messages} - The resource bundle
> for the servlet localized to the language on the request.
> + <li>{@link
> org.apache.juneau.rest.annotation.Properties @Properties} - The
> serializer/parser/servlet properties so they can be read or altered on the
> request.
> + </ul>
> + </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}/*