blob: 0a1894a7908bfd8f907b4b0bb3523a642e8ad168 [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- NewPage -->
<html lang="en">
<head>
<!-- Generated by javadoc -->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Overview (Apache Juneau 9.0.0)</title>
<link rel="stylesheet" type="text/css" href="javadoc.css" title="Style">
<script type="text/javascript" src="script.js"></script>
</head>
<body>
<script type="text/javascript"><!--
try {
if (location.href.indexOf('is-external=true') == -1) {
parent.document.title="Overview (Apache Juneau 9.0.0)";
}
}
catch(err) {
}
//-->
</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="topNav"><a name="navbar.top">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.top.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li class="navBarCell1Rev">Overview</li>
<li>Package</li>
<li>Class</li>
<li><a href="overview-tree.html">Tree</a></li>
<li><a href="deprecated-list.html">Deprecated</a></li>
<li><a href="index-all.html">Index</a></li>
<li><a href="help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?overview-summary.html" target="_top">Frames</a></li>
<li><a href="overview-summary.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_top">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_top");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.top">
<!-- -->
</a></div>
<!-- ========= END OF TOP NAVBAR ========= -->
<div class="header">
<h1 class="title">juneau 9.0.0 API</h1>
</div>
<div class="header">
<div class="subTitle">
<div class="block"><h1 class='title'>Apache Juneau 9.0.0 Documentation</div>
</div>
<p>See: <a href="#overview.description">Description</a></p>
</div>
<div class="contentContainer">
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Packages table, listing packages, and an explanation">
<caption><span>Packages</span><span class="tabEnd">&nbsp;</span></caption>
<tr>
<th class="colFirst" scope="col">Package</th>
<th class="colLast" scope="col">Description</th>
</tr>
<tbody>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/package-summary.html">org.apache.juneau</a></td>
<td class="colLast">
<div class="block">Marshalling API</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/annotation/package-summary.html">org.apache.juneau.annotation</a></td>
<td class="colLast">
<div class="block">Bean and POJO Annotations</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/assertions/package-summary.html">org.apache.juneau.assertions</a></td>
<td class="colLast">
<div class="block">Assertions API</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/collections/package-summary.html">org.apache.juneau.collections</a></td>
<td class="colLast">
<div class="block">Collections classes</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/config/package-summary.html">org.apache.juneau.config</a></td>
<td class="colLast">
<div class="block">Config Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/config/event/package-summary.html">org.apache.juneau.config.event</a></td>
<td class="colLast">
<div class="block">Config Event Support</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/config/internal/package-summary.html">org.apache.juneau.config.internal</a></td>
<td class="colLast">
<div class="block">Internal classes</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/config/mod/package-summary.html">org.apache.juneau.config.mod</a></td>
<td class="colLast">
<div class="block">Config Encoding Support</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/config/store/package-summary.html">org.apache.juneau.config.store</a></td>
<td class="colLast">
<div class="block">Config Storage Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/config/vars/package-summary.html">org.apache.juneau.config.vars</a></td>
<td class="colLast">
<div class="block">Config Predefined SVL Variables</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/cp/package-summary.html">org.apache.juneau.cp</a></td>
<td class="colLast">
<div class="block">Classpath Utilities</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/csv/package-summary.html">org.apache.juneau.csv</a></td>
<td class="colLast">
<div class="block">package-info.java</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/csv/annotation/package-summary.html">org.apache.juneau.csv.annotation</a></td>
<td class="colLast">
<div class="block">CSV Marshalling Annotations</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/dto/package-summary.html">org.apache.juneau.dto</a></td>
<td class="colLast">
<div class="block">Data Transfer Objects</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/dto/atom/package-summary.html">org.apache.juneau.dto.atom</a></td>
<td class="colLast">
<div class="block">ATOM Data Transfer Objects</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/dto/html5/package-summary.html">org.apache.juneau.dto.html5</a></td>
<td class="colLast">
<div class="block">HTML5 Data Transfer Objects</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/dto/jsonschema/package-summary.html">org.apache.juneau.dto.jsonschema</a></td>
<td class="colLast">
<div class="block">JSON-Schema Data Transfer Objects</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/dto/openapi3/package-summary.html">org.apache.juneau.dto.openapi3</a></td>
<td class="colLast">
<div class="block">Swagger Data Transfer Objects</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/dto/swagger/package-summary.html">org.apache.juneau.dto.swagger</a></td>
<td class="colLast">
<div class="block">Swagger Data Transfer Objects</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/dto/swagger/ui/package-summary.html">org.apache.juneau.dto.swagger.ui</a></td>
<td class="colLast">
<div class="block">Swagger UI Generator</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/encoders/package-summary.html">org.apache.juneau.encoders</a></td>
<td class="colLast">
<div class="block">Encoders</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/config/store/package-summary.html">org.apache.juneau.examples.core.config.store</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/dto/package-summary.html">org.apache.juneau.examples.core.dto</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/dto/atom/package-summary.html">org.apache.juneau.examples.core.dto.atom</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/html/package-summary.html">org.apache.juneau.examples.core.html</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/json/package-summary.html">org.apache.juneau.examples.core.json</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/oapi/package-summary.html">org.apache.juneau.examples.core.oapi</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/pojo/package-summary.html">org.apache.juneau.examples.core.pojo</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/rdf/package-summary.html">org.apache.juneau.examples.core.rdf</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/svl/package-summary.html">org.apache.juneau.examples.core.svl</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/uon/package-summary.html">org.apache.juneau.examples.core.uon</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/examples/core/xml/package-summary.html">org.apache.juneau.examples.core.xml</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/examples/parser/package-summary.html">org.apache.juneau.examples.parser</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/examples/rest/package-summary.html">org.apache.juneau.examples.rest</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/examples/rest/command/package-summary.html">org.apache.juneau.examples.rest.command</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/examples/rest/dto/package-summary.html">org.apache.juneau.examples.rest.dto</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/examples/rest/jetty/package-summary.html">org.apache.juneau.examples.rest.jetty</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/examples/rest/springboot/package-summary.html">org.apache.juneau.examples.rest.springboot</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/examples/serializer/package-summary.html">org.apache.juneau.examples.serializer</a></td>
<td class="colLast">
<div class="block">Examples</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/html/package-summary.html">org.apache.juneau.html</a></td>
<td class="colLast">
<div class="block">HTML Marshalling Support</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/html/annotation/package-summary.html">org.apache.juneau.html.annotation</a></td>
<td class="colLast">
<div class="block">HTML Marshalling Annotations</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/http/package-summary.html">org.apache.juneau.http</a></td>
<td class="colLast">
<div class="block">RFC2616 HTTP Headers</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/http/annotation/package-summary.html">org.apache.juneau.http.annotation</a></td>
<td class="colLast">
<div class="block">HTTP Part Annotations</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/http/entity/package-summary.html">org.apache.juneau.http.entity</a></td>
<td class="colLast">
<div class="block">HTTP Entity Beans</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/http/header/package-summary.html">org.apache.juneau.http.header</a></td>
<td class="colLast">
<div class="block">HTTP Header Beans</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/http/part/package-summary.html">org.apache.juneau.http.part</a></td>
<td class="colLast">
<div class="block">HTTP Part Beans</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/http/remote/package-summary.html">org.apache.juneau.http.remote</a></td>
<td class="colLast">
<div class="block">Remote REST API</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/http/resource/package-summary.html">org.apache.juneau.http.resource</a></td>
<td class="colLast">
<div class="block">HTTP Resource Beans</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/http/response/package-summary.html">org.apache.juneau.http.response</a></td>
<td class="colLast">
<div class="block">HTTP Response Exception Beans</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/httppart/package-summary.html">org.apache.juneau.httppart</a></td>
<td class="colLast">
<div class="block">HTTP Part Marshalling Support</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/httppart/bean/package-summary.html">org.apache.juneau.httppart.bean</a></td>
<td class="colLast">
<div class="block">HTTP Part Beans</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/internal/package-summary.html">org.apache.juneau.internal</a></td>
<td class="colLast">
<div class="block">Internal Utilities</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/jena/package-summary.html">org.apache.juneau.jena</a></td>
<td class="colLast">
<div class="block">RDF Marshalling Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/jena/annotation/package-summary.html">org.apache.juneau.jena.annotation</a></td>
<td class="colLast">
<div class="block">RDF Marshalling Annotations</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/json/package-summary.html">org.apache.juneau.json</a></td>
<td class="colLast">
<div class="block">JSON Marshalling Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/json/annotation/package-summary.html">org.apache.juneau.json.annotation</a></td>
<td class="colLast">
<div class="block">JSON Marshalling Annotations</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/jsonschema/package-summary.html">org.apache.juneau.jsonschema</a></td>
<td class="colLast">
<div class="block">JSON-Schema Marshalling Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/jsonschema/annotation/package-summary.html">org.apache.juneau.jsonschema.annotation</a></td>
<td class="colLast">
<div class="block">JSON-Schema Marshalling Annotations</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/marshaller/package-summary.html">org.apache.juneau.marshaller</a></td>
<td class="colLast">
<div class="block">Marshallers</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/microservice/package-summary.html">org.apache.juneau.microservice</a></td>
<td class="colLast">
<div class="block">Microservice API</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/microservice/console/package-summary.html">org.apache.juneau.microservice.console</a></td>
<td class="colLast">
<div class="block">Microservice Console</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/microservice/jetty/package-summary.html">org.apache.juneau.microservice.jetty</a></td>
<td class="colLast">
<div class="block">Microservice API</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/microservice/jetty/resources/package-summary.html">org.apache.juneau.microservice.jetty.resources</a></td>
<td class="colLast">
<div class="block">Predefined Jetty Microservice Resources</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/microservice/jetty/template/package-summary.html">org.apache.juneau.microservice.jetty.template</a></td>
<td class="colLast">
<div class="block">Microservice Samples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/microservice/resources/package-summary.html">org.apache.juneau.microservice.resources</a></td>
<td class="colLast">
<div class="block">Predefined Microservice Resources</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/microservice/springboot/template/package-summary.html">org.apache.juneau.microservice.springboot.template</a></td>
<td class="colLast">
<div class="block">Microservice Samples</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/msgpack/package-summary.html">org.apache.juneau.msgpack</a></td>
<td class="colLast">
<div class="block">MessagePack Marshalling Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/msgpack/annotation/package-summary.html">org.apache.juneau.msgpack.annotation</a></td>
<td class="colLast">
<div class="block">MessagePack Marshalling Annotations</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/oapi/package-summary.html">org.apache.juneau.oapi</a></td>
<td class="colLast">
<div class="block">OpenAPI Marshalling Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/oapi/annotation/package-summary.html">org.apache.juneau.oapi.annotation</a></td>
<td class="colLast">
<div class="block">OpenAPI Marshalling Annotations</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/objecttools/package-summary.html">org.apache.juneau.objecttools</a></td>
<td class="colLast">
<div class="block">Java Object Tools</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/parser/package-summary.html">org.apache.juneau.parser</a></td>
<td class="colLast">
<div class="block">Parser API</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/parser/annotation/package-summary.html">org.apache.juneau.parser.annotation</a></td>
<td class="colLast">
<div class="block">Parser Annotations</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/plaintext/package-summary.html">org.apache.juneau.plaintext</a></td>
<td class="colLast">
<div class="block">Plaintext Marshalling Support</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/plaintext/annotation/package-summary.html">org.apache.juneau.plaintext.annotation</a></td>
<td class="colLast">
<div class="block">Plaintext Marshalling Annotations</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/reflect/package-summary.html">org.apache.juneau.reflect</a></td>
<td class="colLast">
<div class="block">Reflection API</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/package-summary.html">org.apache.juneau.rest</a></td>
<td class="colLast">
<div class="block">REST Server API</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/annotation/package-summary.html">org.apache.juneau.rest.annotation</a></td>
<td class="colLast">
<div class="block">REST Annotations</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/arg/package-summary.html">org.apache.juneau.rest.arg</a></td>
<td class="colLast">
<div class="block">REST Method Argument Beans</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/assertions/package-summary.html">org.apache.juneau.rest.assertions</a></td>
<td class="colLast">
<div class="block">REST Assertions</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/beans/package-summary.html">org.apache.juneau.rest.beans</a></td>
<td class="colLast">
<div class="block">REST Interface Helper Classes</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/client/package-summary.html">org.apache.juneau.rest.client</a></td>
<td class="colLast">
<div class="block">REST Client API</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/client/assertion/package-summary.html">org.apache.juneau.rest.client.assertion</a></td>
<td class="colLast">
<div class="block">REST Client Assertions</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/client/remote/package-summary.html">org.apache.juneau.rest.client.remote</a></td>
<td class="colLast">
<div class="block">Remote REST API</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/config/package-summary.html">org.apache.juneau.rest.config</a></td>
<td class="colLast">
<div class="block">Predefined REST configuration interfaces</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/converter/package-summary.html">org.apache.juneau.rest.converter</a></td>
<td class="colLast">
<div class="block">REST Response Converters</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/debug/package-summary.html">org.apache.juneau.rest.debug</a></td>
<td class="colLast">
<div class="block">REST Debug APIs</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/guard/package-summary.html">org.apache.juneau.rest.guard</a></td>
<td class="colLast">
<div class="block">REST Guards</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/httppart/package-summary.html">org.apache.juneau.rest.httppart</a></td>
<td class="colLast">
<div class="block">REST HTTP Parts</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/jaxrs/package-summary.html">org.apache.juneau.rest.jaxrs</a></td>
<td class="colLast">
<div class="block">JAX-RS Integration</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/logger/package-summary.html">org.apache.juneau.rest.logger</a></td>
<td class="colLast">
<div class="block">REST Logging API</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/matcher/package-summary.html">org.apache.juneau.rest.matcher</a></td>
<td class="colLast">
<div class="block">Predefined Matchers</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/mock/package-summary.html">org.apache.juneau.rest.mock</a></td>
<td class="colLast">
<div class="block">REST Server Mock API</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/processor/package-summary.html">org.apache.juneau.rest.processor</a></td>
<td class="colLast">
<div class="block">HTTP Response Processors</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/remote/package-summary.html">org.apache.juneau.rest.remote</a></td>
<td class="colLast">
<div class="block">Remote service API</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/rrpc/package-summary.html">org.apache.juneau.rest.rrpc</a></td>
<td class="colLast">
<div class="block">REST Remote Procedure Call API</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/servlet/package-summary.html">org.apache.juneau.rest.servlet</a></td>
<td class="colLast">
<div class="block">REST Servlets</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/springboot/package-summary.html">org.apache.juneau.rest.springboot</a></td>
<td class="colLast">
<div class="block">Spring Boot Integration</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/staticfile/package-summary.html">org.apache.juneau.rest.staticfile</a></td>
<td class="colLast">
<div class="block">REST Static Files Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/stats/package-summary.html">org.apache.juneau.rest.stats</a></td>
<td class="colLast">
<div class="block">Method exec stats utilities</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/swagger/package-summary.html">org.apache.juneau.rest.swagger</a></td>
<td class="colLast">
<div class="block">REST Swagger Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/util/package-summary.html">org.apache.juneau.rest.util</a></td>
<td class="colLast">
<div class="block">REST Server Utilities</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/rest/vars/package-summary.html">org.apache.juneau.rest.vars</a></td>
<td class="colLast">
<div class="block">Predefined SVL Variables</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/rest/widget/package-summary.html">org.apache.juneau.rest.widget</a></td>
<td class="colLast">
<div class="block">HTML Widget API</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/serializer/package-summary.html">org.apache.juneau.serializer</a></td>
<td class="colLast">
<div class="block">Serializer API</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/serializer/annotation/package-summary.html">org.apache.juneau.serializer.annotation</a></td>
<td class="colLast">
<div class="block">Serializer Annotations</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/server/config/package-summary.html">org.apache.juneau.server.config</a></td>
<td class="colLast">
<div class="block">Server Config Repository</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/server/config/repository/package-summary.html">org.apache.juneau.server.config.repository</a></td>
<td class="colLast">
<div class="block">Server Config Application</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/server/config/rest/package-summary.html">org.apache.juneau.server.config.rest</a></td>
<td class="colLast">
<div class="block">Server Config REST</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/soap/package-summary.html">org.apache.juneau.soap</a></td>
<td class="colLast">
<div class="block">SOAP/XML Marshalling Support</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/soap/annotation/package-summary.html">org.apache.juneau.soap.annotation</a></td>
<td class="colLast">
<div class="block">SOAP/XML Marshalling Annotations</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/svl/package-summary.html">org.apache.juneau.svl</a></td>
<td class="colLast">
<div class="block">Simple Variable Language</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/svl/vars/package-summary.html">org.apache.juneau.svl.vars</a></td>
<td class="colLast">
<div class="block">Predefined SVL Variables</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/swap/package-summary.html">org.apache.juneau.swap</a></td>
<td class="colLast">
<div class="block">Swap API</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/swaps/package-summary.html">org.apache.juneau.swaps</a></td>
<td class="colLast">
<div class="block">Predefined Swaps</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/uon/package-summary.html">org.apache.juneau.uon</a></td>
<td class="colLast">
<div class="block">UON Marshalling Support</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/uon/annotation/package-summary.html">org.apache.juneau.uon.annotation</a></td>
<td class="colLast">
<div class="block">UON Marshalling Annotations</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/urlencoding/package-summary.html">org.apache.juneau.urlencoding</a></td>
<td class="colLast">
<div class="block">URL-Encoding Marshalling Support</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/urlencoding/annotation/package-summary.html">org.apache.juneau.urlencoding.annotation</a></td>
<td class="colLast">
<div class="block">URL-Encoding Marshalling Annotations</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/utils/package-summary.html">org.apache.juneau.utils</a></td>
<td class="colLast">
<div class="block">URL-Encoding Annotations</div>
</td>
</tr>
<tr class="altColor">
<td class="colFirst"><a href="org/apache/juneau/xml/package-summary.html">org.apache.juneau.xml</a></td>
<td class="colLast">
<div class="block">XML Marshalling Support</div>
</td>
</tr>
<tr class="rowColor">
<td class="colFirst"><a href="org/apache/juneau/xml/annotation/package-summary.html">org.apache.juneau.xml.annotation</a></td>
<td class="colLast">
<div class="block">XML Marshalling Annotations</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="contentContainer"><a name="overview.description">
<!-- -->
</a>
<div class="block"><h1 class='title'>Apache Juneau 9.0.0 Documentation</h1>
<script type='text/javascript'>
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>
<a href='#TOC' id='TOC'></a><h5 class='toc'>Table of Contents</h5>
<ol class='toc'>
<li><p class='toc2'><a class='doclink' href='#Overview'>Overview</a></p>
<ol>
<li><p><a class='doclink' href='#Overview.o.Marshalling'>Marshalling</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#Overview.o.EndToEndRest'>End-to-End REST</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#Overview.o.RestServer'>REST Server</a></p>
<li><p><a class='doclink' href='#Overview.o.RestClient'>REST Client</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#Overview.o.Dtos'>DTOs</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#Overview.o.ConfigFiles'>Config Files</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#Overview.o.FluentAssertions'>Fluent Assertions</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#Overview.o.GeneralDesign'>General Design</a><span class='update'>created: <b>9.0.0</b></span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-marshall'>juneau-marshall</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.Marshallers'>Marshallers</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.SerializersAndParsers'>Serializers and Parsers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.BeanContexts'>Bean Contexts</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport'>Java Beans Support</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport.jm.BeanAnnotation'>@Bean Annotation</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport.jm.BeanpAnnotation'>@Beanp Annotation</a><span class='update'>updated: 8.1.0,8.1.2,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport.jm.BeancAnnotation'>@Beanc Annotation</a><span class='update'>updated: 8.1.0,8.1.2</span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport.jm.BeanIgnoreAnnotation'>@BeanIgnore Annotation</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport.jm.NamePropertyAnnotation'>@NameProperty Annotation</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport.jm.ParentPropertyAnnotation'>@ParentProperty Annotation</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport.jm.PojoBuilders'>POJO Builders</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport.jm.BypassSerialization'>Bypass Serialization using Readers and InputStreams</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.HttpPartSerializersParsers'>HTTP Part Serializers and Parsers</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.ContextSettings'>Context Settings</a><span class='update'>updated: 8.1.3,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.ContextAnnotations'>Context Annotations</a><span class='update'>created: 8.1.0, updated: 8.1.3,8.2.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JsonMap'>JsonMap and JsonList</a><span class='update'>updated: 8.2.0</span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.ComplexDataTypes'>Complex Data Types</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.SerializerSetsParserSets'>SerializerSets and ParserSets</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.Swaps'>Swaps</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.Swaps.jm.DefaultSwaps'>Default Swaps</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.Swaps.jm.AutoSwaps'>Auto-detected swaps</a><span class='update'>created: 8.1.0</span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.Swaps.jm.PerMediaTypeSwaps'>Per-media-type Swaps</a><span class='update'>updated: 8.1.0,8.2.0</span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.Swaps.jm.OneWaySwaps'>One-way Swaps</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.Swaps.jm.SwapAnnotation'>@Swap Annotation</a><span class='update'>updated: 8.0.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.Swaps.jm.TemplatedSwaps'>Templated Swaps</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.Swaps.jm.SurrogateClasses'>Surrogate Classes</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.DynamicallyAppliedAnnotations'>Dynamically Applied Annotations</a><span class='update'>created: 8.1.3, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.BeanDictionaries'>Bean Names and Dictionaries</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.BeanDictionaries.jm.BeanSubTypes'>Bean Subtypes</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.VirtualBeans'>Virtual Beans</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.Recursion'>Non-Tree Models and Recursion Detection</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.ParsingIntoGenericModels'>Parsing into Generic Models</a><span class='update'>updated: 8.2.0</span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.ReadingContinuousStreams'>Reading Continuous Streams</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.MarshallingUris'>URIs</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JacksonComparison'>Comparison with Jackson</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.PojoCategories'>POJO Categories</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.SimpleVariableLanguage'>Simple Variable Language</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.SimpleVariableLanguage.jm.SvlVariables'>SVL Variables</a><span class='update'>updated: 8.0.0,8.1.0</span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.SimpleVariableLanguage.jm.VarResolvers'>VarResolvers and VarResolverSessions</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.SimpleVariableLanguage.jm.DefaultVarResolver'>VarResolver.DEFAULT</a><span class='update'>created: 8.1.0</span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.SimpleVariableLanguage.jm.SvlOtherNotes'>Other Notes</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.Encoders'>Encoders</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.ObjectTools'>Object Tools</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JsonDetails'>JSON Details</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.JsonDetails.jm.JsonMethodology'>JSON Methodology</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JsonDetails.jm.JsonSerializers'>JSON Serializers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JsonDetails.jm.SimplifiedJson'>Simplified JSON</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JsonDetails.jm.JsonParsers'>JSON Parsers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.JsonDetails.jm.JsonAnnotation'>@Json Annotation</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.JsonSchemaDetails'>JSON-Schema Support</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.XmlDetails'>XML Details</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.XmlDetails.jm.XmlMethodology'>XML Methodology</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.XmlDetails.jm.XmlSerializers'>XML Serializers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.XmlDetails.jm.XmlParsers'>XML Parsers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.XmlDetails.jm.XmlBeanTypeNameAnnotation'>@Bean(typeName) Annotation</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.XmlDetails.jm.XmlChildNameAnnotation'>@Xml(childName) Annotation</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.XmlDetails.jm.XmlFormatAnnotation'>@Xml(format) Annotation</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.XmlDetails.jm.XmlNamespaces'>Namespaces</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlDetails'>HTML Details</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlDetails.jm.HtmlMethodology'>HTML Methodology</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlDetails.jm.HtmlSerializers'>HTML Serializers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlDetails.jm.HtmlParsers'>HTML Parsers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlDetails.jm.HtmlAnnotation'>@Html Annotation</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlDetails.jm.HtmlRenderAnnotation'>@Html(render) Annotation</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlDetails.jm.HtmlDocSerializer'>HtmlDocSerializer</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlDetails.jm.BasicHtmlDocTemplate'>BasicHtmlDocTemplate</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlDetails.jm.HtmlCustomTemplates'>Custom Templates</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.HtmlSchema'>HTML-Schema Support</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.UonDetails'>UON Details</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.UonDetails.jm.UonMethodology'>UON Methodology</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.UonDetails.jm.UonSerializers'>UON Serializers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.UonDetails.jm.UonParsers'>UON Parsers</a><span class='update'>updated: <b>9.0.0</b></span></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.UrlEncodingDetails'>URL-Encoding Details</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncMethodology'>URL-Encoding Methodology</a></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncSerializers'>URL-Encoding Serializers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncParsers'>URL-Encoding Parsers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncodingAnnotation'>@UrlEncoding Annotation</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.MsgPackDetails'>MessagePack Details</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.MsgPackDetails.jm.MsgPackSerializers'>MessagePack Serializers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.MsgPackDetails.jm.MsgPackParsers'>MessagePack Parsers</a><span class='update'>updated: <b>9.0.0</b></span></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails'>OpenAPI Details</a><span class='update'>updated: 8.2.0</span></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiMethodology'>OpenAPI Methodology</a><span class='update'>updated: 8.2.0</span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers'>OpenAPI Serializers</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiParsers'>OpenAPI Parsers</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></p>
</ol>
<li><p><a class='doclink' href='#juneau-marshall.jm.BestPractices'>Best Practices</a></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-marshall-rdf'>juneau-marshall-rdf</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall-rdf.jmr.RdfDetails'>RDF Details</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.Serializers'>RDF Serializers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.Parsers'>RDF Parsers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.RdfAnnotation'>@Rdf Annotation</a></p>
<li><p><a class='doclink' href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.Namespaces'>Namespaces</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.UriProperties'>URI Properties</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.RootProperty'>Root Property</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.TypedLiterals'>Typed Literals</a><span class='update'>updated: <b>9.0.0</b></span></p>
</ol>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-dto'>juneau-dto</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-dto.jd.Html5'>HTML5</a></p>
<li><p><a class='doclink' href='#juneau-dto.jd.Atom'>Atom</a></p>
<li><p><a class='doclink' href='#juneau-dto.jd.Swagger'>Swagger</a></p>
<li><p><a class='doclink' href='#juneau-dto.jd.SwaggerUi'>Swagger UI</a></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-config'>juneau-config</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-config.jc.Overview'>Overview</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-config.jc.Overview.jc.SyntaxRules'>Syntax Rules</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-config.jc.ReadingEntries'>Reading Entries</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-config.jc.ReadingEntries.jc.Pojos'>POJOs</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-config.jc.ReadingEntries.jc.Arrays'>Arrays</a></p>
<li><p><a class='doclink' href='#juneau-config.jc.ReadingEntries.jc.JCFObjects'>Java Collection Framework Objects</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-config.jc.ReadingEntries.jc.BinaryData'>Binary Data</a><span class='update'>updated: <b>9.0.0</b></span></p>
</ol>
<li><p><a class='doclink' href='#juneau-config.jc.Variables'>Variables</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-config.jc.Variables.jc.LogicVariables'>Logic Variables</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-config.jc.ModdedEntries'>Modded/Encoded Entries</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-config.jc.Sections'>Sections</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-config.jc.SettingValues'>Setting Values</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-config.jc.SettingValues.jc.FileSystemChanges'>File System Changes</a></p>
<li><p><a class='doclink' href='#juneau-config.jc.SettingValues.jc.CustomEntrySerialization'>Custom Entry Serialization</a></p>
<li><p><a class='doclink' href='#juneau-config.jc.SettingValues.jc.BulkSettingValues'>Setting Values in Bulk</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-config.jc.Listeners'>Listeners</a></p>
<li><p><a class='doclink' href='#juneau-config.jc.SerializingConfigs'>Serializing</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-config.jc.ConfigImports'>Imports</a><span class='update'>updated: 8.1.0</span></p>
<li><p><a class='doclink' href='#juneau-config.jc.ConfigStores'>Config Stores</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-config.jc.ConfigStores.jc.MemoryStore'>MemoryStore</a></p>
<li><p><a class='doclink' href='#juneau-config.jc.ConfigStores.jc.FileStore'>FileStore</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-config.jc.ConfigStores.jc.CustomStores'>Custom ConfigStores</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-config.jc.ConfigStores.jc.StoreListeners'>ConfigStore Listeners</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-config.jc.ReadOnlyConfigs'>Read-only Configs</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-config.jc.ClosingConfigs'>Closing Configs</a></p>
<li><p><a class='doclink' href='#juneau-config.jc.SystemDefaultConfig'>System Default Config</a><span class='update'>created: 8.0.0, updated: 8.1.0</span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-assertions'>juneau-assertions</a><span class='update'>created: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-assertions.ja.Overview'>Overview</a><span class='update'>created: <b>9.0.0</b></span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-rest-common'>juneau-rest-common</a><span class='update'>created: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-common.jrc.org.apache.juneau.http'>org.apache.juneau.http</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-common.jrc.org.apache.juneau.http.annotation'>org.apache.juneau.http.annotation</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-common.jrc.org.apache.juneau.http.header'>org.apache.juneau.http.header</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-common.jrc.org.apache.juneau.http.part'>org.apache.juneau.http.part</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-common.jrc.org.apache.juneau.http.entity'>org.apache.juneau.http.entity</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-common.jrc.org.apache.juneau.http.resource'>org.apache.juneau.http.resource</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-common.jrc.org.apache.juneau.http.response'>org.apache.juneau.http.response</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-common.jrc.org.apache.juneau.http.remote'>org.apache.juneau.http.remote</a><span class='update'>created: <b>9.0.0</b></span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-rest-server'>juneau-rest-server</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Overview'>Overview</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.AnnotatedClasses'>@Rest-Annotated Classes</a><span class='update'>updated: 8.1.2,<b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.PredefinedClasses'>Predefined Classes</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.ChildResources'>Child Resources</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.PathVariables'>Path Variables</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.Deployment'>Deployment</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.LifecycleHooks'>Lifecycle Hooks</a><span class='update'>updated: <b>9.0.0</b></span></p>
</ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods'>@RestOp-Annotated Methods</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.InferredHttpMethodsAndPaths'>Inferred HTTP Methods and Paths</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodParameters'>Java Method Parameters</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodReturnTypes'>Java Method Return Types</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodThrowableTypes'>Java Method Throwable Types</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.PathPatterns'>Path Patterns</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.Matchers'>Matchers</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.OverloadingHttpMethods'>Overloading HTTP Methods</a></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.AdditionalInformation'>Additional Information</a><span class='update'>updated: <b>9.0.0</b></span></p>
</ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HttpParts'>HTTP Parts</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HttpParts.jrs.PartMarshallers'>Part Marshallers</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HttpParts.jrs.HttpPartAnnotations'>HTTP Part Annotations</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HttpParts.jrs.DefaultParts'>Default Parts</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HttpParts.jrs.RequestBeans'>@Request Beans</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HttpParts.jrs.ResponseBeans'>@Response Beans</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HttpParts.jrs.HttpPartApis'>HTTP Part APIs</a><span class='update'>created: <b>9.0.0</b></span></p>
</ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Marshalling'>Marshalling</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HandlingFormPosts'>Form Posts</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Guards'>Guards</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Converters'>Converters</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.LocalizedMessages'>Localized Messages</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Encoders'>Encoders</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.ConfigurationFiles'>Configuration Files</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.SvlVariables'>SVL Variables</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.StaticFiles'>Static files</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.ClientVersioning'>Client Versioning</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Swagger'>Swagger</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger'>BasicRestServlet/BasicRestObject</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo'>Basic Swagger Info</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerTags'>Tags</a></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations'>Operations</a></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters'>Parameters</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses'>Responses</a></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerModels'>Models</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet'>SwaggerUI.css</a></p>
</ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.ExecutionStatistics'>REST method execution statistics</a><span class='update'>created: 8.1.3, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HtmlDocAnnotation'>@HtmlDocConfig</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI'>User Interfaces (UI) vs. Developer Interfaces (DI)</a></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets'>Widgets</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets'>Predefined Widgets</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization'>UI Customization</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets'>Stylesheets</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></p>
</ol>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.LoggingAndDebugging'>Logging / Debugging</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HttpStatusCodes'>HTTP Status Codes</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.BuiltInParameters'>Built-in Parameters</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.UsingWithOsgi'>Using with OSGi</a></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestContext'>RestContext</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestOpContext'>RestOpContext</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.ResponseProcessors'>Response Processors</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.RestRpc'>REST/RPC</a><span class='update'>updated: 8.0.0,<b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.SerializingUris'>Serializing URIs</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.UtilityBeans'>Utility Beans</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.HtmlBeans'>Using with HTML Beans</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-server.jrs.OtherNotes'>Other Notes</a></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-rest-server-rdf'>juneau-rest-server-rdf</a></p>
<li><p class='toc2'><a class='doclink' href='#juneau-rest-server-jaxrs'>juneau-rest-server-jaxrs</a></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-server-jaxrs.jrsj.BaseProvider'>Juneau JAX-RS Provider</a></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-rest-server-springboot'>juneau-rest-server-springboot</a><span class='update'>created: 8.0.0, updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-server-springboot.jrss.Overview'>Overview</a><span class='update'>created: 8.0.0, updated: <b>9.0.0</b></span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-rest-client'>juneau-rest-client</a><span class='update'>updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.PojoMarshalling'>POJO Marshalling</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.RequestParts'>Request Parts</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.RequestContent'>Request Content</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.ResponseStatus'>Response Status</a><span class='update'>created: 8.1.0, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.ResponseHeaders'>Response Headers</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.ResponseContent'>Response Content</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.CustomCallHandlers'>Custom Call Handlers</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Interceptors'>Interceptors</a><span class='update'>created: 8.2.0</span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies'>REST Proxies</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.Remote'>@Remote</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.RemoteMethod'>@RemoteOp</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.Content'>@Content</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.FormData'>@FormData</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.Query'>@Query</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.Header'>@Header</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.Path'>@Path</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.Request'>@Request</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.Response'>@Response</a><span class='update'>updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Proxies.jrc.DualPurposeInterfaces'>Dual-purpose (end-to-end) interfaces</a><span class='update'>created: 8.0.0</span></p>
</ol>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.LoggingAndDebugging'>Logging and Debugging</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.CustomizingHttpClient'>Customizing HttpClient</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.ExtendingRestClient'>Extending RestClient</a><span class='update'>created: 8.2.0</span></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Authentication'>Authentication</a><span class='update'>updated: 8.2.0</span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Authentication.jrc.AuthenticationBASIC'>BASIC Authentication</a></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Authentication.jrc.AuthenticationForm'>FORM-based Authentication</a></p>
<li><p><a class='doclink' href='#juneau-rest-client.jrc.Authentication.jrc.AuthenticationOIDC'>OIDC Authentication</a></p>
</ol>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-rest-mock'>juneau-rest-mock</a><span class='update'>created: 8.1.0, updated: 8.2.0</span></p>
<ol>
<li><p><a class='doclink' href='#juneau-rest-mock.jrm.MockRestClient'>MockRestClient</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-microservice-core'>juneau-microservice-core</a><span class='update'>created: 8.1.0</span></p>
<ol>
<li><p><a class='doclink' href='#juneau-microservice-core.jmc.Overview'>Microservice Overview</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-core.jmc.LifecycleMethods'>Lifecycle Methods</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-core.jmc.Args'>Args</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-core.jmc.Manifest'>Manifest</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-core.jmc.Config'>Config</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-core.jmc.SystemProperties'>System properties</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-core.jmc.VarResolver'>VarResolver</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-core.jmc.ConsoleCommands'>Console Commands</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-core.jmc.Listeners'>Listeners</a><span class='update'>created: 8.0.0</span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-microservice-jetty'>juneau-microservice-jetty</a><span class='update'>created: 8.1.0</span></p>
<ol>
<li><p><a class='doclink' href='#juneau-microservice-jetty.jmj.Overview'>Overview</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-jetty.jmj.LifecycleMethods'>Lifecycle Methods</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-jetty.jmj.ResourceClasses'>Resource Classes</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-jetty.jmj.PredefinedResourceClasses'>Predefined Resource Classes</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-jetty.jmj.Config'>Config</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-jetty.jmj.JettyXml'>Jetty.xml file</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-jetty.jmj.UiCustomization'>UI Customization</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#juneau-microservice-jetty.jmj.Extending'>Extending JettyMicroservice</a><span class='update'>created: 8.0.0</span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#my-jetty-microservice'>my-jetty-microservice</a><span class='update'>created: 8.1.0</span></p>
<ol>
<li><p><a class='doclink' href='#my-jetty-microservice.mjm.Installing'>Installing in Eclipse</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#my-jetty-microservice.mjm.Running'>Running in Eclipse</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#my-jetty-microservice.mjm.Building'>Building and Running from Command-Line</a><span class='update'>created: 8.0.0</span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#my-springboot-microservice'>my-springboot-microservice</a><span class='update'>created: 8.0.0</span></p>
<ol>
<li><p><a class='doclink' href='#my-springboot-microservice.msm.Installing'>Installing in Eclipse</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#my-springboot-microservice.msm.Running'>Running in Eclipse</a><span class='update'>created: 8.0.0</span></p>
<li><p><a class='doclink' href='#my-springboot-microservice.msm.Building'>Building and Running from Command-Line</a><span class='update'>created: 8.0.0</span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#juneau-petstore'>juneau-petstore</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></p>
<ol>
<li><p><a class='doclink' href='#juneau-petstore.jp.RunningTheApp'>Running the Pet Store App</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-petstore.jp.juneau-petstore-api'>juneau-petstore-api</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-petstore.jp.juneau-petstore-client'>juneau-petstore-client</a><span class='update'>created: <b>9.0.0</b></span></p>
<li><p><a class='doclink' href='#juneau-petstore.jp.juneau-petstore-server'>juneau-petstore-server</a><span class='update'>created: <b>9.0.0</b></span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#Glossaries'>Glossaries</a><span class='update'>created: 8.1.3</span></p>
<ol>
<li><p><a class='doclink' href='#Glossaries.g.LanguageSupport'>Language Support</a><span class='update'>created: 8.1.3</span></p>
<li><p><a class='doclink' href='#Glossaries.g.Annotations'>Annotations</a><span class='update'>created: 8.1.3</span></p>
</ol>
<li><p class='toc2'><a class='doclink' href='#Security'>Security Best-Practices</a></p>
<ol>
<li><p><a class='doclink' href='#Security.s.Marshall'>juneau-marshall</a><span class='update'>created: 8.2.0</span></p>
<li><p><a class='doclink' href='#Security.s.Svl'>juneau-svl</a><span class='update'>created: 8.2.0</span></p>
<li><p><a class='doclink' href='#Security.s.Rest'>juneau-rest-server</a><span class='update'>created: 8.2.0</span></p>
</ol>
</ol>
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#Overview' id='Overview'>1 - Overview</a></h2>
<div class='topic'><!-- START: 1 - Overview -->
<h5 class='topic'>About</h5>
<div class='topic'>
<p>
Apache Juneauâ„¢ is a single cohesive Java ecosystem for marshalling Java objects to a wide variety of
language types and creating annotation-based REST end-to-end server and client APIs. The modules
have as few prereqs as possible making them ideal for usage in uber-jars. All modules work with
Java 8 through 18.
</p>
<p>
The Juneau ecosystem consists of the following parts:
</p>
<table class='styled w800'>
<tr>
<th>Category</th><th>Maven Artifacts</th><th>Description</th><th>Prereqs</th>
</tr>
<tr class='dark bb'>
<td rowspan="5" style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-core</td>
<td class='code'><a class='doclink' href='#juneau-marshall'>juneau-marshall</a></td>
<td>
<ul>
<li>Serializers and parsers for JSON (various flavors), XML, HTML, URL-Encoding, UON, OpenAPI, PlainText, CSV, SOAP, and MessagePack.</li>
</ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Apache HttpCore 4.4</li>
</ul>
</td>
</tr>
<tr class='dark bb'>
<td class='code'><a class='doclink' href='#juneau-marshall-rdf'>juneau-marshall-rdf</a></td>
<td>
<ul>
<li>Serializers and parsers for RDF/XML (various flavors), N3, NTriple, and Turtle.
<ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Apache HttpCore 4.4</li>
<li>Apache Jena 2.7.1</li>
</ul>
</td>
</tr>
<tr class='dark bb'>
<td class='code'><a class='doclink' href='#juneau-dto'>juneau-dto</a></td>
<td>
<ul>
<li>Data Transfer Objects for HTML5, Atom, Cognos, JSON-Schema, and Swagger
</ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li><i>None</i></li>
</ul>
</td>
</tr>
<tr class='dark bb'>
<td class='code'><a class='doclink' href='#juneau-config'>juneau-config</a></td>
<td>
<ul>
<li>Configuration File API</li>
</ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li><i>None</i></li>
</ul>
</td>
</tr>
<tr class='dark bb'>
<td class='code'><a class='doclink' href='#juneau-assertions'>juneau-assertions</a></td>
<td>
<ul>
<li>Fluent-style assertions API</li>
</ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li><i>None</i></li>
</ul>
</td>
</tr>
<tr class='light bb'>
<td rowspan="7" style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-rest</td>
<td class='code'><a class='doclink' href='#juneau-rest-server'>juneau-rest-common</a></td>
<td>
<ul>
<li>REST APIs common to client and server side.</li>
<ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Apache HttpCore 4.4</li>
</ul>
</td>
</tr>
<tr class='light bb'>
<td class='code'><a class='doclink' href='#juneau-rest-server'>juneau-rest-server</a></td>
<td>
<ul>
<li>REST Servlet API
<ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Servlet 3.1+</li>
</ul>
</td>
</tr>
<tr class='light bb'>
<td class='code'><a class='doclink' href='#juneau-rest-server-springboot'>juneau-rest-server-springboot</a></td>
<td>
<ul>
<li>REST Spring Boot integration
<ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Spring Boot 2.0+</li>
</ul>
</td>
</tr>
<tr class='light bb'>
<td class='code'><a class='doclink' href='#juneau-rest-server-jaxrs'>juneau-rest-server-jaxrs</a></td>
<td>
<ul>
<li>REST JAX-RS integration
<ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>JAX-RS 2+</li>
</ul>
</td>
</tr>
<tr class='light bb'>
<td class='code'><a class='doclink' href='#juneau-rest-client'>juneau-rest-client</a></td>
<td>
<ul>
<li>REST Client API
<ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Apache HttpClient 4.5</li>
</ul>
</td>
</tr>
<tr class='light bb'>
<td class='code'><a class='doclink' href='#juneau-rest-client'>juneau-rest-mock</a></td>
<td>
<ul>
<li>REST Testing API</li>
<ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Apache HttpClient 4.5</li>
</ul>
</td>
</tr>
<tr class='light bb'>
<td class='code'><a class='doclink' href='#my-springboot-microservice'>my-springboot-microservice</a></td>
<td>
<ul>
<li>Spring Boot developer template</li>
<ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Spring Boot 2.0+</li>
</ul>
</td>
</tr>
<tr class='dark bb'>
<td rowspan="2" style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-examples</td>
<td class='code'>juneau-examples-core</td>
<td>
<ul>
<li>Core code examples</li>
<ul>
</td>
<td></td>
</tr>
<tr class='dark bb'>
<td class='code'>juneau-examples-rest</td>
<td>
<ul>
<li>REST code examples</li>
<ul>
</td>
<td></td>
</tr>
<tr class='light bb'>
<td rowspan="1" style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-all</td>
<td class='code'><c>juneau-all</c></td>
<td>
Combination of the following:
<ul style='margin:0px 10px;'>
<li>juneau-marshall
<li>juneau-dto
<li>juneau-config
<li>juneau-assertions
<li>juneau-rest-common
<li>juneau-rest-server
<li>juneau-rest-client
</ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Servlet 3.1+
<li>Apache HttpClient 4.5+
</ul>
</td>
</tr>
</table>
<p>
The current version of Juneau is <c>9.0.0</c>.
The easiest way to pull in the library is through the following maven dependency:
</p>
<p class='bxml'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-all<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<p>
If you would like to work with the bleeding-edge code, you can access the <c>9.0.1</c>
version through the following repository:
</p>
<p class='bxml'>
<xt>&lt;pluginRepositories&gt;
&lt;pluginRepository&gt;
&lt;id&gt;<xv>apache.snapshots</xv>&lt;/id&gt;
&lt;url&gt;<xv>http://repository.apache.org/snapshots/</xv>&lt;/url&gt;
&lt;snapshots&gt;
&lt;enabled&gt;<xv>true</xv>&lt;/enabled&gt;
&lt;updatePolicy&gt;<xv>always</xv>&lt;/updatePolicy&gt;
&lt;/snapshots&gt;
&lt;/pluginRepository&gt;
&lt;/pluginRepositories&gt;</xt>
</p>
<p>
Each of the components are also packaged as stand-alone OSGi modules.
</p>
</div>
<h5 class='topic'>Features</h5>
<div class='topic'>
<ul class='spaced-list'>
<li>
Fast memory-efficient serialization.
<li>
Fast, safe, memory-efficient parsing. Parsers are not susceptible to deserialization attacks.
<li>
KISS is our mantra! No auto-wiring. No code generation. No dependency injection. Just add it to your classpath and use it. Extremely simple unit testing!
<li>
Enjoyable to use
<li>
Tiny - ~1MB
<li>
Exhaustively tested
<li>
Lots of up-to-date documentation and examples
<li>
Minimal library dependencies making it ideal for use in uber-jars.
<li>
Built on top of Servlet and Apache HttpClient APIs that allow you to use the newest HTTP/2 features
such as request/response multiplexing and server push.
</ul>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Overview.o.Marshalling' id='Overview.o.Marshalling'>1.1 - Marshalling</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 1.1 - Overview.o.Marshalling -->
<div class='topic'>
<p>
The <a class='doclink' href='#juneau-marshall'>juneau-marshall</a> and <a class='doclink' href='#juneau-marshall-rdf'>juneau-marshall-rdf</a> libraries includes easy-to-use and highly customizable serializers and parsers based around
a common API. It allows you to marshall Java POJOs directly to and from a wide variety of language types
without the need for intermediate Document Object Models making them extremely efficient.
</p>
<p>
Supported languages include:
<ul>
<li>JSON
<li>XML
<li>HTML
<li>UON
<li>URL-Encoding
<li>MessagePack
<li>OpenAPI
<li>SOAP/XML
<li>CSV
<li>YAML (coming soon)
<li>RDF/XML
<li>RDF/XML-Abbrev
<li>N-Triple
<li>Turtle
<li>N3
</ul>
</p>
<ul>
<li class='note'>
The marshalling support can be thought of as similar to Jackson except for support of a wide variety of languages.
Additionally, JSON marshalling is about 20% faster than Jackson yet supports the same usecases.
</ul>
<p>
The default serializers can often be used to serialize POJOs in a single line of code:
</p>
<p class='bjava'>
<jc>// A simple bean</jc>
<jk>public class</jk> Person {
<jk>public</jk> String <jf>name</jf> = <js>"John Smith"</js>;
<jk>public int</jk> <jf>age</jf> = 21;
}
<jc>// Produces:
// "{"name":"John Smith","age":21}"</jc>
String <jv>json</jv> = Json.<jsm>of</jsm>(<jk>new</jk> Person());
</p>
<p>
Parsing back into POJOs is equally simple for any of the supported languages.
Language fragments are also supported.
</p>
<p class='bjava'>
<jc>// Parse a JSON object as a bean.</jc>
String <jv>json</jv> = <js>"{\"name\":\"John Smith\","\age\":21}"</js>;
Person <jv>person</jv> = Json.<jsm>to</jsm>(<jv>json</jv>, Person.<jk>class</jk>);
</p>
<p>
Marshalling support is provided for a wide variety of POJO types including:
</p>
<ul>
<li>Primitives and primitive objects
<li>Beans
<li>Java Collections Framework objects (e.g. Collections, Maps)
<li>Arrays
<li>POJOs
</ul>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Pojo Categories</a> for an exhaustive list of categories supported out-of-the-box.
</ul>
</div>
<h5 class='topic'>Serializer/Parser Builders</h5>
<div class='topic'>
<p>
Marshallers like the one shown above are pairings of serializers and parsers.
Serializers and parsers are builder-based using fluent methods allowing you to quickly create, clone, and modify them
in single lines of code.
</p>
<p class='bjava'>
<jc>// Create a serializer from scratch programmatically using a builder.</jc>
JsonSerializer <jv>serializer</jv> = JsonSerializer
.<jsm>create</jsm>()
.simple() <jc>// Simple mode</jc>
.sq() <jc>// Use single quotes</jc>
.timeZone(TimeZone.<jsf>GMT</jsf>) <jc>// For timezone-specific serialization</jc>
.locale(Locale.<jsf>JAPAN</jsf>) <jc>// For locale-specific serialization</jc>
.sortCollections()
.sortProperties()
.keepNullProperties()
.trimStrings()
.beanMethodVisibility(<jsf>PROTECTED</jsf>) <jc>// Control which fields/methods are serialized</jc>
.beanDictionary( <jc>// Adds type variables for resolution during parsing</jc>
MyBeanA.<jk>class</jk>,
MyBeanB.<jk>class</jk>
)
.debug() <jc>// Debug mode</jc>
.build();
</p>
<p>
Many POJOs such as primitives, beans, collections, arrays, and classes with various known constructors and methods are serializable out-of-the-box.
</p>
<p>
<a class='doclink' href='#juneau-marshall.jm.Swaps'>Swaps</a> allow you to replace non-serializable objects with serializable equivalents.
The <a href="org/apache/juneau/swaps/package-summary.html"><code>org.apache.juneau.swaps</code></a> package contains a variety of predefined swaps.
</p>
<p class='bjava'>
<jc>// Create a serializer from scratch programmatically using a builder.</jc>
JsonSerializer <jv>serializer</jv> = JsonSerializer
.<jsm>create</jsm>()
.swaps( <jc>// Swap unserializable classes with surrogate POJOs</jc>
IteratorSwap.<jk>class</jk>, <jc>// Iterators swapped with lists</jc>
ByteArrayBase64Swap.<jk>class</jk>, <jc>// byte[] swapped with base-64 encoded strings</jc>
CalendarSwap.ISO8601DT.<jk>class</jk> <jc>// Calendars swapped with ISO8601-compliant strings</jc>
)
.build();
</p>
<p>
Any POJO that doesn't fit into the category of a bean/collection/array/primitive and doesn't have a swap
associated with it is converted to simple strings.
By default, various instance and static methods and constructors on POJO classes are automatically detected and supported
for marshalling a POJO to and from a string.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.SerializersAndParsers'>Overview &gt; juneau-marshall &gt; Serializers and Parsers</a> for more information.
</ul>
</div>
<h5 class='topic'>Bean Annotations</h5>
<div class='topic'>
<p>
Beans and POJO classes, methods, fields, and constructors can also be annotated with a variety of annotations to customize how they are marshalled:
</p>
<p class='bjava'>
<jc>// Sort bean properties by name.</jc>
<jc>// Exclude city/state from marshalling.</jc>
<ja>@Bean</ja>(sort=<jk>true</jk>, excludeProperties=<js>"city,state"</js>)
<jk>public class</jk> Address { ... }
<jc>// Specify an implementation class for an interface.</jc>
<ja>@Marshalled</ja>(implClass=AutomobileImpl.<jk>class</jk>)
<jk>public interface</jk> Automobile { ... }
</p>
<p>
As a general rule, any capabilities provided by bean annotations can be programmatically specified
via the builder APIs. This allows the marshallers to be used equivalently on either your own code
that you have access to, or external code where you only have access to binaries.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.JavaBeansSupport'>Overview &gt; juneau-marshall &gt; Java Beans Support</a> for more information.
</ul>
</div>
<h5 class='topic'>Configuration Annotations</h5>
<div class='topic'>
<p>
Serializers and parsers can also be configured using annotations.
</p>
<p class='bjava'>
<ja>@BeanConfig</ja>(sortProperties=<js>"true"</js>)
<ja>@SerializerConfig</ja>(quoteChar=<js>"'"</js>)
<ja>@RdfConfig</ja>(rdfxml_tab=<js>"5"</js>, addRootProperty=<js>"true"</js>)
<jk>public class</jk> MyAnnotatedClass {...}
<jc>// Create a serializer configured using annotations.</jc>
JsonSerializer <jv>serializer</jv> = JsonSerializer
.<jsm>create</jsm>()
.applyAnnotations(MyAnnotatedClass.<jk>class</jk>)
.build();
</p>
<p>
Config annotations are extensively used in the REST Servlet APIs to configure how POJOs are marshalled through REST interfaces.
</p>
<p>
Config variables also support embedded variables for resolving settings at runtime.
</p>
<p class='bjava'>
<jc>// Sort properties depending on value of system property "sortProperties".</jc>
<ja>@BeanConfig</ja>(sortProperties=<js>"$S{sortProperties,false}"</js>)
</p>
<p>
Default values for config settings can be overridden via system properties or environment variables.
For example, the system property "BeanContext.sortProperties" or environment variable "BEANCONTEXT_SORTPROPERTIES" can be
used to set the default value for the sort properties setting.
</p>
<p>
Bean annotations can also be programmatically attached to POJOs using config annototations like so:
</p>
<p class='bjava'>
<ja>@Bean</ja>(onClass=Address.<jk>class</jk>, sort=<jk>true</jk>, excludeProperties=<js>"city,state"</js>)
<jk>public class</jk> MyAnnotatedClass {...}
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.ContextAnnotations'>Overview &gt; juneau-marshall &gt; Context Annotations</a> for more information.
</ul>
</div>
<h5 class='topic'>Simplified JSON Marshalling</h5>
<div class='topic'>
<p>
The <a href="org/apache/juneau/json/SimpleJsonSerializer.html" title="class in org.apache.juneau.json"><code>SimpleJsonSerializer</code></a> class can be used to serialized POJOs into Simplified JSON notation.
</p>
<p>
Simplified JSON is identical to JSON except for the following:
</p>
<ul class='spaced-list'>
<li>JSON attributes are only quoted when necessary.
<li>Uses single-quotes for quoting.
</ul>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Some free-form JSON.</jc>
Map <jv>map</jv> = JsonMap.<jsm>of</jsm>(
<js>"foo"</js>, <js>"x1"</js>,
<js>"_bar"</js>, <js>"x2"</js>,
<js>" baz "</js>, <js>"x3"</js>,
<js>"123"</js>, <js>"x4"</js>,
<js>"return"</js>, <js>"x5"</js>,
<js>""</js>, <js>"x6"</js>
);
</p>
<p class='bjson'>
<joc>// Serialized to standard JSON</joc>
{
<jok>"foo"</jok>: <jov>"x1"</jov>,
<jok>"_bar"</jok>: <jov>"x2"</jov>,
<jok>" baz "</jok>: <jov>"x3"</jov>,
<jok>"123"</jok>: <jov>"x4"</jov>,
<jok>"return"</jok>: <jov>"x5"</jov>,
<jok>""</jok>: <jov>"x6"</jov>
}
</p>
<p class='bjson'>
<joc>// Serialized to simplified JSON</joc>
{
<jok>foo</jok>: <jov>'x1'</jov>,
<jok>_bar</jok>: <jov>'x2'</jov>,
<jok>' baz '</jok>: <jov>'x3'</jov>, <joc>// Quoted due to embedded spaces.</joc>
<jok>'123'</jok>: <jov>'x4'</jov>, <joc>// Quoted to prevent confusion with number.</joc>
<jok>'return'</jok>: <jov>'x5'</jov>, <joc>// Quoted because it's a keyword.</joc>
<jok>''</jok>: <jov>'x6'</jov> <joc>// Quoted because it's an empty string.</joc>
}
</p>
<p>
Simplified JSON is still valid Javascript.
The advantage to simplified JSON is you can represent it in a Java String in minimal form with minimal escaping.
This is particularly useful in cases such as unit testing where you can easily validate POJOs by simplifying them to Simplified JSON and do a simple string comparison.
</p>
<p class='bjava'>
WriterSerializer <jv>serializer</jv> = SimpleJsonSerializer.<jsf>DEFAULT</jsf>;
<jsm>assertString</jsm>(<jv>serializer</jv>.toString(<jv>myPojo</jv>)).is(<js>"{foo:'bar',baz:123}"</js>);
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.JsonDetails.jm.SimplifiedJson'>Overview &gt; juneau-marshall &gt; JSON Details &gt; Simplified JSON</a> for more information.
</ul>
</div>
<h5 class='topic'>UON Marshalling</h5>
<div class='topic'>
<p>
The Marshalling API also supports UON (URL-Encoded Object Notation).
It allows JSON-like data structures (OBJECT, ARRAY, NUMBER, BOOLEAN, STRING, NULL) in HTTP constructs (query parameters, form parameters,
headers, URL parts) without violating RFC2396.
This allows POJOs to be converted directly into these HTTP constructs which is not possible in other languages such as JSON.
</p>
<p class='buon'>
(
id=1,
name=<js>'John+Smith'</js>,
uri=<js>http://sample/addressBook/person/1</js>,
addressBookUri=<js>http://sample/addressBook</js>,
birthDate=<js>1946-08-12T00:00:00Z</js>,
addresses=@(
(
uri=<js>http://sample/addressBook/address/1</js>,
personUri=<js>http://sample/addressBook/person/1</js>,
id=<js>1</js>,
street=<js>'100+Main+Street'</js>,
city=<js>Anywhereville</js>,
state=<js>NY</js>,
zip=<js>12345</js>,
isCurrent=<jk>true</jk>
)
)
)
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.UonDetails'>UON Details</a> for more information.
</ul>
</div>
<h5 class='topic'>OpenAPI Marshalling</h5>
<div class='topic'>
<p>
The Marshalling API also supports schema-based OpenAPI serialization.
It allows HTTP parts to be marshalled to-and-from POJOs based on OpenAPI schema definitions.
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.httpart.HttpPartSchema.*;
<jc>// Schema - Pipe-delimited list of comma-delimited longs.</jc>
HttpPartSchema <jv>schema</jv> = <jsm>tArrayPipes</jsm>().items(
<jsm>tArrayCsv</jsm>().items(
<jsm>tInt64</jsm>()
)
).build();
<jc>// Our value to serialize</jc>
Object <jv>value</jv> = <jk>new long</jk>[][]{{1,2,3},{4,5,6},{7,8,9}};
<jc>// Produces "1,2,3|4,5,6|7,8,9"</jc>
String <jv>output</jv> = OpenApi.<jsm>of</jsm>(<jv>schema</jv>, <jv>value</jv>);
</p>
<p>
Schema-based serialization and parsing is used heavily in both the server and client REST APIs with built-in schema
validations support in various HTTP part annotations.
</p>
<p class='bjava'>
<jc>// REST server method with HTTP parts using schema validation.</jc>
<ja>@RestGet</ja>
<jk>public void</jk> doGet(
<ja>@Query</ja>(name=<js>"myParam"</js>, schema=<ja>@Schema</ja>(min=1, max=32)) <jk>int</jk> <jv>myParam</jv>,
<ja>@Header</ja>(<js>"MyHeader"</js>, schema=<ja>@Schema</ja>(pattern=<js>"foo.*"</js>)) String <jv>p2</jv>
) {...}
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails'>OpenAPI Details</a> for more information.
</ul>
</div>
<h5 class='topic'>JsonMap/JsonList</h5>
<div class='topic'>
<p>
The <a href="org/apache/juneau/collections/JsonMap.html" title="class in org.apache.juneau.collections"><code>JsonMap</code></a> and <a href="org/apache/juneau/collections/JsonList.html" title="class in org.apache.juneau.collections"><code>JsonList</code></a> collections classes allow you
to programmatically build generic JSON data structures. They are similar in concept to
<c>JSONObject</c> and <c>JSONArray</c> that you find in other JSON marshalling APIs but
can be used to generate DOMs in any of the supported languages.
</p>
<p class='bjava'>
<jc>// Create JSON strings from scratch using fluent-style code.</jc>
String <jv>myMap</jv> = JsonMap.<jsm>create</jsm>().append(<js>"foo"</js>,<js>"bar"</js>).asJson();
String <jv>myList</jv> = JsonList.<jsm>of</jsm>(<js>"foo"</js>, 123, <jk>null</jk>, <jv>jsonObject</jv>).asJson();
<jc>// Parse directly from JSON into generic DOMs.</jc>
Map&lt;String,Object&gt; <jv>myMap</jv> = JsonMap.<jsm>ofJson</jsm>(<js>"{foo:'bar'}"</js>);
List&lt;Object&gt; <jv>myList</jv> = JsonList.<jsm>ofJson</jsm>(<js>"['foo',123,null]"</js>);
</p>
<p>
These classes provide lots of convenience methods including:
</p>
<ul>
<li>Methods for direct marshalling to/from any of the other supported languages.
<li>Methods for quick conversions to other data types including collections, beans, arrays, etc...
</ul>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.JsonMap'>JsonMap and JsonList</a> for more information.
</ul>
</div>
<h5 class='topic'>Serializer and Parser Sets</h5>
<div class='topic'>
<p>
<a href="org/apache/juneau/serializer/SerializerSet.html" title="class in org.apache.juneau.serializer"><code>SerializerSet</code></a> and <a href="org/apache/juneau/parser/ParserSet.html" title="class in org.apache.juneau.parser"><code>ParserSet</code></a> classes allow serializers and parsers
to be retrieved by W3C-compliant HTTP <code>Accept</code> and <code>Content-Type</code> values:
</p>
<p class='bjava'>
<jc>// Construct a new serializer group with configuration parameters that get applied
// to all serializers.</jc>
SerializerSet <jv>serializerSet</jv> = SerializerSet
.<jsm>create</jsm>()
.add(JsonSerializer.<jk>class</jk>, UrlEncodingSerializer.<jk>class</jk>);
.forEach(<jv>x</jv> -> <jv>x</jv>.swaps(CalendarSwap.ISO8601DT.<jk>class</jk>))
.forEachWS(<jv>x</jv> -> <jv>x</jv>.useWhitespace())
.build();
<jc>// Find the appropriate serializer by Accept type and serialize our POJO to the specified writer.</jc>
<jc>// Fully RFC2616 compliant.</jc>
<jv>serializerSet</jv>
.getSerializer(<js>"text/invalid, text/json;q=0.8, text/*;q:0.6, *\/*;q=0.0"</js>)
.serialize(<jv>person</jv>, <jv>myWriter</jv>);
<jc>// Construct a new parser group with configuration parameters that get applied to all parsers.</jc>
ParserSet <jv>parserSet</jv> = ParserSet
.<jsm>create</jsm>()
.add(JsonParser.<jk>class</jk>, UrlEncodingParser.<jk>class</jk>);
.forEach(<jv>x</jv> -> <jv>x</jv>.swaps(CalendarSwap.ISO8601DT.<jk>class</jk>))
.build();
Person <jv>person</jv> = <jv>parserSet</jv>
.getParser(<js>"text/json"</js>)
.parse(<jv>myReader</jv>, Person.<jk>class</jk>);
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.SerializerSetsParserSets'>SerializerSets and ParserSets</a> for more information.
</ul>
</div>
<h5 class='topic'>SVL Variables</h5>
<div class='topic'>
<p>
The <a href="org/apache/juneau/svl/package-summary.html"><code>org.apache.juneau.svl</code></a> package defines an API for a language called "Simple Variable Language".
In a nutshell, Simple Variable Language (or SVL) is text that contains variables of the form
<js>"$varName{varKey}"</js>.
</p>
<p>
Variables can be recursively nested within the varKey (e.g. <js>"$FOO{$BAR{xxx},$BAZ{xxx}}"</js>).
Variables can also return values that themselves contain more variables.
</p>
<p class='bjava'>
<jc>// Use the default variable resolver to resolve a string that
// contains $S (system property) variables</jc>
String <jv>myProperty</jv> = VarResolver.<jsf>DEFAULT</jsf>.resolve(<js>"The Java home directory is $S{java.home}"</js>);
</p>
<p>
The SVL variables are used widely throughout various annotations defined in Juneau allowing many features to be configured
via external sources such as configuration files or environment variables/system properties. The SVL APIs are
extensible allowing for the addition of new types of variables.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.SimpleVariableLanguage'>Simple Variable Language</a> for more information.
</ul>
</div>
</div><!-- END: 1.1 - Overview.o.Marshalling -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Overview.o.EndToEndRest' id='Overview.o.EndToEndRest'>1.2 - End-to-End REST</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 1.2 - Overview.o.EndToEndRest -->
<div class='topic'>
<p>
The <a class='doclink' href='#juneau-rest-server'>juneau-rest-server</a> and <a class='doclink' href='#juneau-rest-client'>juneau-rest-client</a> libraries
provide server and client side REST capabilities that can be used by themselves, or together to create
simplified yet sophisticated Java-based REST communications layers that completely hide away the complexities
of the REST protocol.
</p>
<p>
A typical pattern is to define a REST API on the server side:
</p>
<p class='bjava'>
<ja>@Rest</ja>(path=<js>"/petstore"</js>)
<jk>public class</jk> PetStoreRest {
<ja>@RestPost</ja>(path=<js>"/pets"</js>, guards=AdminGuard.<jk>class</jk>)
<jk>public</jk> Ok addPet(
<ja>@Content</ja> CreatePet <jv>createPetBean</jv>,
<ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
<ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
) <jk>throws</jk> BadRequest, Unauthorized, InternalServerError {
<jc>// Process request here.</jc>
<jk>return</jk> Ok.<jsf>OK</jsf>; <jc>// Standard 400-OK response.</jc>
}
}
</p>
<p>
Then define a Java interface that can be provided to consumers of your API to access your REST API:
</p>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStoreClient {
<ja>@RemotePost</ja>(<js>"/pets"</js>)
Ok addPet(
<ja>@Content</ja> CreatePet <jv>createPet</jv>,
<ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
<ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
) <jk>throws</jk> BadRequest, Unauthorized, InternalServerError;
}
</p>
<p>
Note that you may choose to have your service class implement your interface. The REST libraries will
happily look for annotations defined on methods of parent classes and interfaces. It's up to you how
you want to design it.
</p>
<p>
Finally, the <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> class is used to construct a remote proxy to our REST service:
<p class='bjava'>
<jc>// Use a RestClient with default Simple JSON support and BASIC auth.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().simpleJson().basicAuth(...).build();
<jc>// Instantiate our proxy interface.</jc>
PetStoreClient <jv>store</jv> = <jv>client</jv>.getRemote(PetStoreClient.<jk>class</jk>, <js>"http://localhost:10000"</js>);
<jc>// Use it to create a pet.</jc>
CreatePet <jv>createPet</jv> = <jk>new</jk> CreatePet(<js>"Fluffy"</js>, 9.99);
Pet <jv>pet</jv> = <jv>store</jv>.addPet(<jv>createPet</jv>, UUID.<jsm>randomUUID</jsm>(), <jk>true</jk>);
</p>
<p>
The call above translates to the following REST call:
</p>
<p class='bcode'>
POST http://localhost:10000/petstore/pets?debug=true HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
E-Tag: 475588d4-0b27-4f56-9296-cc683251d314
{
name: 'Fluffy',
price: 9.99
}
</p>
<p>
It looks simplistic but the server and client APIs are highly sophisticated libraries that allow you
to perform complex tasks using very little code.
</p>
</div>
</div><!-- END: 1.2 - Overview.o.EndToEndRest -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Overview.o.RestServer' id='Overview.o.RestServer'>1.3 - REST Server</a></h3>
<div class='topic'><!-- START: 1.3 - Overview.o.RestServer -->
<h5 class='topic'>@Rest-Annotated Resources</h5>
<div class='topic'>
<p>
A REST resource is simply a Java class annotated with <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>.
The most common case is a class that extends <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a>, which itself is simply an
extension of <code>HttpServlet</code> which allows it to be deployed as a servlet.
</p>
<p class='bjava'>
<jc>// Sample REST resource that prints out a simple "Hello world!" message.</jc>
<ja>@Rest</ja>(
path=<js>"/helloWorld"</js>,
title=<js>"Hello World"</js>,
description=<js>"An example of the simplest-possible resource"</js>
)
<ja>@HtmlDoc</ja>(
navlinks={
<js>"up: request:/.."</js>,
<js>"options: servlet:/?method=OPTIONS"</js>
},
aside={
<js>"&lt;div style='max-width:400px' class='text'&gt;"</js>,
<js>" &lt;p&gt;This page shows a resource that simply response with a 'Hello world!' message&lt;/p&gt;"</js>,
<js>" &lt;p&gt;The POJO serialized is a simple String.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<ja>@BeanConfig</ja>(sortProperties=<js>"true"</js>)
<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniveralConfig {
<ja>@RestGet</ja>(path=<js>"/*"</js>, summary=<js>"Responds with \"Hello world!\""</js>)
<jk>public</jk> String sayHello() {
<jk>return</jk> <js>"Hello world!"</js>;
}
}
</p>
<p>
This is what it looks like in a browser.
</p>
<p class='bcode'>
http://localhost:10000/helloWorld
</p>
<img class='bordered w800' src='doc-files/jrs.HelloWorldExample.1.png'>
<ul class='spaced-list'>
<li>Parsers for request bodies are selected based on the request <c>Content-Type</c> header.
<li>Serializers for response bodies are selected based on the request <c>Accept</c> header.
<ul>
<li>In this case, it's the <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a> serializer based on the
browser's default <c>Accept</c> header that's asking for HTML.
</ul>
<li>REST resource classes and methods can be annotated with configuration annotations for the serializers and parsers (such as <ja>@HtmlConfig</ja> and <ja>@BeanConfig</ja> shown above).
<li>Annotations such as the title, summary, and descriptions shown above are used for auto-generated Swagger UI pages (described later).
</ul>
</div>
<h5 class='topic'>REST Children</h5>
<div class='topic'>
<p>
Child Resources are REST servlets or objects that are linked to parent resources through the
<a href="org/apache/juneau/rest/annotation/Rest.html#children--"><code>@Rest(children)</code></a> annotation.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jd>/** Parent Resource */</jd>
<ja>@Rest</ja>(
path=<js>"/parent"</js>,
children={
MyChildResource.<jk>class</jk>
}
)
<jk>public</jk> MyParentResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p class='bjava'>
<jd>/** Child Resource */</jd>
<ja>@Rest</ja>(
path=<js>"/child"</js> <jc>// Path relative to parent resource.</jc>
)
<jc>// Note that we don't need to extend from RestServlet.</jc>
<jk>public</jk> MyChildResource <jk>implements</jk> BasicUniversalConfig {
...
}
</p>
<p>
The path of the child resource gets appended to the path of the parent resource.
So in the example above, the child resource is accessed through the URL <l>/parent/child</l>.
</p>
<p>
The advantage of using child resources is that they do not need to be declared in the JEE <l>web.xml</l>
file.
Initialization of and access to the child resources occurs through the parent resource.
Children can be nested arbitrary deep to create complex REST interfaces with a single top-level REST servlet.
</p>
</div>
<h5 class='topic'>Predefined Configuration Interfaces</h5>
<div class='topic'>
<p>
The servlets in the previous section implemented the <a href="org/apache/juneau/rest/config/BasicUniversalConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicUniversalConfig</code></a> which simply defines
a preconfigured set of annotations that get inherited by the child classes:
</p>
<p class='bjava'>
<jd>/**
* Predefined configuration for a REST resource that supports all languages
* and provides common default configuration values.</jd>
*/</jd>
<ja>@Rest</ja>(
<jc>// Default serializers for all Java methods in the class.</jc>
serializers={
HtmlDocSerializer.<jk>class</jk>,
HtmlStrippedDocSerializer.<jk>class</jk>,
HtmlSchemaDocSerializer.<jk>class</jk>,
JsonSerializer.<jk>class</jk>,
SimpleJsonSerializer.<jk>class</jk>,
JsonSchemaSerializer.<jk>class</jk>,
XmlDocSerializer.<jk>class</jk>,
UonSerializer.<jk>class</jk>,
UrlEncodingSerializer.<jk>class</jk>,
OpenApiSerializer.<jk>class</jk>,
MsgPackSerializer.<jk>class</jk>,
SoapXmlSerializer.<jk>class</jk>,
PlainTextSerializer.<jk>class</jk>,
CsvSerializer.<jk>class</jk>
},
<jc>// Default parsers for all Java methods in the class.</jc>
parsers={
JsonParser.<jk>class</jk>,
SimpleJsonParser.<jk>class</jk>,
XmlParser.<jk>class</jk>,
HtmlParser.<jk>class</jk>,
UonParser.<jk>class</jk>,
UrlEncodingParser.<jk>class</jk>,
OpenApiParser.<jk>class</jk>,
MsgPackParser.<jk>class</jk>,
PlainTextParser.<jk>class</jk>,
CsvParser.<jk>class</jk>
}
)
<jk>public interface</jk> BasicUniversalConfig <jk>extends</jk> DefaultConfig, DefaultHtmlConfig {}
</p>
<p class='bjava'>
<jd>/**
* Predefined REST configuration that defines common default values for all configurations.
*/</jd>
<ja>@Rest</ja>(
<jc>// Configuration file.</jc>
config=<js>"$S{j.configFile,$E{J_CONFIG_FILE,SYSTEM_DEFAULT}}"</js>,
<jc>// Standard fields.</jc>
path=<js>""</js>,
roleGuard=<js>""</js>,
rolesDeclared=<js>""</js>,
<jc>// Configuration beans.</jc>
converters={},
encoders={IdentityEncoder.<jk>class</jk>},
guards={},
parsers={},
partParser=OpenApiParser.<jk>class</jk>,
partSerializer=OpenApiSerializer.<jk>class</jk>,
responseProcessors={
ReaderProcessor.<jk>class</jk>,
InputStreamProcessor.<jk>class</jk>,
ThrowableProcessor.<jk>class</jk>,
HttpResponseProcessor.<jk>class</jk>,
HttpResourceProcessor.<jk>class</jk>,
HttpEntityProcessor.<jk>class</jk>,
ResponseBeanProcessor.<jk>class</jk>,
PlainTextPojoProcessor.<jk>class</jk>,
SerializedPojoProcessor.<jk>class</jk>
},
restOpArgs={
AttributeArg.<jk>class</jk>,
ContentArg.<jk>class</jk>,
FormDataArg.<jk>class</jk>,
HasFormDataArg.<jk>class</jk>,
HasQueryArg.<jk>class</jk>,
HeaderArg.<jk>class</jk>,
HttpServletRequestArgs.<jk>class</jk>,
HttpServletResponseArgs.<jk>class</jk>,
HttpSessionArgs.<jk>class</jk>,
InputStreamParserArg.<jk>class</jk>,
MethodArg.<jk>class</jk>,
ParserArg.<jk>class</jk>,
PathArg.<jk>class</jk>,
QueryArg.<jk>class</jk>,
ReaderParserArg.<jk>class</jk>,
RequestBeanArg.<jk>class</jk>,
ResponseBeanArg.<jk>class</jk>,
ResponseHeaderArg.<jk>class</jk>,
ResponseCodeArg.<jk>class</jk>,
RestContextArgs.<jk>class</jk>,
RestSessionArgs.<jk>class</jk>,
RestOpContextArgs.<jk>class</jk>,
RestOpSessionArgs.<jk>class</jk>,
RestRequestArgs.<jk>class</jk>,
RestResponseArgs.<jk>class</jk>,
DefaultArg.<jk>class</jk>
},
serializers={},
<jc>// Configurable settings.</jc>
allowedHeaderParams=<js>"$S{j.allowedHeaderParams,$E{J_ALLOWED_HEADER_PARAMS,Accept,Content-Type}}"</js>,
allowedMethodHeaders=<js>"$S{j.allowedMethodHeaders,$E{J_ALLOWED_METHOD_HEADERS,}}"</js>,
allowedMethodParams=<js>"$S{j.allowedMethodParams,$E{J_ALLOWED_METHOD_PARAMS,HEAD,OPTIONS}}"</js>,
clientVersionHeader=<js>"$S{j.clientVersionHeader,$E{J_CLIENT_VERSION_HEADER,Client-Version}}"</js>,
debug=<js>"$S{j.debug,$E{J_DEBUG,}}"</js>,
debugOn=<js>"$S{j.debugOn,$E{J_DEBUG_ON,}}"</js>,
defaultAccept=<js>"$S{j.defaultAccept,$E{J_DEFAULT_ACCEPT,}}"</js>,
defaultCharset=<js>"$S{j.defaultCharset,$E{J_DEFAULT_CHARSET,UTF-8}}"</js>,
defaultContentType=<js>"$S{j.defaultContentType,$E{J_DEFAULT_CONTENT_TYPE,}}"</js>,
defaultRequestAttributes=<js>"$S{j.defaultRequestAttributes,$E{J_DEFAULT_REQUEST_ATTRIBUTES,}}"</js>,
defaultRequestHeaders=<js>"$S{j.defaultRequestHeaders,$E{J_DEFAULT_REQUEST_HEADERS,}}"</js>,
defaultResponseHeaders=<js>"$S{j.defaultResponseHeaders,$E{J_DEFAULT_RESPONSE_HEADERS,}}"</js>,
disableContentParam=<js>"$S{j.disableContentParam,$E{J_DISABLE_CONTENT_PARAM,false}}"</js>,
maxInput=<js>"$S{j.maxInput,$E{J_MAX_INPUT,1000000}}"</js>,
messages=<js>"$S{j.messages,$E{J_MESSAGES,}}"</js>,
renderResponseStackTraces=<js>"$S{j.renderResponseStackTraces,$E{J_RENDER_RESPONSE_STACK_TRACES,false}}"</js>,
uriAuthority=<js>"$S{j.uriAuthority,$E{J_URI_AUTHORITY,}}"</js>,
uriContext=<js>"$S{j.uriContext,$E{J_URI_CONTEXT,}}"</js>,
uriRelativity=<js>"$S{j.uriRelativity,$E{J_URI_RELATIVITY,}}"</js>,
uriResolution=<js>"$S{j.uriResolution,$E{J_URI_RESOLUTION,}}"</js>,
<jc>// Metadata settings.</jc>
consumes={},
description=<js>""</js>,
produces={},
siteName=<js>"$S{j.siteName,$E{J_SITE_NAME,}}"</js>,
swagger=@Swagger,
title=<js>"$S{j.title,$E{J_TITLE,}}"</js>,
<jc>// Injectable/overridable beans.</jc>
beanStore=BeanStore.Void.<jk>class</jk>, <jc>// Defaults to BeanStore.</jc>
callLogger=CallLogger.Void.<jk>class</jk>, <jc>// Defaults to BasicCallLogger.</jc>
debugEnablement=DebugEnablement.Void.<jk>class</jk>, <jc>// Defaults to BasicDefaultEnablement.</jc>
fileFinder=FileFinder.Void.<jk>class</jk>, <jc>// Defaults to BasicFileFinder.</jc>
staticFiles=StaticFiles.Void.<jk>class</jk>, <jc>// Defaults to BasicStaticFiles.</jc>
swaggerProvider=SwaggerProvider.Void.<jk>class</jk>, <jc>// Defaults to BasicSwaggerProvider.</jc>
<jc>// Overridable context classes.</jc>
contextClass=RestContext.<jk>class</jk>,
restChildrenClass=RestChildren.<jk>class</jk>,
restOpContextClass=RestOpContext.<jk>class</jk>,
restOperationsClass=RestOperations.<jk>class</jk>
)
<ja>@BeanConfig</ja>(
<jc>// When parsing generated beans, ignore unknown properties
// that may only exist as getters and not setters.</jc>
ignoreUnknownBeanProperties=<js>"true"</js>,
ignoreUnknownEnumValues=<js>"true"</js>
)
<ja>@SerializerConfig</ja>(
<jc>// Enable automatic resolution of URI objects to root-relative values.</jc>
uriResolution=<js>"ROOT_RELATIVE"</js>
)
<jk>public interface</jk> DefaultConfig {}
</p>
<p class='bjava'>
<jd>/**
* Predefined REST configuration that defines common default values the HTML Doc serializer.
*/</jd>
<ja>@HtmlDocConfig</ja>(
<jc>// Default page header contents.</jc>
header={
<js>"&lt;h1&gt;$RS{title}&lt;/h1&gt;"</js>, <jc>// Use @Rest(title)</jc>
<js>"&lt;h2&gt;$RS{operationSummary,description}&lt;/h2&gt;"</js>, <jc>// Use either @RestOp(summary) or @Rest(description)</jc>
<js>"$C{REST/header}"</js> <jc>// Extra header HTML defined in external config file.</jc>
},
<jc>// Basic page navigation links.</jc>
navlinks={
<js>"up: request:/.."</js>
},
<jc>// Default stylesheet to use for the page.
// Can be overridden from external config file.
// Default is DevOps look-and-feel (aka Depression look-and-feel).</jc>
stylesheet=<js>"$C{REST/theme,servlet:/htdocs/themes/devops.css}"</js>,
<jc>// Default contents to add to the &lt;head&gt; section of the HTML page.
// Use it to add a favicon link to the page.</jc>
head=<js>"$C{REST/head}"</js>,
<jc>// No default page footer contents.
// Can be overridden from external config file.</jc>
footer=<js>"$C{REST/footer}"</js>,
<jc>// By default, table cell contents should not wrap.</jc>
nowrap=<js>"true"</js>
)
<jk>public interface</jk> DefaultHtmlConfig {}
</p>
<p>
The <a href="org/apache/juneau/rest/config/package-summary.html"><code>org.apache.juneau.rest.config</code></a> package contains other basic configurations for use.
Annotations are aggregated from child-to-parent order allowing for these basic configurations
to be extended and modified, or you can create your own annotations from scratch.
</p>
</div>
<h5 class='topic'>REST Group Pages</h5>
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/servlet/BasicRestServletGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServletGroup</code></a> class provides a default "router" page for
child resources when a parent resource is nothing more than a grouping of child resources.
</p>
<p>
The <l>RootResources</l> class in the Samples project is an example of a router page:
</p>
<p class='bjava'>
<jd>/**
* Sample REST resource showing how to implement a "router" resource page.
*/</jd>
<ja>@Rest</ja>(
path=<js>"/"</js>,
title=<js>"Root resources"</js>,
description=<js>"Example of a router resource page."</js>,
children={
HelloWorldResource.<jk>class</jk>,
PetStoreResource.<jk>class</jk>,
DtoExamples.<jk>class</jk>,
ConfigResource.<jk>class</jk>,
LogsResource.<jk>class</jk>,
ShutdownResource.<jk>class</jk>
}
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicRestServletGroup <jk>implements</jk> BasicUniversalConfig {
<jc>// NO CODE!!!</jc>
}
</p>
<p>
When you bring up this resource in a browser, you see the following that provides a list
of navigable links to your child resources:
</p>
<p class='bcode'>
http://localhost:10000
</p>
<img class='bordered w800' src='doc-files/jrs.RouterPages.1.png'/>
</div>
<h5 class='topic'>REST Resource Methods</h5>
<div class='topic'>
<p>
The real power behind the REST server API is the ability to define Java methods as REST endpoints.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestPost</ja>(path=<js>"/pets"</js>, guards=AdminGuard.<jk>class</jk>)
<jk>public</jk> Ok addPet(
<ja>@Content</ja> CreatePet <jv>createPetBean</jv>,
<ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
<ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
) <jk>throws</jk> BadRequest, Unauthorized, InternalServerError {
<jc>// Process request.</jc>
<jk>return</jk> Ok.<jsf>OK</jsf>;
}
</p>
<p>
Java methods on <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a>-annotated classes have the following format:
</p>
<p class='bjava'>
<ja>@RestOp</ja>(method=<js>"..."</js>, path=<js>"..."</js>)
<ja><i>&lt;config-annotations&gt;</i></ja>
<jk>public</jk> <i>&lt;return-type&gt;</i> method(<i>&lt;args&gt;</i>) <jk>throws</jk> <i>&lt;throwables&gt;</i> {
...
}
</p>
<p>
The various parts require their own topics to fully appreciate the scope of abilities but the following is a summary:
</p>
<ul class='spaced-list'>
<li>Annotated with <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestOp</code></a>.
<ul>
<li>Also available: <a href="org/apache/juneau/rest/annotation/RestGet.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestGet</code></a> / <a href="org/apache/juneau/rest/annotation/RestPut.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestPut</code></a> / <a href="org/apache/juneau/rest/annotation/RestPost.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestPost</code></a> / <a href="org/apache/juneau/rest/annotation/RestDelete.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestDelete</code></a>.
<li>Annotation optional if using standard naming conventions (e.g. <c>getFoo()</c> equivalent to <c><ja>@RestGet</ja>(path=<js>"/foo"</js>)</c>).
</ul>
<li>Optionally annotated with config annotations such as <a href="org/apache/juneau/annotation/BeanConfig.html" title="annotation in org.apache.juneau.annotation"><code>@BeanConfig</code></a> and <a href="org/apache/juneau/html/annotation/HtmlDocConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>@HtmlDocConfig</code></a> that
customize the behavior of serializers and parsers at the method level.
<li>Returned object gets serialized as the HTTP response body.
<ul>
<li>Typically a POJO serialized based on <a href="org/apache/juneau/http/header/Accept.html" title="class in org.apache.juneau.http.header"><code>Accept</code></a> request header.
<li>Support for raw values such as <c>Readers</c> and <c>InputStreams</c> (among others).
<li>Support for response beans annotated with <a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>@Response</code></a>.
<li>Support for Apache Http Core interfaces: <code>HttpEntity</code> / <code>HttpResponse</code> / <a href="org/apache/juneau/http/resource/HttpResource.html" title="interface in org.apache.juneau.http.resource"><code>HttpResource</code></a>.
<li>Standard HTTP responses such as <a href="org/apache/juneau/http/response/Ok.html" title="class in org.apache.juneau.http.response"><code>Ok</code></a> and <a href="org/apache/juneau/http/response/TemporaryRedirect.html" title="class in org.apache.juneau.http.response"><code>TemporaryRedirect</code></a> provided in <a href="org/apache/juneau/http/response/package-summary.html"><code>org.apache.juneau.http.response</code></a> package.
<li>Extensible API for defining custom return types.
</ul>
<li>A wide range of possible argument types including:
<ul>
<li>Standard <code>HttpServletRequest</code> / <code>HttpServletResponse</code> objects.
<li>Extended <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> / <a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a> objects.
<li>Parsed HTTP parts with either the arguments or beans annotated with <a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>@Path</code></a> / <a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>@Header</code></a> / <a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>@Query</code></a> / <a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>@FormData</code></a>.
<li>Parsed HTTP body with either the argument or bean annotated with <a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>@Content</code></a>.
<li>Raw HTTP request body with <c>InputStream</c> or <c>Reader</c>.
<li>Raw HTTP response body with <c>OutputStream</c> or <c>Writer</c>.
<li>Request beans annotated with <a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>@Request</code></a>.
<li>Response beans annotated with <a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>@Response</code></a>.
<li>Standard HTTP headers such as <a href="org/apache/juneau/http/header/Accept.html" title="class in org.apache.juneau.http.header"><code>Accept</code></a> and <a href="org/apache/juneau/http/header/ContentType.html" title="class in org.apache.juneau.http.header"><code>ContentType</code></a> provided in <a href="org/apache/juneau/http/header/package-summary.html"><code>org.apache.juneau.http.header</code></a> package.
<li>Auto-generated <a href="org/apache/juneau/dto/swagger/Swagger.html" title="class in org.apache.juneau.dto.swagger"><code>Swagger</code></a>.
<li>Various other standard objects such as <a href="https://docs.oracle.com/javase/8/docs/api/java/security/Principal.html?is-external=true" title="class or interface in java.security"><code>Principal</code></a>, <code>Cookie</code>, <code>HttpSession</code>, and <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html?is-external=true" title="class or interface in java.util"><code>ResourceBundle</code></a>.
<li>Spring beans or other injectable beans.
<li>Extensible API for defining custom argument types.
</ul>
<li>Throwables can be anything.
<ul>
<li>Typically one of the standard HTTP responses such as <a href="org/apache/juneau/http/response/BadRequest.html" title="class in org.apache.juneau.http.response"><code>BadRequest</code></a> or <a href="org/apache/juneau/http/response/NotFound.html" title="class in org.apache.juneau.http.response"><code>NotFound</code></a> provided in <a href="org/apache/juneau/http/response/package-summary.html"><code>org.apache.juneau.http.response</code></a> package.
<li>Can define your own <a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>@Response</code></a>-annotated throwables.
<li>Anything else gets converted to an <a href="org/apache/juneau/http/response/InternalServerError.html" title="class in org.apache.juneau.http.response"><code>InternalServerError</code></a>.
</ul>
</ul>
</div>
<h5 class='topic'>Deploying as a Servlet</h5>
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> class is the entry point for your REST resources.
It extends directly from <l>HttpServlet</l> and is deployed like any other servlet (such as a standard <c>web.xml</c> file).
</p>
<p>
When the servlet <l>init()</l> method is called, it triggers the code to find and process the <l>@Rest</l>
annotations on that class and all child classes.
These get constructed into a <a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a> object that holds all the configuration
information about your resource in a read-only object.
</p>
<p>
Most developers are not going to be using the <l>RestServlet</l> class itself, and instead will
extend from one of the preconfigured default servlets such as <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> and <a href="org/apache/juneau/rest/servlet/BasicRestServletGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServletGroup</code></a>
which provides universal language support, basic instrumentation, and auto-generated Swagger UI.
</p>
</div>
<h5 class='topic'>Deploying in Spring Boot</h5>
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/springboot/BasicSpringRestServlet.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServlet</code></a> class is typically entry point for your REST resources
when working within a Spring Boot environment. It extends from
<a href="org/apache/juneau/rest/springboot/SpringRestServlet.html" title="class in org.apache.juneau.rest.springboot"><code>SpringRestServlet</code></a> which provides additional capabilities including:
</p>
<ul>
<li>Your REST resources can be defined as injectable Spring beans.
<li>Various capabilities within the REST Server library (e.g. logging, instrumentation, call handling, API extensions) can be defined via
Spring beans and automatically pulled into the framework.
</ul>
<p>
Most developers are not going to be using the <l>RestServlet</l> class itself, and instead will
extend from one of the preconfigured default servlets such as <a href="org/apache/juneau/rest/springboot/BasicSpringRestServlet.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServlet</code></a> and <a href="org/apache/juneau/rest/springboot/BasicSpringRestServletGroup.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServletGroup</code></a>
that have the same capabilites as the <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> and <a href="org/apache/juneau/rest/servlet/BasicRestServletGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServletGroup</code></a> counterparts.
</p>
<h5 class='figure'>Example configuration file:</h5>
<p class='bjava'>
<ja>@Configuration</ja>
<jk>public class</jk> MySpringConfiguration {
<jd>/**
* Our root REST bean.
* Note that this must extend from SpringRestServlet so that child resources can be
* resolved as Spring beans.
* All REST objects are attached to this bean using the <a href="org/apache/juneau/rest/annotation/Rest.html#children--"><code>Rest.children()</code></a> annotation.
*/</jd>
<ja>@Bean</ja>
<jk>public</jk> RootResources getRootResources() {
<jk>return new</jk> RootResources();
}
<jd>/**
* Optionally return the HelloWorldResource object as an injectable bean.
*/</jd>
<ja>@Bean</ja>
<jk>public</jk> HelloWorldResource getHelloWorldResource() {
<jk>return new</jk> HelloWorldResource();
}
<jd>/**
* Map our servlet to a path.
*/</jd>
<ja>@Bean</ja>
<jk>public</jk> ServletRegistrationBean&lt;Servlet&gt; getRootServlet(RootResources <jv>rootResources</jv>) {
<jk>return new</jk> ServletRegistrationBean<>(<jv>rootResources</jv>, <js>"/*"</js>);
}
}
</p>
<p class='bjava'>
<ja>@Rest</ja>(
children={
HelloWorldResource.<jk>class</jk>
}
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicSpringRestServletGroup <jk>implements</jk> BasicUniversalConfig {
<jc>// No code!</jc>
}
</p>
</div>
<h5 class='topic'>Additional Information</h5>
<div class='topic'>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-rest-server'>Overview &gt; juneau-rest-server</a> for more information.
</ul>
</div>
</div><!-- END: 1.3 - Overview.o.RestServer -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Overview.o.RestClient' id='Overview.o.RestClient'>1.4 - REST Client</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 1.4 - Overview.o.RestClient -->
<div class='topic'>
<p>
Built upon the feature-rich Apache HttpClient library, the Juneau RestClient API adds support for fluent-style
REST calls and the ability to perform marshalling of POJOs to and from HTTP parts.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a basic REST client with JSON support and download a bean.</jc>
MyBean <jv>bean</jv> = RestClient.<jsm>create</jsm>()
.simpleJson()
.build()
.get(<jsf>URI</jsf>)
.run()
.assertStatus().asCode().is(200)
.assertHeader(<js>"Content-Type"</js>).matchesSimple(<js>"application/json*"</js>)
.getContent().as(MyBean.<jk>class</jk>);
</p>
</div>
<h5 class='topic'>REST Testing Framework</h5>
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/mock/MockRestClient.html" title="class in org.apache.juneau.rest.mock"><code>MockRestClient</code></a> class is used for performing serverless unit testing of <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a>-annotated
and <a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>@Remote</code></a>-annotated classes. It perform full serialization and parsing of the HTTP request and responses,
but bypasses the network layer to significantly improve speed while still performing real testing.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>public class</jk> MockTest {
<jc>// A simple bean with one field.</jc>
<jk>public static class</jk> MyBean {
<jk>public int</jk> <jf>foo</jf> = 1;
}
<jc>// Our REST resource to test.</jc>
<jc>// Simply echos the response.</jc>
<ja>@Rest</ja>
<jk>public static class</jk> EchoRest <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicJsonConfig {
<ja>@RestPut</ja>
<jk>public</jk> MyBean echo(<ja>@Content</ja> MyBean <jv>bean</jv>) {
<jk>return</jk> <jv>bean</jv>;
}
}
<jc>// Our JUnit test.</jc>
<ja>@Test</ja>
<jk>public void</jk> testEcho() <jk>throws</jk> Exception {
MyBean <jv>myBean</jv> = <jk>new</jk> MyBean();
<jc>// Do a round-trip on the bean through the REST interface</jc>
<jv>myBean</jv> = MockRestClient
.<jsm>create</jsm>(EchoRest.<jk>class</jk>)
.simpleJson()
.build()
.put(<js>"/echo"</js>, <jv>myBean</jv>)
.run()
.assertStatus().is(200)
.assertContent().is(<js>"{foo:1}"</js>)
.getContent().as(MyBean.<jk>class</jk>);
<jsm>assertEquals</jsm>(1, <jv>myBean</jv>.<jf>foo</jf>);
}
}
</p>
</div>
<h5 class='topic'>Additional Information</h5>
<div class='topic'>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-rest-client'>Overview &gt; juneau-rest-client</a> for more information.
</ul>
</div>
</div><!-- END: 1.4 - Overview.o.RestClient -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Overview.o.Dtos' id='Overview.o.Dtos'>1.5 - DTOs</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 1.5 - Overview.o.Dtos -->
<div class='topic'>
<p>
The <a class='doclink' href='#juneau-dto'>juneau-dto</a> library contains several predefined POJOs for generating commonly-used document types that
are designed to be used with the Juneau Marshaller APIs for both serializing and parsing.
</p>
</div>
<h5 class='topic'>HTML5</h5>
<div class='topic'>
<p>
The Juneau HTML5 DTOs are simply beans with fluent-style setters that allow you to quickly construct HTML
fragments as Java objects. These object can then be serialized to HTML using one of the existing HTML
serializers, or to other languages such as JSON using the JSON serializers.
</p>
<p>
The <a href="org/apache/juneau/dto/html5/HtmlBuilder.html" title="class in org.apache.juneau.dto.html5"><code>HtmlBuilder</code></a> class is a utility class with predefined static methods
that allow you to easily construct DTO instances in a minimal amount of code.
</p>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
<jc>// An HTML table</jc>
Object <jv>mytable</jv> =
<jsm>table</jsm>(
<jsm>tr</jsm>(
<jsm>th</jsm>(<js>"c1"</js>),
<jsm>th</jsm>(<js>"c2"</js>)
),
<jsm>tr</jsm>(
<jsm>td</jsm>(<js>"v1"</js>),
<jsm>td</jsm>(<js>"v2"</js>)
)
);
String <jv>html</jv> = Html.<jsm>of</jsm>(<jv>mytable</jv>);
</p>
<p class='bxml'><xt>
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;<xv>c1</xv>&lt;/th&gt;
&lt;th&gt;<xv>c2</xv>&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>v1</xv>&lt;/td&gt;
&lt;td&gt;<xv>v2</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
</xt></p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-dto.jd.Html5'>HTML5</a> for more information.
</ul>
</div>
<h5 class='topic'>ATOM</h5>
<div class='topic'>
<p>
The Juneau ATOM feed DTOs are simply beans with fluent-style setters.
The following code shows a feed being created programmatically using the
<a href="org/apache/juneau/dto/atom/AtomBuilder.html" title="class in org.apache.juneau.dto.atom"><code>AtomBuilder</code></a> class.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.atom.AtomBuilder.*;
Feed <jv>feed</jv> =
<jsm>feed</jsm>(<js>"tag:juneau.apache.org"</js>, <js>"Juneau ATOM specification"</js>, <js>"2016-01-02T03:04:05Z"</js>)
.subtitle(<jsm>text</jsm>(<js>"html"</js>).text(<js>"Describes &lt;em&gt;stuff&lt;/em&gt; about Juneau"</js>))
.links(
<jsm>link</jsm>(<js>"alternate"</js>, <js>"text/html"</js>, <js>"http://juneau.apache.org"</js>).hreflang(<js>"en"</js>),
<jsm>link</jsm>(<js>"self"</js>, <js>"application/atom+xml"</js>, <js>"http://juneau.apache.org/feed.atom"</js>)
)
.rights(<js>"Copyright (c) ..."</js>)
.generator(
<jsm>generator</jsm>(<js>"Juneau"</js>).uri(<js>"http://juneau.apache.org/"</js>).version(<js>"1.0"</js>)
)
.entries(
<jsm>entry</jsm>(<js>"tag:juneau.sample.com,2013:1.2345"</js>, <js>"Juneau ATOM specification snapshot"</js>, <js>"2016-01-02T03:04:05Z"</js>)
.links(
<jsm>link</jsm><js>"alternate"</js>, <js>"text/html"</js>, <js>"http://juneau.apache.org/juneau.atom"</js>),
<jsm>link</jsm>(<js>"enclosure"</js>, <js>"audio/mpeg"</js>, <js>"http://juneau.apache.org/audio/juneau_podcast.mp3"</js>).length(1337)
)
.published(<js>"2016-01-02T03:04:05Z"</js>)
.authors(
<jsm>person</jsm>(<js>"Jane Smith"</js>).uri(<js>"http://juneau.apache.org/"</js>).email(<js>"janesmith@apache.org"</js>)
)
.contributors(
<jsm>person</jsm>(<js>"John Smith"</js>)
)
.content(
<jsm>content</jsm>(<js>"xhtml"</js>)
.lang(<js>"en"</js>)
.base(<js>"http://www.apache.org/"</js>)
.text(<js>"&lt;div&gt;&lt;p&gt;&lt;i&gt;[Update: Juneau supports ATOM.]&lt;/i&gt;&lt;/p&gt;&lt;/div&gt;"</js>)
)
);
<jc>// Create a serializer with readable output, no namespaces yet.</jc>
XmlSerializer <jv>serializer</jv> = XmlSerializer.<jsm>create</jsm>().sq().ws().build();
<jc>// Serialize to ATOM/XML</jc>
String <jv>atomXml</jv> = <jv>serializer</jv>.serialize(<jv>feed</jv>);
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-dto.jd.Atom'>Atom</a> for more information.
</ul>
</div>
<h5 class='topic'>Swagger</h5>
<div class='topic'>
<p>
The Juneau Swagger DTOs are simply beans with fluent-style setters that allow you to quickly construct
Swagger documents as Java objects.
These object can then be serialized to JSON using one of the existing JSON serializers, or to other
languages such as XML or HTML using the other serializers.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>static import</jk> org.apache.juneau.dto.swagger.SwaggerBuilder.*;
Swagger <jv>swagger</jv> = <jsm>swagger</jsm>()
.swagger(<js>"2.0"</js>)
.info(
<jsm>info</jsm>(<js>"Swagger Petstore"</js>, <js>"1.0.0"</js>)
.description(<js>"This is a sample server Petstore server."</js>)
.termsOfService(<js>"http://swagger.io/terms/"</js>)
.contact(
<jsm>contact</jsm>().email(<js>"apiteam@swagger.io"</js>)
)
.license(
<jsm>license</jsm>(<js>"Apache 2.0"</js>).url(<js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>)
)
)
.host(<js>"petstore.swagger.io"</js>)
.basePath(<js>"/v2"</js>)
.tags(
<jsm>tag</jsm>(<js>"pet"</js>).description(<js>"Everything about your Pets"</js>)
.externalDocs(
<jsm>externalDocumentation</jsm>(<js>"http://swagger.io"</js>, <js>"http://swagger.io"</js>)
)
)
.schemes(<js>"http"</js>)
.path(<js>"/pet"</js>, <js>"post"</js>,
<jsm>operation</jsm>()
.tags(<js>"pet"</js>)
.summary(<js>"Add a new pet to the store"</js>)
.description(<js>""</js>)
.operationId(<js>"addPet"</js>)
.consumes(MediaType.<jsf>JSON</jsf>, MediaType.<jsf>XML</jsf>)
.produces(MediaType.<jsf>JSON</jsf>, MediaType.<jsf>XML</jsf>)
.parameters(
<jsm>parameterInfo</jsm>(<js>"body"</js>, <js>"body"</js>)
.description(<js>"Pet object that needs to be added to the store"</js>)
.required(<jk>true</jk>)
)
.response(405, <jsm>responseInfo</jsm>(<js>"Invalid input"</js>))
);
<jc>// Serialize using JSON serializer.</jc>
String <jv>swaggerJson</jv> = Json.<jsm>of</jsm>(<jv>swagger</jv>);
<jc>// Or just use toString() or asJson().</jc>
String <jv>swaggerJson</jv> = <jv>swagger</jv>.asJson();
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-dto.jd.Swagger'>Swagger</a> for more information.
</ul>
</div>
<h5 class='topic'>SwaggerUI</h5>
<div class='topic'>
<p>
The <a href="org/apache/juneau/dto/swagger/ui/SwaggerUI.html" title="class in org.apache.juneau.dto.swagger.ui"><code>SwaggerUI</code></a> class is a DTO class for generating Swagger user interfaces
from <a href="org/apache/juneau/dto/swagger/Swagger.html" title="class in org.apache.juneau.dto.swagger"><code>Swagger</code></a> beans.
</p>
<p>
The <c>PetStore</c> example described later provides an example of auto-generated Swagger JSON:
</p>
<img class='bordered w900' src='doc-files/jd.SwaggerUI.json.png'>
<p>
Using <a href="org/apache/juneau/dto/swagger/ui/SwaggerUI.html" title="class in org.apache.juneau.dto.swagger.ui"><code>SwaggerUI</code></a>, we're able to render that JSON as a Swagger user interface
when the request is asking for HTML:
</p>
<img class='bordered w900' src='doc-files/jd.SwaggerUI.html.png'>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-dto.jd.SwaggerUi'>Swagger UI</a> for more information.
</ul>
</div>
</div><!-- END: 1.5 - Overview.o.Dtos -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Overview.o.ConfigFiles' id='Overview.o.ConfigFiles'>1.6 - Config Files</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 1.6 - Overview.o.ConfigFiles -->
<div class='topic'>
<p>
The <a class='doclink' href='#juneau-config'>juneau-config</a> library contains a powerful API for creating and using INI-style config files.
</p>
<h5 class='figure'>Example configuration file:</h5>
<p class='bini'>
<cc># A set of entries</cc>
<cs>[Section1]</cs>
<cc># An integer</cc>
<ck>key1</ck> = <cv>1</cv>
<cc># A boolean</cc>
<ck>key2</ck> = <cv>true</cv>
<cc># An array</cc>
<ck>key3</ck> = <cv>1,2,3</cv>
<cc># A POJO</cc>
<ck>key4</ck> = <cv>http://bar</cv>
</p>
<p>
Config files are accessed through the <a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a> class which
are created through the <a href="org/apache/juneau/config/Config.Builder.html" title="class in org.apache.juneau.config"><code>Config.Builder</code></a> class.
Builder creator methods are provided on the <c>Config</c> class:
</p>
<p class='bjava'>
<jc>// Create a Config object</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
<jc>// Read values from section #1</jc>
<jk>int</jk> <jv>key1</jv> = <jv>config</jv>.getInt(<js>"Section1/key1"</js>);
<jk>boolean</jk> <jv>key2</jv> = <jv>config</jv>.getBoolean(<js>"Section1/key2"</js>);
<jk>int</jk>[] <jv>key3</jv> = <jv>config</jv>.getObject(<js>"Section1/key3"</js>, <jk>int</jk>[].<jk>class</jk>);
URL <jv>key4</jv> = <jv>config</jv>.getObject(<js>"Section1/key4"</js>, URL.<jk>class</jk>);
</p>
<p>
The config language may look simple but it is a very powerful feature with many capabilities.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-config'>juneau-config</a> for more information.
</ul>
</div>
</div><!-- END: 1.6 - Overview.o.ConfigFiles -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Overview.o.FluentAssertions' id='Overview.o.FluentAssertions'>1.7 - Fluent Assertions</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 1.7 - Overview.o.FluentAssertions -->
<div class='topic'>
<p>
The <a class='doclink' href='#juneau-assertions'>juneau-assertions</a> module in Juneau is a powerful API for performing fluent style assertions.
</p>
<p>
Fluent assertions have two types of methods:
</p>
<ul>
<li><c>"asX"</c> methods which perform transformations.
<li><c>"isX"</c> methods which perform assertions.
</ul>
<p>
Multiple transformations and assertions can be performed per statement.
</p>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.assertions.Assertions.*;
<jk>import static</jk> org.apache.juneau.assertions.AssertionPredicates.*;
<jc>// Check the contents of a string.</jc>
<jsm>assertString</jsm>(<js>"foo, bar"</js>)
.asSplit(<js>","</js>)
.asTrimmed()
.is(<js>"foo"</js>, <js>"bar"</js>);
<jc>// Extract a subset of properties from a list of beans and compare using Simplified JSON.</jc>
List&lt;MyBean&gt; <jv>myListOfBeans</jv> = ...;
<jsm>assertBeanList</jsm>(<jv>myListOfBeans</jv>)
.asPropertyMaps(<js>"a,b"</js>)
.asJson().is(<js>"[{a:1,b:'foo'}]"</js>);
<jc>// Perform an arbitrary Predicate check against a bean.</jc>
MyBean <jv>myBean</jv> = ...;
<jsm>assertBean</jsm>(<jv>myBean</jv>)
.is(<jv>x</jv> -> <jsm>isValidCheck</jsm>(<jv>x</jv>))
<jc>// Check that a list of strings has less than 10 entries and the first</jc>
<jc>// 3 entries are [foo, bar*, null] using assertion predicates.</jc>
List&lt;String&gt; <jv>myListOfStrings</jv> = ...;
<jsm>assertStringList</jsm>(<jv>myListOfStrings</jv>)
.asSize().isLt(10)
.asFirst(3)
.is(<jsm>eq</jsm>(<js>"foo"</js>),<jsm>match</jsm>(<js>"bar*"</js>),<jsm>isNull</jsm>())
<jc>// Check that an exception is thrown and is the specified type and has the specified message.</jc>
<jsm>assertThrown</jsm>(()-><jv>myBean</jv>.runBadMethod())
.isExists()
.isExactType(RuntimeException.<jk>class</jk>)
.asMessage().is(<js>"foo"</js>);
</p>
<p>
The Assertions APIs are used throughout the REST client and server APIs for performing inline assertions on REST requests and responses.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a basic REST client with JSON support and download a bean.</jc>
MyBean <jv>bean</jv> = RestClient.<jsm>create</jsm>()
.simpleJson()
.build()
.get(<jsf>URI</jsf>)
.run()
.assertStatus().asCode().is(200)
.assertHeader(<js>"Content-Type"</js>).isMatches(<js>"application/json*"</js>)
.getContent().assertValue().asString().isContains(<js>"OK"</js>)
.getContent().as(MyBean.<jk>class</jk>);
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-assertions.ja.Overview'>Fluent Assertions</a> for more information.
</ul>
</div>
</div><!-- END: 1.7 - Overview.o.FluentAssertions -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Overview.o.GeneralDesign' id='Overview.o.GeneralDesign'>1.8 - General Design</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 1.8 - Overview.o.GeneralDesign -->
<div class='topic'>
<p>
The Juneau framework uses the design pattern of builders, context, and session objects:
</p>
<ul>
<li>Context Builders - Modifiable objects that allow you to define configuration settings for contexts.
<li>Contexts - Unmodifiable thread-safe objects meant to be cacheable and reusable.
<li>Sessions - Modifiable objects usually meant for one-time use.
</ul>
<p>
This is a general design pattern used throughout the framework including the REST client and server APIs.
</p>
<p>
The following shows the general pattern for creating sessions:
</p>
<p class='bjava'>
<jc>// Create a reusable context object (in this case a serializer).</jc>
WriterSerializer <jv>serializer</jv> = JsonSerializer
.<jsm>create</jsm>() <jc>// Instantiates a context builder.</jc>
.findFluentSetters() <jc>// Sets a configuration value.</jc>
.build(); <jc>// Creates a context.</jc>
<jc>// Create a one-time session object.</jc>
WriterSerializerSession <jv>session</jv> = <jv>serializer</jv>
.createSession() <jc>// Instantiates a session builder.</jc>
.useWhitespace() <jc>// Sets a session value.</jc>
.build(); <jc>// Creates a session.</jc>
<jc>// Use it.</jc>
String <jv>json</jv> = <jv>session</jv>.serialize(<jv>myBean</jv>);
</p>
<p>
Typically developers will not deal with session objects and will just use convenience
methods on the context classes themselves that handle creation of sessions:
</p>
<p class='bjava'>
<jc>// Just use serialize method on WriterSerializer class.</jc>
String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>myBean</jv>);
</p>
<p>
Most context objects also have static default instances that can be used in leu of
creating new contexts as well:
</p>
<p class='bjava'>
<jc>// Just use one of the static context instances.</jc>
String <jv>json</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>myBean</jv>);
</p>
<p>
Most context classes also have the ability to clone and modify existing context objects:
</p>
<p class='bjava'>
<jc>// Clone and modify an existing context object.</jc>
WriterSerializer <jv>serializer</jv> = JsonSerializer
.<jsf>DEFAULT</jsf>
.copy() <jc>// Instantiates a context builder.</jc>
.findFluentSetters() <jc>// Sets a configuration value.</jc>
.build(); <jc>// Creates a context.</jc>
</p>
<p>
The default values of many context settings can also be set via system properties and environment variables.
The javadocs on these settings will identify when this is possible.
</p>
<p>
The framework makes heavy use of caching of existing context objects with the same builder settings.
This is a critical reason why Juneau achieve impressive performance.
Using Java reflection to find out all information about a bean type is expensive.
By caching context objects, we only need to reflect that bean type once and store that information in the context
for reuse by all serializers and parsers that share the same bean context configuration settings.
</p>
</div>
</div><!-- END: 1.8 - Overview.o.GeneralDesign -->
</div><!-- END: 1 - Overview -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-marshall' id='juneau-marshall'>2 - juneau-marshall</a></h2>
<div class='topic'><!-- START: 2 - juneau-marshall -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-marshall<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-marshall-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.marshall_9.0.0.jar
</p>
<p>
The <c>juneau-marshall</c> artifact contains the following:
</p>
<ul>
<li>Foundation for all serializers and parsers.
<li>Implementations for all serializers and parsers except RDF languages.
<li>Extensions to Apache HttpCore components used by both client and server APIs.
<li>Assertions APIs.
<li>Various reusable utilities used throughout the framework.
</ul>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Marshallers' id='juneau-marshall.jm.Marshallers'>2.1 - Marshallers</a></h3>
<div class='topic'><!-- START: 2.1 - juneau-marshall.jm.Marshallers -->
<div class='topic'>
<p>
<a href="org/apache/juneau/marshaller/Marshaller.html" title="class in org.apache.juneau.marshaller"><code>Marshallers</code></a> are simple pairings of a <a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a>
and <a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a> with convenience methods for serializing and parsing POJOs.
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/marshaller/Marshaller.html" title="class in org.apache.juneau.marshaller"><code>Marshaller</code></a>
<ul>
<li class='jm'><c>T</c>&nbsp;&nbsp;<a href="org/apache/juneau/marshaller/Marshaller.html#read-java.lang.Object-java.lang.Class-"><code>read(Object,Class&lt;T&gt;)</code></a>
</ul>
<ul>
<li class='jac'><a href="org/apache/juneau/marshaller/CharMarshaller.html" title="class in org.apache.juneau.marshaller"><code>CharMarshaller</code></a>
<ul>
<li class='jm'><c>String</c>&nbsp;&nbsp;<a href="org/apache/juneau/marshaller/CharMarshaller.html#write-java.lang.Object-"><code>write(Object)</code></a>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/marshaller/Csv.html" title="class in org.apache.juneau.marshaller"><code>Csv</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Html.html" title="class in org.apache.juneau.marshaller"><code>Html</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Json.html" title="class in org.apache.juneau.marshaller"><code>Json</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/OpenApi.html" title="class in org.apache.juneau.marshaller"><code>OpenApi</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/PlainText.html" title="class in org.apache.juneau.marshaller"><code>PlainText</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/SimpleJson.html" title="class in org.apache.juneau.marshaller"><code>SimpleJson</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Uon.html" title="class in org.apache.juneau.marshaller"><code>Uon</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/UrlEncoding.html" title="class in org.apache.juneau.marshaller"><code>UrlEncoding</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Xml.html" title="class in org.apache.juneau.marshaller"><code>Xml</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/N3.html" title="class in org.apache.juneau.marshaller"><code>N3</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/NTriple.html" title="class in org.apache.juneau.marshaller"><code>NTriple</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/RdfXml.html" title="class in org.apache.juneau.marshaller"><code>RdfXml</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/RdfXmlAbbrev.html" title="class in org.apache.juneau.marshaller"><code>RdfXmlAbbrev</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Turtle.html" title="class in org.apache.juneau.marshaller"><code>Turtle</code></a>
</ul>
</ul>
<li class='jac'><a href="org/apache/juneau/marshaller/StreamMarshaller.html" title="class in org.apache.juneau.marshaller"><code>StreamMarshaller</code></a>
<ul>
<li class='jm'><c><jk>byte</jk>[]</c>&nbsp;&nbsp;<a href="org/apache/juneau/marshaller/StreamMarshaller.html#write-java.lang.Object-"><code>write(Object)</code></a>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/marshaller/MsgPack.html" title="class in org.apache.juneau.marshaller"><code>MsgPack</code></a>
</ul>
</ul>
</ul>
</ul>
</li>
</ul>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Using instance.</jc>
Json <jv>json</jv> = <jk>new</jk> Json();
MyPojo <jv>myPojo</jv> = <jv>json</jv>.read(<jv>string</jv>, MyPojo.<jk>class</jk>);
String <jv>string</jv> = <jv>json</jv>.write(<jv>myPojo</jv>);
</p>
<p class='bjava'>
<jc>// Using DEFAULT instance.</jc>
MyPojo <jv>myPojo</jv> = Json.<jsf>DEFAULT</jsf>.read(<jv>string</jv>, MyPojo.<jk>class</jk>);
String <jv>string</jv> = Json.<jsf>DEFAULT</jsf>.write(<jv>myPojo</jv>);
</p>
<p>
Juneau comes with the following predefined marshallers:
</p>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/marshaller/Csv.html" title="class in org.apache.juneau.marshaller"><code>Csv</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Html.html" title="class in org.apache.juneau.marshaller"><code>Html</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Json.html" title="class in org.apache.juneau.marshaller"><code>Json</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/MsgPack.html" title="class in org.apache.juneau.marshaller"><code>MsgPack</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/OpenApi.html" title="class in org.apache.juneau.marshaller"><code>OpenApi</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/PlainText.html" title="class in org.apache.juneau.marshaller"><code>PlainText</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/SimpleJson.html" title="class in org.apache.juneau.marshaller"><code>SimpleJson</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Uon.html" title="class in org.apache.juneau.marshaller"><code>Uon</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/UrlEncoding.html" title="class in org.apache.juneau.marshaller"><code>UrlEncoding</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Xml.html" title="class in org.apache.juneau.marshaller"><code>Xml</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/N3.html" title="class in org.apache.juneau.marshaller"><code>N3</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/NTriple.html" title="class in org.apache.juneau.marshaller"><code>NTriple</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/RdfXml.html" title="class in org.apache.juneau.marshaller"><code>RdfXml</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/RdfXmlAbbrev.html" title="class in org.apache.juneau.marshaller"><code>RdfXmlAbbrev</code></a>
<li class='jc'><a href="org/apache/juneau/marshaller/Turtle.html" title="class in org.apache.juneau.marshaller"><code>Turtle</code></a>
</ul>
<p>
Each predefined marshaller also includes static convenience from/to methods to make it even easier to
perform marshalling on POJOs:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/marshaller/Json.html" title="class in org.apache.juneau.marshaller"><code>Json</code></a>
<ul>
<li class='jm'><c>String</c>&nbsp;&nbsp;<i><a href="org/apache/juneau/marshaller/Json.html#of-java.lang.Object-"><code>of(Object)</code></a></i>
<li class='jm'><c>T</c>&nbsp;&nbsp;<i><a href="org/apache/juneau/marshaller/Json.html#to-java.lang.Object-java.lang.Class-"><code>to(Object,Class&lt;T&gt;)</code></a></i>
</ul>
</li>
</ul>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Using shortcut static methods.</jc>
MyPojo <jv>myPojo</jv> = Json.<jsm>to</jsm>(<jv>jsonString</jv>, MyPojo.<jk>class</jk>);
String <jv>json</jv> = Json.<jsm>of</jsm>(<jv>myPojo</jv>);
</p>
</div>
</div><!-- END: 2.1 - juneau-marshall.jm.Marshallers -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.SerializersAndParsers' id='juneau-marshall.jm.SerializersAndParsers'>2.2 - Serializers and Parsers</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.2 - juneau-marshall.jm.SerializersAndParsers -->
<div class='topic'>
<p>
One of the goals of Juneau was to make serialization as simple as possible.
In a single line of code, you should be able to serialize and parse most POJOs.
Despite this simplicity, Juneau provides lots of extensibility and configuration properties for tailoring how
POJOs are serialized and parsed.
</p>
<p>
The built-in serializers in Juneau are fast, efficient, and highly configurable.
They work by serializing POJOs directly to streams instead of using intermediate Document Object Model
objects.
</p>
<p>
In most cases, you can serialize objects in one line of code by using one of the default serializers:
</p>
<p class='bjava'>
<jc>// A simple bean</jc>
<jk>public class</jk> Person {
<jk>public</jk> String <jf>name</jf> = <js>"John Smith"</js>;
<jk>public int</jk> <jf>age</jf> = 21;
}
<jc>// Serialize to JSON, XML, or HTML</jc>
Person <jv>person</jv> = <jk>new</jk> Person();
<jc>// Produces:
// "{\"name\":\"John Smith\",\"age\":21}"</jc>
String <jv>json</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>person</jv>);
<jc>// Produces:
// "{name:'John Smith',age:21}"</jc>
String <jv>json</jv> = SimpleJsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>person</jv>);
<jc>// Produces:
// &lt;object&gt;
// &lt;name&gt;John Smith&lt;/name&gt;
// &lt;age&gt;21&lt;/age&gt;
// &lt;/object&gt;</jc>
String <jv>xml</jv> = XmlSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>person</jv>);
<jc>// Produces:
// &lt;table&gt;
// &lt;tr&gt;&lt;th&gt;key&lt;/th&gt;&lt;th&gt;value&lt;/th&gt;&lt;/tr&gt;
// &lt;tr&gt;&lt;td&gt;name&lt;/td&gt;&lt;td&gt;John Smith&lt;/td&gt;&lt;/tr&gt;
// &lt;tr&gt;&lt;td&gt;age&lt;/td&gt;&lt;td&gt;21&lt;/td&gt;&lt;/tr&gt;
// &lt;/table&gt;</jc>
String <jv>html</jv> = HtmlSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>person</jv>);
<jc>// Produces:
// "(name='John Smith',age=21)"</jc>
String <jv>uon</jv> = UonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>person</jv>);
<jc>// Produces:
// "name='John+Smith'&amp;age=21"</jc>
String <jv>urlencoding</jv> = UrlEncodingSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>person</jv>);
<jc>// Produces:
// 82 A4 6E 61 6D 65 AA 4A 6F 68 6E 20 53 6D 69 74 68 A3 61 67 65 15 </jc>
<jk>byte</jk>[] <jv>bytes</jv> = MsgPackSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>person</jv>);
</p>
<p>
In addition to the default serializers, customized serializers can be created using various built-in options:
</p>
<p class='bjava'>
<jc>// Use one of the default serializers to serialize a POJO</jc>
String <jv>json</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>someObject</jv>);
<jc>// Create a custom serializer for lax syntax using single quote characters</jc>
JsonSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().simple().sq().build();
<jc>// Clone an existing serializer and modify it to use single-quotes</jc>
JsonSerializer <jv>serializer</jv> = JsonSerializer.<jsf>DEFAULT</jsf>.copy().sq().build();
<jc>// Serialize a POJO to JSON</jc>
String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>someObject</jv>);
</p>
<p>
Default serialization support is provided for Java primitives, <c>Maps</c>, <c>Collections</c>,
beans, and arrays.
Extensible support for other data types such as <c>Calendars</c>, <c>Dates</c>,
<c>Iterators</c> is available through the use of POJO swaps (described later).
</p>
<hr>
<p>
Parsers work by parsing input directly into POJOs instead of having to create intermediate Document Object
Models.
This allows them to parse input with minimal object creation.
</p>
<p>
Like the serializers, you can often parse objects in one line of code by using one of the default parsers:
</p>
<p class='bjava'>
<jc>// Use one of the predefined parsers.</jc>
Parser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>;
<jc>// Parse a JSON object as a bean.</jc>
String <jv>json</jv> = <js>"{name:'John Smith',age:21}"</js>;
Person <jv>person</jv> = <jv>parser</jv>.parse(<jv>json</jv>, Person.<jk>class</jk>);
<jc>// Or parse it into a generic Map.</jc>
Map <jv>map</jv> = <jv>parser</jv>.parse(<jv>json</jv>, Map.<jk>class</jk>);
<jc>// Parse a JSON string.</jc>
<jv>json</jv> = <js>"'foobar'"</js>;
String <jv>string</jv> = <jv>parser</jv>.parse(<jv>json</jv>, String.<jk>class</jk>);
<jc>// Parse a JSON number as a Long or Float.</jc>
<jv>json</jv> = <js>"123"</js>;
Long <jv>_long</jv> = <jv>parser</jv>.parse(<jv>json</jv>, Long.<jk>class</jk>);
Float <jv>_float</jv> = <jv>parser</jv>.parse(<jv>json</jv>, Float.<jk>class</jk>);
<jc>// Parse a JSON object as a HashMap&lt;String,Person&gt;.</jc>
<jv>json</jv> = <js>"{a:{name:'John Smith',age:21},b:{name:'Joe Smith',age:42}}"</js>;
Map&lt;String,Person&gt; <jv>map2</jv> = <jv>parser</jv>.parse(<jv>json</jv>, HashMap.<jk>class</jk>, String.<jk>class</jk>, Person.<jk>class</jk>)
<jc>// Parse a JSON object as a HashMap&lt;String,LinkedList&lt;Person&gt;&gt;.</jc>
<jv>json</jv> = <js>"{a:[{name:'John Smith',age:21},{name:'Joe Smith',age:42}]}"</js>;
Map&lt;String,List&lt;Person&gt;&gt; <jv>map3</jv> = <jv>parser</jv>.parse(<jv>json</jv>, HashMap.<jk>class</jk>, String.<jk>class</jk>,
LinkedList.<jk>class</jk>, Person.<jk>class</jk>)
<jc>// Parse a JSON array of integers as a Collection of Integers or int[] array.</jc>
<jv>json</jv> = <js>"[1,2,3]"</js>;
List&lt;Integer&gt; <jv>list</jv> = <jv>parser</jv>.parse(<jv>json</jv>, LinkedList.<jk>class</jk>, Integer.<jk>class</jk>);
<jk>int</jk>[] <jv>ints</jv> = <jv>parser</jv>.parse(<jv>json</jv>, <jk>int</jk>[].<jk>class</jk>);
</p>
<p>
The parsers can also be used to populating existing bean and collection objects:
</p>
<p class='bjava'>
<jc>// Use one of the predefined parsers.</jc>
Parser <jv>parser</jv> = JsonParser.<jsf>DEFAULT</jsf>;
<jc>// Populate the properties on an existing bean from a JSON object.</jc>
String <jv>json</jv> = <js>"{name:'John Smith',age:21}"</js>;
Person <jv>person</jv> = <jk>new</jk> Person();
<jv>parser</jv>.parseIntoBean(<jv>json</jv>, <jv>person</jv>);
<jc>// Populate an existing list from a JSON array of numbers.</jc>
<jv>json</jv> = <js>"[1,2,3]"</js>;
List&lt;Integer&gt; <jv>list</jv> = <jk>new</jk> LinkedList&lt;Integer&gt;();
<jv>parser</jv>.parseIntoCollection(<jv>json</jv>, <jv>list</jv>, Integer.<jk>class</jk>);
<jc>// Populate an existing map from a JSON object containing beans.</jc>
<jv>json</jv> = <js>"{a:{name:'John Smith',age:21},b:{name:'Joe Smith',age:42}}"</js>;
Map&lt;String,Person&gt; <jv>map</jv> = <jk>new</jk> TreeMap&lt;String,Person&gt;();
<jv>parser</jv>.parseIntoMap(<jv>json</jv>, <jv>map</jv>, String.<jk>class</jk>, Person.<jk>class</jk>);
</p>
<br>
<div class='info'>
In the example above, we're parsing "lax" JSON (single quotes, unquoted attributes).
The JSON parser can handle any valid JSON syntax (such as quoted or unquoted attributes, single or double
quotes).
It can also handle JSON fragments and embedded Javascript comments.
Many of the JSON examples provided will use lax syntax which is easier to read since we don't have to deal
with escapes.
</div>
<ul class='seealso'>
<li class='doclink'><a class='doclink' href='#Glossaries.g.LanguageSupport'>Language Support</a> - Glossary of all supported languages.
<li class='jc'><a href="org/apache/juneau/examples/serializer/ImageSerializer.html" title="class in org.apache.juneau.examples.serializer"><code>ImageSerializer</code></a> - Example of a custom serializer.
<li class='jc'><a href="org/apache/juneau/examples/parser/ImageParser.html" title="class in org.apache.juneau.examples.parser"><code>ImageParser</code></a> - Example of a custom parser.
</ul>
</div>
</div><!-- END: 2.2 - juneau-marshall.jm.SerializersAndParsers -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.BeanContexts' id='juneau-marshall.jm.BeanContexts'>2.3 - Bean Contexts</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.3 - juneau-marshall.jm.BeanContexts -->
<div class='topic'>
<p>
At the heart of the marshalling APIs is the <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>Bean Context</code></a> API that provides a common
framework for marshalling beans and POJOs across all serializers and parsers.
All serializers and parsers (and their builders) extend from the bean context API classes.
</p>
<p>
One important feature of the bean context API is the ability to wrap Java beans inside maps to allow
properties to be accessed through a Map layer. Although this is used internally by all the serializers and parsers,
it's often useful to use this feature by itself.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Wrap a bean in a map and do some simple get/set calls.</jc>
BeanMap&lt;MyBean&gt; <jv>myBeanMap</jv> = BeanContext.<jsf>DEFAULT_SESSION</jsf>.toBeanMap(<jv>myBean</jv>);
<jv>myBeanMap</jv>.put(<js>"myProperty"</js>, 123);
<jk>int</jk> <jv>myProperty</jv> = <jv>myBeanMap</jv>.get(<js>"myProperty"</js>, <jk>int</jk>.<jk>class</jk>);
</p>
<p>
The bean context API provides many settings that fine-tune how POJOs should be handled during marshalling.
</p>
<ul class='seealso'>
<li class='jc'><a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
</ul>
</div>
</div><!-- END: 2.3 - juneau-marshall.jm.BeanContexts -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JavaBeansSupport' id='juneau-marshall.jm.JavaBeansSupport'>2.4 - Java Beans Support</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.4 - juneau-marshall.jm.JavaBeansSupport -->
<div class='topic'>
<p>
Out-of-the-box, Juneau supports marshalling of Java beans with standard public getters and setters, public
fields, and fluent setters (e.g. <c>withX</c> naming convention). There are also many settings and
annotations that can be used to customize how bean properties are detected. The following is an example of
some of the ways to define bean properties:
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jc>// Public field property.</jc>
<jk>public</jk> String <jf>property1</jf>;
<jc>// Standard public getters/setters.</jc>
<jk>public</jk> String getProperty2() {...}
<jk>public void</jk> setProperty2(String <jv>value</jv>) {...}
<jc>// With fluent-style setter.</jc>
<jk>public</jk> String getProperty3() {...}
<jk>public</jk> MyBean withProperty3(String <jv>value</jv>) {...}
<jc>// Read-only property (ignored by parsers).</jc>
<jk>public</jk> String getProperty4() {...}
<jc>// Write-only property (ignored by serializers).</jc>
<jk>public void</jk> setProperty5(String <jv>value</jv>) {...}
<jc>// Non-standard getters/setters identified by annotation.</jc>
<ja>@Beanp</ja>
<jk>public</jk> String property6() {...}
<ja>@Beanp</ja>
<jk>public void</jk> property6(String value) {...}
<jc>// Non-standard getters/setters identified by annotation with overridden names.</jc>
<ja>@Beanp</ja>(<js>"property7"</js>)
<jk>public</jk> String property7X() {...}
<ja>@Beanp</ja>(<js>"property7"</js>)
<jk>public void</jk> property7X(String <jv>value</jv>) {...}
<jc>// Non-public getters/setters identified by annotation.</jc>
<ja>@Beanp</ja>
<jk>private</jk> String getProperty8() {...}
<ja>@Beanp</ja>
<jk>private void</jk> setProperty8(String <jv>value</jv>) {...}
<jc>// Ignore a method that looks like a getter.</jc>
<ja>@BeanIgnore</ja>
<jk>public</jk> String getNotAProperty() {...}
}
</p>
<p>
Several settings exist to allow you to customize how bean properties are handled by serializers and parsers:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanClassVisibility-org.apache.juneau.Visibility-"><code>beanClassVisibility(Visibility)</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanConstructorVisibility-org.apache.juneau.Visibility-"><code>beanConstructorVisibility(Visibility)</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanFieldVisibility-org.apache.juneau.Visibility-"><code>beanFieldVisibility(Visibility)</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanMethodVisibility-org.apache.juneau.Visibility-"><code>beanMethodVisibility(Visibility)</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beansRequireDefaultConstructor--"><code>beansRequireDefaultConstructor()</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beansRequireSerializable--"><code>beansRequireSerializable()</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beansRequireSettersForGetters--"><code>beansRequireSettersForGetters()</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#disableBeansRequireSomeProperties--"><code>disableBeansRequireSomeProperties()</code></a>
</ul>
</li>
</ul>
<p>
Settings and equivalent annotations are also available to control which properties are marshalled and how they are ordered.
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanProperties-java.lang.Class-java.lang.String-"><code>beanProperties(Class,String)</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanPropertiesExcludes-java.lang.Class-java.lang.String-"><code>beanPropertiesExcludes(Class,String)</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanPropertiesReadOnly-java.lang.Class-java.lang.String-"><code>beanPropertiesReadOnly(Class,String) </code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanPropertiesWriteOnly-java.lang.Class-java.lang.String-"><code>beanPropertiesWriteOnly(Class,String)</code></a>
</ul>
</li>
</ul>
<p>
It's common to use the <a href="org/apache/juneau/annotation/Bean.html#properties--"><code>@Bean(properties|p)</code></a> annotation to force the ordering
of properties during marshalling. IBM JVMs keep the ordering of fields and methods in the compiled bytecodebut
Oracle JVMs do not and return fields/methods in random order. The <a href="org/apache/juneau/annotation/Bean.html#properties--"><code>@Bean(properties|p)</code></a> annotation was added to
help with this limitation.
</p>
<p class='bjava'>
<jc>// Bean should be marshalled with properties in the specified order.</jc>
<ja>@Bean</ja>(properties=<js>"foo,bar,baz"</js>)
<jk>public class</jk> MyBean {
...
}
</p>
<ul class='seealso'>
<li class='doclink'><a class='doclink' href='#juneau-marshall.jm.PojoCategories'>POJO Categories</a> - Marshalling rules for POJOs.
<li class='doclink'><a class='doclink' href='#juneau-marshall.jm.BeanDictionaries'>Bean Dictionaries</a> - Handling properties with subclassable types.
</ul>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JavaBeansSupport.jm.BeanAnnotation' id='juneau-marshall.jm.JavaBeansSupport.jm.BeanAnnotation'>2.4.1 - @Bean Annotation</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.4.1 - juneau-marshall.jm.JavaBeansSupport.jm.BeanAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a> annotation is used to tailor how beans are
interpreted by the framework.
</p>
<p>
Bean property inclusion and ordering on a bean class can be done using the
<a href="org/apache/juneau/annotation/Bean.html#properties--"><code>@Bean(properties|p)</code></a> annotation.
</p>
<p class='bjava'>
<jc>// Address class with only street/city/state properties (in that order).</jc>
<jc>// All other properties are ignored.</jc>
<ja>@Bean</ja>(properties=<js>"street,city,state"</js>)
<jk>public class</jk> Address { ... }
</p>
<p>
Bean properties can be excluded using the <a href="org/apache/juneau/annotation/Bean.html#excludeProperties--"><code>@Bean(excludeProperties|xp)</code></a>
annotation.
</p>
<p class='bjava'>
<jc>// Address class with only street/city/state properties (in that order).</jc>
<jc>// All other properties are ignored.</jc>
<ja>@Bean</ja>(excludeProperties=<js>"city,state"</js>})
<jk>public class</jk> Address { ... }
</p>
<p>
Bean properties can be sorted alphabetically using <a href="org/apache/juneau/annotation/Bean.html#sort--"><code>@Bean(sort)</code></a>
</p>
<p class='bjava'>
<jc>// Address class with only street/city/state properties (in that order).</jc>
<jc>// All other properties are ignored.</jc>
<ja>@Bean</ja>(sort=<jk>true</jk>)
<jk>public class</jk> MyBean { ... }
</p>
<p>
The <a href="org/apache/juneau/annotation/Bean.html#propertyNamer--"><code>@Bean(propertyNamer)</code></a> annotation
is used to provide customized naming of properties.
</p>
<p>
Property namers are used to transform bean property names from standard form to some other form.
For example, the <a href="org/apache/juneau/PropertyNamerDLC.html" title="class in org.apache.juneau"><code>PropertyNamerDLC</code></a> will convert property names to
dashed-lowercase, and these will be used as attribute names in JSON and element names in XML.
</p>
<p class='bjava'>
<jc>// Define a class with dashed-lowercase property names.</jc>
<ja>@Bean</ja>(propertyNamer=PropertyNamerDashedLC.<jk>class</jk>)
<jk>public class</jk> MyBean { ... }
</p>
<p>
The <a href="org/apache/juneau/annotation/Bean.html#interfaceClass--"><code>@Bean(interfaceClass)</code></a> annotation is used
to limit properties on beans to specific interface classes.
When specified, only the list of properties defined on the interface class will be used during
serialization.
Additional properties on subclasses will be ignored.
</p>
<p class='bjava'>
<jc>// Parent class</jc>
<ja>@Bean</ja>(interfaceClass=A.<jk>class</jk>)
<jk>public abstract class</jk> A {
<jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
}
<jc>// Child class</jc>
<jk>public class</jk> A1 <jk>extends</jk> A {
<jk>public</jk> String <jf>f1</jf> = <js>"f1"</js>;
}
A1 <jv>a1</jv> = <jk>new</jk> A1();
String <jv>result</jv> = SimpleJson.<jsm>of</jsm>(<jv>a1</jv>);
<jsm>assertEquals</jsm>(<js>"{f0:'f0'}"</js>, <jv>result</jv>); <jc>// Note f1 is not serialized.</jc>
</p>
<p>
Note that this annotation can be used on the parent class so that it filters to all child classes.
Or can be set individually on the child classes.
</p>
<p>
The <a href="org/apache/juneau/annotation/Bean.html#stopClass--"><code>@Bean(stopClass)</code></a> annotation is another
way to limit which properties are serialized (except from the opposite direction).
It's identical in purpose to the stop class specified by <a href="https://docs.oracle.com/javase/8/docs/api/java/beans/Introspector.html?is-external=true#getBeanInfo-java.lang.Class-java.lang.Class-" title="class or interface in java.beans"><code>Introspector.getBeanInfo(Class, Class)</code></a>.
Any properties in the stop class or in its base classes will be ignored during analysis.
</p>
<p>
For example, in the following class hierarchy, instances of <c>C3</c> will include property
<c>p3</c> but not <c>p1</c> or <c>p2</c>.
</p>
<p class='bjava'>
<jk>public class</jk> C1 {
<jk>public int</jk> getP1();
}
<jk>public class</jk> C2 <jk>extends</jk> C1 {
<jk>public int</jk> getP2();
}
<ja>@Bean</ja>(stopClass=C2.<jk>class</jk>)
<jk>public class</jk> C3 <jk>extends</jk> C2 {
<jk>public int</jk> getP3();
}
</p>
<p>
The <a href="org/apache/juneau/annotation/Bean.html#interceptor--"><code>@Bean(interceptor)</code></a> annotation
and <a href="org/apache/juneau/swap/BeanInterceptor.html" title="class in org.apache.juneau.swap"><code>BeanInterceptor</code></a> class can be used to perform interception
and inline handling of bean getter and setter calls.
</p>
<p class='bjava'>
<jc>// Interceptor that strips out sensitive information on Address beans.</jc>
<jk>public class</jk> AddressInterceptor <jk>extends</jk> BeanInterceptor&lt;Address&gt; {
<ja>@Override</ja>
<jk>public</jk> Object readProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) {
<jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>))
<jk>return</jk> <js>"redacted"</js>;
<jk>return</jk> <jv>value</jv>;
}
<ja>@Override</ja>
<jk>public</jk> Object writeProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) {
<jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>) &amp;&amp; <js>"redacted"</js>.equals(<jv>value</jv>))
<jk>return</jk> TaxInfoUtils.<jsm>lookup</jsm>(<jv>bean</jv>.getStreet(), <jv>bean</jv>.getCity(), <jv>bean</jv>.getState());
<jk>return</jk> <jv>value</jv>;
}
}
<jc>// Register interceptor on bean class.</jc>
<ja>@Bean</ja>(interceptor=AddressInterceptor.<jk>class</jk>)
<jk>public class</jk> Address {
<jk>public</jk> String getTaxInfo() {...}
<jk>public void</jk> setTaxInfo(String <jv>value</jv>) {...}
}
</p>
<p>
The <a href="org/apache/juneau/annotation/Bean.html#on--"><code>@Bean(on)</code></a> and <a href="org/apache/juneau/annotation/Bean.html#onClass--"><code>@Bean(onClass)</code></a>
annotations can be used to programmatically attach <ja>@Bean</ja> annotations to classes.
</p>
<p class='bjava'>
<ja>@Bean</ja>(onClass=Address.<jk>class</jk>, sort=<jk>true</jk>, excludeProperties=<js>"city,state"</js>)
<jk>public class</jk> MyAnnotatedClass {...}
<jc>// Create a serializer configured using annotations.</jc>
JsonSerializer <jv>serializer</jv> = JsonSerializer
.<jsm>create</jsm>()
.applyAnnotations(MyAnnotatedClass.<jk>class</jk>)
.build();
</p>
</div><!-- END: 2.4.1 - juneau-marshall.jm.JavaBeansSupport.jm.BeanAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JavaBeansSupport.jm.BeanpAnnotation' id='juneau-marshall.jm.JavaBeansSupport.jm.BeanpAnnotation'>2.4.2 - @Beanp Annotation</a><span class='update'>updated: 8.1.0,8.1.2,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.4.2 - juneau-marshall.jm.JavaBeansSupport.jm.BeanpAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/annotation/Beanp.html" title="annotation in org.apache.juneau.annotation"><code>@Beanp</code></a> annotation is used to tailor how
individual bean properties are interpreted by the framework.
</p>
<p>
The <a href="org/apache/juneau/annotation/Beanp.html#name--"><code>@Beanp(name)</code></a> annotation
is used to override the name of the bean property.
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<ja>@Beanp</ja>(name=<js>"Bar"</js>)
<jk>public</jk> String getFoo() {...}
}
</p>
<p>
The <a href="org/apache/juneau/annotation/Name.html" title="annotation in org.apache.juneau.annotation"><code>@Name</code></a> annotation is a shortcut for specifying a bean property name:
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<ja>@Name</ja>(<js>"Bar"</js>)
<jk>public</jk> String getFoo() {...}
}
</p>
<p>
If the <a href="org/apache/juneau/BeanContext.Builder.html#beanFieldVisibility-org.apache.juneau.Visibility-"><code>beanFieldVisibility</code></a> setting on the bean context excludes this field
(e.g. the visibility is set to the default of PUBLIC but the field is PROTECTED), this annotation
can be used to force the field to be identified as a property.
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<ja>@Beanp</ja>
<jk>protected</jk> String getFoo() {...}
}
</p>
<p>
The bean property named <js>"*"</js> is the designated "dynamic property" which allows for "extra" bean
properties not otherwise defined.
This is similar in concept to the Jackson <ja>@JsonGetterAll</ja> and <ja>@JsonSetterAll</ja>
annotations but generalized for all supported marshall languages.
The primary purpose is for backwards compatibility in parsing newer streams with addition
information into older beans.
</p>
<p>
The following shows various ways of using dynamic bean properties.
</p>
<p class='bjava'>
<jc>// Option #1 - A simple public Map field.</jc>
<jc>// The field name can be anything.</jc>
<jk>public class</jk> BeanWithDynaField {
<ja>@Beanp</ja>(<js>"*"</js>)
<jk>public</jk> Map&lt;String,Object&gt; <jf>extraStuff</jf> = <jk>new</jk> LinkedHashMap&lt;String,Object&gt;();
}
<jc>// Option #2 - Getters and setters.</jc>
<jc>// Method names can be anything.</jc>
<jc>// Getter must return a Map with String keys.</jc>
<jc>// Setter must take in two arguments, a String and Object.</jc>
<jk>public class</jk> BeanWithDynaMethods {
<ja>@Beanp</ja>(<js>"*"</js>)
<jk>public</jk> Map&lt;String,Object&gt; getMyExtraStuff() {
...
}
<ja>@Beanp</ja>(<js>"*"</js>)
<jk>public void</jk> setAnExtraField(String <jv>name</jv>, Object <jv>value</jv>) {
...
}
}
<jc>// Option #3 - Getter only.</jc>
<jc>// Properties will be added through the getter.</jc>
<jk>public class</jk> BeanWithDynaGetterOnly {
<ja>@Beanp</ja>(<js>"*"</js>)
<jk>public</jk> Map&lt;String,Object&gt; getMyExtraStuff() {
...
}
}
</p>
<p>
Similar rules apply for value types and swaps.
The property values optionally can be any serializable type or use swaps.
</p>
<p class='bjava'>
<jc>// A serializable type other than Object.</jc>
<jk>public class</jk> BeanWithDynaFieldWithListValues {
<ja>@Beanp</ja>(<js>"*"</js>)
<jk>public</jk> Map&lt;String,List&lt;String&gt;&gt; getMyExtraStuff() {
...
}
}
<jc>// A swapped value.</jc>
<jk>public class</jk> BeanWithDynaFieldWithSwappedValues {
<ja>@Beanp</ja>(name=<js>"*"</js>, swap=TemporalCalendarSwap.IsoOffsetDateTime.<jk>class</jk>)
<jk>public</jk> Map&lt;String,Calendar&gt; getMyExtraStuff() {
...
}
}
</p>
<div class='info'>
Note that if you're not interested in these additional properties, you can also use the
<a href="org/apache/juneau/BeanContext.Builder.html#ignoreUnknownBeanProperties--"><code>ignoreUnknownBeanProperties</code></a> setting to ignore values
that don't fit into existing properties.
</div>
<p>
The <a href="org/apache/juneau/annotation/Beanp.html#value--"><code>@Beanp(value)</code></a> annotation
is a synonym for <a href="org/apache/juneau/annotation/Beanp.html#name--"><code>@Beanp(name)</code></a>.
Use it in cases where you're only specifying a name so that you can shorten your annotation.
</p>
<p>
The following annotations are equivalent:
</p>
<p class='bjava'>
<ja>@Beanp</ja>(name=<js>"foo"</js>)
<ja>@Beanp</ja>(<js>"foo"</js>)
</p>
<p>
The <a href="org/apache/juneau/annotation/Beanp.html#type--"><code>@Beanp(type)</code></a> annotation
is used to identify a specialized class type for a generalized property.
Normally the type is inferred through reflection of the field type or getter return type.
However, you'll want to specify this value if you're parsing beans where the bean property class
is an interface or abstract class to identify the bean type to instantiate.
Otherwise, you may cause an <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InstantiationException.html?is-external=true" title="class or interface in java.lang"><code>InstantiationException</code></a> when trying to set these fields.
</p>
<p>
This property must denote a concrete class with a no-arg constructor.
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jc>// Identify concrete type as a HashMap.</jc>
<ja>@Beanp</ja>(type=HashMap.<jk>class</jk>)
<jk>public</jk> Map <jf>p1</jf>;
}
</p>
<p>
The <a href="org/apache/juneau/annotation/Beanp.html#params--"><code>@Beanp(params)</code></a> annotation
is for bean properties of type map or collection.
It's used to identify the class types of the contents of the bean property object when
the general parameter types are interfaces or abstract classes.
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jc>// This is a HashMap&lt;String,Integer&gt;.</jc>
<ja>@Beanp</ja>(type=HashMap.<jk>class</jk>, params={String.<jk>class</jk>,Integer.<jk>class</jk>})
<jk>public</jk> Map <jf>p1</jf>;
}
</p>
<p>
The <a href="org/apache/juneau/annotation/Beanp.html#properties--"><code>@Beanp(properties)</code></a>
annotation is used to limit which child properties are rendered by the serializers.
It can be used on any of the following bean property types:
</p>
<ul class='spaced-list'>
<li>Beans - Only render the specified properties of the bean.
<li>Maps - Only render the specified entries in the map.
<li>Bean/Map arrays - Same but applied to each element in the array.
<li>Bean/Map collections - Same but applied to each element in the collection.
</ul>
<p class='bjava'>
<jk>public class</jk> MyClass {
<jc>// Only render 'f1' when serializing this bean property.</jc>
<ja>@Beanp</ja>(properties={<js>"f1"</js>})
<jk>public</jk> MyChildClass <jf>x1</jf> = <jk>new</jk> MyChildClass();
}
<jk>public class</jk> MyChildClass {
<jk>public int</jk> <jf>f1</jf> = 1;
<jk>public int</jk> <jf>f2</jf> = 2;
}
<jc>// Renders "{x1:{f1:1}}"</jc>
String <jv>json</jv> = Json.<jsm>of</jsm>(<jk>new</jk> MyClass());
</p>
<p>
The <a href="org/apache/juneau/annotation/Beanp.html#format--"><code>@Beanp(format)</code></a>
annotation specifies a String format for converting a bean property value to a formatted string.
</p>
<p class='bjava'>
<jc>// Serialize a float as a string with 2 decimal places.</jc>
<ja>@Beanp</ja>(format=<js>"$%.2f"</js>)
<jk>public float</jk> <jf>price</jf>;
</p>
</div>
</div><!-- END: 2.4.2 - juneau-marshall.jm.JavaBeansSupport.jm.BeanpAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JavaBeansSupport.jm.BeancAnnotation' id='juneau-marshall.jm.JavaBeansSupport.jm.BeancAnnotation'>2.4.3 - @Beanc Annotation</a><span class='update'>updated: 8.1.0,8.1.2</span></h4>
<div class='topic'><!-- START: 2.4.3 - juneau-marshall.jm.JavaBeansSupport.jm.BeancAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/annotation/Beanc.html" title="annotation in org.apache.juneau.annotation"><code>@Beanc</code></a> annotation is used to
map constructor arguments to property names on bean with read-only properties.
Since method parameter names are lost during compilation, this annotation essentially redefines
them so that they are available at runtime.
</p>
<p>
The definition of a read-only bean is a bean with properties with only getters, like shown below:
</p>
<p class='bjava'>
<jc>// Our read-only bean.</jc>
<jk>public class</jk> Person {
<jk>private final</jk> String <jf>name</jf>;
<jk>private final int</jk> <jf>age</jf>;
<ja>@Beanc</ja>(properties=<js>"name,age"</js>})
<jk>public</jk> Person(String <jv>name</jv>, <jk>int</jk> <jv>age</jv>) {
<jk>this</jk>.<jf>name</jf> = <jv>name</jv>;
<jk>this</jk>.<jf>age</jf> = <jv>age</jv>;
}
<jc>// Read only properties.</jc>
<jc>// Getters but no setters.</jc>
<jk>public</jk> String getName() {
<jk>return</jk> <jf>name</jf>;
}
<jk>public int</jk> getAge() {
<jk>return</jk> <jf>age</jf>;
}
}
</p>
<p class='bjava'>
<jc>// Parsing into a read-only bean.</jc>
String <jv>json</jv> = <js>"{name:'John Smith',age:45}"</js>;
Person <jv>person</jv> = Json.<jsm>to</jsm>(<jv>json</jv>, Person.<jk>class</jk>);
String <jv>name</jv> = <jv>person</jv>.getName(); <jc>// "John Smith"</jc>
<jk>int</jk> <jv>age</jv> = <jv>person</jv>.getAge(); <jc>// 45</jc>
</p>
<p>
Beans can also be defined with a combination of read-only and read-write properties.
</p>
<p>
The <a href="org/apache/juneau/annotation/Name.html" title="annotation in org.apache.juneau.annotation"><code>@Name</code></a> annotation can also be used instead of <c><ja>@Beanc</ja>(properties)</c>:
</p>
<p class='bjava'>
<ja>@Beanc</ja>
<jk>public</jk> Person(<ja>@Name</ja>(<js>"name"</js>) String <jv>name</jv>, <ja>@Name</ja>(<js>"age"</js>) <jk>int</jk> <jv>age</jv>) {
<jk>this</jk>.<jf>name</jf> = <jv>name</jv>;
<jk>this</jk>.<jf>age</jf> = <jv>age</jv>;
}
</p>
<p>
If neither <c><ja>@Beanc</ja>(properties)</c> or <ja>@Name</ja> is used to identify the bean property names,
we will try to use the parameter names if they are available in the bytecode.
</p>
</div>
</div><!-- END: 2.4.3 - juneau-marshall.jm.JavaBeansSupport.jm.BeancAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JavaBeansSupport.jm.BeanIgnoreAnnotation' id='juneau-marshall.jm.JavaBeansSupport.jm.BeanIgnoreAnnotation'>2.4.4 - @BeanIgnore Annotation</a></h4>
<div class='topic'><!-- START: 2.4.4 - juneau-marshall.jm.JavaBeansSupport.jm.BeanIgnoreAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/annotation/BeanIgnore.html" title="annotation in org.apache.juneau.annotation"><code>@BeanIgnore</code></a> annotation is used to
ignore classes, fields, and methods from being interpreted as beans or bean components.
</p>
<p>
When applied to classes, objects will be converted to strings even though they look like beans.
</p>
<p class='bjava'>
<jc>// Not really a bean! Use toString() instead!</jc>
<ja>@BeanIgnore</ja>
<jk>public class</jk> MyBean {...}
</p>
<p>
When applied to fields and getters/setters, they will be ignored as bean properties.
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jc>// Not a bean property!</jc>
<ja>@BeanIgnore</ja>
<jk>public</jk> String <jf>foo</jf>;
<jc>// Not a bean property!</jc>
<ja>@BeanIgnore</ja>
<jk>public</jk> String getBar() {...}
}
</p>
</div>
</div><!-- END: 2.4.4 - juneau-marshall.jm.JavaBeansSupport.jm.BeanIgnoreAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JavaBeansSupport.jm.NamePropertyAnnotation' id='juneau-marshall.jm.JavaBeansSupport.jm.NamePropertyAnnotation'>2.4.5 - @NameProperty Annotation</a></h4>
<div class='topic'><!-- START: 2.4.5 - juneau-marshall.jm.JavaBeansSupport.jm.NamePropertyAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/annotation/NameProperty.html" title="annotation in org.apache.juneau.annotation"><code>@NameProperty</code></a> annotation is used to
identify a setter as a method for setting the name of a POJO as it's known by its parent object.
</p>
<p>
A commonly-used case is when you're parsing a JSON map containing beans where one of the bean
properties is the key used in the map.
</p>
<p class='bjson'>
<jc>// JSON</jc>
{
<jok>id1</jok>: {<jok>name</jok>: <jov>'John Smith'</jov>, <jok>sex</jok>: <jov>'M'</jov>},
<jok>id2</jok>: {<jok>name</jok>: <jov>'Jane Doe'</jov>, <jok>sex</jok>: <jov>'F'</jov>}
}
</p>
<p class='bjava'>
<jk>public class</jk> Person {
<ja>@NameProperty</ja>
<jk>public</jk> String <jf>id</jf>; <jc>// Value gets assigned from object key</jc>
<jk>public</jk> String <jf>name</jf>;
<jk>public char</jk> <jf>sex</jf>;
}
</p>
</div>
</div><!-- END: 2.4.5 - juneau-marshall.jm.JavaBeansSupport.jm.NamePropertyAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JavaBeansSupport.jm.ParentPropertyAnnotation' id='juneau-marshall.jm.JavaBeansSupport.jm.ParentPropertyAnnotation'>2.4.6 - @ParentProperty Annotation</a></h4>
<div class='topic'><!-- START: 2.4.6 - juneau-marshall.jm.JavaBeansSupport.jm.ParentPropertyAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/annotation/ParentProperty.html" title="annotation in org.apache.juneau.annotation"><code>@ParentProperty</code></a> annotation is used to
identify a setter as a method for adding a parent reference to a child object.
</p>
<p>
A commonly-used case is when you're parsing beans and a child bean has a reference to a parent bean.
</p>
<p class='bjava'>
<jk>public class</jk> AddressBook {
<jk>public</jk> List&lt;Person&gt; <jf>people</jf>;
}
<jk>public class</jk> Person {
<ja>@ParentProperty</ja>
<jk>public</jk> AddressBook <jf>addressBook</jf>; <jc>// A reference to the containing address book.</jc>
<jk>public</jk> String <jf>name</jf>;
<jk>public char</jk> <jf>sex</jf>;
}
</p>
<p>
Parsers will automatically set this field for you in the child beans.
</p>
</div>
</div><!-- END: 2.4.6 - juneau-marshall.jm.JavaBeansSupport.jm.ParentPropertyAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JavaBeansSupport.jm.PojoBuilders' id='juneau-marshall.jm.JavaBeansSupport.jm.PojoBuilders'>2.4.7 - POJO Builders</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.4.7 - juneau-marshall.jm.JavaBeansSupport.jm.PojoBuilders -->
<div class='topic'>
<p>
Juneau parsers can use builders to instantiate POJOs.
This is useful in cases where you want to create beans with read-only properties.
Note that while it's possible to do this using the <a href="org/apache/juneau/annotation/Beanc.html" title="annotation in org.apache.juneau.annotation"><code>@Beanc</code></a>
annotation, using builders can often be cleaner.
</p>
<p>
A typical builder usage is shown below:
</p>
<p class='bjava'>
MyBean <jv>bean</jv> = MyBean.<jsm>create</jsm>().foo(<js>"foo"</js>).bar(123).build();
</p>
<p>
The typical code for such a builder using a static inner class is shown below:
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jc>// Read-only properties.</jc>
<jk>public final</jk> String <jf>foo</jf>;
<jk>public final int</jk> <jf>bar</jf>;
<jc>// Private constructor.</jc>
<jk>private</jk> MyBean(Builder <jv>builder</jv>) {
<jk>this</jk>.<jf>foo</jf> = <jv>builder</jv>.<jf>foo</jf>;
<jk>this</jk>.<jf>bar</jf> = <jv>builder</jv>.<jf>bar</jf>;
}
<jc>// Static method that creates a builder.</jc>
<jk>public static</jk> Builder <jsm>create</jsm>() {
<jk>return new</jk> Builder();
}
<jc>// Builder class.</jc>
<jk>public static class</jk> Builder {
String <jf>foo</jf>;
<jk>int</jk> <jf>bar</jf>;
<jc>// Method that creates the bean.</jc>
<jk>public</jk> MyBean build() {
<jk>return new</jk> MyBean(<jk>this</jk>);
}
<jc>// Bean property setters.</jc>
<ja>@Beanp</ja>
<jk>public</jk> Builder foo(String <jv>foo</jv>) {
<jk>this</jk>.<jf>foo</jf> = <jv>foo</jv>;
<jk>return this</jk>;
}
<ja>@Beanp</ja>
<jk>public</jk> Builder bar(<jk>int</jk> <jv>bar</jv>) {
<jk>this</jk>.<jf>bar</jf> = <jv>bar</jv>;
<jk>return this</jk>;
}
}
}
</p>
<p>
The POJO class can be any type including beans.
Builders MUST be beans with one or more writable properties.
The bean properties themselves do not need to be readable (i.e. getters are optional).
</p>
<p>
Builders require two parts:
</p>
<ol>
<li>A way to detect and instantiate a builder using reflection.
<li>A way to instantiate a POJO from a builder.
</ol>
<p>
The first can be accomplished through <b>any</b> of the following:
</p>
<ul class='spaced-list'>
<li>A static <c>create()</c> method on the POJO class that returns a builder instance.
<p class='bjava nomargin'>
<jk>public static</jk> Builder <jsm>create</jsm>() {...}
</p>
<li>A public constructor on the POJO class that takes in a single parameter that implements the <a href="org/apache/juneau/swap/Builder.html" title="interface in org.apache.juneau.swap"><code>Builder</code></a> interface.
<br>The builder class must have a public no-arg constructor.
<p class='bjava nomargin'>
<jk>public</jk> MyBean(Builder <jv>builder</jv>) {...}
</p>
<li>A <a href="org/apache/juneau/annotation/Builder.html" title="annotation in org.apache.juneau.annotation"><code>@Builder</code></a> annotation on the POJO class to explicitly identify it.
<br>The builder class must have a public no-arg constructor.
<p class='bjava nomargin'>
<ja>@Builder</ja>(Builder.<jk>class</jk>)
<jk>public class</jk> MyBean {...}
</p>
</ul>
<p>
The second can be accomplished through <b>any</b> of the following:
</p>
<ul class='spaced-list'>
<li>The existence of a <c>build()</c> method on the builder class.
<p class='bjava nomargin'>
<jk>public</jk> MyBean build() {...}
</p>
<li>The existence of a public constructor on the POJO class that takes in the builder instance.
<p class='bjava nomargin'>
<jk>public</jk> MyBean(Builder <jv>builder</jv>) {...}
</p>
</ul>
<ul class='seealso'>
<li class='ja'><a href="org/apache/juneau/annotation/Builder.html" title="annotation in org.apache.juneau.annotation"><code>Builder</code></a>
<li class='jic'><a href="org/apache/juneau/swap/Builder.html" title="interface in org.apache.juneau.swap"><code>Builder</code></a>
</ul>
</div>
</div><!-- END: 2.4.7 - juneau-marshall.jm.JavaBeansSupport.jm.PojoBuilders -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JavaBeansSupport.jm.BypassSerialization' id='juneau-marshall.jm.JavaBeansSupport.jm.BypassSerialization'>2.4.8 - Bypass Serialization using Readers and InputStreams</a></h4>
<div class='topic'><!-- START: 2.4.8 - juneau-marshall.jm.JavaBeansSupport.jm.BypassSerialization -->
<div class='topic'>
<p>
Juneau serializers treat instances of <c>Readers</c> and <c>InputStreams</c> special by
simply serializing their contents directly to the output stream or writer.
This allows you to embed fully customized serializer output.
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jc>// A bean property that produces raw JSON.</jc>
<jk>public</jk> Reader <jf>f1</jf> = <jk>new</jk> StringReader(<js>"{'foo':'bar'}"</js>);
}
<jc>// Produces "{f1:{'foo':'bar'}}"</jc>
String <jv>json</jv> = SimpleJson.<jsm>of</jsm>(<jk>new</jk> MyBean());
</p>
<p>
Note that if you're serializing Readers and InputStreams, it's up to you to make sure you're producing
valid output (in this case JSON).
</p>
<p>
A more typical scenario where this is useful is by using swaps to convert POJOs to Readers whose
contents are determined via the <a href="org/apache/juneau/BeanSession.html#getMediaType--"><code>BeanSession.getMediaType()</code></a> method.
In the following example, we're customizing the JSON output for a particular bean type but leaving
all other renditions as-is:
</p>
<p class='bjava'>
<ja>@Swap</ja>(MyBeanSwapSometimes.<jk>class</jk>)
<jk>public class</jk> MyBean {...}
<jc>// A swap that produces specialized output for JSON but default serialization for</jc>
<jc>// all other media types.</jc>
<jk>public class</jk> MyBeanSwapSometimes <jk>extends</jk> ObjectSwap&lt;MyBean,Object&gt; {
<jk>public</jk> Object swap(BeanSession <jv>session</jv>, MyPojo <jv>object</jv>) <jk>throws</jk> Exception {
MediaType <jv>mediaType</jv> = <jv>session</jv>.getMediaType();
<jk>if</jk> (<jv>mediaType</jv>.hasSubType(<js>"json"</js>))
<jk>return new</jk> StringReader(<js>"{myPojo:'foobar'}"</js>); <jc>// Custom JSON output</jc>
<jk>return</jk> <jv>object</jv>; <jc>// Otherwise serialize it as a normal bean</jc>
}
}
</p>
<div class='info'>
Due to the nature of the RDF serializers, Readers and InputStreams are serialized as literals,
not as RDF text.
This is due to the fact that the RDF serializers use a DOM for serialization so we don't have
access to the underlying stream.
</div>
</div>
</div><!-- END: 2.4.8 - juneau-marshall.jm.JavaBeansSupport.jm.BypassSerialization -->
</div><!-- END: 2.4 - juneau-marshall.jm.JavaBeansSupport -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HttpPartSerializersParsers' id='juneau-marshall.jm.HttpPartSerializersParsers'>2.5 - HTTP Part Serializers and Parsers</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.5 - juneau-marshall.jm.HttpPartSerializersParsers -->
<div class='topic'>
<p>
There is a separate set of serializers and parsers for marshalling HTTP parts (query, form-data, headers, path variables, and plain-text request bodies).
The distinction is that these are designed to marshall directly to-and-from strings based on Open-API schema information.
</p>
<p class='bjava'>
<jc>// Schema information about our part.</jc>
HttpPartSchema <jv>schema</jv> = HttpPartSchema
.<jsm>tArrayPipes</jsm>()
.items(
HttpPartSchema
.<jsm>tArrayCsv</jsm>()
.items(
HttpPartSchema.<jsm>tInt64</jsm>(<js>"integer"</js>,<js>"int64"</js>)
)
)
.build();
<jc>// Our value to serialize</jc>
Object <jv>value</jv> = <jk>new long</jk>[][]{{1,2,3},{4,5,6},{7,8,9}};
<jc>// Produces "1,2,3|4,5,6|7,8,9"</jc>
String <jv>output</jv> = OpenApi.<jsm>of</jsm>(HttpPartType.<jsf>HEADER</jsf>, <jv>schema</jv>, <jv>value</jv>);
<jc>// Produces "[[1,2,3],[4,5,6],[7,8,9]]</jc>
<jk>long</jk>[][] <jv>value</jv> = OpenApi.<jsm>to</jsm>(HttpPartType.<jsf>HEADER</jsf>, <jv>schema</jv>, <jv>output</jv>, <jk>long</jk>[][].<jk>class</jk>);
</p>
<p>
The <a href="org/apache/juneau/httppart/HttpPartSchema.html" title="class in org.apache.juneau.httppart"><code>HttpPartSchema</code></a> class also provides convenience static methods for creation of custom schemas.
The equivalent to the schema above can be structured like so:
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.httppart.HttpPartSchema.*;
<jc>// Schema information about our part.</jc>
HttpPartSchema <jv>schema</jv> = <jsm>tArrayPipes</jsm>(<jsm>tArrayCsv</jsm>(<jsm>tInt64</jsm>())).build();
</p>
<p>
The class hierarchy for the part marshallers are:
</p>
<ul class='javatree'>
<li class='jic'><a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/httppart/SimplePartSerializer.html" title="class in org.apache.juneau.httppart"><code>SimplePartSerializer</code></a> - Serializes directly to strings.
<li class='jc'><a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a> - Serializes to UON notation.
<ul>
<li class='jc'><a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> - Serializes using Open-API schema rules.
</ul>
</li>
</ul>
</li>
<li class='jic'><a href="org/apache/juneau/httppart/HttpPartParser.html" title="interface in org.apache.juneau.httppart"><code>HttpPartParser</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/httppart/SimplePartParser.html" title="class in org.apache.juneau.httppart"><code>SimplePartParser</code></a> - Parses directly from strings.
<li class='jc'><a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a> - Parses from UON notation.
<ul>
<li class='jc'><a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a> - Parses using Open-API schema rules.
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.5 - juneau-marshall.jm.HttpPartSerializersParsers -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.ContextSettings' id='juneau-marshall.jm.ContextSettings'>2.6 - Context Settings</a><span class='update'>updated: 8.1.3,<b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.6 - juneau-marshall.jm.ContextSettings -->
<div class='topic'>
<p>
Serializers and parsers have a wide variety of configurable settings. Their builders all extend from the
<a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a> class that allows you to easily construct new instances from scratch or build upon existing instances.
For example, the following code shows how to configure a JSON serializer:
</p>
<p class='bjava'>
WriterSerializer <jv>serializer</jv> = JsonSerializer
.<jsm>create</jsm>() <jc>// Create a JsonSerializer.Builder</jc>
.simpleMode() <jc>// Simple mode</jc>
.ws() <jc>// Use whitespace</jc>
.sq() <jc>// Use single quotes </jc>
.sortProperties() <jc>// Sort bean properties by name</jc>
.build(); <jc>// Create a JsonSerializer</jc>
</p>
<p>
However, each of the serializers and parsers already contain reusable instances with common configurations.
For example, JSON has the following predefined reusable serializers and parsers:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/json/JsonSerializer.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/json/JsonSerializer.html#DEFAULT_READABLE"><code>DEFAULT_READABLE</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/json/SimpleJsonSerializer.html" title="class in org.apache.juneau.json"><code>SimpleJsonSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/json/SimpleJsonSerializer.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/json/SimpleJsonSerializer.html#DEFAULT_READABLE"><code>DEFAULT_READABLE</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/json/JsonParser.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/json/JsonParser.html#DEFAULT_STRICT"><code>DEFAULT_STRICT</code></a>
</ul>
</li>
</ul>
<p>
These can be used directly, as follows:
</p>
<p class='bjava'>
<jc>// Serialize a POJO to LAX JSON.</jc>
String <jv>json</jv> = SimpleJsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>myPojo</jv>);
</p>
<p>
For performance reasons, serializers and parsers are immutable.
However, they can be 'copied' and modified using the <c>copy()</c> method.
</p>
<p class='bjava'>
<jc>// Clone and customize an existing serializer.</jc>
WriterSerializer <jv>serializer</jv> = SimpleJsonSerializer.<jsf>DEFAULT</jsf>
.copy() <jc>// Create a new builder with copied settings.</jc>
.quoteChar(<js>'"'</js>) <jc>// Use a different quote character.</jc>
.build();
</p>
<p>
Default values for configurable settings can be set globally using either system properties or environment variables.
<br>For example, the default <c>useWhitespace</c> setting can be set by either the system property <js>"WriterSerializer.useWhitespace"</js>
or environment variable <js>"WRITERSERIALIZER_USEWHITESPACE"</js>.
The builder setters will identify when default values can be set this way.
</p>
</div>
</div><!-- END: 2.6 - juneau-marshall.jm.ContextSettings -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.ContextAnnotations' id='juneau-marshall.jm.ContextAnnotations'>2.7 - Context Annotations</a><span class='update'>created: 8.1.0, updated: 8.1.3,8.2.0,<b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.7 - juneau-marshall.jm.ContextAnnotations -->
<div class='topic'>
<p>
All configurable properties described in the previous section have annotation equivalents that can be applied on
classes or methods.
</p>
<p>
In the section on the REST server API, we describe how to configure serializers and parsers using <ja>@XConfig</ja>
annotations like those shown below:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/addressBook"</js>,
title=<js>"Address Book REST API"</js>
...
)
<ja>@SerializerConfig</ja>(quoteChar=<js>"'"</js>)
<ja>@RdfConfig</ja>(rdfxml_tab=<js>"5"</js>, addRootProperty=<js>"true"</js>)
<ja>@BeanConfig</ja>(sortProperties=<js>"true"</js>, examples=<js>"Feed: $F{AddressBook_example.json}"</js>)
<ja>@Bean</ja>(onClass=Address.<jk>class</jk>, properties=<js>"street,city,state"</js>)
<jk>public class</jk> AddressBookResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
...
}
</p>
<p>
Config annotations defined on classes and methods can be applied to serializers and parsers using the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#applyAnnotations-java.lang.Class...-"><code>applyAnnotations(Class...)</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#applyAnnotations-java.lang.reflect.Method...-"><code>applyAnnotations(Method...)</code></a>
</ul>
</li>
</ul>
<p>
The following example shows how annotations defined on a dummy class can be applied to a serializer:
</p>
<p class='bjava'>
<ja>@SerializerConfig</ja>(quoteChar=<js>"'"</js>)
<ja>@Bean</ja>(on=<js>"Address"</js>, properties=<js>"street,city,state"</js>)
<jk>public static class</jk> DummyClass {}
WriterSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().applyAnnotations(DummyClass.<jk>class</jk>).build();
String <jv>json</jv> = <jv>serializer</jv>.toString(<jv>addressBean</jv>);
</p>
<p>
Config annotations are provided for all serializers and parsers:
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/annotation/BeanConfig.html" title="annotation in org.apache.juneau.annotation"><code>BeanConfig</code></a>
<li class='ja'><a href="org/apache/juneau/csv/annotation/CsvConfig.html" title="annotation in org.apache.juneau.csv.annotation"><code>CsvConfig</code></a>
<li class='ja'><a href="org/apache/juneau/html/annotation/HtmlConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlConfig</code></a>
<li class='ja'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlDocConfig</code></a>
<li class='ja'><a href="org/apache/juneau/json/annotation/JsonConfig.html" title="annotation in org.apache.juneau.json.annotation"><code>JsonConfig</code></a>
<li class='ja'><a href="org/apache/juneau/jsonschema/annotation/JsonSchemaConfig.html" title="annotation in org.apache.juneau.jsonschema.annotation"><code>JsonSchemaConfig</code></a>
<li class='ja'><a href="org/apache/juneau/msgpack/annotation/MsgPackConfig.html" title="annotation in org.apache.juneau.msgpack.annotation"><code>MsgPackConfig</code></a>
<li class='ja'><a href="org/apache/juneau/oapi/annotation/OpenApiConfig.html" title="annotation in org.apache.juneau.oapi.annotation"><code>OpenApiConfig</code></a>
<li class='ja'><a href="org/apache/juneau/parser/annotation/ParserConfig.html" title="annotation in org.apache.juneau.parser.annotation"><code>ParserConfig</code></a>
<li class='ja'><a href="org/apache/juneau/plaintext/annotation/PlainTextConfig.html" title="annotation in org.apache.juneau.plaintext.annotation"><code>PlainTextConfig</code></a>
<li class='ja'><a href="org/apache/juneau/jena/annotation/RdfConfig.html" title="annotation in org.apache.juneau.jena.annotation"><code>RdfConfig</code></a>
<li class='ja'><a href="org/apache/juneau/serializer/annotation/SerializerConfig.html" title="annotation in org.apache.juneau.serializer.annotation"><code>SerializerConfig</code></a>
<li class='ja'><a href="org/apache/juneau/soap/annotation/SoapXmlConfig.html" title="annotation in org.apache.juneau.soap.annotation"><code>SoapXmlConfig</code></a>
<li class='ja'><a href="org/apache/juneau/uon/annotation/UonConfig.html" title="annotation in org.apache.juneau.uon.annotation"><code>UonConfig</code></a>
<li class='ja'><a href="org/apache/juneau/urlencoding/annotation/UrlEncodingConfig.html" title="annotation in org.apache.juneau.urlencoding.annotation"><code>UrlEncodingConfig</code></a>
<li class='ja'><a href="org/apache/juneau/xml/annotation/XmlConfig.html" title="annotation in org.apache.juneau.xml.annotation"><code>XmlConfig</code></a>
</ul>
<p>
Annotations normally applied to bean classes/methods/fields/parameters
can also be programmatically attatched to beans by using the <js>"on"</js> or <js>"onClass"</js> annotation values as seen
on the <ja>@Bean</ja> annotation in the example above.
These include:
</p>
<p>
Annotations can also be applied directly to serializers and parsers using the following method:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#annotations-java.lang.annotation.Annotation...-"><code>annotations(Annotation...)</code></a>
</ul>
</li>
</ul>
<p>
The following example shows a concrete implementation of an annotation can be applied to a serializer:
</p>
<p class='bjava'>
<jk>public class</jk> Address {...}
<ja>Bean</ja> <jv>ba</jv> = <jk>new</jk> BeanAnnotation(<js>"Address"</js>).properties(<js>"street,city,state"</js>);
WriterSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().annotations(<jv>ba</jv>).build();
String <jv>json</jv> = <jv>serializer</jv>.toString(<jv>addressBean</jv>); <jc>// Will print street,city,state</jc>
</p>
<p>
Concrete annotation implementations are provided for all annotations.
</p>
<p>
Any number of matching config or concrete annotations can be applied. They are applied in the order they are provided
to the context. Therefore any values can be overridden. Config and concrete annotations also override any class or method
level annotations
</p>
<p class='bjava'>
<ja>@Bean</ja>(properties=<js>"street,city"</js>) <jc>// Will be overridden</jc>
<jk>public class</jk> Address {...}
<ja>Bean</ja> <jv>beanAnnotation</jv> = <jk>new</jk> BeanAnnotation(<js>"Address"</js>).properties(<js>"street,city,state"</js>);
WriterSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().annotations(<jv>beanAnnotation</jv>).build();
String <jv>json</jv> = <jv>serializer</jv>.toString(<jv>addressBean</jv>); <jc>// Will print street,city,state</jc>
</p>
<ul class='seealso'>
<li class='doclink'><a class='doclink' href='#Glossaries.g.Annotations'>Annotations Glossary</a> for the list of all annotations defined.
</ul>
</div>
</div><!-- END: 2.7 - juneau-marshall.jm.ContextAnnotations -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JsonMap' id='juneau-marshall.jm.JsonMap'>2.8 - JsonMap and JsonList</a><span class='update'>updated: 8.2.0</span></h3>
<div class='topic'><!-- START: 2.8 - juneau-marshall.jm.JsonMap -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/collections/JsonMap.html" title="class in org.apache.juneau.collections"><code>JsonMap</code></a> and <a href="org/apache/juneau/collections/JsonList.html" title="class in org.apache.juneau.collections"><code>JsonList</code></a> classes are generic Java
representations of JSON objects and arrays.
These classes can be used to create "unstructured" models for serialization (as opposed to "structured"
models consisting of beans).
If you want to quickly generate JSON/XML/HTML from generic maps/collections, or parse JSON/XML/HTML into
generic maps/collections, these classes work well.
</p>
<p>
These classes extend directly from the following JCF classes:
</p>
<ul class='javatree'>
<li class='jc'>
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/LinkedHashMap.html?is-external=true" title="class or interface in java.util"><code>java.util.LinkedHashMap</code></a>
<ul>
<li class='jc'>
<a href="org/apache/juneau/collections/JsonMap.html" title="class in org.apache.juneau.collections"><code>org.apache.juneau.collections.JsonMap</code></a>
</ul>
</li>
<li class='jc'>
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html?is-external=true" title="class or interface in java.util"><code>java.util.LinkedList</code></a>
<ul>
<li class='jc'>
<a href="org/apache/juneau/collections/JsonList.html" title="class in org.apache.juneau.collections"><code>org.apache.juneau.collections.JsonList</code></a>
</ul>
</li>
</ul>
<p>
The <l>JsonMap</l> and <l>JsonList</l> classes are very similar to the <l>JSONObject</l> and
<l>JSONArray</l> classes found in other libraries.
However, the names were chosen because the concepts of <l>Maps</l> and <l>Lists</l> are already familiar to
Java programmers, and these classes can be used with any of the serializers or parsers.
</p>
<p>
These object can be serialized in one of two ways:
</p>
<ol class='spaced-list'>
<li>
Using the provided <a href="org/apache/juneau/collections/JsonMap.html#writeTo-java.io.Writer-"><code>JsonMap.writeTo(java.io.Writer)</code></a> or
<a href="org/apache/juneau/collections/JsonList.html#writeTo-java.io.Writer-"><code>JsonList.writeTo(java.io.Writer)</code></a> methods.
<li>
Passing them to one of the <a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a> serialize methods.
<li>
Simply calling the <a href="org/apache/juneau/collections/JsonMap.html#asJson--"><code>JsonMap.asJson()</code></a>/<a href="org/apache/juneau/collections/JsonMap.html#toString--"><code>JsonMap.toString()</code></a> or <a href="org/apache/juneau/collections/JsonList.html#asString--"><code>JsonList.asString()</code></a>/<a href="org/apache/juneau/collections/JsonList.html#toString--"><code>JsonList.toString()</code></a>
methods which will serialize it as Simplified JSON.
</ol>
<p>
Any valid JSON can be parsed into an unstructured model consisting of generic
<a href="org/apache/juneau/collections/JsonMap.html" title="class in org.apache.juneau.collections"><code>JsonMap</code></a> and <a href="org/apache/juneau/collections/JsonList.html" title="class in org.apache.juneau.collections"><code>JsonList</code></a> objects.
(Any valid XML can also be parsed into an unstructured model)
</p>
<p class='bjava'>
<jc>// Parse an arbitrary JSON document into an unstructered data model
// consisting of JsonMaps, JsonLists, and java primitive objects.</jc>
String <jv>json</jv> = <js>"{a:{name:'John Smith',age:21},b:{name:'Joe Smith',age:42}}"</js>;
JsonMap <jv>map</jv> = Json.<jsm>to</jsm>(<jv>json</jv>, JsonMap.<jk>class</jk>);
<jc>// Use JsonMap API to extract data from the unstructured model.</jc>
<jk>int</jk> <jv>johnSmithAge</jv> = <jv>map</jv>.getMap(<js>"a"</js>).getInt(<js>"age"</js>);
<jc>// Convert it back into JSON.</jc>
<jv>json</jv> = Json.<jsm>of</jsm>(<jv>map</jv>);
<jc>// Or convert it to XML.</jc>
String <jv>xml</jv> = Xml.<jsm>of</jsm>(<jv>map</jv>);
<jc>// Or just use toString() or asJson().</jc>
<jv>json</jv> = <jv>map</jv>.toString();
<jv>json</jv> = <jv>map</jv>.asJson();
</p>
<p>
The <c>JsonMap</c> and <c>JsonList</c> classes have many convenience features:
</p>
<p class='bjava'>
<jc>// Convert the map to a bean.</jc>
MyBean <jv>myBean</jv> = <jv>map</jv>.cast(MyBean.<jk>class</jk>);
<jc>// Find entries by multiple keys.</jc>
MyBean <jv>myBean</jv> = <jv>map</jv>.find(MyBean.<jk>class</jk>, <js>"key1"</js>, <js>"key2"</js>);
<jc>// Fluent-style appenders.</jc>
<jv>map</jv>.append(<js>"key1"</js>, <js>"val1"</js>).append(<js>"key2"</js>, <js>"val2"</js>);
<jc>// REST-like functions for manipulating nodes in the data structure using URL-like notation.</jc>
<jv>map</jv>.getAt(<js>"foo/bar/myBean"</js>, MyBean.<jk>class</jk>);
<jv>map</jv>.putAt(<js>"foo/bar/myBean"</js>, MyBean.<jk>class</jk>);
<jv>map</jv>.postAt(<js>"foo/bar/myListOfBeans"</js>, MyBean.<jk>class</jk>);
<jv>map</jv>.deleteAt(<js>"foo/bar/myBean"</js>);
<jc>// Copy with inclusion or exclusion.</jc>
JsonMap <jv>map2</jv> = <jv>map</jv>.include(<js>"key1"</js>, <js>"key2"</js>, <js>"key3"</js>);
JsonMap <jv>map3</jv> = <jv>map</jv>.exclude(<js>"key1"</js>, <js>"key2"</js>, <js>"key3"</js>);
<jc>// Serialize using another serializer.</jc>
String <jv>xml</jv> = <jv>map</jv>.serializeTo(XmlSerializer.<jsf>DEFAULT</jsf>);
<jc>// Nested maps.</jc>
<jv>map</jv>.inner(<jv>anotherMap</jv>);
</p>
<div class='info'>
As a general rule, if you do not specify a target type during parsing, or if the target type cannot be
determined through reflection, the parsers automatically generate <l>JsonMaps</l> and <l>JsonLists</l>.
</div>
</div>
</div><!-- END: 2.8 - juneau-marshall.jm.JsonMap -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.ComplexDataTypes' id='juneau-marshall.jm.ComplexDataTypes'>2.9 - Complex Data Types</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.9 - juneau-marshall.jm.ComplexDataTypes -->
<div class='topic'>
<p>
The Juneau parsers have the ability to parse into complex data types that consist of multidimensional arrays and nested maps and collections
using the methods below:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/parser/Parser.html#parse-java.lang.Object-java.lang.Class-"><code>parse(Object,Class)</code></a>
<li class='jm'><a href="org/apache/juneau/parser/Parser.html#parse-java.lang.Object-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>parse(Object,Type,Type...)</code></a>
</ul>
</li>
</ul>
<p>
Arrays are simple enough and can be constructed using the first method:
</p>
<p class='bjava'>
String <jv>json</jv> = <js>"[1,2,3]"</js>;
<jk>int</jk>[] <jv>array</jv> = Json.<jsm>to</jsm>(<jv>json</jv>, <jk>int</jk>[].<jk>class</jk>);
</p>
<p>
For data types consisting of nested collections an maps such as <c>Map&lt;String,List&lt;MyBean&gt;&gt;</c>, you need to
use the second parse method that allows you to define the parameter types of the collections classes.
For example:
</p>
<p class='bjava'>
String <jv>json</jv> = <js>"{foo:[{bar:'baz'}]}"</js>;
TreeMap&lt;String,List&lt;MyBean&gt;&gt; <jv>map</jv> = Json.<jsm>to</jsm>(
<jv>json</jv>, <jc>// Input being parsed.</jc>
TreeMap.<jk>class</jk>, <jc>// Top-level data type.</jc>
String.<jk>class</jk>, <jc>// Key type of map.</jc>
LinkedList.<jk>class</jk>, <jc>// Value type of map.</jc>
MyBean.<jk>class</jk> <jc>// Value type of list.</jc>
);
</p>
<p>
<c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type.
<br><c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value types.
<br>The arguments can be arbitrarily long to indicate arbitrarily complex data structures.
</p>
<p>
Similar methods for converting to complex types can be found on the <a href="org/apache/juneau/rest/httppart/RequestContent.html" title="class in org.apache.juneau.rest.httppart"><code>RequestContent</code></a> and <a href="org/apache/juneau/rest/httppart/RequestHttpPart.html" title="class in org.apache.juneau.rest.httppart"><code>RequestHttpPart</code></a> classes,
and the <a href="org/apache/juneau/BeanSession.html#convertToType-java.lang.Object-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>BeanSession.convertToType(Object,Type,Type...)</code></a> method.
</p>
</div>
</div><!-- END: 2.9 - juneau-marshall.jm.ComplexDataTypes -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.SerializerSetsParserSets' id='juneau-marshall.jm.SerializerSetsParserSets'>2.10 - SerializerSets and ParserSets</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.10 - juneau-marshall.jm.SerializerSetsParserSets -->
<div class='topic'>
<p>
On top of the serializers and parsers are the <a href="org/apache/juneau/serializer/SerializerSet.html" title="class in org.apache.juneau.serializer"><code>SerializerSet</code></a> and
<a href="org/apache/juneau/parser/ParserSet.html" title="class in org.apache.juneau.parser"><code>ParserSet</code></a> classes.
These classes allow serializers and parsers to be grouped and retrieved by W3C-compliant HTTP <c>Accept</c>
and <c>Content-Type</c> values...
</p>
<p class='bjava'>
<jc>// Construct a new serializer group with configuration parameters that get applied
// to all serializers.</jc>
SerializerSet <jv>serializers</jv> = SerializerSet.<jsm>create</jsm>()
.add(JsonSerializer.<jk>class</jk>, UrlEncodingSerializer.<jk>class</jk>)
.forEach(<jv>x</jv> -> <jv>x</jv>.swaps(TemporalCalendarSwap.IsoLocalDateTime.<jk>class</jk>))
.forEachWS(<jv>x</jv> -> <jv>x</jv>.ws()) <jc>// or .useWhitespace(true)</jc>
.build();
<jc>// Find the appropriate serializer by Accept type and serialize our POJO to the
// specified writer.</jc>
<jv>serializers</jv>
.getSerializer(<js>"text/invalid, text/json;q=0.8, text/*;q:0.6, *\/*;q=0.0"</js>)
.serialize(<jv>myPerson</jv>, <jv>myWriter</jv>);
<jc>// Construct a new parser group with configuration parameters that get applied to all parsers.</jc>
ParserSet <jv>parsers</jv> = ParserSet.<jsm>create</jsm>()
.add(JsonSerializer.<jk>class</jk>, UrlEncodingSerializer.<jk>class</jk>)
.forEach(<jv>x</jv> -> <jv>x</jv>.swaps(CalendarSwap.IsoLocalDateTime.<jk>class</jk>))
.build();
Person <jv>myPerson</jv> = <jv>parsers</jv>
.getParser(<js>"text/json"</js>)
.parse(<jv>myReader</jv>, Person.<jk>class</jk>);
</p>
<p>
The REST servlet API builds upon the <c>SerializerSet</c> and <c>ParserSet</c> classes
to provide annotated REST servlets that automatically negotiate the HTTP media types and allow the developer
to work with requests and responses as POJOs.
</p>
</div>
</div><!-- END: 2.10 - juneau-marshall.jm.SerializerSetsParserSets -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Swaps' id='juneau-marshall.jm.Swaps'>2.11 - Swaps</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.11 - juneau-marshall.jm.Swaps -->
<div class='topic'>
<p>
<a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>Swaps</code></a> are a critical component of Juneau.
They allow the serializers and parsers to handle Java objects that wouldn't normally be serializable.
</p>
<p>
Swaps are, simply put, 'object swappers' that swap in serializable objects for
non-serializable ones during serialization, and vis-versa during parsing.
Some examples of non-serializable objects are <c>File</c>, <c>Reader</c>,
<c>Iterable</c>, etc...
These are classes that aren't beans and cannot be represented as simple maps, collections, or primitives.
</p>
<p>
In the following example, we introduce a <c>ObjectSwap</c> that will swap in a bean of a particular type
with a map containing customized key-value pairs:
</p>
<p class='bjava'>
<jc>// Sample swap for converting a bean to a specialized map of key-value pairs.</jc>
<jk>public class</jk> MyBeanSwap <jk>extends</jk> ObjectSwap&lt;MyBean,JsonMap&gt; {
<jc>// Converts a bean to a generic map.</jc>
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> JsonMap swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) {
<jk>return</jk> JsonMap.<jsm>of</jsm>(<js>"foo"</js>, <jv>bean</jv>.getBar());
}
<jc>// Converts the generic map back into a bean.</jc>
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> MyBean unswap(BeanSession <jv>session</jv>, JsonMap <jv>map</jv>, ClassMeta&lt;?&gt; <jv>hint</jv>) <jk>throws</jk> Exception {
MyBean <jv>bean</jv> = <jk>new</jk> MyBean();
<jv>bean</jv>.setBar(<jv>map</jv>.getString(<js>"foo"</js>));
<jk>return</jk> <jv>bean</jv>;
}
}
</p>
<p>
The swap can then be associated with serializers and parsers like so:
</p>
<p class='bjava'>
<jc>// Create a new JSON serializer with our swap.</jc>
WriterSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().simple().swaps(MyBeanSwap.<jk>class</jk>).build();
String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
<jc>// Create a JSON parser with our swap.</jc>
ReaderParser <jv>parser</jv> = JsonParser.<jsm>create</jsm>().swaps(MyBeanSwap.<jk>class</jk>).build();
MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
</p>
<p>
Another example of a <c>ObjectSwap</c> is one that converts <c><jk>byte</jk>[]</c> arrays to
BASE64-encoded strings:
</p>
<p class='bjava'>
<jk>public class</jk> ByteArrayBase64Swap <jk>extends</jk> StringSwap&lt;<jk>byte</jk>[]&gt; {
<ja>@Override</ja> <jc>/* StringSwap */</jc>
<jk>public</jk> String swap(<jk>byte</jk>[] <jv>bytes</jv>) <jk>throws</jk> Exception {
ByteArrayOutputStream <jv>baos</jv> = <jk>new</jk> ByteArrayOutputStream();
OutputStream <jv>b64os</jv> = MimeUtility.encode(<jv>baos</jv>, <js>"base64"</js>);
<jv>b64os</jv>.write(<jv>bytes</jv>);
<jv>b64os</jv>.close();
<jk>return new</jk> String(<jv>baos</jv>.toByteArray());
}
<ja>@Override</ja> <jc>/* StringSwap */</jc>
<jk>public byte</jk>[] unswap(String <jv>string</jv>, ClassMeta&lt;?&gt; <jv>hint</jv>) <jk>throws</jk> Exception {
<jk>byte</jk>[] <jv>bytes</jv> = <jv>string</jv>.getBytes();
ByteArrayInputStream <jv>bais</jv> = <jk>new</jk> ByteArrayInputStream(<jv>bytes</jv>);
InputStream <jv>b64is</jv> = MimeUtility.<jsm>decode</jsm>(<jv>bais</jv>, <js>"base64"</js>);
<jk>byte</jk>[] <jv>tmp</jv> = <jk>new byte</jk>[<jv>bytes</jv>.<jf>length</jf>];
<jk>int</jk> <jv>n</jv> = <jv>b64is</jv>.read(<jv>tmp</jv>);
<jk>byte</jk>[] <jv>res</jv> = <jk>new byte</jk>[<jv>n</jv>];
System.<jsm>arraycopy</jsm>(<jv>tmp</jv>, 0, <jv>res</jv>, 0, <jv>n</jv>);
<jk>return</jk> <jv>res</jv>;
}
}
</p>
<p>
The following example shows the BASE64 swap in use:
</p>
<p class='bjava'>
<jc>// Create a JSON serializer and register the BASE64 encoding swap with it.</jc>
WriterSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().simple().swaps(ByteArrayBase64Swap.<jk>class</jk>).build();
ReaderParser <jv>parser</jv> = JsonParser.<jsm>create</jsm>().swaps(ByteArrayBase64Swap.<jk>class</jk>).build();
<jk>byte</jk>[] <jv>bytes</jv> = {1,2,3};
String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>bytes</jv>); <jc>// Produces "'AQID'"</jc>
<jv>bytes</jv> = <jv>parser</jv>.parse(<jv>json</jv>, <jk>byte</jk>[].<jk>class</jk>); <jc>// Reproduces {1,2,3}</jc>
<jk>byte</jk>[][] <jv>bytes2d</jv> = {{1,2,3},{4,5,6},<jk>null</jk>};
<jv>json</jv> = <jv>serializer</jv>.serialize(<jv>bytes2d</jv>); <jc>// Produces "['AQID','BAUG',null]"</jc>
<jv>bytes2d</jv> = <jv>parser</jv>.parse(<jv>json</jv>, <jk>byte</jk>[][].<jk>class</jk>); <jc>// Reproduces {{1,2,3},{4,5,6},null}</jc>
</p>
<p>
The <a href="org/apache/juneau/BeanContextable.Builder.html#swap-java.lang.Class-java.lang.Class-org.apache.juneau.utils.ThrowingFunction-"><code>BeanContextable.Builder.swap(Class,Class,ThrowingFunction)</code></a> and <a href="org/apache/juneau/BeanContextable.Builder.html#swap-java.lang.Class-java.lang.Class-org.apache.juneau.utils.ThrowingFunction-org.apache.juneau.utils.ThrowingFunction-"><code>BeanContextable.Builder.swap(Class,Class,ThrowingFunction,ThrowingFunction)</code></a>
methods are another way to define swaps by using functions.
</p>
<p class='bjava'>
<jc>// Use a function to convert beans to strings.</jc>
WriterSerializer <jv>serializer</jv> = JsonSerializer
.<jsm>create</jsm>()
.simple()
.swap(MyBean.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> -> <jsm>myBeanStringifier</jsm>(<jv>x</jv>))
.build();
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Swaps.jm.DefaultSwaps' id='juneau-marshall.jm.Swaps.jm.DefaultSwaps'>2.11.1 - Default Swaps</a></h4>
<div class='topic'><!-- START: 2.11.1 - juneau-marshall.jm.Swaps.jm.DefaultSwaps -->
<div class='topic'>
<p>
By default, all serializers and parsers have built in <c>ObjectSwaps</c> defined for the following common data types:
</p>
<ul class='javatreec'>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html?is-external=true" title="class or interface in java.util"><code>Enumeration</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html?is-external=true" title="class or interface in java.util"><code>Iterator</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html?is-external=true" title="class or interface in java.util"><code>Locale</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Class.html?is-external=true" title="class or interface in java.util"><code>Class</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html?is-external=true" title="class or interface in java.time"><code>Instant</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html?is-external=true" title="class or interface in java.time"><code>ZonedDateTime</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html?is-external=true" title="class or interface in java.time"><code>LocalDate</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html?is-external=true" title="class or interface in java.time"><code>LocalDateTime</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html?is-external=true" title="class or interface in java.time"><code>LocalTime</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html?is-external=true" title="class or interface in java.time"><code>OffsetDateTime</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/OffsetTime.html?is-external=true" title="class or interface in java.time"><code>OffsetTime</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/Year.html?is-external=true" title="class or interface in java.time"><code>Year</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/YearMonth.html?is-external=true" title="class or interface in java.time"><code>YearMonth</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/Temporal.html?is-external=true" title="class or interface in java.time"><code>Temporal</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html?is-external=true" title="class or interface in java.util"><code>TimeZone</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/javax/xml/datatype/XMLGregorianCalendar.html?is-external=true" title="class or interface in javax.xml.datatype"><code>XMLGregorianCalendar</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html?is-external=true" title="class or interface in java.time"><code>ZoneId</code></a>
</ul>
<p>
Various other swaps are provided in the <a href="org/apache/juneau/swaps/package-summary.html"><code>org.apache.juneau.swaps</code></a> package.
</p>
</div>
</div><!-- END: 2.11.1 - juneau-marshall.jm.Swaps.jm.DefaultSwaps -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Swaps.jm.AutoSwaps' id='juneau-marshall.jm.Swaps.jm.AutoSwaps'>2.11.2 - Auto-detected swaps</a><span class='update'>created: 8.1.0</span></h4>
<div class='topic'><!-- START: 2.11.2 - juneau-marshall.jm.Swaps.jm.AutoSwaps -->
<div class='topic'>
<p>
Various methods can be defined on a class directly to affect how it gets serialized.
This can often be simpler than using <c>ObjectSwaps</c>.
</p>
<p>
Objects serialized as <c>Strings</c> can be parsed back into their original objects by
implementing one of the following methods on the class:
</p>
<ul class='spaced-list'>
<li>
<c><jk>public static</jk> T fromString(String)</c> method.
<br>Any of the following method names also work:
<ul>
<li><c>valueOf(String)</c>
<li><c>parse(String)</c>
<li><c>parseString(String)</c>
<li><c>forName(String)</c>
<li><c>forString(String)</c>
</ul>
<li>
<c><jk>public</jk> T(String)</c> constructor.
</ul>
<p>
Note that these methods cover conversion from several built-in Java types, meaning the parsers can
automatically construct these objects from strings:
</p>
<ul>
<li><c>fromString(String)</c> - <a href="https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html?is-external=true" title="class or interface in java.util"><code>UUID</code></a>
<li><c>valueOf(String)</c> - <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Byte.html?is-external=true" title="class or interface in java.lang"><code>Byte</code></a>,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html?is-external=true" title="class or interface in java.lang"><code>Float</code></a>,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang"><code>Integer</code></a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Short.html?is-external=true" title="class or interface in java.lang"><code>Short</code></a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/sql/Date.html?is-external=true" title="class or interface in java.sql"><code>Date</code></a>,
<a href="https://docs.oracle.com/javase/8/docs/api/java/sql/Time.html?is-external=true" title="class or interface in java.sql"><code>Time</code></a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/sql/Timestamp.html?is-external=true" title="class or interface in java.sql"><code>Timestamp</code></a>
<li><c>parse(String)</c> - <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true" title="class or interface in java.text"><code>DateFormat</code></a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/text/MessageFormat.html?is-external=true" title="class or interface in java.text"><code>MessageFormat</code></a>,
<a href="https://docs.oracle.com/javase/8/docs/api/java/text/NumberFormat.html?is-external=true" title="class or interface in java.text"><code>NumberFormat</code></a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a>, <a href="https://docs.oracle.com/javase/8/docs/api/java/util/logging/Level.html?is-external=true" title="class or interface in java.util.logging"><code>Level</code></a>
<li><c>parseString(String)</c> - <a href="https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/DatatypeConverter.html?is-external=true" title="class or interface in javax.xml.bind"><code>DatatypeConverter</code></a>
<li><c>forName(String)</c> - <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html?is-external=true" title="class or interface in java.lang"><code>Class</code></a>
</ul>
<p>
If you want to force a bean-like class to be serialized as a string, you can use the
<a href="org/apache/juneau/annotation/BeanIgnore.html" title="annotation in org.apache.juneau.annotation"><code>@BeanIgnore</code></a> annotation on the class to force it to be
serialized to a string using the <c>toString()</c> method.
</p>
<p>
Serializing to other intermediate objects can be accomplished by defining a swap method directly on the
class:
</p>
<ul>
<li><c><jk>public</jk> X swap()</c> method, where <c>X</c> is any serializable object.
<li><c><jk>public</jk> X swap(BeanSession)</c> method, where <c>X</c> is any serializable object.
<li><c><jk>public static</jk> MyPojo unswap(X)</c> method, where <c>X</c> is any serializable object.
<li><c><jk>public static</jk> MyPojo swap(X,BeanSession)</c> method, where <c>X</c> is any serializable object.
</ul>
<p>
Serializing to and from Maps can be accomplished by defining any of the following methods:
</p>
<ul>
<li><c><jk>public</jk> Map toMap()</c> method.
<br>Can be any type of map with string keys and object vals.
<li><c><jk>public</jk> JsonMap toMap()</c> method.
<li><c><jk>public</jk> Map toMap(BeanSession)</c> method.
<br>Can be any type of map with string keys and object vals.
<li><c><jk>public</jk> JsonMap toMap(BeanSession)</c> method.
<li><c><jk>public static</jk> MyPojo fromMap(Map)</c> method.
<br>Can be any type of map with string keys and object vals.
<li><c><jk>public static</jk> MyPojo fromMap(JsonMap)</c> method.
<li><c><jk>public static</jk> MyPojo fromMap(Map,BeanSession)</c> method.
<br>Can be any type of map with string keys and object vals.
<li><c><jk>public static</jk> MyPojo fromMap(JsonMap,BeanSession)</c> method.
</ul>
<p>
The <c>BeanSession</c> parameter allows you access to various information about the current
serialization session.
For example, you could provide customized results based on the media type being produced
(<a href="org/apache/juneau/BeanSession.html#getMediaType--"><code>BeanSession.getMediaType()</code></a>).
</p>
<p>
The following example shows how an HTML5 form template object can be created that gets serialized as a
populated HTML5 <a href="org/apache/juneau/dto/html5/Form.html" title="class in org.apache.juneau.dto.html5"><code>Form</code></a> bean.
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
<jd>/**
* A simple HTML form template whose serialized form is an HTML5 Form object.
*/</jd>
<jk>public class</jk> FormTemplate {
<jk>private</jk> String <jf>action</jf>;
<jk>private int</jk> <jf>value1</jf>;
<jk>private boolean</jk> <jf>value2</jf>;
<jc>// Some constructor that initializes our fields. </jc>
<jk>public</jk> FormTemplate(String <jv>action</jv>, <jk>int</jk> <jv>value1</jv>, <jk>boolean</jk> <jv>value2</jv>) {
<jk>this</jk>.<jf>action</jf> = <jv>action</jv>;
<jk>this</jk>.<jf>value1</jf> = <jv>value1</jv>;
<jk>this</jk>.<jf>value2</jf> = <jv>value2</jv>;
}
<jc>// Special swap method that converts this template to a serializable bean</jc>
<jk>public</jk> Form swap(BeanSession <jv>session</jv>) {
<jk>return</jk> <jsm>form</jsm>(<jf>action</jf>,
<jsm>input</jsm>(<js>"text"</js>).name(<js>"v1"</js>).value(<jf>value1</jf>),
<jsm>input</jsm>(<js>"text"</js>).name(<js>"v2"</js>).value(<jf>value2</jf>)
);
}
}
</p>
<p>
Swapped objects can be converted back into their original form by the parsers by specifying one of the
following methods:
</p>
<ul>
<li><c><jk>public static</jk> T unswap(BeanSession, X)</c> method where <c>X</c> is the
swap class type.
<li><c><jk>public</jk> T(X)</c> constructor where <c>X</c> is the swap class type.
</ul>
<p>
The following shows how our form template class can be modified to allow the parsers to reconstruct our
original object:
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
<jd>/**
* A simple HTML form template whose serialized form is an HTML5 Form object.
* This time with parsing support.
*/</jd>
<ja>@Bean</ja>(dictionary=HtmlBeanDictionary.<jk>class</jk>)
<jk>public class</jk> FormTemplate {
<jk>private</jk> String <jf>action</jf>;
<jk>private int</jk> <jf>value1</jf>;
<jk>private boolean</jk> <jf>value2</jf>;
<jc>// Our 'unswap' constructor</jc>
<jk>public</jk> FormTemplate(Form <jv>form</jv>) {
<jk>this</jk>.<jf>action</jf> = <jv>form</jv>.getAttr(<js>"action"</js>);
<jk>this</jk>.<jf>value1</jf> = <jv>form</jv>.getChild(Input.<jk>class</jk>, 0)
.getAttr(<jk>int</jk>.<jk>class</jk>, <js>"value"</js>);
<jk>this</jk>.<jf>value2</jf> = <jv>form</jv>.getChild(Input.<jk>class</jk>, 1)
.getAttr(<jk>boolean</jk>.<jk>class</jk>, <js>"value"</js>);
}
<jk>public</jk> FormTemplate(String <jv>action</jv>, <jk>int</jk> <jv>value1</jv>, <jk>boolean</jk> <jv>value2</jv>) {
<jk>this</jk>.<jf>action</jf> = <jv>action</jv>;
<jk>this</jk>.<jf>value1</jf> = <jv>value1</jv>;
<jk>this</jk>.<jf>value2</jf> = <jv>value2</jv>;
}
<jk>public</jk> Form swap(BeanSession <jv>session</jv>) {
<jk>return</jk> <jsm>form</jsm>(<jf>action</jf>,
<jsm>input</jsm>(<js>"text"</js>).name(<js>"v1"</js>).value(<jf>value1</jf>),
<jsm>input</jsm>(<js>"text"</js>).name(<js>"v2"</js>).value(<jf>value2</jf>)
);
}
}
</p>
</div>
</div><!-- END: 2.11.2 - juneau-marshall.jm.Swaps.jm.AutoSwaps -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Swaps.jm.PerMediaTypeSwaps' id='juneau-marshall.jm.Swaps.jm.PerMediaTypeSwaps'>2.11.3 - Per-media-type Swaps</a><span class='update'>updated: 8.1.0,8.2.0</span></h4>
<div class='topic'><!-- START: 2.11.3 - juneau-marshall.jm.Swaps.jm.PerMediaTypeSwaps -->
<div class='topic'>
<p>
Swaps can also be defined per-media-type.
</p>
<p>
The <a href="org/apache/juneau/swap/ObjectSwap.html#forMediaTypes--"><code>ObjectSwap.forMediaTypes()</code></a> method can be overridden to
provide a set of media types that the swap is invoked on.
It's also possible to define multiple swaps against the same object as long as they're differentiated
by media type.
When multiple swaps are defined, the best-match media type is used.
</p>
<p>
In the following example, we define 3 swaps against the same object.
One for JSON, one for XML, and one for all other types.
</p>
<p class='bjava'>
<jk>public class</jk> ObjectSwapTest {
<jk>public static class</jk> MyPojo {}
<jk>public static class</jk> MyJsonSwap <jk>extends</jk> StringSwap&lt;MyPojo&gt; {
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> MediaType[] forMediaTypes() {
<jk>return</jk> MediaType.<jsm>forStrings</jsm>(<js>"&#42;/json"</js>);
}
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> String swap(BeanSession <jv>session</jv>, MyPojo <jv>pojo</jv>) <jk>throws</jk> Exception {
<jk>return</jk> <js>"It's JSON!"</js>;
}
}
<jk>public static class</jk> MyXmlSwap <jk>extends</jk> StringSwap&lt;MyPojo&gt; {
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> MediaType[] forMediaTypes() {
<jk>return</jk> MediaType.<jsm>forStrings</jsm>(<js>"&#42;/xml"</js>);
}
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> String swap(BeanSession <jv>session</jv>, MyPojo <jv>pojo</jv>) <jk>throws</jk> Exception {
<jk>return</jk> <js>"It's XML!"</js>;
}
}
<jk>public static class</jk> MyOtherSwap <jk>extends</jk> StringSwap&lt;MyPojo&gt; {
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> MediaType[] forMediaTypes() {
<jk>return</jk> MediaType.<jsm>forStrings</jsm>(<js>"&#42;/*"</js>);
}
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> String swap(BeanSession <jv>session</jv>, MyPojo <jv>pojo</jv>) <jk>throws</jk> Exception {
<jk>return</jk> <js>"It's something else!"</js>;
}
}
<ja>@Test</ja>
<jk>public void</jk> doTest() <jk>throws</jk> Exception {
SerializerSet <jv>serializers</jv> = SerializersSet.<jsm>create</jsm>()
.add(JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>, HtmlSerializer.<jk>class</jk>)
.forEach(<jv>x</jv> -> <jv>x</jv>.swaps(MyJsonSwap.<jk>class</jk>, MyXmlSwap.<jk>class</jk>, MyOtherSwap.<jk>class</jk>))
.forEachWS(<jv>x</jv> -> <jv>x</jv>.ws())
.build();
MyPojo <jv>myPojo</jv> = <jk>new</jk> MyPojo();
String <jv>json</jv> = <jv>seralizers</jv>.getWriterSerializer(<js>"text/json"</js>).serialize(<jv>myPojo</jv>);
<jsm>assertEquals</jsm>(<js>"'It\\'s JSON!'"</js>, <jv>json</jv>);
String <jv>xml</jv> = <jv>seralizers</jv>.getWriterSerializer(<js>"text/xml"</js>).serialize(<jv>myPojo</jv>);
<jsm>assertEquals</jsm>(<js>"&lt;string&gt;It's XML!&lt;/string&gt;"</js>, <jv>xml</jv>);
String <jv>html</jv> = <jv>seralizers</jv>.getWriterSerializer(<js>"text/html"</js>).serialize(<jv>myPojo</jv>);
<jsm>assertEquals</jsm>(<js>"&lt;string&gt;It's something else!&lt;/string&gt;"</js>, <jv>html</jv>);
}
}
</p>
<p>
When multiple swaps match the same media type, a best-match algorithm is applied to find the correct
swap to use.
</p>
<p>
In later sections we describe how annotations can be used to shorten this syntax:
</p>
<p class='bjava'>
<ja>@Swap</ja>(MyJsonSwap.<jk>class</jk>)
<ja>@Swap</ja>(MyXmlSwap.<jk>class</jk>)
<ja>@Swap</ja>(MyOtherSwap.<jk>class</jk>)
<jk>public static class</jk> MyPojo {}
<ja>@Swap</ja>(mediaTypes=<js>"&#42;/json"</js>)
<jk>public static class</jk> MyJsonSwap <jk>extends</jk> ObjectSwap&lt;MyPojo,String&gt; {...}
<ja>@Swap</ja>(mediaTypes=<js>"&#42;/xml"</js>)
<jk>public static class</jk> MyXmlSwap <jk>extends</jk> ObjectSwap&lt;MyPojo,String&gt; {...}
<ja>@Swap</ja>(mediaTypes=<js>"&#42;/*"</js>)
<jk>public static class</jk> MyOtherSwap <jk>extends</jk> ObjectSwap&lt;MyPojo,String&gt; {...}
</p>
</div>
</div><!-- END: 2.11.3 - juneau-marshall.jm.Swaps.jm.PerMediaTypeSwaps -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Swaps.jm.OneWaySwaps' id='juneau-marshall.jm.Swaps.jm.OneWaySwaps'>2.11.4 - One-way Swaps</a></h4>
<div class='topic'><!-- START: 2.11.4 - juneau-marshall.jm.Swaps.jm.OneWaySwaps -->
<div class='topic'>
<p>
In the previous sections, we defined two-way swaps, meaning swaps where the original objects could be
reconstructing during parsing.
However, there are certain kinds of objects that we may want to support for serializing but that are not
possible to reconstruct during parsing.
For these, we can use one-way object swaps.
</p>
<p>
A one-way swap is simply an object transform that only implements the <code>swap()</code> method.
The <code>unswap()</code> method is simply left unimplemented.
</p>
<p>
An example of a one-way swaps would be one that allows <code>Iterators</code> to be serialized as JSON arrays.
It can make sense to be able to render <code>Iterators</code> as arrays but in general it's not possible to
reconstruct an <code>Iterator</code> during parsing.
</p>
<p class='bjava'>
<jk>public class</jk> IteratorSwap <jk>extends</jk> ObjectSwap&lt;Iterator,List&gt; {
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> List swap(Iterator <jv>iterator</jv>) {
List <jv>list</jv> = <jk>new</jk> LinkedList();
<jk>while</jk> (<jv>iterator</jv>.hasNext())
<jv>list</jv>.add(<jv>iterator</jv>.next());
<jk>return</jk> <jv>list</jv>;
}
}
</p>
<p>
Here is an example of our one-way swap being used.
Note that trying to parse the original object will cause a <a href="org/apache/juneau/parser/ParseException.html" title="class in org.apache.juneau.parser"><code>ParseException</code></a>
to be thrown.
</p>
<p class='bjava'>
<jc>// Create a JSON serializer that can serialize Iterators.</jc>
WriterSerializer <jv>serializer</jv> = JsonSerializer.<jsm>create</jsm>().simple().swaps(IteratorSwap.<jk>class</jk>).build();
<jc>// Construct an iterator we want to serialize.</jc>
Iterator <jv>iterator</jv> = JsonList.<jsm>of</jsm>(1,2,3).iterator();
<jc>// Serialize our Iterator</jc>
String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>iterator</jv>); <jc>// Produces "[1,2,3]"</jc>
<jc>// Try to parse it.</jc>
ReaderParser <jv>parser</jv> = JsonParser.<jsm>create</jsm>().swaps(IteratorSwap.<jk>class</jk>).build();
<jv>iterator</jv> = <jv>parser</jv>.parse(<jv>json</jv>, Iterator.<jk>class</jk>); <jc>// Throws ParseException!!!</jc>
</p>
</div>
</div><!-- END: 2.11.4 - juneau-marshall.jm.Swaps.jm.OneWaySwaps -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Swaps.jm.SwapAnnotation' id='juneau-marshall.jm.Swaps.jm.SwapAnnotation'>2.11.5 - @Swap Annotation</a><span class='update'>updated: 8.0.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.11.5 - juneau-marshall.jm.Swaps.jm.SwapAnnotation -->
<div class='topic'>
<p>
<a href="org/apache/juneau/annotation/Swap.html" title="annotation in org.apache.juneau.annotation"><code>@Swap</code></a> can be used to associate a swap class using an
annotation.
This is often cleaner than using the builder <c>swaps()</c> method since you can keep
your swap class near your POJO class.
</p>
<p class='bjava'>
<ja>@Swap</ja>(MyObjectSwap.<jk>class</jk>)
<jk>public class</jk> MyPojo {
...
}
<jc>// Sample swap for converting MyPojo classes to a simple string.</jc>
<jk>public class</jk> MyObjectSwap <jk>extends</jk> ObjectSwap&lt;MyPojo,String&gt; {
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> String swap(BeanSession <jv>session</jv>, MyPojo <jv>pojo</jv>) {
<jk>return</jk> <jv>pojo</jv>.toSomeSerializableForm();
}
}
</p>
<p>
Multiple swaps can be associated with a class using multiple <a href="org/apache/juneau/annotation/Swap.html" title="annotation in org.apache.juneau.annotation"><code>@Swap</code></a> annotations:
</p>
<p class='bjava'>
<ja>@Swap</ja>(MyJsonSwap.<jk>class</jk>)
<ja>@Swap</ja>(MyXmlSwap.<jk>class</jk>)
<ja>@Swap</ja>(MyOtherSwap.<jk>class</jk>)
<jk>public class</jk> MyPojo {}
</p>
<p>
<c>Readers</c> get serialized directly to the output of a serializer.
Therefore it's possible to implement a swap that provides fully-customized output.
</p>
<p class='bjava'>
<jk>public class</jk> MyJsonSwap <jk>extends</jk> ObjectSwap&lt;MyPojo,Reader&gt; {
<jk>public</jk> MediaType[] forMediaTypes() {
<jk>return</jk> MediaType.<jsm>forStrings</jsm>(<js>"&#42;/json"</js>);
}
<jk>public</jk> Reader swap(BeanSession <jv>session</jv>, MyPojo <jv>pojo</jv>) <jk>throws</jk> Exception {
<jk>return new</jk> StringReader(<js>"{message:'Custom JSON!'}"</js>);
}
}
</p>
<p>
The <ja>@Swap</ja> annotation can also be used on getters and setters as well to apply a swap
to individual property values:
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jk>private</jk> MyPojo <jf>myPojo</jf>;
<jc>// Swap applied to bean property.</jc>
<ja>@Beanp</ja>(swap=MyPojoSwap.<jk>class</jk>)
<jk>public</jk> MyPojo getMyPojo() {
<jk>return</jk> <jf>myPojo</jf>;
}
}
</p>
<p>
When applied to bean properties, the swap annotation need only be applied to either the getter, setter, or field.
</p>
<p>
The swap annotation can also be applied to the private field of a bean property, like so:
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<ja>@Beanp</ja>(swap=MyPojoSwap.<jk>class</jk>)
<jk>private</jk> MyPojo <jf>myPojo</jf>;
<jk>public</jk> MyPojo getMyPojo() {
<jk>return</jk> <jf>myPojo</jf>;
}
<jk>public</jk> MyBean setMyPojo(MyPojo <jv>myPojo</jv>) {
<jk>this</jk>.<jf>myPojo</jf> = <jv>myPojo</jv>;
<jk>return this</jk>;
}
}
</p>
</div>
</div><!-- END: 2.11.5 - juneau-marshall.jm.Swaps.jm.SwapAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Swaps.jm.TemplatedSwaps' id='juneau-marshall.jm.Swaps.jm.TemplatedSwaps'>2.11.6 - Templated Swaps</a></h4>
<div class='topic'><!-- START: 2.11.6 - juneau-marshall.jm.Swaps.jm.TemplatedSwaps -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/annotation/Swap.html#template--"><code>@Swap(template)</code></a> annotation allows you to associate
arbitrary contextual strings with swaps.
The primary purpose is for providing template names, such as for Apache FreeMarker, therefore
the name 'template'.
However, the usage of the string is open-ended.
</p>
<p>
For example, you could pair a template string like so:
</p>
<p class='bjava'>
<ja>@Swap</ja>(impl=FreeMarkerSwap.<jk>class</jk>, template=<js>"MyPojo.div.ftl"</js>)
<jk>public class</jk> MyPojo {}
</p>
<p>
The implementation of the FreeMarker swap would look something like this:
</p>
<p class='bjava'>
<jc>// Our templated swap class.</jc>
<jk>public class</jk> FreeMarkerSwap <jk>extends</jk> ObjectSwap&lt;Object,Reader&gt; {
<jk>public</jk> MediaType[] forMediaTypes() {
<jc>// Make sure this only applies to the HTML serializer.</jc>
<jk>return</jk> MediaType.<jsm>forStrings</jsm>(<js>"&#42;/html"</js>);
}
<jk>public</jk> Reader swap(BeanSession <jv>session</jv>, Object <jv>object</jv>, String <jv>template</jv>) <jk>throws</jk> Exception {
<jc>// Call some method that uses FreeMarker to convert 'o' to raw HTML using </jc>
<jc>// the 'MyPojo.div.ftl' template.</jc>
<jk>return</jk> getFreeMarkerReader(<jv>template</jv>, <jv>object</jv>);
}
}
</p>
</div>
</div><!-- END: 2.11.6 - juneau-marshall.jm.Swaps.jm.TemplatedSwaps -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Swaps.jm.SurrogateClasses' id='juneau-marshall.jm.Swaps.jm.SurrogateClasses'>2.11.7 - Surrogate Classes</a></h4>
<div class='topic'><!-- START: 2.11.7 - juneau-marshall.jm.Swaps.jm.SurrogateClasses -->
<div class='topic'>
<p>
Surrogate classes are very similar in concept to <c>ObjectSwaps</c> except they're simpler to define.
</p>
<p>
For example, let's say we want to be able to serialize the following class but it's not serializable for
some reason (for example, there are no properties exposed):
</p>
<p class='bjava'>
<jc>// Not serializable because it's not a bean because it has no public properties.</jc>
<jk>public class</jk> MyNonSerializableClass {
<jk>protected</jk> String <jf>foo</jf>;
}
</p>
<p>
This could be solved with the following <c>ObjectSwap</c>.
</p>
<p class='bjava'>
<jc>// A serializable bean with 1 property.</jc>
<jk>public class</jk> MySerializableSurrogate {
<jk>public</jk> String <jf>foo</jf>;
}
<jc>// An ObjectSwap that swaps out our non-serializable object with our serializable object.</jc>
<jk>public class</jk> MySwap <jk>extends</jk> ObjectSwap&lt;MyNonSerializableClass,MySerializableSurrogate&gt; {
<ja>@Override</ja> <jc>/* ObjectSwap */</jc>
<jk>public</jk> MySerializableSurrogate swap(MyNonSerializableClass <jv>object</jv>) {
<jc>// Create some serializable class and manually copy the data into it.</jc>
MySerializableSurrogate <jv>surrogate</jv> = <jk>new</jk> MySerializableSurrogate();
<jv>surrogate</jv>.<jf>foo</jf> = <jv>object</jv>.<jf>foo</jf>;
<jk>return</jk> <jv>surrogate</jv>;
}
}
</p>
<p>
However, the same can be accomplished by using a surrogate class that simply contains a constructor with
the non-serializable class as an argument:
</p>
<p class='bjava'>
<jk>public class</jk> MySerializableSurrogate {
<jk>public</jk> String <jf>foo</jf>;
<jc>// Constructor takes in our non-serializable object!</jc>
<jk>public</jk> MySerializableSurrogate(MyNonSerializableClass <jv>object</jv>) {
<jk>this</jk>.<jf>foo</jf> = <jv>object</jv>.<jf>foo</jf>;
}
}
</p>
<p>
The surrogate class is registered in the same way as a <c>ObjectSwap</c>:
</p>
<p class='bjava'>
<jc>// Create a JSON serializer that can serialize our unserializable object.</jc>
WriterSerializer <jv>serializer</jv> = JsonSerializer
.<jsm>create</jsm>()
.swaps(MySerializableSurrogate.<jk>class</jk>)
.build();
</p>
<p>
When the serializer encounters the non-serializable class, it will serialize an instance of the surrogate
instead.
</p>
<ul class='seealso'>
<li class='jic'><a href="org/apache/juneau/swap/Surrogate.html" title="interface in org.apache.juneau.swap"><code>Surrogate</code></a>
</ul>
</div>
</div><!-- END: 2.11.7 - juneau-marshall.jm.Swaps.jm.SurrogateClasses -->
</div><!-- END: 2.11 - juneau-marshall.jm.Swaps -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.DynamicallyAppliedAnnotations' id='juneau-marshall.jm.DynamicallyAppliedAnnotations'>2.12 - Dynamically Applied Annotations</a><span class='update'>created: 8.1.3, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.12 - juneau-marshall.jm.DynamicallyAppliedAnnotations -->
<div class='topic'>
<p>
In the section <a class='doclink' href='#juneau-marshall.jm.Swaps'>Swaps</a>, you were introduced to annotations that can be applied to bean
classes, methods, fields, and constructors such as <a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a>:
</p>
<p class='bjava'>
<jc>// Address class with only street/city/state properties (in that order).</jc>
<jc>// All other properties are ignored.</jc>
<ja>@Bean</ja>(properties=<js>"street,city,state"</js>)
<jk>public class</jk> Address { ... }
</p>
<p>
An alternate way of applying these annotations is to attach them to unrelated classes and methods and then
tell your serializer or parser where to find them.
</p>
<p class='bjava'>
<jc>// Unannotated class.</jc>
<jk>public class</jk> Address { ... }
<ja>@Bean</ja>(onClass=Address.<jk>class</jk>, properties=<js>"street,city,state"</js>)
<jk>public static class</jk> DummyClass {}
WriterSerializer <jv>serializer</jv> = JsonSerializer
.<jsm>create</jsm>()
.applyAnnotations(DummyClass.<jk>class</jk>)
.build();
String <jv>json</jv> = <jv>serializer</jv>.toString(<jv>addressBean</jv>);
</p>
<p>
The advantage to this approach is it allows you to use Juneau annotations on classes/methods/fields/constructors
where you might not have access to the source code, or when you only want to selectively apply the annotation
under certain scenarios instead of globally.
</p>
<p>
For example, the following shows the <ja>@Bean</ja> annotation being selectively applied on a single REST method
(described later in <a class='doclink' href='#juneau-rest-server'>juneau-rest-server</a>):
</p>
<p class='bjava'>
<ja>@RestGet</ja>
<ja>@Bean</ja>(onClass=Address.<jk>class</jk>, properties=<js>"street,city,state"</js>)
<jk>public</jk> List&lt;Address&gt; getAddresses() {}
</p>
<p>
Any Juneau annotation that has an <c>on()/onClass()</c> method can be applied dynamically this way.
These include:
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>Bean</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/Beanc.html" title="annotation in org.apache.juneau.annotation"><code>Beanc</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/BeanIgnore.html" title="annotation in org.apache.juneau.annotation"><code>BeanIgnore</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/Beanp.html" title="annotation in org.apache.juneau.annotation"><code>Beanp</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/Example.html" title="annotation in org.apache.juneau.annotation"><code>Example</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/NameProperty.html" title="annotation in org.apache.juneau.annotation"><code>NameProperty</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/ParentProperty.html" title="annotation in org.apache.juneau.annotation"><code>ParentProperty</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/Swap.html" title="annotation in org.apache.juneau.annotation"><code>Swap</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/Uri.html" title="annotation in org.apache.juneau.annotation"><code>Uri</code></a>
<li class='ja'><a href="org/apache/juneau/csv/annotation/Csv.html" title="annotation in org.apache.juneau.csv.annotation"><code>Csv</code></a>
<li class='ja'><a href="org/apache/juneau/html/annotation/Html.html" title="annotation in org.apache.juneau.html.annotation"><code>Html</code></a>
<li class='ja'><a href="org/apache/juneau/json/annotation/Json.html" title="annotation in org.apache.juneau.json.annotation"><code>Json</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/Schema.html" title="annotation in org.apache.juneau.annotation"><code>Schema</code></a>
<li class='ja'><a href="org/apache/juneau/msgpack/annotation/MsgPack.html" title="annotation in org.apache.juneau.msgpack.annotation"><code>MsgPack</code></a>
<li class='ja'><a href="org/apache/juneau/oapi/annotation/OpenApi.html" title="annotation in org.apache.juneau.oapi.annotation"><code>OpenApi</code></a>
<li class='ja'><a href="org/apache/juneau/plaintext/annotation/PlainText.html" title="annotation in org.apache.juneau.plaintext.annotation"><code>PlainText</code></a>
<li class='ja'><a href="org/apache/juneau/soap/annotation/SoapXml.html" title="annotation in org.apache.juneau.soap.annotation"><code>SoapXml</code></a>
<li class='ja'><a href="org/apache/juneau/uon/annotation/Uon.html" title="annotation in org.apache.juneau.uon.annotation"><code>Uon</code></a>
<li class='ja'><a href="org/apache/juneau/urlencoding/annotation/UrlEncoding.html" title="annotation in org.apache.juneau.urlencoding.annotation"><code>UrlEncoding</code></a>
<li class='ja'><a href="org/apache/juneau/xml/annotation/Xml.html" title="annotation in org.apache.juneau.xml.annotation"><code>Xml</code></a>
<li class='ja'><a href="org/apache/juneau/jena/annotation/Rdf.html" title="annotation in org.apache.juneau.jena.annotation"><code>Rdf</code></a>
</ul>
<p>
The valid pattern matches are:
</p>
<ul class='spaced-list'>
<li>Classes:
<ul>
<li>Fully qualified:
<ul>
<li><js>"com.foo.MyClass"</js>
</ul>
<li>Fully qualified inner class:
<ul>
<li><js>"com.foo.MyClass$Inner1$Inner2"</js>
</ul>
<li>Simple:
<ul>
<li><js>"MyClass"</js>
</ul>
<li>Simple inner:
<ul>
<li><js>"MyClass$Inner1$Inner2"</js>
<li><js>"Inner1$Inner2"</js>
<li><js>"Inner2"</js>
</ul>
</ul>
<li>Methods:
<ul>
<li>Fully qualified with args:
<ul>
<li><js>"com.foo.MyClass.myMethod(String,int)"</js>
<li><js>"com.foo.MyClass.myMethod(java.lang.String,int)"</js>
<li><js>"com.foo.MyClass.myMethod()"</js>
</ul>
<li>Fully qualified:
<ul>
<li><js>"com.foo.MyClass.myMethod"</js>
</ul>
<li>Simple with args:
<ul>
<li><js>"MyClass.myMethod(String,int)"</js>
<li><js>"MyClass.myMethod(java.lang.String,int)"</js>
<li><js>"MyClass.myMethod()"</js>
</ul>
<li>Simple:
<ul>
<li><js>"MyClass.myMethod"</js>
</ul>
<li>Simple inner class:
<ul>
<li><js>"MyClass$Inner1$Inner2.myMethod"</js>
<li><js>"Inner1$Inner2.myMethod"</js>
<li><js>"Inner2.myMethod"</js>
</ul>
</ul>
<li>Fields:
<ul>
<li>Fully qualified:
<ul>
<li><js>"com.foo.MyClass.myField"</js>
</ul>
<li>Simple:
<ul>
<li><js>"MyClass.myField"</js>
</ul>
<li>Simple inner class:
<ul>
<li><js>"MyClass$Inner1$Inner2.myField"</js>
<li><js>"Inner1$Inner2.myField"</js>
<li><js>"Inner2.myField"</js>
</ul>
</ul>
<li>Constructors:
<ul>
<li>Fully qualified with args:
<ul>
<li><js>"com.foo.MyClass(String,int)"</js>
<li><js>"com.foo.MyClass(java.lang.String,int)"</js>
<li><js>"com.foo.MyClass()"</js>
</ul>
<li>Simple with args:
<ul>
<li><js>"MyClass(String,int)"</js>
<li><js>"MyClass(java.lang.String,int)"</js>
<li><js>"MyClass()"</js>
</ul>
<li>Simple inner class:
<ul>
<li><js>"MyClass$Inner1$Inner2()"</js>
<li><js>"Inner1$Inner2()"</js>
<li><js>"Inner2()"</js>
</ul>
</ul>
<li>A comma-delimited list of anything on this list.
</ul>
</div>
</div><!-- END: 2.12 - juneau-marshall.jm.DynamicallyAppliedAnnotations -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.BeanDictionaries' id='juneau-marshall.jm.BeanDictionaries'>2.13 - Bean Names and Dictionaries</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.13 - juneau-marshall.jm.BeanDictionaries -->
<div class='topic'>
<p>
While parsing into beans, Juneau attempts to determine the class types of bean properties through
reflection on the bean property getter or setter.
Often this is insufficient if the property type is an interface or abstract class that cannot be
instantiated.
This is where bean names and dictionaries come into play.
</p>
<p>
Bean names and dictionaries are used for identifying class types when they cannot be inferred through
reflection.
</p>
<p>
Bean classes are given names through the <a href="org/apache/juneau/annotation/Bean.html#typeName--"><code>@Bean(typeName)</code></a>
annotation.
These names are then added to the serialized output as virtual <js>"_type"</js> properties (or element
names in XML).
</p>
<p>
On the parsing side, these type names are resolved to classes through the use of bean dictionaries.
</p>
<p>
For example, if a bean property is of type <c>Object</c>, then the serializer will add
<js>"_type"</js> attributes so that the class can be determined during parsing.
</p>
<p class='bjava'>
<ja>@Bean</ja>(typeName=<js>"foo"</js>)
<jk>public class</jk> Foo {
<jc>// A bean property where the object types cannot be inferred since it's an Object[].</jc>
<ja>@Beanp</ja>(dictionary={Bar.<jk>class</jk>,Baz.<jk>class</jk>})
<jk>public</jk> Object[] <jf>x</jf> = <jk>new</jk> Object[]{<jk>new</jk> Bar(), <jk>new</jk> Baz()};
}
<ja>@Bean</ja>(typeName=<js>"bar"</js>)
<jk>public class</jk> Bar {}
<ja>@Bean</ja>(typeName=<js>"baz"</js>)
<jk>public class</jk> Baz {}
</p>
<p>
When serialized as JSON, <js>"_type"</js> attributes would be added when needed to infer the type during
parsing:
</p>
<p class='bjson'>
{
x: [
{_type:<js>'bar'</js>},
{_type:<js>'baz'</js>}
]
}
</p>
<p>
Type names can be represented slightly differently in different languages.
For example, the dictionary name is used as element names when serialized to XML.
This allows the <c>typeName</c> annotation to be used as a shortcut for defining element names for
beans.
</p>
<p>
When serialized as XML, the bean is rendered as:
</p>
<p class='bxml'>
<xt>&lt;foo&gt;</xt>
<xt>&lt;x&gt;</xt>
<xt>&lt;bar/&gt;</xt>
<xt>&lt;baz/&gt;</xt>
<xt>&lt;/x&gt;</xt>
<xt>&lt;/foo&gt;</xt>
</p>
<p>
Bean dictionaries are registered through the following:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/annotation/Beanp.html" title="annotation in org.apache.juneau.annotation"><code>Beanp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/annotation/Beanp.html#dictionary--"><code>dictionary</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>Bean</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/annotation/Bean.html#dictionary--"><code>dictionary</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanDictionary-java.lang.Class...-"><code>beanDictionary(Class...)</code></a>
</ul>
</li>
</ul>
<p>
The bean dictionary setting can consist of any of the following types:
</p>
<ul>
<li>Any bean class that specifies a value for <a href="org/apache/juneau/annotation/Bean.html#typeName--"><code>@Bean(typeName)</code></a>.
<li>Any subclass of <a href="org/apache/juneau/BeanDictionaryList.html" title="class in org.apache.juneau"><code>BeanDictionaryList</code></a> containing a collection of bean classes with type name annotations.
<li>Any subclass of <a href="org/apache/juneau/BeanDictionaryMap.html" title="class in org.apache.juneau"><code>BeanDictionaryMap</code></a> containing a mapping of type names to classes without type name annotations.
<li>Any array or collection of the objects above.
</ul>
<p class='bjava'>
<jc>// Create a parser and tell it which classes to try to resolve.</jc>
ReaderParser <jv>parser</jv> = JsonParser
.<jsm>create</jsm>()
.dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>)
.build();
<jc>// Use the predefined HTML5 bean dictionary which is a BeanDictionaryList.</jc>
ReaderParser <jv>parser</jv> = HtmlParser
.<jsm>create</jsm>()
.dictionary(HtmlBeanDictionary.<jk>class</jk>)
.build();
</p>
<p>
The <js>"_type"</js> property name can be overridden through the following:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>Bean</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/annotation/Bean.html#typePropertyName--"><code>typePropertyName</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#typePropertyName-java.lang.String-"><code>typePropertyName(String)</code></a>
</ul>
</li>
</ul>
<p>
When using the annotation, you'll typically want to define it on an interface class so that it can
be inherited by all subclasses.
</p>
<p class='bjava'>
<ja>@Bean</ja>(typePropertyName=<js>"mytype"</js>, dictionary={MyClass1.<jk>class</jk>,MyClass2.<jk>class</jk>})
<jk>public interface</jk> MyInterface {...}
<ja>@Bean</ja>(typeName=<js>"C1"</js>)
<jk>public class</jk> MyClass1 <jk>implements</jk> MyInterface {...}
<ja>@Bean</ja>(typeName=<js>"C2"</js>)
<jk>public class</jk> MyClass2 <jk>implements</jk> MyInterface {...}
MyInterface[] <jv>x</jv> = <jk>new</jk> MyInterface[]{ <jk>new</jk> MyClass1(), <jk>new</jk> MyClass2() };
<jc>// Produces "[{mytype:'C1',...},{mytype:'C2',...}]"</jc>
String <jv>json</jv> = SimpleJsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jv>x</jv>);
</p>
<div class='info'>
Type names do not need to be universally unique.
However, they must be unique within a dictionary.
</div>
<div class='info'>
The following reserved words cannot be used as type names:
<c>object, array, number, boolean, null</c>.
</div>
<div class='info'>
Serialized type names are DISABLED by default.
They must be enabled on the serializer using the
<a href="org/apache/juneau/serializer/Serializer.Builder.html#addBeanTypes--"><code>Serializer.Builder.addBeanTypes()</code></a>
setting.
</div>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.BeanDictionaries.jm.BeanSubTypes' id='juneau-marshall.jm.BeanDictionaries.jm.BeanSubTypes'>2.13.1 - Bean Subtypes</a></h4>
<div class='topic'><!-- START: 2.13.1 - juneau-marshall.jm.BeanDictionaries.jm.BeanSubTypes -->
<div class='topic'>
<p>
In addition to the bean type name support described above, simplified support is provided
for bean subtypes.
</p>
<p>
Bean subtypes are similar in concept to bean type names, except for the following differences:
</p>
<ul>
<li>You specify the list of possible subclasses through an annotation on a parent bean class.
<li>You do not need to register the subtype classes on the bean dictionary of the parser.
</ul>
<p>
In the following example, the abstract class has two subclasses:
</p>
<p class='bjava'>
<jc>// Abstract superclass</jc>
<ja>@Bean</ja>(
dictionary={A1.<jk>class</jk>, A2.<jk>class</jk>}
)
<jk>public abstract class</jk> A {
<jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
}
<jc>// Subclass 1</jc>
<ja>@Bean</ja>(typeName=<js>"A1"</js>)
<jk>public class</jk> A1 <jk>extends</jk> A {
<jk>public</jk> String <jf>f1</jf>;
}
<jc>// Subclass 2</jc>
<ja>@Bean</ja>(typeName=<js>"A2"</js>)
<jk>public class</jk> A2 <jk>extends</jk> A {
<jk>public</jk> String <jf>f2</jf>;
}
</p>
<p>
When serialized, the subtype is serialized as a virtual <js>"_type"</js> property:
</p>
<p class='bjava'>
A1 <jv>object</jv> = <jk>new</jk> A1();
<jv>object</jv>.<jf>f1</jf> = <js>"f1"</js>;
String <jv>json</jv> = SimpleJson.<jsm>of</jsm>(<jv>object</jv>);
<jsm>assertEquals</jsm>(<js>"{_type:'A1',f1:'f1',f0:'f0'}"</js>, <jv>json</jv>);
</p>
<p>
The following shows what happens when parsing back into the original object.
</p>
<p class='bjava'>
A <jv>object</jv> = Json.<jsm>to</jsm>(<jv>json</jv>, A.<jk>class</jk>);
<jsm>assertTrue</jsm>(<jv>object</jv> <jk>instanceof</jk> A1);
</p>
</div>
</div><!-- END: 2.13.1 - juneau-marshall.jm.BeanDictionaries.jm.BeanSubTypes -->
</div><!-- END: 2.13 - juneau-marshall.jm.BeanDictionaries -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.VirtualBeans' id='juneau-marshall.jm.VirtualBeans'>2.14 - Virtual Beans</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.14 - juneau-marshall.jm.VirtualBeans -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/BeanContext.Builder.html#disableInterfaceProxies--"><code>BeanContext.Builder.disableInterfaceProxies()</code></a> setting (enabled by default) allows
the Juneau parsers to parse content into virtual beans (bean interfaces without implementation classes).
</p>
<p>
For example, the following code creates an instance of the specified unimplemented interface:
</p>
<p class='bjava'>
<jc>// Our unimplemented interface</jc>
<jk>public interface</jk> Address {
String getStreet();
<jk>void</jk> setStreet(String <jv>value</jv>);
String getCity();
<jk>void</jk> setCity(String <jv>value</jv>);
StateEnum getState();
<jk>void</jk> setState(StateEnum <jv>value</jv>);
<jk>int</jk> getZip();
<jk>void</jk> setZip(<jk>int</jk> <jv>value</jv>);
}
<jc>// Our code</jc>
Address <jv>address</jv> = Json.<jsm>to</jsm>(
<js>"{street:'123 Main St', city:'Anywhere', state:'PR', zip:12345}"</js>,
Address.<jk>class</jk>
);
<jk>int</jk> <jv>zip</jv> = <jv>address</jv>.getZip();
<jv>address</jv>.setState(StateEnum.<jsf>NY</jsf>);
</p>
<p>
Getter and setter values can be any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>parsable</a> values, even other virtual beans.
</p>
<p>
Under-the-covers, a virtual bean is simply a proxy interface on top of an existing <a href="org/apache/juneau/BeanMap.html" title="class in org.apache.juneau"><code>BeanMap</code></a>
instance. From a programmatic point-of-view, they're indistinguishable from real beans, and can be
manipulated and serialized like any other bean.
</p>
<p>
Virtual beans can also be created programmatically using the <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a> class:
</p>
<p class='bjava'>
Address <jv>address</jv> = BeanContext.<jsf>DEFAULT</jsf>.createSession().newBean(Address.<jk>class</jk>);
</p>
</div>
</div><!-- END: 2.14 - juneau-marshall.jm.VirtualBeans -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Recursion' id='juneau-marshall.jm.Recursion'>2.15 - Non-Tree Models and Recursion Detection</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.15 - juneau-marshall.jm.Recursion -->
<div class='topic'>
<p>
The Juneau Serializer API is designed to be used against POJO tree structures.
It expects that there not be loops in the POJO model (e.g. children with references to parents, etc...).
If you try to serialize models with loops, you will usually cause a <c>StackOverflowError</c> to
be thrown (if <a href="org/apache/juneau/BeanTraverseContext.Builder.html#maxDepth-int-"><code>BeanTraverseContext.Builder.maxDepth(int)</code></a> is not reached
first).
</p>
<p>
If you still want to use the Juneau serializers on such models, Juneau provides the
<a href="org/apache/juneau/BeanTraverseContext.Builder.html#detectRecursions--"><code>BeanTraverseContext.Builder.detectRecursions()</code></a> setting.
It tells the serializer to look for instances of an object in the current branch of the tree and skip
serialization when a duplicate is encountered.
</p>
<p>
For example, let's make a POJO model out of the following classes:
</p>
<p class='bjava'>
<jk>public class</jk> A {
<jk>public</jk> B <jf>b</jf>;
}
<jk>public class</jk> B {
<jk>public</jk> C <jf>c</jf>;
}
<jk>public class</jk> C {
<jk>public</jk> A <jf>a</jf>;
}
</p>
<p>
Now we create a model with a loop and serialize the results.
</p>
<p class='bjava'>
<jc>// Clone an existing serializer and set property for detecting recursions.</jc>
JsonSerializer <jv>serializer</jv> = SimpleJsonSerializer
.<jsf>DEFAULT_READABLE</jsf>
.copy()
.detectRecursions()
.build();
<jc>// Create a recursive loop.</jc>
A <jv>a</jv> = <jk>new</jk> A();
<jv>a</jv>.<jf>b</jf> = <jk>new</jk> B();
<jv>a</jv>.<jf>b</jf>.<jf>c</jf> = <jk>new</jk> C();
<jv>a</jv>.<jf>b</jf>.<jf>c</jf>.<jf>a</jf> = <jv>a</jv>;
<jc>// Serialize to JSON.</jc>
String <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>a</jv>);
</p>
<p>
What we end up with is the following, which does not serialize the contents of the <c>c</c> field:
</p>
<p class='bjson'>
{
<jok>b</jok>: {
<jok>c</jok>: {
}
}
}
</p>
<p>
Without recursion detection enabled, this would cause a stack-overflow error.
</p>
<p>
Recursion detection introduces a performance penalty of around 20%.
For this reason the setting is disabled by default.
</p>
</div>
</div><!-- END: 2.15 - juneau-marshall.jm.Recursion -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.ParsingIntoGenericModels' id='juneau-marshall.jm.ParsingIntoGenericModels'>2.16 - Parsing into Generic Models</a><span class='update'>updated: 8.2.0</span></h3>
<div class='topic'><!-- START: 2.16 - juneau-marshall.jm.ParsingIntoGenericModels -->
<div class='topic'>
<p>
The Juneau parsers are not limited to parsing back into the original bean classes.
If the bean classes are not available on the parsing side, the parser can also be used to
parse into a generic model consisting of <c>Maps</c>, <c>Collections</c>, and primitive
objects.
</p>
<p>
You can parse into any <c>Map</c> type (e.g. <c>HashMap</c>, <c>TreeMap</c>) but
using <a href="org/apache/juneau/collections/JsonMap.html" title="class in org.apache.juneau.collections"><code>JsonMap</code></a> is recommended since it has many convenience methods
for converting values to various types.
The same is true when parsing collections. You can use any Collection (e.g. <c>HashSet</c>,
<c>LinkedList</c>) or array (e.g. <c>Object[]</c>, <c>String[]</c>,
<c>String[][]</c>) but using <a href="org/apache/juneau/collections/JsonList.html" title="class in org.apache.juneau.collections"><code>JsonList</code></a> is recommended.
</p>
<p>
When the map or list type is not specified, or is the abstract <c>Map</c>, <c>Collection</c>,
or <c>List</c> types, the parser will use <c>JsonMap</c> and <c>JsonList</c> by
default.
</p>
<p>
For example, given the following JSON:
</p>
<p class='bjson'>
{
id: <jk>1</jk>,
name: <js>'John Smith'</js>,
uri: <js>'http://sample/addressBook/person/1'</js>,
addressBookUri: <js>'http://sample/addressBook'</js>,
birthDate: <js>'1946-08-12T00:00:00Z'</js>,
addresses: [
{
uri: <js>'http://sample/addressBook/address/1'</js>,
personUri: <js>'http://sample/addressBook/person/1'</js>,
id: <jk>1</jk>,
street: <js>'100 Main Street'</js>,
city: <js>'Anywhereville'</js>,
state: <js>'NY'</js>,
zip: <jk>12345</jk>,
isCurrent: <jk>true</jk>
}
]
}
</p>
<p>
We can parse this into a generic <c>JsonMap</c>:
</p>
<p class='bjava'>
<jc>// Parse JSON into a generic POJO model.</jc>
JsonMap <jv>map</jv> = Json.<jsm>to</jsm>(<jv>json</jv>, JsonMap.<jk>class</jk>);
<jc>// Convert it back to JSON.</jc>
String <jv>json</jv> = SimpleJson.<jsm>of</jsm>(<jv>map</jv>);
</p>
<p>
What we end up with is the exact same output.
Even the numbers and booleans are preserved because they are parsed into <c>Number</c> and
<c>Boolean</c> objects when parsing into generic models.
</p>
<p class='bjson'>
{
id: <jk>1</jk>,
name: <js>'John Smith'</js>,
uri: <js>'http://sample/addressBook/person/1'</js>,
addressBookUri: <js>'http://sample/addressBook'</js>,
birthDate: <js>'1946-08-12T00:00:00Z'</js>,
addresses: [
{
uri: <js>'http://sample/addressBook/address/1'</js>,
personUri: <js>'http://sample/addressBook/person/1'</js>,
id: <jk>1</jk>,
street: <js>'100 Main Street'</js>,
city: <js>'Anywhereville'</js>,
state: <js>'NY'</js>,
zip: <jk>12345</jk>,
isCurrent: <jk>true</jk>
}
]
}
</p>
<p>
Once parsed into a generic model, various convenience methods are provided on the <c>JsonMap</c>
and <c>JsonList</c> classes to retrieve values:
</p>
<p class='bjava'>
<jc>// Parse JSON into a generic POJO model.</jc>
JsonMap <jv>map</jv> = Json.<jsm>to</jsm>(<jv>json</jv>, JsonMap.<jk>class</jk>);
<jc>// Get some simple values.</jc>
String <jv>name</jv> = <jv>map</jv>.getString(<js>"name"</js>);
<jk>int</jk> <jv>id</jv> = <jv>map</jv>.getInt(<js>"id"</js>);
<jc>// Get a value convertable from a String.</jc>
URI <jv>uri</jv> = <jv>map</jv>.get(URI.<jk>class</jk>, <js>"uri"</js>);
<jc>// Get a value using a swap.</jc>
TemporalCalendarSwap <jv>swap</jv> = <jk>new</jk> TemporalCalendarSwap.IsoInstant();
Calendar <jv>birthDate</jv> = <jv>map</jv>.get(<jv>swap</jv>, <js>"birthDate"</js>);
<jc>// Get the addresses.</jc>
JsonList <jv>addresses</jv> = <jv>map</jv>.getList(<js>"addresses"</js>);
<jc>// Get the first address and convert it to a bean.</jc>
Address <jv>address</jv> = <jv>addresses</jv>.get(Address.<jk>class</jk>, 0);
</p>
<p>
As a general rule, parsing into beans is often more efficient than parsing into generic models.
And working with beans is often less error prone than working with generic models.
</p>
</div>
</div><!-- END: 2.16 - juneau-marshall.jm.ParsingIntoGenericModels -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.ReadingContinuousStreams' id='juneau-marshall.jm.ReadingContinuousStreams'>2.17 - Reading Continuous Streams</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.17 - juneau-marshall.jm.ReadingContinuousStreams -->
<div class='topic'>
<p>
The following parsers can be configured to read continuous streams of objects from the same input stream:
</p>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a>
<li class='jc'><a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a>
<li class='jc'><a href="org/apache/juneau/msgpack/MsgPackParser.html" title="class in org.apache.juneau.msgpack"><code>MsgPackParser</code></a>
</ul>
<p>
The <a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a> and <a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a>
classes can read continuous streams by using the <a href="org/apache/juneau/parser/Parser.Builder.html#unbuffered--"><code>Parser.Builder.unbuffered()</code></a>
setting.
This prevents the parsers from using an internal buffer that would read past the end of the currently
parsed POJO.
</p>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// If you're calling parse on the same input multiple times, use a session instead of the parser directly.</jc>
ReaderParserSession <jv>session</jv> = JsonParser.<jsm>create</jsm>().unbuffered().build().createSession();
Object <jv>pojo</jv>;
Reader <jv>reader</jv>;
<jv>reader</jv> = <jk>new</jk> StringReader(<js>"{foo:'bar'}{baz:'qux'}"</js>);
<jv>pojo</jv> = <jv>session</jv>.parse(<jv>reader</jv>, JsonMap.<jk>class</jk>); <jc>// {foo:'bar'}</jc>
<jv>pojo</jv> = <jv>session</jv>.parse(<jv>reader</jv>, JsonMap.<jk>class</jk>); <jc>// {baz:'qux'}</jc>
<jv>reader</jv> = <jk>new</jk> StringReader(<js>"[123][456]"</js>);
<jv>pojo</jv> = <jv>session</jv>.parse(<jv>reader</jv>, <jk>int</jk>[].<jk>class</jk>); <jc>// [123]</jc>
<jv>pojo</jv> = <jv>session</jv>.parse(<jv>reader</jv>, <jk>int</jk>[].<jk>class</jk>); <jc>// [456]</jc>
</p>
<p>
Note that this isn't perfect in all cases since you can't combine two JSON numbers into a single
reader (e.g. <c>"123" + "456" = "123456"</c>).
</p>
<p>
For obvious reasons, do not use the following properties when reading continuous streams:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/json/JsonParser.Builder.html" title="class in org.apache.juneau.json"><code>JsonParser.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/json/JsonParser.Builder.html#validateEnd--"><code>validateEnd()</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/uon/UonParser.Builder.html" title="class in org.apache.juneau.uon"><code>UonParser.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/uon/UonParser.Builder.html#validateEnd--"><code>validateEnd()</code></a>
</ul>
</li>
<li class='jac'><a href="org/apache/juneau/parser/Parser.Builder.html" title="class in org.apache.juneau.parser"><code>Parser.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/parser/Parser.Builder.html#autoCloseStreams--"><code>validateEnd()</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/msgpack/MsgPackParser.html" title="class in org.apache.juneau.msgpack"><code>MsgPackParser</code></a> class doesn't use any internal buffering to begin with, so it can be used with
continuous streams without any special properties.
</p>
</div>
</div><!-- END: 2.17 - juneau-marshall.jm.ReadingContinuousStreams -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.MarshallingUris' id='juneau-marshall.jm.MarshallingUris'>2.18 - URIs</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.18 - juneau-marshall.jm.MarshallingUris -->
<div class='topic'>
<p>
Juneau serializers have sophisticated support for transforming relative URIs to absolute form.
</p>
<p>
The following example shows a bean containing URIs of various forms and how they end up serialized.
</p>
<p class='bjava'>
<jc>// Our bean with properties containing various kinds of URIs.</jc>
<jk>public class</jk> TestURIs {
<jk>public</jk> URI
<jf>a</jf> = URI.<jsm>create</jsm>(<js>"http://www.apache.org/a"</js>),
<jf>b</jf> = URI.<jsm>create</jsm>(<js>"/b"</js>),
<jf>c</jf> = URI.<jsm>create</jsm>(<js>"/c/x/y"</js>),
<jf>d</jf> = URI.<jsm>create</jsm>(<js>"d"</js>),
<jf>e</jf> = URI.<jsm>create</jsm>(<js>"e/x/y"</js>),
<jf>f</jf> = URI.<jsm>create</jsm>(<js>""</js>),
<jf>g</jf> = URI.<jsm>create</jsm>(<js>"context:/g/x"</js>),
<jf>h</jf> = URI.<jsm>create</jsm>(<js>"context:/h"</js>),
<jf>i</jf> = URI.<jsm>create</jsm>(<js>"context:/"</js>),
<jf>j</jf> = URI.<jsm>create</jsm>(<js>"context:/.."</js>),
<jf>k</jf> = URI.<jsm>create</jsm>(<js>"servlet:/k/x"</js>),
<jf>l</jf> = URI.<jsm>create</jsm>(<js>"servlet:/l"</js>),
<jf>m</jf> = URI.<jsm>create</jsm>(<js>"servlet:/"</js>),
<jf>n</jf> = URI.<jsm>create</jsm>(<js>"servlet:/.."</js>),
<jf>o</jf> = URI.<jsm>create</jsm>(<js>"request:/o/x"</js>),
<jf>p</jf> = URI.<jsm>create</jsm>(<js>"request:/p"</js>),
<jf>q</jf> = URI.<jsm>create</jsm>(<js>"request:/"</js>),
<jf>r</jf> = URI.<jsm>create</jsm>(<js>"request:/.."</js>);
}
<jc>// Create a serializer.</jc>
WriterSerializer <jv>serializer</jv> = JsonSerializer
<jsm>create</jsm>()
.simple()
.uriContext(
UriContext.of(
<js>"http://foo.com:123"</js>, <jc>// Authority</jc>
<js>"/myContext"</js>, <jc>// Context root</jc>
<js>"/myServlet"</js>, <jc>// Servlet path</jc>
<js>"/myPath"</js> <jc>// Path info</jc>
)
)
.uriResolution(<jsf>ABSOLUTE</jsf>)
.uriRelativity(<jsf>RESOURCE</jsf>)
.build();
<jc>// Produces:</jc>
<jc>// {</jc>
<jc>// a:'http://www.apache.org/a',</jc>
<jc>// b:'http://foo.com:123/b',</jc>
<jc>// c:'http://foo.com:123/c/x/y',</jc>
<jc>// d:'http://foo.com:123/myContext/myServlet/d',</jc>
<jc>// e:'http://foo.com:123/myContext/myServlet/e/x/y',</jc>
<jc>// f:'http://foo.com:123/myContext/myServlet',</jc>
<jc>// g:'http://foo.com:123/myContext/g/x',</jc>
<jc>// h:'http://foo.com:123/myContext/h',</jc>
<jc>// i:'http://foo.com:123/myContext',</jc>
<jc>// j:'http://foo.com:123'</jc>
<jc>// k:'http://foo.com:123/myContext/myServlet/k/x',</jc>
<jc>// l:'http://foo.com:123/myContext/myServlet/l',</jc>
<jc>// m:'http://foo.com:123/myContext/myServlet',</jc>
<jc>// n:'http://foo.com:123/myContext',</jc>
<jc>// o:'http://foo.com:123/myContext/myServlet/myPath/o/x',</jc>
<jc>// p:'http://foo.com:123/myContext/myServlet/myPath/p',</jc>
<jc>// q:'http://foo.com:123/myContext/myServlet/myPath',</jc>
<jc>// r:'http://foo.com:123/myContext/myServlet'</jc>
<jc>// }</jc>
String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> TestURIs());
</p>
<p>
URI resolution is controlled by the following settings:
</p>
<ul class='javatree'>
<li class='jm'><a href="org/apache/juneau/serializer/Serializer.Builder.html#uriContext-org.apache.juneau.UriContext-"><code>Serializer.Builder.uriContext(UriContext)</code></a>
<br>Setting that defines the URI contextual information used to resolve relative URIs.
</li>
<li class='jm'><a href="org/apache/juneau/serializer/Serializer.Builder.html#uriRelativity-org.apache.juneau.UriRelativity-"><code>Serializer.Builder.uriRelativity(UriRelativity)</code></a>
<br>Setting that defines how relative URIs should be interpreted.
<br>Possible values:
<ul>
<li class='jf'><a href="org/apache/juneau/UriRelativity.html#RESOURCE"><code>UriRelativity.RESOURCE</code></a>
<br>Relative URIs should be considered relative to the servlet URI.
<br>(e.g. <js>"http://host:port/context-root/servlet-path"</js>).
<li class='jf'><a href="org/apache/juneau/UriRelativity.html#PATH_INFO"><code>UriRelativity.PATH_INFO</code></a>
<br>Relative URIs should be considered relative to the request URI.
<br>(e.g. <js>"http://host:port/context-root/servlet-path/path-info"</js>).
</ul>
</li>
<li class='jm'><a href="org/apache/juneau/serializer/Serializer.Builder.html#uriResolution-org.apache.juneau.UriResolution-"><code>Serializer.Builder.uriResolution(UriResolution)</code></a>
<br>Setting that defines the final format of serialized URIs.
<br>Possible values:
<ul>
<li class='jf'><a href="org/apache/juneau/UriResolution.html#ABSOLUTE"><code>UriResolution.ABSOLUTE</code></a>
<br>Resolve to an absolute URL.
<br>(e.g. <js>"http://host:port/context-root/servlet-path/path-info"</js>).
<li class='jf'><a href="org/apache/juneau/UriResolution.html#ROOT_RELATIVE"><code>UriResolution.ROOT_RELATIVE</code></a>
<br>Resolve to a root-relative URL.
<br>(e.g. <js>"/context-root/servlet-path/path-info"</js>).
<li class='jf'><a href="org/apache/juneau/UriResolution.html#NONE"><code>UriResolution.NONE</code></a>
<br>Don't do any URL resolution.
</ul>
</li>
</ul>
<p>
Juneau automatically interprets any <a href="https://docs.oracle.com/javase/8/docs/api/java/net/URL.html?is-external=true" title="class or interface in java.net"><code>URL</code></a> and <a href="https://docs.oracle.com/javase/8/docs/api/java/net/URI.html?is-external=true" title="class or interface in java.net"><code>URI</code></a> objects as URIs and will
resolve them accordingly.
The <a href="org/apache/juneau/annotation/Uri.html" title="annotation in org.apache.juneau.annotation"><code>@Uri</code></a> annotation can be used to extend that to other bean
properties and class types so that they also get interpreted as URIs.
For example:
</p>
<p class='bjava'>
<jc>// Applied to a class whose toString() method returns a URI.</jc>
<ja>@URI</ja>
<jk>public class</jk> MyURI {
<ja>@Override</ja> <jc>/* Object */</jc>
<jk>public</jk> String toString() {
<jk>return</jk> <js>"http://localhost:9080/foo/bar"</js>;
}
}
<jc>// Applied to bean properties</jc>
<jk>public class</jk> MyBean {
<ja>@URI</ja>
<jk>public</jk> String <jf>beanUri</jf>;
<ja>@URI</ja>
<jk>public</jk> String getParentUri() {
...
}
}
</p>
</div>
</div><!-- END: 2.18 - juneau-marshall.jm.MarshallingUris -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JacksonComparison' id='juneau-marshall.jm.JacksonComparison'>2.19 - Comparison with Jackson</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.19 - juneau-marshall.jm.JacksonComparison -->
<div class='topic'>
<p>
Juneau was developed independently from Jackson but shares many of the same features and capabilities.
Whereas Jackson was created to work primarily with JSON, Juneau was created to work for multiple languages.
Therefore, the terminology and annotations in Juneau are similar but language-agnostic.
</p>
<p>
The following charts describe equivalent features between the two libraries:
</p>
<h5 class='topic'>Annotations</h5>
<table class='styled w800'>
<tr><th>Jackson</th><th>Juneau</th></tr>
<tr>
<td>
<ja>@JsonGetter</ja>
<br><ja>@JsonSetter</ja>
</td>
<td>
<a href="org/apache/juneau/annotation/Beanp.html" title="annotation in org.apache.juneau.annotation"><code>@Beanp</code></a>
</td>
</tr>
<tr>
<td>
<ja>@JsonAnyGetter</ja>
<br><ja>@JsonAnySetter</ja>
</td>
<td>
<a href="org/apache/juneau/annotation/Beanp.html#name--"><code>@Beanp(name="*")</code></a>
</td>
</tr>
<tr>
<td>
<ja>@JsonIgnore</ja>
<br><ja>@JsonIgnoreType</ja>
</td>
<td>
<a href="org/apache/juneau/annotation/BeanIgnore.html" title="annotation in org.apache.juneau.annotation"><code>@BeanIgnore</code></a>
</td>
</tr>
<tr>
<td><c><ja>@JsonIgnoreProperties</ja>({...})</c></td>
<td>
<a href="org/apache/juneau/annotation/Bean.html#excludeProperties--"><code>@Bean(excludeProperties|xp)</code></a>
</td>
</tr>
<tr>
<td><c><ja>@JsonAutoDetect</ja>(fieldVisibility=...)</c></td>
<td>
No equivalent annotation but can be controlled via:
<br><a href="org/apache/juneau/BeanContext.Builder.html#beanFieldVisibility-org.apache.juneau.Visibility-"><code>BeanContext.Builder.beanFieldVisibility(Visibility)</code></a>
<br><a href="org/apache/juneau/BeanContext.Builder.html#beanMethodVisibility-org.apache.juneau.Visibility-"><code>BeanContext.Builder.beanMethodVisibility(Visibility)</code></a>
</td>
</tr>
<tr>
<td>
<ja>@JsonCreator</ja>
<br><ja>@JsonProperty</ja>
</td>
<td>
<a href="org/apache/juneau/annotation/Beanc.html" title="annotation in org.apache.juneau.annotation"><code>@Beanc</code></a>
</td>
</tr>
<tr>
<td><ja>@JacksonInject</ja></td>
<td>
No equivalent.
</td>
</tr>
<tr>
<td>
<ja>@JsonSerialize</ja>
<br><ja>@JsonDeserialize</ja>
</td>
<td>
Juneau uses swaps to convert non-serializable object to serializable forms:
<br><a href="org/apache/juneau/annotation/Swap.html" title="annotation in org.apache.juneau.annotation"><code>@Swap</code></a>
</td>
</tr>
<tr>
<td><ja>@JsonInclude</ja></td>
<td>
No equivalent annotation but can be controlled via various settings:
<br><a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a>
<br><a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a>
</td>
</tr>
<tr>
<td><ja>@JsonPropertyOrder</ja></td>
<td>
<a href="org/apache/juneau/annotation/Bean.html#properties--"><code>@Bean(properties="...")</code></a>
<br><a href="org/apache/juneau/annotation/Bean.html#sort--"><code>@Bean(sort=x)</code></a>
</td>
</tr>
<tr>
<td>
<ja>@JsonValue</ja>
<br><ja>@JsonRawValue</ja>
</td>
<td>
Can be replicated using swaps with <c>Reader</c> swapped values.
</td>
</tr>
</table>
</div>
</div><!-- END: 2.19 - juneau-marshall.jm.JacksonComparison -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.PojoCategories' id='juneau-marshall.jm.PojoCategories'>2.20 - POJO Categories</a></h3>
<div class='topic'><!-- START: 2.20 - juneau-marshall.jm.PojoCategories -->
<div class='topic'>
<p>
In general, Juneau allows for marshalling for a wide variety of POJO types including:
</p>
<p>
The following chart shows POJOs categorized into groups and whether they can be serialized or parsed:
</p>
<h5 class='figure'>General POJO serialization/parsing support</h5>
<table class='styled w800' style='border-collapse:collapse'>
<tr><th>Group</th><th>Description</th><th>Examples</th><th>Can<br>serialize?</th><th>Can<br>parse?</th></tr>
<tr class='dark bb' style='background-color:lightyellow;'>
<td style='text-align:center'>1</td>
<td><b>Java primitives and primitive objects</b></td>
<td>
<ul class='normal'>
<li><code>String</code>
<li><code>Integer</code>
<li><code>Float</code>
<li><code>Boolean</code>
</ul>
</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
</tr>
<tr class='dark bb' style='background-color:lightyellow'>
<td style='text-align:center'>2</td>
<td><b>Java Collections Framework objects, Java arrays, Java Optionals</b></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr class='light bb'>
<td style='text-align:center'>2a</td>
<td>
<b>With standard keys/values</b>
<br>Map keys are group [1, 4a, 6a] objects.
<br>Map, Collection, Optional, and array values are group [1, 2, 3ac, 4a, 6a] objects.
</td>
<td>
<ul class='normal'>
<li><c>HashSet&lt;String,Integer&gt;</c>
<li><c>TreeMap&lt;Integer,Bean&gt;</c>
<li><c>List&lt;<jk>int</jk>[][]&gt;</c>
<li><c>Bean[]</c>
<li><c>Optional&lt;Bean&gt;</c>
</ul>
</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
</tr>
<tr class='light bb'>
<td style='text-align:center'>2b</td>
<td>
<b>With non-standard keys/values</b>
<br>Map keys are group [2, 3, 4b, 5, 6b, 7] objects.
<br>Map, Collection, and array values are group [3b, 4b, 5, 6b, 7] objects.
</td>
<td>
<ul class='normal'>
<li><c>HashSet&lt;Bean,Integer&gt;</c>
<li><c>TreeMap&lt;Integer,Reader&gt;</c>
<li><c>Optional&lt;Reader&gt;</c>
</ul>
</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:salmon;text-align:center'><b>no</b></td>
</tr>
<tr class='dark bb' style='background-color:lightyellow'>
<td style='text-align:center'>3</td>
<td><b>Java Beans</b></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr class='light bb'>
<td style='text-align:center'>3a</td>
<td>
<b>With standard properties</b>
<br>These are beans that have one or more properties defined by public getter
or public fields.
<br>Properties can also be defined as final read-only fields and passed in as constructor args.
<br>Property values are group [1, 2, 3ac, 4a, 6a] objects.
</td>
<td>&nbsp;</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
</tr>
<tr class='light bb'>
<td style='text-align:center'>3b</td>
<td>
<b>With non-standard properties or not true beans</b>
<br>These include true beans that have one or more properties defined by getter
and setter methods or properties but property types include group [3b, 4b, 5, 6b, 7] objects.
<br>This also includes classes that look like beans but aren't true beans.
For example, classes that have getters but not setters, or classes without no-arg constructors.
</td>
<td>&nbsp;</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:salmon;text-align:center'><b>no</b></td>
</tr>
<tr class='light bb'>
<td style='text-align:center'>3c</td>
<td>
<b>Virtual beans</b>
<br>These are unimplemented bean interfaces with properties of type [1, 2, 3ac, 4a, 6a] objects.
<br>Parsers will automatically create interface proxies on top of BeanMap instances.
</td>
<td>&nbsp;</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
</tr>
<tr class='light bb'>
<td style='text-align:center'>3d</td>
<td>
<b>Read-only beans without setters</b>
<br>The same as 3a but without property setters or constructor args.
</td>
<td>&nbsp;</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:salmon;text-align:center'><b>no</b></td>
</tr>
<tr class='dark bb' style='background-color:lightyellow'>
<td style='text-align:center'>4</td>
<td>
<b>Swapped objects</b>
<br>These are objects that are not directly serializable but have
<a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwaps</code></a> associated with them.
The purpose of a POJO swap is to convert an object to another object that is easier to serialize
and parse.
For example, the <a href="org/apache/juneau/swaps/TemporalDateSwap.IsoLocalDateTime.html" title="class in org.apache.juneau.swaps"><code>TemporalDateSwap.IsoLocalDateTime</code></a> class can be used to
serialize <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a> objects to ISO8601 strings, and parse them back into
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a> objects.
</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr class='light bb'>
<td style='text-align:center'>4a</td>
<td>
<b>2-way swapped to group [1, 2a, 3ac] objects</b>
<br>For example, a swap that converts a <code>Date</code> to a <code>String</code>.
</td>
<td>
<ul class='normal'>
<li><c>java.util.Date</c>
<li><c>java.util.GregorianCalendar</c>
</ul>
</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
</tr>
<tr class='light bb'>
<td style='text-align:center'>4b</td>
<td>
<b>1-way swapped to group [1, 2, 3] objects</b>
<br>For example, a swap that converts an <code>Iterator</code> to a <code>List</code>.
This would be one way, since you cannot reconstruct an <code>Iterator</code>.
</td>
<td>
<ul class='normal'>
<li><c>java.util.Iterator</c>
</ul>
</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:salmon;text-align:center'><b>no</b></td>
</tr>
<tr class='dark bb' style='background-color:lightyellow'>
<td style='text-align:center'>5</td>
<td>
<b>Readers and InputStreams</b>
<br>Contents are serialized directly to the output stream or writer.
<br>Typically used for low-level language-specific replacement of POJOs using per-Media-Type
POJO swaps.
</td>
<td>
<ul class='normal'>
<li><code>FileInputStream</code>
<li><code>StringReader</code>
</ul>
</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:salmon;text-align:center'><b>no</b></td>
</tr>
<tr class='dark bb' style='background-color:lightyellow'>
<td style='text-align:center'>6</td>
<td>
<b>Non-serializable objects with standard methods for converting to a serializable form</b><br>
</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr class='light bb' style='background-color:lightyellow'>
<td style='text-align:center'>6a</td>
<td>
Classes with a method that converts it to a serializable form:
<ul>
<li><c><jk>public</jk> X swap(BeanSession);</c> where <c>X</c> is in groups
[1, 2a, 3ac].
<li><c><jk>public</jk> String toString();</c> where the string is any meaningful data.
</ul>
And a method that converts it back into the original object:
<ul>
<li><c><jk>public static</jk> T fromString(String);</c>
<li><c><jk>public static</jk> T valueOf(String);</c>
<li><c><jk>public static</jk> T parse(String);</c>
<li><c><jk>public static</jk> T parseString(String);</c>
<li><c><jk>public static</jk> T forName(String);</c>
<li><c><jk>public static</jk> T forString(String);</c>
<li><c><jk>public</jk> T(X);</c> where <c>X</c> is in groups [1, 2a, 3ac].
<li><c><jk>public static</jk> T unswap(BeanSession,X);</c> where <c>X</c> is in
groups [1, 2a, 3ac].
</ul>
</td>
<td>
<ul class='normal'>
<li><c>java.lang.Class</c>
<li><c>java.sql.Time</c>
<li><c>java.sql.Timestamp</c>
<li><c>java.text.MessageFormat</c>
<li><c>java.text.NumberFormat</c>
<li><c>java.util.Date</c>
<li><c>java.util.UUID</c>
<li><c>java.util.logging.Level</c>
<li><c>javax.xml.bind.DatatypeConverter</c>
</ul>
</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
</tr>
<tr class='light bb' style='background-color:lightyellow'>
<td style='text-align:center'>6b</td>
<td>
Classes that only have a method to convert to a serializable form:
<ul>
<li><c><jk>public</jk> X swap(BeanSession);</c> where <c>X</c> is in groups
[1, 2, 3].
<li><c><jk>public</jk> String toString();</c> where the string is any meaningful data.
</ul>
</td>
<td>&nbsp;</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:salmon;text-align:center'><b>no</b></td>
</tr>
<tr class='dark' style='background-color:lightyellow'>
<td style='text-align:center'>7</td>
<td>
<b>All other objects</b>
<br>Anything that doesn't fall into one of the groups above are simply converted to <code>Strings</code>
using the <code>toString()</code> method.
</td>
<td>&nbsp;</td>
<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
<td style='background-color:salmon;text-align:center'><b>no</b></td>
</tr>
</table>
<div class='info'>
Serializers are designed to work on tree-shaped POJO models.
These are models where there are no referential loops (e.g. leaves with references to nodes, or nodes
in one branch referencing nodes in another branch).
There is a serializer setting <code>detectRecursions</code> to look for and handle these kinds of loops
(by setting these references to <jk>null</jk>) but it is not enabled by default since it introduces
a moderate performance penalty.
</div>
<h5 class='topic' id='PojosConveribleToStrings'>POJOs convertible to/from Strings</h5>
<p>
A separate category exists for POJOs that can be converted to and from Strings.
These are used in places such as:
</p>
<ul class='spaced-list'>
<li>Serializing of POJOs to Strings in the REST client API when no serializers are registered.
<li>Parsing of POJOs from Strings in the REST server API for <js>"text/plain"</js> requests where
<js>"text/plain"</js> is not already mapped to an existing serializer.
</ul>
<p>
As a general rule, all POJOs are converted to Strings using the <c>toString()</c> method.
However, there is one exception:
</p>
<ul class='spaced-list'>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html?is-external=true" title="class or interface in java.util"><code>TimeZone</code></a> - Uses <a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html?is-external=true#getID--" title="class or interface in java.util"><code>TimeZone.getID()</code></a>
</ul>
<p>
POJOs are convertible from Strings using any of the following (matched in the specified order):
</p>
<ul class='spaced-list'>
<li>Any of the following public static non-deprecated methods:
<ul>
<li><c>create(String)</c>
<li><c>fromString(String)</c>
<li><c>fromValue(String)</c>
<li><c>valueOf(String)</c>
<li><c>parse(String)</c>
<li><c>parseString(String)</c>
<li><c>forName(String)</c>
<li><c>forString(String)</c>
</ul>
<li>Has a public constructor that takes in a <c>String</c>.
</ul>
<p>
Exceptions exist for the following classes:
</p>
<ul class='spaced-list'>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html?is-external=true" title="class or interface in java.util"><code>TimeZone</code></a> - Uses <a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html?is-external=true#getTimeZone-java.lang.String-" title="class or interface in java.util"><code>TimeZone.getTimeZone(String)</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html?is-external=true" title="class or interface in java.util"><code>Locale</code></a> - Uses <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html?is-external=true#forLanguageTag-java.lang.String-" title="class or interface in java.util"><code>Locale.forLanguageTag(String)</code></a> after replacing <js>'_'</js> with <js>'-'</js>.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a> - Blank and <js>"null"</js> are interpreted as null values.
<li>Primitives (except for <c><jk>void</jk>.<jk>class</jk></c>) - Uses the primitive wrapper classes for instantiating from Strings.
</ul>
<h5 class='topic' id='PojosConveribleToOtherTypes'>POJOs convertible to/from other types</h5>
<p>
POJOs are also converted to various other types in places such as the Open-API serializers and parsers.
In this section, the type being converted to will be referred to as <c>X</c>.
</p>
<p>
POJOs are considered convertible from X if it has any of the following (matched in the specified order):
</p>
<ul class='spaced-list'>
<li>Any any of the following public static non-deprecated methods:
<ul>
<li><c>create(X)</c>
<li><c>from*(X)</c>
</ul>
<li>Has a public constructor that takes in an <c>X</c>.
<li>The X class has a public non-static no-arg non-deprecated method called <c>to*()</c>.
</ul>
<p>
POJOs are considered convertible from X if any of the reverse of above are true.
</p>
</div>
</div><!-- END: 2.20 - juneau-marshall.jm.PojoCategories -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.SimpleVariableLanguage' id='juneau-marshall.jm.SimpleVariableLanguage'>2.21 - Simple Variable Language</a></h3>
<div class='topic'><!-- START: 2.21 - juneau-marshall.jm.SimpleVariableLanguage -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/svl/package-summary.html"><code>org.apache.juneau.svl</code></a> packages defines an API for a language called "Simple Variable Language".
In a nutshell, Simple Variable Language (or SVL) is text that contains variables of the form <js>"$varName{varKey}"</js>.
It is used extensively in the Config, REST and Microservice APIs.
</p>
<p>
Most variables can be recursively nested within the varKey (e.g. <js>"$FOO{$BAR{xxx},$BAZ{xxx}}"</js>)
and can return values that themselves contain more variables.
</p>
<p>
The <a href="org/apache/juneau/svl/VarResolver.html" title="class in org.apache.juneau.svl"><code>VarResolver</code></a> class is used to resolve variables.
The <a href="org/apache/juneau/svl/VarResolver.html#DEFAULT"><code>VarResolver.DEFAULT</code></a> resolver is a reusable instance of this class
configured with the following basic variables:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/svl/vars/SystemPropertiesVar.html" title="class in org.apache.juneau.svl.vars"><code>SystemPropertiesVar</code></a> - <c>$S{key[,default]}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/EnvVariablesVar.html" title="class in org.apache.juneau.svl.vars"><code>EnvVariablesVar</code></a> - <c>$E{key[,default]}</c>
</ul>
<p>
The following logic variables are also provided:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/svl/vars/IfVar.html" title="class in org.apache.juneau.svl.vars"><code>IfVar</code></a> - <c>$IF{arg,then[,else]}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/SwitchVar.html" title="class in org.apache.juneau.svl.vars"><code>SwitchVar</code></a> - <c>$SW{arg,pattern1:then1[,pattern2:then2...]}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/CoalesceVar.html" title="class in org.apache.juneau.svl.vars"><code>CoalesceVar</code></a> - <c>$CO{arg1[,arg2...]}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/PatternMatchVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternMatchVar</code></a> - <c>$PM{arg,pattern}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/PatternReplaceVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternReplaceVar</code></a> - <c>$PR{arg,pattern,replace}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/PatternExtractVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternExtractVar</code></a> - <c>$PE{arg,pattern,groupIndex}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/NotEmptyVar.html" title="class in org.apache.juneau.svl.vars"><code>NotEmptyVar</code></a> - <c>$NE{arg}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/UpperCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>UpperCaseVar</code></a> - <c>$UC{arg}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/LowerCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>LowerCaseVar</code></a> - <c>$LC{arg}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/LenVar.html" title="class in org.apache.juneau.svl.vars"><code>LenVar</code></a> - <c>$LN{arg[,delimiter]}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/SubstringVar.html" title="class in org.apache.juneau.svl.vars"><code>SubstringVar</code></a> - <c>$ST{arg,start[,end]}</c>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Use the default variable resolver to resolve a string that contains
// $S (system property) variables.</jc>
String <jv>property</jv> = VarResolver.<jsf>DEFAULT</jsf>.resolve(<js>"The Java home directory is $S{java.home}"</js>);
</p>
<p>
The following shows how variables can be arbitrarily nested...
</p>
<p class='bjava'>
<jc>// Look up a property in the following order:
// 1) MYPROPERTY environment variable.
// 2) 'my.property' system property if environment variable not found.
// 3) 'not found' string if system property not found.</jc>
String <jv>property</jv> = VarResolver.<jsf>DEFAULT</jsf>.resolve(<js>"$E{MYPROPERTY,$S{my.property,not found}}"</js>);
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.SimpleVariableLanguage.jm.SvlVariables' id='juneau-marshall.jm.SimpleVariableLanguage.jm.SvlVariables'>2.21.1 - SVL Variables</a><span class='update'>updated: 8.0.0,8.1.0</span></h4>
<div class='topic'><!-- START: 2.21.1 - juneau-marshall.jm.SimpleVariableLanguage.jm.SvlVariables -->
<div class='topic'>
<p>
Variables are defined through the <a href="org/apache/juneau/svl/Var.html" title="class in org.apache.juneau.svl"><code>Var</code></a> API.
The API comes with several predefined variables and is easily extensible.
</p>
<p>
The following is an example of a variable that performs URL-Encoding on strings.
</p>
<p class='bjava'>
<jc>// First create our var.</jc>
<jk>public class</jk> UrlEncodeVar <jk>extends</jk> SimpleVar {
<jc>// Must have a no-arg constructor!</jc>
<jk>public</jk> UrlEncodeVar() {
<jk>super</jk>(<js>"UE"</js>);
}
<jc>// The method we must implement</jc>
<ja>@Override</ja>
<jk>public</jk> String resolve(VarResolverSession <jv>session</jv>, String <jv>key</jv>) {
<jk>return</jk> URLEncoder.<jsm>encode</jsm>(<jv>key</jv>, <js>"UTF-8"</js>);
}
}
<jc>// Next create a var resolver that extends the existing DEFAULT resolver
// that supports resolving system properties.</jc>
VarResolver <jv>varResolver</jv> = VarResolver.<jsf>DEFAULT</jsf>
.copy()
.vars(UrlEncodeVar.<jk>class</jk>)
.build();
<jc>// Retrieve a system property and URL-encode it if necessary.</jc>
String <jv>myProperty</jv> = <jv>varResolver</jv>.resolve(<js>"$UE{$S{my.property}}"</js>);
</p>
<p>
The following shows the class hierarchy of the <a href="org/apache/juneau/svl/Var.html" title="class in org.apache.juneau.svl"><code>Var</code></a> class:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/svl/Var.html" title="class in org.apache.juneau.svl"><code>Var</code></a> - Superclass of all vars.
<ul>
<li class='jac'><a href="org/apache/juneau/svl/SimpleVar.html" title="class in org.apache.juneau.svl"><code>SimpleVar</code></a> - Superclass of all vars that return strings.
<ul>
<li class='jac'><a href="org/apache/juneau/svl/DefaultingVar.html" title="class in org.apache.juneau.svl"><code>DefaultingVar</code></a> - Variables that define a default value if the resolve method returns null.
<ul>
<li class='jac'><a href="org/apache/juneau/svl/MapVar.html" title="class in org.apache.juneau.svl"><code>MapVar</code></a> - Variables that pull values from maps.
</ul>
</li>
<li class='jac'><a href="org/apache/juneau/svl/MultipartVar.html" title="class in org.apache.juneau.svl"><code>MultipartVar</code></a> - Variables that consist of 2 or more comma-delimited arguments.
</ul>
</li>
<li class='jac'><a href="org/apache/juneau/svl/StreamedVar.html" title="class in org.apache.juneau.svl"><code>StreamedVar</code></a> - Superclass of all vars that stream their value to writers.
</ul>
</li>
</ul>
<p>
The following is the list of default variables defined in all modules:
</p>
<table class='styled w800'>
<tr>
<th>Module</th><th>Class</th><th>Pattern</th>
</tr>
<tr class='dark'>
<td rowspan='16' style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-svl</td>
<td><a href="org/apache/juneau/svl/vars/EnvVariablesVar.html" title="class in org.apache.juneau.svl.vars"><code>EnvVariablesVar</code></a></td>
<td class='code'>$E{key[,default]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/SystemPropertiesVar.html" title="class in org.apache.juneau.svl.vars"><code>SystemPropertiesVar</code></a></td>
<td class='code'>$S{key[,default]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/ArgsVar.html" title="class in org.apache.juneau.svl.vars"><code>ArgsVar</code></a></td>
<td class='code'>$A{key[,default]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/ManifestFileVar.html" title="class in org.apache.juneau.svl.vars"><code>ManifestFileVar</code></a></td>
<td class='code'>$MF{key[,default]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/IfVar.html" title="class in org.apache.juneau.svl.vars"><code>IfVar</code></a></td>
<td class='code'>$IF{arg,then[,else]}</td>
</tr>
<tr class='dark dd'>
<td><a href="org/apache/juneau/svl/vars/SwitchVar.html" title="class in org.apache.juneau.svl.vars"><code>SwitchVar</code></a></td>
<td class='code'>$SW{arg,pattern1:then1[,pattern2:then2...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/CoalesceVar.html" title="class in org.apache.juneau.svl.vars"><code>CoalesceVar</code></a></td>
<td class='code'>$CO{arg1[,arg2...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/PatternMatchVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternMatchVar</code></a></td>
<td class='code'>$PM{arg,pattern}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/PatternReplaceVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternReplaceVar</code></a></td>
<td class='code'>$PR{arg,pattern,replace}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/PatternExtractVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternExtractVar</code></a></td>
<td class='code'>$PE{arg,pattern,groupdIndex}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/NotEmptyVar.html" title="class in org.apache.juneau.svl.vars"><code>NotEmptyVar</code></a></td>
<td class='code'>$NE{arg}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/UpperCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>UpperCaseVar</code></a></td>
<td class='code'>$UC{arg}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/LowerCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>LowerCaseVar</code></a></td>
<td class='code'>$LC{arg}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/LenVar.html" title="class in org.apache.juneau.svl.vars"><code>LenVar</code></a></td>
<td class='code'>$LN{arg[,delimiter]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/SubstringVar.html" title="class in org.apache.juneau.svl.vars"><code>SubstringVar</code></a></td>
<td class='code'>$ST{arg,start[,end]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/html/HtmlWidgetVar.html" title="class in org.apache.juneau.html"><code>HtmlWidgetVar</code></a></td>
<td class='code'>$W{name}</td>
</tr>
<tr class='light dd'>
<td rowspan='1' style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-config</td>
<td><a href="org/apache/juneau/config/vars/ConfigVar.html" title="class in org.apache.juneau.config.vars"><code>ConfigVar</code></a></td>
<td class='code'>$C{key[,default]}</td>
</tr>
<tr class='dark'>
<td rowspan='15' style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-rest-server</td>
<td><a href="org/apache/juneau/rest/vars/FileVar.html" title="class in org.apache.juneau.rest.vars"><code>FileVar</code></a></td>
<td class='code'>$F{path[,default]}}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/ServletInitParamVar.html" title="class in org.apache.juneau.rest.vars"><code>ServletInitParamVar</code></a></td>
<td class='code'>$I{name[,default]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/LocalizationVar.html" title="class in org.apache.juneau.rest.vars"><code>LocalizationVar</code></a></td>
<td class='code'>$L{key[,args...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestAttributeVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestAttributeVar</code></a></td>
<td class='code'>$RA{key1[,key2...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestFormDataVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestFormDataVar</code></a></td>
<td class='code'>$RF{key1[,key2...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestHeaderVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestHeaderVar</code></a></td>
<td class='code'>$RH{key1[,key2...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestPathVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestPathVar</code></a></td>
<td class='code'>$RP{key1[,key2...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestQueryVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestQueryVar</code></a></td>
<td class='code'>$RQ{key1[,key2...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestSwaggerVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestSwaggerVar</code></a></td>
<td class='code'>$RS{key}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestVar</code></a></td>
<td class='code'>$R{key1[,key2...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/SerializedRequestAttrVar.html" title="class in org.apache.juneau.rest.vars"><code>SerializedRequestAttrVar</code></a></td>
<td class='code'>$SA{contentType,key[,default]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/SwaggerVar.html" title="class in org.apache.juneau.rest.vars"><code>SwaggerVar</code></a></td>
<td class='code'>$SS{key1[,key2...]}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/UrlVar.html" title="class in org.apache.juneau.rest.vars"><code>UrlVar</code></a></td>
<td class='code'>$U{uri}></td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/UrlEncodeVar.html" title="class in org.apache.juneau.rest.vars"><code>UrlEncodeVar</code></a></td>
<td class='code'>$UE{uriPart}</td>
</tr>
</table>
</div>
</div><!-- END: 2.21.1 - juneau-marshall.jm.SimpleVariableLanguage.jm.SvlVariables -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.SimpleVariableLanguage.jm.VarResolvers' id='juneau-marshall.jm.SimpleVariableLanguage.jm.VarResolvers'>2.21.2 - VarResolvers and VarResolverSessions</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.21.2 - juneau-marshall.jm.SimpleVariableLanguage.jm.VarResolvers -->
<div class='topic'>
<p>
The main class for performing variable resolution is <a href="org/apache/juneau/svl/VarResolver.html" title="class in org.apache.juneau.svl"><code>VarResolver</code></a>.
Two methods are provided for resolving variables:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/svl/VarResolver.html" title="class in org.apache.juneau.svl"><code>VarResolver</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/svl/VarResolver.html#resolve-java.lang.String-"><code>resolve(String)</code></a>
- Resolves variables and returns the results as a simple string.
<li class='jm'><a href="org/apache/juneau/svl/VarResolver.html#resolveTo-java.lang.String-java.io.Writer-"><code>resolveTo(String,Writer)</code></a>
- Resolves variables and sends results to a writer.
</ul>
</li>
</ul>
<p>
Var resolvers can rely on the existence of other objects.
For example, <a href="org/apache/juneau/config/vars/ConfigVar.html" title="class in org.apache.juneau.config.vars"><code>ConfigVar</code></a> relies on the existence of a <a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>.
This is accomplished through the following method:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/svl/VarResolver.Builder.html" title="class in org.apache.juneau.svl"><code>VarResolver.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/svl/VarResolver.Builder.html#bean-java.lang.Class-T-"><code>bean(Class&lt;T&gt;, T)</code></a> - Specify a bean for all sessions.
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/svl/VarResolverSession.html" title="class in org.apache.juneau.svl"><code>VarResolverSession</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/svl/VarResolverSession.html#bean-java.lang.Class-T-"><code>bean(Class&lt;T&gt;, T)</code></a> - Specify a bean for this session.
</ul>
</li>
</ul>
<p>
Beans are accessible through the following method:
</p>
<ul class='javatree'>
<li class='jm'><a href="org/apache/juneau/svl/VarResolverSession.html#getBean-java.lang.Class-"><code>VarResolverSession.getBean(Class)</code></a>
</ul>
<p>
Var resolvers can be cloned and extended by using the <a href="org/apache/juneau/svl/VarResolver.html#copy--"><code>VarResolver.copy()</code></a> method.
Cloning a resolver will copy it's <a href="org/apache/juneau/svl/Var.html" title="class in org.apache.juneau.svl"><code>Var</code></a> class names and context objects.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a resolver that copies the default resolver and adds $C and $A vars.</jc>
VarResolver <jv>myVarResolver</jv> = VarResolver
.<jsf>DEFAULT</jsf>
.copy()
.vars(ConfigVar.<jk>class</jk>, ArgsVar.<jk>class</jk>)
.build();
</p>
</div>
</div><!-- END: 2.21.2 - juneau-marshall.jm.SimpleVariableLanguage.jm.VarResolvers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.SimpleVariableLanguage.jm.DefaultVarResolver' id='juneau-marshall.jm.SimpleVariableLanguage.jm.DefaultVarResolver'>2.21.3 - VarResolver.DEFAULT</a><span class='update'>created: 8.1.0</span></h4>
<div class='topic'><!-- START: 2.21.3 - juneau-marshall.jm.SimpleVariableLanguage.jm.DefaultVarResolver -->
<div class='topic'>
<p>
<a href="org/apache/juneau/svl/VarResolver.html#DEFAULT"><code>VarResolver.DEFAULT</code></a> is a reusable variable resolver with default support for the following variables:
</p>
<ul>
<li><c>$S{key[,default]}</c> - <a href="org/apache/juneau/svl/vars/SystemPropertiesVar.html" title="class in org.apache.juneau.svl.vars"><code>SystemPropertiesVar</code></a>
<li><c>$E{key[,default]}</c> - <a href="org/apache/juneau/svl/vars/EnvVariablesVar.html" title="class in org.apache.juneau.svl.vars"><code>EnvVariablesVar</code></a>
<li><c>$A{key[,default]}</c> - <a href="org/apache/juneau/svl/vars/ArgsVar.html" title="class in org.apache.juneau.svl.vars"><code>ArgsVar</code></a>
<li><c>$MF{key[,default]}</c> - <a href="org/apache/juneau/svl/vars/ManifestFileVar.html" title="class in org.apache.juneau.svl.vars"><code>ManifestFileVar</code></a>
<li><c>$SW{stringArg,pattern:thenValue[,pattern:thenValue...]}</c> - <a href="org/apache/juneau/svl/vars/SwitchVar.html" title="class in org.apache.juneau.svl.vars"><code>SwitchVar</code></a>
<li><c>$IF{arg,then[,else]}</c> - <a href="org/apache/juneau/svl/vars/IfVar.html" title="class in org.apache.juneau.svl.vars"><code>IfVar</code></a>
<li><c>$CO{arg[,arg2...]}</c> - <a href="org/apache/juneau/svl/vars/CoalesceVar.html" title="class in org.apache.juneau.svl.vars"><code>CoalesceVar</code></a>
<li><c>$PM{arg,pattern}</c> - <a href="org/apache/juneau/svl/vars/PatternMatchVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternMatchVar</code></a>
<li><c>$PR{stringArg,pattern,replace}</c>- <a href="org/apache/juneau/svl/vars/PatternReplaceVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternReplaceVar</code></a>
<li><c>$PE{arg,pattern,groupIndex}</c> - <a href="org/apache/juneau/svl/vars/PatternExtractVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternExtractVar</code></a>
<li><c>$UC{arg}</c> - <a href="org/apache/juneau/svl/vars/UpperCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>UpperCaseVar</code></a>
<li><c>$LC{arg}</c> - <a href="org/apache/juneau/svl/vars/LowerCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>LowerCaseVar</code></a>
<li><c>$NE{arg}</c> - <a href="org/apache/juneau/svl/vars/NotEmptyVar.html" title="class in org.apache.juneau.svl.vars"><code>NotEmptyVar</code></a>
<li><c>$LN{arg[,delimiter]}</c> - <a href="org/apache/juneau/svl/vars/LenVar.html" title="class in org.apache.juneau.svl.vars"><code>LenVar</code></a>
<li><c>$ST{arg,start[,end]}</c> - <a href="org/apache/juneau/svl/vars/SubstringVar.html" title="class in org.apache.juneau.svl.vars"><code>SubstringVar</code></a>
</ul>
</div>
</div><!-- END: 2.21.3 - juneau-marshall.jm.SimpleVariableLanguage.jm.DefaultVarResolver -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.SimpleVariableLanguage.jm.SvlOtherNotes' id='juneau-marshall.jm.SimpleVariableLanguage.jm.SvlOtherNotes'>2.21.4 - Other Notes</a></h4>
<div class='topic'><!-- START: 2.21.4 - juneau-marshall.jm.SimpleVariableLanguage.jm.SvlOtherNotes -->
<div class='topic'>
<ul class='spaced-list'>
<li>
The escape character <js>'\'</js> can be used when necessary to escape the following characters:
<c>$ , { }</c>
<li>
<b>WARNING:</b> It is possible to cause <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/StackOverflowError.html?is-external=true" title="class or interface in java.lang"><code>StackOverflowErrors</code></a> if
your nested variables result in a recursive loop (e.g. the environment variable
<c>'MYPROPERTY'</c> has the value <c>'$E{MYPROPERTY}'</c>).
So don't do that!
<li>
As a general rule, this class tries to be as efficient as possible by not creating new strings when not
needed.
<br>For example, calling the resolve method on a string that doesn't contain variables (e.g.
<c>resolver.resolve(<js>"foobar"</js>)</c>) will simply be a no-op and return the same string.
</ul>
</div>
</div><!-- END: 2.21.4 - juneau-marshall.jm.SimpleVariableLanguage.jm.SvlOtherNotes -->
</div><!-- END: 2.21 - juneau-marshall.jm.SimpleVariableLanguage -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.Encoders' id='juneau-marshall.jm.Encoders'>2.22 - Encoders</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.22 - juneau-marshall.jm.Encoders -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/encoders/package-summary.html"><code>org.apache.juneau.encoders</code></a> package defines an API for handling encoding-based matching
of <c>Accept-Encoding</c>/<c>Content-Encoding</c> HTTP headers. It consists of the following classes:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/encoders/EncoderSet.html" title="class in org.apache.juneau.encoders"><code>EncoderSet</code></a>
<li class='jcc'><a href="org/apache/juneau/encoders/Encoder.html" title="class in org.apache.juneau.encoders"><code>Encoder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/encoders/IdentityEncoder.html" title="class in org.apache.juneau.encoders"><code>IdentityEncoder</code></a>
<li class='jc'><a href="org/apache/juneau/encoders/GzipEncoder.html" title="class in org.apache.juneau.encoders"><code>GzipEncoder</code></a>
</ul>
</ul>
<h5 class='topic'>EncoderSet</h5>
<p>
The <a href="org/apache/juneau/encoders/EncoderSet.html" title="class in org.apache.juneau.encoders"><code>EncoderSet</code></a> class represents the set of <code>encoders</code> keyed by codings.
It maintains a set of encoders and the codings that they can handle.
The <a href="org/apache/juneau/encoders/EncoderSet.html#getEncoderMatch-java.lang.String-"><code>getEncoderMatch(String)</code></a> and <a href="org/apache/juneau/encoders/EncoderSet.html#getEncoder-java.lang.String-"><code>EncoderSet.getEncoder(String)</code></a>
methods are then used to find appropriate encoders for specific <c>Accept-Encoding</c> and <c>Content-Encoding</c> header values.
</p>
<h5 class='topic'>Match ordering</h5>
<p>
Encoders are tried in the order they appear in the set. The <a href="org/apache/juneau/encoders/EncoderSet.Builder.html#add-java.lang.Class...-"><code>EncoderSet.Builder.add(Class...)</code></a> / <a href="org/apache/juneau/encoders/EncoderSet.Builder.html#add-org.apache.juneau.encoders.Encoder...-"><code>EncoderSet.Builder.add(Encoder...)</code></a>
methods prepend the values to the list to allow them the opportunity to override encoders already in the list.
</p>
<p>
For example, calling <code>builder.add(E1.<jk>class</jk>,E2.<jk>class</jk>).add(E3.<jk>class</jk>,
E4.<jk>class</jk>)</code> will result in the order <c>E3, E4, E1, E2</c>.
</p>
<h5 class='section'>Example:</h5>
<p class='bjava'>
<jc>// Create an encoder group with support for gzip compression.</jc>
EncoderSet <jv>encoders</jv> = EncoderSet
.<jsm>create</jsm>()
.add(GzipEncoder.<jk>class</jk>)
.build();
<jc>// Should return "gzip"</jc>
String <jv>matchedCoding</jv> = <jv>encoders</jv>.findMatch(<js>"compress;q=1.0, gzip;q=0.8, identity;q=0.5, *;q=0"</js>);
<jc>// Get the encoder</jc>
Encoder <jv>encoder</jv> = <jv>encoders</jv>.getEncoder(<jv>matchedCoding</jv>);
</p>
<h5 class='topic'>Encoder API</h5>
<p>
The <a href="org/apache/juneau/encoders/Encoder.html" title="class in org.apache.juneau.encoders"><code>Encoder</code></a> interface is used for enabling decompression on requests and compression on responses, such as support for GZIP compression.
It is used to wrap input and output streams within compression/decompression streams.
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/encoders/Encoder.html" title="class in org.apache.juneau.encoders"><code>Encoder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/encoders/Encoder.html#getCodings--"><code>getCodings()</code></a>
<li class='jm'><a href="org/apache/juneau/encoders/Encoder.html#getInputStream-java.io.InputStream-"><code>getInputStream(InputStream)</code></a>
<li class='jm'><a href="org/apache/juneau/encoders/Encoder.html#getOutputStream-java.io.OutputStream-"><code>getOutputStream(OutputStream)</code></a>
</ul>
</ul>
<p>
Encoders are registered with <c>RestServlets</c> through the <ja>@Rest(encoders)</ja> annotation.
</p>
</div>
</div><!-- END: 2.22 - juneau-marshall.jm.Encoders -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.ObjectTools' id='juneau-marshall.jm.ObjectTools'>2.23 - Object Tools</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 2.23 - juneau-marshall.jm.ObjectTools -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/objecttools/package-summary.html"><code>org.apache.juneau.objecttools</code></a> package defines convenience utility classes for accessing
and manipulating POJOs. It consists of the following classes:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/objecttools/ObjectRest.html" title="class in org.apache.juneau.objecttools"><code>ObjectRest</code></a>
<li class='jc'><a href="org/apache/juneau/objecttools/ObjectSearcher.html" title="class in org.apache.juneau.objecttools"><code>ObjectSearcher</code></a>
<li class='jc'><a href="org/apache/juneau/objecttools/ObjectSorter.html" title="class in org.apache.juneau.objecttools"><code>ObjectSorter</code></a>
<li class='jc'><a href="org/apache/juneau/objecttools/ObjectViewer.html" title="class in org.apache.juneau.objecttools"><code>ObjectViewer</code></a>
<li class='jc'><a href="org/apache/juneau/objecttools/ObjectPaginator.html" title="class in org.apache.juneau.objecttools"><code>ObjectPaginator</code></a>
<li class='jc'><a href="org/apache/juneau/objecttools/ObjectIntrospector.html" title="class in org.apache.juneau.objecttools"><code>ObjectIntrospector</code></a>
<li class='jc'><a href="org/apache/juneau/objecttools/ObjectMerger.html" title="class in org.apache.juneau.objecttools"><code>ObjectMerger</code></a>
</ul>
<h5 class='topic'>ObjectRest</h5>
<p>
The <a href="org/apache/juneau/objecttools/ObjectRest.html" title="class in org.apache.juneau.objecttools"><code>ObjectRest</code></a> class provides the ability to perform standard REST operations (GET, PUT, POST, DELETE) against nodes in a POJO model.
Nodes in the POJO model are addressed using URLs.
</p>
<p>
A POJO model is defined as a tree model where nodes consist of consisting of the following:
</p>
<ul class='spaced-list'>
<li>
<code>Maps</code> and Java beans representing JSON objects.
<li>
<code>Collections</code> and arrays representing JSON arrays.
<li>
Java beans.
</ul>
<p>
Leaves of the tree can be any type of object.
</p>
<p>
Use <a href="org/apache/juneau/objecttools/ObjectRest.html#get-java.lang.String-"><code>get()</code></a> to retrieve an element from a JSON tree.
<br>Use <a href="org/apache/juneau/objecttools/ObjectRest.html#put-java.lang.String-java.lang.Object-"><code>put()</code></a> to create (or overwrite) an element in a JSON tree.
<br>Use <a href="org/apache/juneau/objecttools/ObjectRest.html#post-java.lang.String-java.lang.Object-"><code>post()</code></a> to add an element to a list in a JSON tree.
<br>Use <a href="org/apache/juneau/objecttools/ObjectRest.html#delete-java.lang.String-"><code>delete()</code></a> to remove an element from a JSON tree.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Construct an unstructured POJO model</jc>
JsonMap <jv>map</jv> = JsonMap.<jsm>ofJson</jsm>(<js>""</js>
+ <js>"{"</js>
+ <js>" name:'John Smith', "</js>
+ <js>" address:{ "</js>
+ <js>" streetAddress:'21 2nd Street', "</js>
+ <js>" city:'New York', "</js>
+ <js>" state:'NY', "</js>
+ <js>" postalCode:10021 "</js>
+ <js>" }, "</js>
+ <js>" phoneNumbers:[ "</js>
+ <js>" '212 555-1111', "</js>
+ <js>" '212 555-2222' "</js>
+ <js>" ], "</js>
+ <js>" additionalInfo:null, "</js>
+ <js>" remote:false, "</js>
+ <js>" height:62.4, "</js>
+ <js>" 'fico score':' &gt; 640' "</js>
+ <js>"} "</js>
);
<jc>// Wrap Map inside an ObjectRest object</jc>
ObjectRest <jv>johnSmith</jv> = ObjectRest.<jsm>create</jsm>(<jv>map</jv>);
<jc>// Get a simple value at the top level</jc>
<jc>// "John Smith"</jc>
String <jv>name</jv> = <jv>johnSmith</jv>.getString(<js>"name"</js>);
<jc>// Change a simple value at the top level</jc>
<jv>johnSmith</jv>.put(<js>"name"</js>, <js>"The late John Smith"</js>);
<jc>// Get a simple value at a deep level</jc>
<jc>// "21 2nd Street"</jc>
String <jv>streetAddress</jv> = <jv>johnSmith</jv>.getString(<js>"address/streetAddress"</js>);
<jc>// Set a simple value at a deep level</jc>
<jv>johnSmith</jv>.put(<js>"address/streetAddress"</js>, <js>"101 Cemetery Way"</js>);
<jc>// Get entries in a list</jc>
<jc>// "212 555-1111"</jc>
String <jv>firstPhoneNumber</jv> = <jv>johnSmith</jv>.getString(<js>"phoneNumbers/0"</js>);
<jc>// Add entries to a list</jc>
<jv>johnSmith</jv>.post(<js>"phoneNumbers"</js>, <js>"212 555-3333"</js>);
<jc>// Delete entries from a model</jc>
<jv>johnSmith</jv>.delete(<js>"fico score"</js>);
<jc>// Add entirely new structures to the tree</jc>
JsonMap <jv>medicalInfo</jv> = JsonMap.<jsm>ofJson</jsm>(<js>""</js>
+ <js>"{"</js>
+ <js>" currentStatus: 'deceased',"</js>
+ <js>" health: 'non-existent',"</js>
+ <js>" creditWorthiness: 'not good'"</js>
+ <js>"}"</js>
);
<jv>johnSmith</jv>.put(<js>"additionalInfo/medicalInfo"</js>, <jv>medicalInfo</jv>);
</p>
<p>
In the special case of collections/arrays of maps/beans, a special XPath-like selector notation can be used in lieu
of index numbers on GET requests to return a map/bean with a specified attribute value.
<br>The syntax is <code>@attr=val</code>, where attr is the attribute name on the child map, and val is the matching value.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Get map/bean with name attribute value of 'foo' from a list of items</jc>
Map <jv>map</jv> = <jv>objectRest</jv>.getMap(<js>"/items/@name=foo"</js>);
</p>
<ul class='notes'>
<li class='note'>This class is used in the <a href="org/apache/juneau/rest/converter/Traversable.html" title="class in org.apache.juneau.rest.converter"><code>Traversable</code></a> REST response converter.
</ul>
<h5 class='topic'>ObjectSearcher</h5>
<p>
The <a href="org/apache/juneau/objecttools/ObjectSearcher.html" title="class in org.apache.juneau.objecttools"><code>ObjectSearcher</code></a> class is designed to provide searches across arrays and collections of maps or beans.
It allows you to quickly filter beans and maps using simple yet sophisticated search arguments.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
MyBean[] <jv>arrayOfBeans</jv> = ...;
ObjectSearcher <jv>searcher</jv> = ObjectSearcher.<jsm>create</jsm>();
<jc>// Returns a list of beans whose 'foo' property is 'X' and 'bar' property is 'Y'.</jc>
List&lt;MyBean&gt; <jv>result</jv> = <jv>searcher</jv>.run(<jv>arrayOfBeans</jv>, <js>"foo=X,bar=Y"</js>);
</p>
<p>
The tool can be used against the following data types:
</p>
<ul>
<li>Arrays/collections of maps or beans.
</ul>
<p>
The default searcher is configured with the following matcher factories that provides the capabilities of matching
against various data types. This list is extensible:
</p>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/objecttools/StringMatcherFactory.html" title="class in org.apache.juneau.objecttools"><code>StringMatcherFactory</code></a>
<li class='jc'><a href="org/apache/juneau/objecttools/NumberMatcherFactory.html" title="class in org.apache.juneau.objecttools"><code>NumberMatcherFactory</code></a>
<li class='jc'><a href="org/apache/juneau/objecttools/TimeMatcherFactory.html" title="class in org.apache.juneau.objecttools"><code>TimeMatcherFactory</code></a>
</ul>
<p>
The <a href="org/apache/juneau/objecttools/StringMatcherFactory.html" title="class in org.apache.juneau.objecttools"><code>StringMatcherFactory</code></a> class provides searching based on the following patterns:
</p>
<ul>
<li><js>"property=foo"</js> - Simple full word match
<li><js>"property=fo*"</js>, <js>"property=?ar"</js> - Meta-character matching
<li><js>"property=foo bar"</js>(implicit), <js>"property=^foo ^bar"</js>(explicit) - Multiple OR'ed patterns
<li><js>"property=+fo* +*ar"</js> - Multiple AND'ed patterns
<li><js>"property=fo* -bar"</js> - Negative patterns
<li><js>"property='foo bar'"</js> - Patterns with whitespace
<li><js>"property=foo\\'bar"</js> - Patterns with single-quotes
<li><js>"property=/foo\\s+bar"</js> - Regular expression match
</ul>
<p>
The <a href="org/apache/juneau/objecttools/NumberMatcherFactory.html" title="class in org.apache.juneau.objecttools"><code>NumberMatcherFactory</code></a> class provides searching based on the following patterns:
</p>
<ul>
<li><js>"property=1"</js> - A single number
<li><js>"property=1 2"</js> - Multiple OR'ed numbers
<li><js>"property=-1 -2"</js> - Multiple OR'ed negative numbers
<li><js>"property=1-2"</js>,<js>"property=-2--1"</js> - A range of numbers (whitespace ignored)
<li><js>"property=1-2 4-5"</js> - Multiple OR'ed ranges
<li><js>"property=&lt;1"</js>,<js>"property=&lt;=1"</js>,<js>"property=&gt;1"</js>,<js>"property=&gt;=1"</js> - Open-ended ranges
<li><js>"property=!1"</js>,<js>"property=!1-2"</js> - Negation
</ul>
<p>
The <a href="org/apache/juneau/objecttools/TimeMatcherFactory.html" title="class in org.apache.juneau.objecttools"><code>TimeMatcherFactory</code></a> class provides searching based on the following patterns:
</p>
<ul>
<li><js>"property=2011"</js> - A single year
<li><js>"property=2011 2013 2015"</js> - Multiple years
<li><js>"property=2011-01"</js> - A single month
<li><js>"property=2011-01-01"</js> - A single day
<li><js>"property=2011-01-01T12"</js> - A single hour
<li><js>"property=2011-01-01T12:30"</js> - A single minute
<li><js>"property=2011-01-01T12:30:45"</js> - A single second
<li><js>"property=&gt;2011"</js>,<js>"property=&gt;=2011"</js>,<js>"property=&lt;2011"</js>,<js>"property=&lt;=2011"</js> - Open-ended ranges
<li><js>"property=&gt;2011"</js>,<js>"property=&gt;=2011"</js>,<js>"property=&lt;2011"</js>,<js>"property=&lt;=2011"</js> - Open-ended ranges
<li><js>"property=2011 - 2013-06-30"</js> - Closed ranges
</ul>
<ul class='notes'>
<li class='note'>This class is used in the <a href="org/apache/juneau/rest/converter/Queryable.html" title="class in org.apache.juneau.rest.converter"><code>Queryable</code></a> REST response converter.
</ul>
<h5 class='topic'>ObjectSorter</h5>
<p>
The <a href="org/apache/juneau/objecttools/ObjectSorter.html" title="class in org.apache.juneau.objecttools"><code>ObjectSorter</code></a> class is designed to sort arrays and collections of maps or beans.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
MyBean[] <jv>arrayOfBeans</jv> = ...;
ObjectSorter <jv>sorter</jv> = ObjectSorter.<jsm>create</jsm>();
<jc>// Returns a list of beans sorted accordingly.</jc>
List&lt;MyBean&gt; <jv>result</jv> = <jv>sorter</jv>.run(<jv>arrayOfBeans</jv>, <js>"foo,bar-"</js>);
</p>
<p>
The tool can be used against the following data types:
</p>
<ul>
<li>Arrays/collections of maps or beans.
</ul>
<p>
The arguments are a simple comma-delimited list of property names optionally suffixed with <js>'+'</js> and <js>'-'</js> to
denote ascending/descending order.
</p>
<ul class='notes'>
<li class='note'>This class is used in the <a href="org/apache/juneau/rest/converter/Queryable.html" title="class in org.apache.juneau.rest.converter"><code>Queryable</code></a> REST response converter.
</ul>
<h5 class='topic'>ObjectViewer</h5>
<p>
The <a href="org/apache/juneau/objecttools/ObjectViewer.html" title="class in org.apache.juneau.objecttools"><code>ObjectViewer</code></a> class is designed to extract properties from collections of maps or beans.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
MyBean[] <jv>arrayOfBeans</jv> = ...;
ObjectViewer <jv>viewer</jv> = ObjectViewer.<jsm>create</jsm>();
<jc>// Returns the 'foo' and 'bar' properties extracted into a list of maps.</jc>
List&lt;Map&gt; <jv>result</jv> = <jv>viewer</jv>.run(<jv>arrayOfBeans</jv>, <js>"foo,bar"</js>);
</p>
<p>
The tool can be used against the following data types:
</p>
<ul>
<li>Arrays/collections of maps or beans.
<li>Singular maps or beans.
</ul>
<ul class='notes'>
<li class='note'>This class is used in the <a href="org/apache/juneau/rest/converter/Queryable.html" title="class in org.apache.juneau.rest.converter"><code>Queryable</code></a> REST response converter.
</ul>
<h5 class='topic'>ObjectPaginator</h5>
<p>
The <a href="org/apache/juneau/objecttools/ObjectPaginator.html" title="class in org.apache.juneau.objecttools"><code>ObjectPaginator</code></a> class is designed to extract sublists from arrays/collections of maps or beans.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
MyBean[] <jv>arrayOfBeans</jv> = ...;
ObjectPaginator <jv>paginator</jv> = ObjectPaginator.<jsm>create</jsm>();
<jc>// Returns all rows from 100 to 110.</jc>
List&lt;MyBean&gt; <jv>result</jv> = <jv>paginator</jv>.run(<jv>arrayOfBeans</jv>, 100, 10);
</p>
<p>
The tool can be used against the following data types:
</p>
<ul>
<li>Arrays/collections of maps or beans.
</ul>
<ul class='notes'>
<li class='note'>This class is used in the <a href="org/apache/juneau/rest/converter/Queryable.html" title="class in org.apache.juneau.rest.converter"><code>Queryable</code></a> REST response converter.
</ul>
<h5 class='topic'>ObjectIntrospector</h5>
<p>
The <a href="org/apache/juneau/objecttools/ObjectIntrospector.html" title="class in org.apache.juneau.objecttools"><code>ObjectIntrospector</code></a> class is used to invoke methods on <code>Objects</code> using arguments in serialized form.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
String <jv>string1</jv> = <js>"foobar"</js>;
String <jv>string2</jv> = ObjectIntrospector
.create(<jv>string</jv>)
.invoke(String.<jk>class</jk>, <js>"substring(int,int)"</js>, <js>"[3,6]"</js>); <jc>// "bar"</jc>
</p>
<p>
The arguments passed to the identified method are POJOs serialized in JSON format. Arbitrarily complex arguments can be passed
in as arguments.
</p>
<ul class='notes'>
<li class='note'>This class is used in the <a href="org/apache/juneau/rest/converter/Introspectable.html" title="class in org.apache.juneau.rest.converter"><code>Introspectable</code></a> REST response converter.
<li class='warn'>This is an extremely powerful but potentially dangerous tool. Use wisely.
</ul>
<h5 class='topic'>ObjectMerger</h5>
<p>
The <a href="org/apache/juneau/objecttools/ObjectMerger.html" title="class in org.apache.juneau.objecttools"><code>ObjectMerger</code></a> class is used for merging POJOs behind a single interface.
This is particularly useful in cases where you want to define beans with 'default' values.
</p>
<p>
For example, given the following bean classes:
</p>
<p class='bjava'>
<jk>public interface</jk> IA {
String getX();
<jk>void</jk> setX(String <jv>x</jv>);
}
<jk>public class</jk> A <jk>implements</jk> IA {
<jk>private</jk> String <jf>x</jf>;
<jk>public</jk> A(String <jv>x</jv>) {
<jk>this</jk>.<jf>x</jf> = <jv>x</jv>;
}
<jk>public</jk> String getX() {
<jk>return</jk> <jf>x</jf>;
}
<jk>public void</jk> setX(String <jv>x</jv>) {
<jk>this</jk>.<jf>x</jf> = <jv>x</jv>;
}
}
</p>
<p>
The getters will be called in order until the first non-null value is returned:
</p>
<p class='bjava'>
<jv>merge</jv> = ObjectMerger.<jsm>merger</jsm>(IA.<jk>class</jk>, <jk>new</jk> A(<js>"1"</js>), <jk>new</jk> A(<js>"2"</js>));
<jsm>assertEquals</jsm>(<js>"1"</js>, <jv>merge</jv>.getX());
<jv>merge</jv> = ObjectMerger.<jsm>merger</jsm>(IA.<jk>class</jk>, <jk>new</jk> A(<jk>null</jk>), <jk>new</jk> A(<js>"2"</js>));
<jsm>assertEquals</jsm>(<js>"2"</js>, <jv>merge</jv>.getX());
<jv>merge</jv> = ObjectMerger.<jsm>merger</jsm>(IA.<jk>class</jk>, <jk>new</jk> A(<jk>null</jk>), <jk>new</jk> A(<jk>null</jk>));
<jsm>assertEquals</jsm>(<jk>null</jk>, <jv>merge</jv>.getX());
</p>
</div>
</div><!-- END: 2.23 - juneau-marshall.jm.ObjectTools -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JsonDetails' id='juneau-marshall.jm.JsonDetails'>2.24 - JSON Details</a></h3>
<div class='topic'><!-- START: 2.24 - juneau-marshall.jm.JsonDetails -->
<div class='topic'>
<p>
Juneau supports converting arbitrary POJOs to and from JSON using ultra-efficient serializers and parsers.
The JSON serializer converts POJOs directly to JSON without the need for intermediate DOM objects using a
highly-efficient state machine.
Likewise, the JSON parser creates POJOs directly from JSON without the need for intermediate DOM objects.
</p>
<p>
The following example shows JSON for a typical bean:
</p>
<h5 class='figure'>Sample Beans</h5>
<p class='bjava'>
<jk>public class</jk> Person {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>name</jf>;
<ja>@Swap</ja>(TemporalCalendarSwap.IsoInstant.<jk>class</jk>) <jk>public</jk> Calendar <jf>birthDate</jf>;
<jk>public</jk> List&lt;Address&gt; <jf>addresses</jf>;
<jc>// Getters/setters omitted</jc>
}
<jk>public class</jk> Address {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>street</jf>, <jf>city</jf>;
<jk>public</jk> StateEnum <jf>state</jf>;
<jk>public int</jk> <jf>zip</jf>;
<jk>public boolean</jk> <jf>isCurrent</jf>;
<jc>// Getters/setters omitted</jc>
}
</p>
<h5 class='figure'>Sample Code</h5>
<p class='bjava'>
Person <jv>person</jv> = <jk>new</jk> Person()
.name(<js>"John Smith"</js>)
.birthDate(<js>"1946-08-12T00:00:00Z"</js>)
.addresses(
<jk>new</jk> Address()
.street(<js>"100 Main Street"</js>)
.city(<js>"Anywhereville"</js>)
.state(<jsf>NY</jsf>)
.zip(12345)
.isCurrent(<jk>true</jk>);
);
</p>
<h5 class='figure'>Normal JSON</h5>
<p class='bjson'>
{
<js>"name"</js>: <js>"John Smith"</js>,
<js>"birthDate"</js>: <js>"1946-08-12T00:00:00Z"</js>,
<js>"addresses"</js>: [
{
<js>"street"</js>: <js>"100 Main Street"</js>,
<js>"city"</js>: <js>"Anywhereville"</js>,
<js>"state"</js>: <js>"NY"</js>,
<js>"zip"</js>: 12345,
<js>"isCurrent"</js>: <jk>true</jk>
}
]
}
</p>
<h5 class='figure'>Simplified JSON</h5>
<p class='bjson'>
{
name: <js>'John Smith'</js>,
birthDate: <js>'1946-08-12T00:00:00Z'</js>,
addresses: [
{
street: <js>'100 Main Street'</js>,
city: <js>'Anywhereville'</js>,
state: <js>'NY'</js>,
zip: 12345,
isCurrent: <jk>true</jk>
}
]
}
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JsonDetails.jm.JsonMethodology' id='juneau-marshall.jm.JsonDetails.jm.JsonMethodology'>2.24.1 - JSON Methodology</a></h4>
<div class='topic'><!-- START: 2.24.1 - juneau-marshall.jm.JsonDetails.jm.JsonMethodology -->
<div class='topic'>
<p>
The JSON data type produced depends on the Java object type being serialized.
</p>
<ul class='spaced-list'>
<li>
Primitives and primitive objects are converted to JSON primitives.
<li>
Beans and Maps are converted to JSON objects.
<li>
Collections and arrays are converted to JSON arrays.
<li>
Anything else is converted to JSON strings.
</ul>
<h5 class='figure'>Data type conversions:</h5>
<table class='styled w800'>
<tr>
<th>POJO type</th>
<th>JSON type</th>
<th>Example</th>
<th>Serialized form</th>
</tr>
<tr>
<td>String</td>
<td>String</td>
<td><c>serialize(<js>"foobar"</js>);</c></td>
<td><c><js>'foobar'</js></c>
</tr>
<tr>
<td>Number</td>
<td>Number</td>
<td><c>serialize(123);</c></td>
<td><c>123</c>
</tr>
<tr>
<td>Boolean</td>
<td>Boolean</td>
<td><c>serialize(<jk>true</jk>);</c></td>
<td><c><jk>true</jk></c>
</tr>
<tr>
<td>Null</td>
<td>Null</td>
<td><c>serialize(<jk>null</jk>);</c></td>
<td><c><jk>null</jk></c>
</tr>
<tr>
<td>Beans with properties of any type on this list</td>
<td>Object</td>
<td><c>serialize(<jk>new</jk> MyBean());</c></td>
<td><c>{p1:<js>'val1'</js>,p2:<jk>true</jk>}</c>
</tr>
<tr>
<td>Maps with values of any type on this list</td>
<td>Object</td>
<td><c>serialize(<jk>new</jk> TreeMap());</c></td>
<td><c>{key1:<js>'val1'</js>,key2:<jk>true</jk>}</c>
</tr>
<tr>
<td>Collections and arrays of any type on this list</td>
<td>Array</td>
<td><c>serialize(<jk>new</jk> Object[]{1,<js>"foo"</js>,<jk>true</jk>});</c></td>
<td><c>[1,<js>'foo'</js>,<jk>true</jk>]</c>
</tr>
</table>
<p>
In addition, swaps can be used to convert non-serializable POJOs into serializable forms, such as converting
<c>Calendar</c> object to ISO8601 strings, or <c><jk>byte</jk>[]</c> arrays to Base-64
encoded strings.
</p>
</div>
</div><!-- END: 2.24.1 - juneau-marshall.jm.JsonDetails.jm.JsonMethodology -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JsonDetails.jm.JsonSerializers' id='juneau-marshall.jm.JsonDetails.jm.JsonSerializers'>2.24.2 - JSON Serializers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.24.2 - juneau-marshall.jm.JsonDetails.jm.JsonSerializers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a> class is used to serialize POJOs into JSON.
</p>
<p>
The class hierarchy for the builder of this serializer is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanTraverseContext.Builder.html" title="class in org.apache.juneau"><code>BeanTraverseContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializer.Builder.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/json/JsonSerializer.Builder.html" title="class in org.apache.juneau.json"><code>JsonSerializer.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured serializers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/json/JsonSerializer.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/json/JsonSerializer.html#DEFAULT_READABLE"><code>DEFAULT_READABLE</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/json/SimpleJsonSerializer.html" title="class in org.apache.juneau.json"><code>SimpleJsonSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/json/SimpleJsonSerializer.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/json/SimpleJsonSerializer.html#DEFAULT_READABLE"><code>DEFAULT_READABLE</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.24.2 - juneau-marshall.jm.JsonDetails.jm.JsonSerializers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JsonDetails.jm.SimplifiedJson' id='juneau-marshall.jm.JsonDetails.jm.SimplifiedJson'>2.24.3 - Simplified JSON</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.24.3 - juneau-marshall.jm.JsonDetails.jm.SimplifiedJson -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/json/SimpleJsonSerializer.html" title="class in org.apache.juneau.json"><code>SimpleJsonSerializer</code></a> class can be used to serialized POJOs into Simplified JSON notation.
</p>
<p>
Simplified JSON is identical to JSON except for the following:
</p>
<ul class='spaced-list'>
<li>JSON attributes are only quoted when necessary.
<li>Uses single-quotes for quoting.
</ul>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Some free-form JSON.</jc>
JsonMap <jv>map</jv> = JsonMap.<jsm>of</jsm>(
<js>"foo"</js>, <js>"x1"</js>,
<js>"_bar"</js>, <js>"x2"</js>,
<js>" baz "</js>, <js>"x3"</js>,
<js>"123"</js>, <js>"x4"</js>,
<js>"return"</js>, <js>"x5"</js>,
<js>""</js>, <js>"x6"</js>
);
</p>
<p class='bjson'>
<joc>// Serialized to standard JSON</joc>
{
<jok>"foo"</jok>: <jov>"x1"</jov>,
<jok>"_bar"</jok>: <jov>"x2"</jov>,
<jok>" baz "</jok>: <jov>"x3"</jov>,
<jok>"123"</jok>: <jov>"x4"</jov>,
<jok>"return"</jok>: <jov>"x5"</jov>,
<jok>""</jok>: <jov>"x6"</jov>
}
</p>
<p class='bjson'>
<joc>// Serialized to simplified JSON</joc>
{
<jok>foo</jok>: <jov>'x1'</jov>,
<jok>_bar</jok>: <jov>'x2'</jov>,
<jok>' baz '</jok>: <jov>'x3'</jov>, <joc>// Quoted due to embedded spaces.</joc>
<jok>'123'</jok>: <jov>'x4'</jov>, <joc>// Quoted to prevent confusion with number.</joc>
<jok>'return'</jok>: <jov>'x5'</jov>, <joc>// Quoted because it's a keyword.</joc>
<jok>''</jok>: <jov>'x6'</jov> <joc>// Quoted because it's an empty string.</joc>
}
</p>
<p>
The advantage to simplified JSON is you can represent it in a Java String in minimal form with minimal escaping.
This is particularly useful in cases such as unit testing where you can easily validate POJOs by simplifying them to Simplified JSON and do a simple string comparison.
</p>
<p class='bjava'>
WriterSerializer <jv>serializer</jv> = SimpleJsonSerializer.<jsf>DEFAULT</jsf>;
<jsm>assertEquals</jsm>(<js>"{foo:'bar',baz:123}"</js>, <jv>serializer</jv>.toString(<jv>myPojo</jv>));
</p>
<ul class='seealso'>
<li class='jc'><a href="org/apache/juneau/json/JsonSerializer.Builder.html" title="class in org.apache.juneau.json"><code>JsonSerializer.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/json/JsonSerializer.Builder.html#simpleMode--"><code>simpleMode()</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.24.3 - juneau-marshall.jm.JsonDetails.jm.SimplifiedJson -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JsonDetails.jm.JsonParsers' id='juneau-marshall.jm.JsonDetails.jm.JsonParsers'>2.24.4 - JSON Parsers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.24.4 - juneau-marshall.jm.JsonDetails.jm.JsonParsers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a> class is used to parse JSON into POJOs.
</p>
<p>
The class hierarchy for the builder of this parser is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/Parser.Builder.html" title="class in org.apache.juneau.parser"><code>Parser.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/ReaderParser.Builder.html" title="class in org.apache.juneau.parser"><code>ReaderParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/json/JsonParser.Builder.html" title="class in org.apache.juneau.json"><code>JsonParser.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured parsers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/json/JsonParser.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/json/JsonParser.html#DEFAULT_STRICT"><code>DEFAULT_STRICT</code></a>
</ul>
</li>
</ul>
<p>
The JSON parser supports ALL valid JSON, including:
</p>
<ul class='spaced-list'>
<li>
Javascript comments.
<li>
Single or double quoted values.
<li>
Quoted (strict) or unquoted (non-strict) attributes.
<li>
JSON fragments (such as string, numeric, or boolean primitive values).
<li>
Concatenated strings.
</ul>
</div>
</div><!-- END: 2.24.4 - juneau-marshall.jm.JsonDetails.jm.JsonParsers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JsonDetails.jm.JsonAnnotation' id='juneau-marshall.jm.JsonDetails.jm.JsonAnnotation'>2.24.5 - @Json Annotation</a></h4>
<div class='topic'><!-- START: 2.24.5 - juneau-marshall.jm.JsonDetails.jm.JsonAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/json/annotation/Json.html" title="annotation in org.apache.juneau.json.annotation"><code>@Json</code></a> annotation
is used to override the behavior of <a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a> on individual bean classes or properties.
</p>
<p>
The annotation can be applied to beans as well as other objects serialized to other types (e.g. strings).
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/json/annotation/Json.html" title="annotation in org.apache.juneau.json.annotation"><code>Json</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/json/annotation/Json.html#wrapperAttr--"><code>wrapperAttr</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/json/annotation/Json.html#wrapperAttr--"><code>@Json(wrapperAttr)</code></a> annotation
can be used to wrap beans inside a JSON object with a specified attribute name.
</p>
<h5 class='figure'>Example:</h5>
<p class='bbjavacode w800'>
<ja>@Json</ja>(wrapperAttr=<js>"personBean"</js>)
<jk>public class</jk> Person {
<jk>public</jk> String <jf>name</jf> = <js>"John Smith"</js>;
}
</p>
<p>
The following shows the JSON representation with and without the annotation present:
</p>
<table class='styled w800'>
<tr>
<th>Without annotation</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
{
<jok>name</jok>: <jov>'John Smith'</jov>
}
</td>
<td class='code'>
{
<jok>personBean</jok>: {
<jok>name</jok>: <jov>'John Smith'</jov>
}
}
</td>
</tr>
</table>
</div>
</div><!-- END: 2.24.5 - juneau-marshall.jm.JsonDetails.jm.JsonAnnotation -->
</div><!-- END: 2.24 - juneau-marshall.jm.JsonDetails -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.JsonSchemaDetails' id='juneau-marshall.jm.JsonSchemaDetails'>2.25 - JSON-Schema Support</a></h3>
<div class='topic'><!-- START: 2.25 - juneau-marshall.jm.JsonSchemaDetails -->
<div class='topic'>
<p>
Juneau provides the <a href="org/apache/juneau/json/JsonSchemaSerializer.html" title="class in org.apache.juneau.json"><code>JsonSchemaSerializer</code></a> class for generating JSON-Schema
documents that describe the output generated by the <a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a> class.
This class shares the same properties as <c>JsonSerializer</c>.
For convenience the <a href="org/apache/juneau/json/JsonSerializer.html#getSchemaSerializer--"><code>JsonSerializer.getSchemaSerializer()</code></a> method has been
added for creating instances of schema serializers from the regular serializer instance.
</p>
<h5 class='figure'>Sample Beans</h5>
<p class='bjava'>
<jk>public class</jk> Person {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>name</jf>;
<jk>public</jk> Calendar <jf>birthDate</jf>;
<jk>public</jk> List&lt;Address&gt; <jf>addresses</jf>;
<jc>// Getters/setters omitted</jc>
}
<jk>public class</jk> Address {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>street</jf>, <jf>city</jf>;
<jk>public</jk> StateEnum <jf>state</jf>;
<jk>public int</jk> <jf>zip</jf>;
<jk>public boolean</jk> <jf>isCurrent</jf>;
<jc>// Getters/setters omitted</jc>
}
</p>
<p>
The code for creating our POJO model and generating JSON-Schema is shown below:
</p>
<p class='bjava'>
<jc>// Get the one of the default schema serializers.</jc>
JsonSchemaSerializer <jv>serializer</jv> = JsonSchemaSerializer.<jsf>DEFAULT_SIMPLE_READABLE</jsf>;
<jc>// Get the JSON Schema for the POJO.</jc>
String <jv>jsonSchema</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> Person());
<jc>// This also works.</jc>
<jv>jsonSchema</jv> = <jv>serializer</jv>.serialize(Person.<jk>class</jk>);
</p>
<h5 class='figure'>JSON Schema</h5>
<p class='bjson'>
{
<jok>type: <jov>'object'</jov>,
<jok>description</jok>: <jov>'org.apache.juneau.sample.Person'</jov>,
<jok>properties</jok>: {
<jok>name</jok>: {
<jok>type</jok>: <jov>'string'</jov>,
<jok>description</jok>: <jov>'java.lang.String'</jov>
},
<jok>birthDate</jok>: {
<jok>type</jok>: <jov>'string'</jov>,
<jok>description</jok>: <jov>'java.util.Calendar'</jov>
},
<jok>addresses</jok>: {
<jok>type</jok>: <jov>'array'</jov>,
<jok>description</jok>: <jov>'java.util.LinkedList&lt;org.apache.juneau.sample.Address&gt;'</jov>,
<jok>items</jok>: {
<jok>type</jok>: <jov>'object'</jov>,
<jok>description</jok>: <jov>'org.apache.juneau.sample.Address'</jov>,
<jok>properties</jok>: {
<jok>street</jok>: {
<jok>type</jok>: <jov>'string'</jov>,
<jok>description</jok>: <jov>'java.lang.String'</jov>
},
<jok>city</jok>: {
<jok>type</jok>: <jov>'string'</jov>,
<jok>description</jok>: <jov>'java.lang.String'</jov>
},
<jok>state</jok>: {
<jok>type</jok>: <jov>'string'</jov>,
<jok>description</jok>: <jov>'java.lang.String'</jov>
},
<jok>zip</jok>: {
<jok>type</jok>: <jov>'number'</jov>,
<jok>description</jok>: <jov>'int'</jov>
},
<jok>isCurrent</jok>: {
<jok>type</jok>: <jov>'boolean'</jov>,
<jok>description</jok>: <jov>'boolean'</jov>
}
}
}
}
}
}
</p>
</div>
</div><!-- END: 2.25 - juneau-marshall.jm.JsonSchemaDetails -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.XmlDetails' id='juneau-marshall.jm.XmlDetails'>2.26 - XML Details</a></h3>
<div class='topic'><!-- START: 2.26 - juneau-marshall.jm.XmlDetails -->
<div class='topic'>
<p>
Juneau supports converting arbitrary POJOs to and from XML using ultra-efficient serializers and parsers.
The XML serializer converts POJOs directly to XML without the need for intermediate DOM objects.
Likewise, the XML parser uses a STaX parser and creates POJOs directly without intermediate DOM objects.
</p>
<p>
Unlike frameworks such as JAXB, Juneau does not require POJO classes to be annotated to produce and consume
XML.
However, several XML annotations are provided for handling namespaces and fine-tuning the format of the XML produced.
</p>
<p>
The following example shows XML for a typical bean:
</p>
<h5 class='figure'>Sample Beans</h5>
<p class='bjava'>
<ja>@Bean</ja>(typeName=<js>"person"</js>)
<jk>public class</jk> Person {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>name</jf>;
<ja>@Swap</ja>(TemporalCalendarSwap.IsoInstant.<jk>class</jk>) <jk>public</jk> Calendar <jf>birthDate</jf>;
<jk>public</jk> List&lt;Address&gt; <jf>addresses</jf>;
<jc>// Getters/setters omitted</jc>
}
<ja>@Bean</ja>(typeName=<js>"address"</js>)
<jk>public class</jk> Address {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>street</jf>, <jf>city</jf>;
<jk>public</jk> StateEnum <jf>state</jf>;
<jk>public int</jk> <jf>zip</jf>;
<jk>public boolean</jk> <jf>isCurrent</jf>;
<jc>// Getters/setters omitted</jc>
}
</p>
<h5 class='figure'>Sample Code</h5>
<p class='bjava'>
Person <jv>person</jv> = <jk>new</jk> Person()
.name(<js>"John Smith"</js>)
.birthDate(<js>"1946-08-12T00:00:00Z"</js>)
.addresses(
<jk>new</jk> Address()
.street(<js>"100 Main Street"</js>)
.city(<js>"Anywhereville"</js>)
.state(<jsf>NY</jsf>)
.zip(12345)
.isCurrent(<jk>true</jk>);
);
</p>
<h5 class='figure'>Normal XML:</h5>
<p class='bxml'>
<xt>&lt;person&gt;</xt>
<xt>&lt;name&gt;</xt>John Smith<xt>&lt;/name&gt;</xt>
<xt>&lt;birthDate&gt;</xt>1946-08-12T04:00:00Z<xt>&lt;/birthDate&gt;</xt>
<xt>&lt;addresses&gt;</xt>
<xt>&lt;address&gt;</xt>
<xt>&lt;street&gt;</xt>100 Main Street<xt>&lt;/street&gt;</xt>
<xt>&lt;city&gt;</xt>Anywhereville<xt>&lt;/city&gt;</xt>
<xt>&lt;state&gt;</xt>NY<xt>&lt;/state&gt;</xt>
<xt>&lt;zip&gt;</xt>12345<xt>&lt;/zip&gt;</xt>
<xt>&lt;isCurrent&gt;</xt>true<xt>&lt;/isCurrent&gt;</xt>
<xt>&lt;/address&gt;</xt>
<xt>&lt;/addresses&gt;</xt>
<xt>&lt;/person&gt;</xt>
</p>
<p>
Juneau produces JSON-equivalent XML, meaning any valid JSON document can be losslessly converted into an XML
equivalent.
In fact, all of the Juneau serializers and parsers are built upon this JSON-equivalence.
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.XmlDetails.jm.XmlMethodology' id='juneau-marshall.jm.XmlDetails.jm.XmlMethodology'>2.26.1 - XML Methodology</a></h4>
<div class='topic'><!-- START: 2.26.1 - juneau-marshall.jm.XmlDetails.jm.XmlMethodology -->
<div class='topic'>
<p>
The following examples show how different data types are represented in XML.
They mirror how the data structures are represented in JSON.
<h5 class='topic'>Simple types</h5>
<p>
The representation of loose (not a direct bean property value) simple types are shown below:
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>XML</th>
</tr>
<tr>
<td>string</td>
<td class='code'><js>'foo'</js></td>
<td class='code'><xt>&lt;string&gt;</xt>foo<xt>&lt;/string&gt;</xt></td>
</tr>
<tr>
<td>boolean</td>
<td class='code'><jk>true</jk></td>
<td class='code'><xt>&lt;boolean&gt;</xt>true<xt>&lt;/boolean&gt;</xt></td>
</tr>
<tr>
<td>integer</td>
<td class='code'>123</td>
<td class='code'><xt>&lt;number&gt;</xt>123<xt>&lt;/number&gt;</xt></td>
</tr>
<tr>
<td>float</td>
<td class='code'>1.23</td>
<td class='code'><xt>&lt;number&gt;</xt>1.23<xt>&lt;/number&gt;</xt></td>
</tr>
<tr>
<td>null</td>
<td class='code'><jk>null</jk></td>
<td class='code'><xt>&lt;null/&gt;</xt></td>
</tr>
</table>
<h5 class='topic'>Maps</h5>
<p>
Loose maps and beans use the element <xt>&lt;object&gt;</xt> for encapsulation.
</p>
<p>
<xa>_type</xa> attributes are added to bean properties or map entries if the type cannot be inferred
through reflection (e.g. an <c>Object</c> or superclass/interface value type).
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>XML</th>
</tr>
<tr>
<td class='code'>
Map&lt;String,String&gt;
</td>
<td class='code'>
{
k1: <js>'v1'</js>
k2: <jk>null</jk>
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;k1&gt;<xv>v1</xv>&lt;/k1&gt;
&lt;k2 <xa>_type</xa>=<xs>'null'</xs>/&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
Map&lt;String,Number&gt;
</td>
<td class='code'>
{
k1: 123,
k2: 1.23,
k3: <jk>null</jk>
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;k1&gt;<xv>123</xv>&lt;/k1&gt;
&lt;k2&gt;<xv>1.23</xv>&lt;/k2&gt;
&lt;k3 <xa>_type</xa>=<xs>'null'</xs>/&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
Map&lt;String,Object&gt;
</td>
<td class='code'>
{
k1: <js>'v1'</js>
k2: 123,
k3: 1.23,
k4: <jk>true</jk>,
k5: <jk>null</jk>
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;k1&gt;<xv>v1</xv>&lt;/k1&gt;
&lt;k2 <xa>_type</xa>=<xs>'number'</xs>&gt;<xv>123</xv>&lt;/k2&gt;
&lt;k3 <xa>_type</xa>=<xs>'number'</xs>&gt;<xv>1.23</xv>&lt;/k3&gt;
&lt;k4 <xa>_type</xa>=<xs>'boolean'</xs>&gt;<xv>true</xv>&lt;/k4&gt;
&lt;k5 <xa>_type</xa>=<xs>'null'</xs>/&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
<h5 class='topic'>Arrays</h5>
<p>
Loose collections and arrays use the element <xt>&lt;array&gt;</xt> for encapsulation.
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>XML</th>
</tr>
<tr>
<td class='code'>
String[]
</td>
<td class='code'>
[
<js>'foo'</js>
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;array&gt;
&lt;string&gt;<xv>foo</xv>&lt;/string&gt;
&lt;null/&gt;
&lt;/array&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
Number[]
</td>
<td class='code'>
[
123,
1.23,
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;array&gt;
&lt;number&gt;<xv>123</xv>&lt;/number&gt;
&lt;number&gt;<xv>1.23</xv>&lt;/number&gt;
&lt;null/&gt;
&lt;/array&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
Object[]
</td>
<td class='code'>
[
<js>'foo'</js>,
123,
1.23,
<jk>true</jk>,
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;array&gt;
&lt;string&gt;<xv>foo</xv>&lt;/string&gt;
&lt;number&gt;<xv>123</xv>&lt;/number&gt;
&lt;number&gt;<xv>1.23</xv>&lt;/number&gt;
&lt;boolean&gt;<xv>true</xv>&lt;/boolean&gt;
&lt;null/&gt;
&lt;/array&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
String[][]
</td>
<td class='code'>
[
[<js>'foo'</js>, <jk>null</jk>],
<jk>null</jk>,
]
</td>
<td class='code'><xt>
&lt;array&gt;
&lt;array&gt;
&lt;string&gt;<xv>foo</xv>&lt;/string&gt;
&lt;null/&gt;
&lt;/array&gt;
&lt;null/&gt;
&lt;/array&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<jk>int</jk>[]
</td>
<td class='code'>
[
123
]
</td>
<td class='code'><xt>
&lt;array&gt;
&lt;number&gt;<xv>123</xv>&lt;/number&gt;
&lt;/array&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<jk>boolean</jk>[]
</td>
<td class='code'>
[
<jk>true</jk>
]
</td>
<td class='code'><xt>
&lt;array&gt;
&lt;boolean&gt;<xv>true</xv>&lt;/boolean&gt;
&lt;/array&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
List&lt;String&gt;
</td>
<td class='code'>
[
<js>'foo'</js>
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;array&gt;
&lt;string&gt;<xv>foo</xv>&lt;/string&gt;
&lt;null/&gt;
&lt;/array&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
List&lt;Number&gt;
</td>
<td class='code'>
[
123,
1.23,
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;array&gt;
&lt;number&gt;<xv>123</xv>&lt;/number&gt;
&lt;number&gt;<xv>1.23</xv>&lt;/number&gt;
&lt;null/&gt;
&lt;/array&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
List&lt;Object&gt;
</td>
<td class='code'>
[
<js>'foo'</js>,
123,
1.23,
<jk>true</jk>,
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;array&gt;
&lt;string&gt;<xv>foo</xv>&lt;/string&gt;
&lt;number&gt;<xv>123</xv>&lt;/number&gt;
&lt;number&gt;<xv>1.23</xv>&lt;/number&gt;
&lt;boolean&gt;<xv>true</xv>&lt;/boolean&gt;
&lt;null/&gt;
&lt;/array&gt;
</xt></td>
</tr>
</table>
<h5 class='topic'>Beans</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>XML</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<jk>public</jk> String <jf>a</jf>;
<jk>public</jk> <jk>int</jk> <jf>b</jf>;
<jk>public</jk> Object <jf>c</jf>; <jc>// String value</jc>
<jk>public</jk> Object <jf>d</jf>; <jc>// Integer value</jc>
<jk>public</jk> MyBean2 <jf>e</jf>;
<jk>public</jk> String[] <jf>f</jf>;
<jk>public</jk> <jk>int</jk>[] <jf>g</jf>;
}
<jk>class</jk> MyBean2 {
String <jf>h</jf>;
}
</td>
<td class='code'>
{
<jok>a</jok>: <jov>'foo'</jov>,
<jok>b</jok>: <jov>123</jov>,
<jok>c</jok>: <jov>'bar'</jov>,
<jok>d</jok>: <jov>456</jov>,
<jok>e</jok>: {
<jok>h</jok>: <jov>'baz'</jov>
}
<jok>f</jok>: [<jov>'qux'</jov>]
<jok>g</jok>: [<jov>789</jov>]
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;<xv>foo</xv>&lt;/a&gt;
&lt;b&gt;<xv>123</xv>&lt;/b&gt;
&lt;c&gt;<xv>bar</xv>&lt;/c&gt;
&lt;d <xa>_type</xa>=<xs>'number'</xs>&gt;<xv>456</xv>&lt;/d&gt;
&lt;e&gt;
&lt;h&gt;<xv>baz</xv>&lt;/h&gt;
&lt;/e&gt;
&lt;f&gt;
&lt;string&gt;<xv>qux</xv>&lt;/string&gt;
&lt;/f&gt;
&lt;g&gt;
&lt;number&gt;<xv>789</xv>&lt;/number&gt;
&lt;/g&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
<h5 class='topic'>Beans with Map properties</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>XML</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<jk>public</jk> Map&lt;String,String&gt; <jf>a</jf>;
<jk>public</jk> Map&lt;String,Number&gt; <jf>b</jf>;
<jk>public</jk> Map&lt;String,Object&gt; <jf>c</jf>;
}
</td>
<td class='code'>
{
<jok>a</jok>: {
<jok>k1</jok>: <jov>'foo'</jov>
},
<jok>b</jok>: {
<jok>k2</jok>: <jov>123</jov>
},
<jok>c</jok>: {
<jok>k3</jok>: <jov>'bar'</jov>,
<jok>k4</jok>: <jov>456</jov>,
<jok>k5</jok>: <jov>true</jov>,
<jok>k6</jok>: <jov>null</jov>
}
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;k1&gt;<xv>foo</xv>&lt;/k1&gt;
&lt;/a&gt;
&lt;b&gt;
&lt;k2&gt;<xv>123</xv>&lt;/k2&gt;
&lt;/b&gt;
&lt;c&gt;
&lt;k3&gt;<xv>bar</xv>&lt;/k3&gt;
&lt;k4 <xa>_type</xa>=<xs>'number'</xs>&gt;<xv>456</xv>&lt;/k4&gt;
&lt;k5 <xa>_type</xa>=<xs>'boolean'</xs>&gt;<xv>true</xv>&lt;/k5&gt;
&lt;k6 <xa>_type</xa>=<xs>'null'</xs>/&gt;
&lt;/c&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
</div>
</div><!-- END: 2.26.1 - juneau-marshall.jm.XmlDetails.jm.XmlMethodology -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.XmlDetails.jm.XmlSerializers' id='juneau-marshall.jm.XmlDetails.jm.XmlSerializers'>2.26.2 - XML Serializers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.26.2 - juneau-marshall.jm.XmlDetails.jm.XmlSerializers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/xml/XmlSerializer.html" title="class in org.apache.juneau.xml"><code>XmlSerializer</code></a> class is used to serialize POJOs into XML.
</p>
<p>
The <a href="org/apache/juneau/xml/XmlDocSerializer.html" title="class in org.apache.juneau.xml"><code>XmlDocSerializer</code></a> class is the same but serializes a <xt>&lt;?xml?&gt;</xt> header
at the top of the file.
</p>
<p>
The class hierarchy for the builder of this serializer is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanTraverseContext.Builder.html" title="class in org.apache.juneau"><code>BeanTraverseContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializer.Builder.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/xml/XmlSerializer.Builder.html" title="class in org.apache.juneau.xml"><code>XmlSerializer.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured serializers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/xml/XmlSerializer.html" title="class in org.apache.juneau.xml"><code>XmlSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT_JUNEAU_NAMESPACE"><code>DEFAULT_JUNEAU_NAMESPACE</code></a>
<li class='jf'><a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT_NS"><code>DEFAULT_NS</code></a>
<li class='jf'><a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT_NS_SQ"><code>DEFAULT_NS_SQ</code></a>
<li class='jf'><a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT_NS_SQ_READABLE"><code>DEFAULT_NS_SQ_READABLE</code></a>
<li class='jf'><a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT_SQ"><code>DEFAULT_SQ</code></a>
<li class='jf'><a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT_SQ_READABLE"><code>DEFAULT_SQ_READABLE</code></a>
<li class='jf'><a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT_XS_NAMESPACE"><code>DEFAULT_XS_NAMESPACE</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.26.2 - juneau-marshall.jm.XmlDetails.jm.XmlSerializers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.XmlDetails.jm.XmlParsers' id='juneau-marshall.jm.XmlDetails.jm.XmlParsers'>2.26.3 - XML Parsers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.26.3 - juneau-marshall.jm.XmlDetails.jm.XmlParsers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/xml/XmlParser.html" title="class in org.apache.juneau.xml"><code>XmlParser</code></a> class is used to parse XML into POJOs.
</p>
<p>
The class hierarchy for the builder of this parser is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/Parser.Builder.html" title="class in org.apache.juneau.parser"><code>Parser.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/ReaderParser.Builder.html" title="class in org.apache.juneau.parser"><code>ReaderParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/xml/XmlParser.Builder.html" title="class in org.apache.juneau.xml"><code>XmlParser.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured parsers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/xml/XmlParser.html" title="class in org.apache.juneau.xml"><code>XmlParser</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/xml/XmlParser.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.26.3 - juneau-marshall.jm.XmlDetails.jm.XmlParsers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.XmlDetails.jm.XmlBeanTypeNameAnnotation' id='juneau-marshall.jm.XmlDetails.jm.XmlBeanTypeNameAnnotation'>2.26.4 - @Bean(typeName) Annotation</a></h4>
<div class='topic'><!-- START: 2.26.4 - juneau-marshall.jm.XmlDetails.jm.XmlBeanTypeNameAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/annotation/Bean.html#typeName--"><code>@Bean(typeName)</code></a> annotation can be used to
override the Juneau default name on bean elements.
Types names serve two distinct purposes:
</p>
<ol>
<li>To override the element name.
<li>To serve as a class identifier so that the bean class can be inferred during parsing if it
cannot automatically be inferred through reflection.
</ol>
<h5 class='figure'>Example</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>Without annotation</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<jk>public</jk> String <jf>a</jf>;
<jk>public int</jk> <jf>b</jf>;
}
</td>
<td class='code'>
{
a: <js>'foo'</js>,
b: 123
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;<xv>foo</xv>&lt;/id&gt;
&lt;b&gt;<xv>123</xv>&lt;/name&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;X&gt;
&lt;a&gt;<xv>foo</xv>&lt;/id&gt;
&lt;b&gt;<xv>123</xv>&lt;/name&gt;
&lt;/X&gt;
</xt></td>
</tr>
</table>
<p>
On bean properties, a <xa>_type</xa> attribute will be added if a type name is present and the bean
class cannot be inferred through reflection.
</p>
<p>
In the following example, a type attribute is used on property 'b' but not property 'a' since
'b' is of type <c>Object</c> and therefore the bean class cannot be inferred.
</p>
<h5 class='figure'>Example</h5>
<table class='styled w800'>
<tr>
<th>Java</th>
<th>Without annotation</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<jk>public</jk> BeanX <jf>a</jf> = <jk>new</jk> BeanX();
<jk>public</jk> Object <jf>b</jf> = <jk>new</jk> BeanX();
}
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> BeanX {
<jk>public</jk> String <jf>fx</jf> = <js>"foo"</js>;
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/a&gt;
&lt;b&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/b&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/a&gt;
&lt;b <xa>_type</xa>=<xs>'X'</xs>&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/b&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
<div class='info'>
<c>string</c>, <c>number</c>, <c>boolean</c>, <c>object</c>,
<c>array</c>, and <c>null</c> are reserved keywords that cannot be used as type names.
</div>
<p>
Beans with type names are often used in conjunction with the
<a href="org/apache/juneau/annotation/Bean.html#dictionary--"><code>@Bean(dictionary)</code></a> and
<a href="org/apache/juneau/annotation/Beanp.html#dictionary--"><code>@Beanp(dictionary)</code></a>
annotations so that the beans can be resolved at parse time.
These annotations are not necessary during serialization but are needed during parsing in order to
resolve the bean types.
</p>
<p>
The following examples show how type names are used under various circumstances.
</p>
<p>
Pay special attention to when <xa>_type</xa> attributes are and are not used.
</p>
<h5 class='figure'>Examples</h5>
<table class='styled w800'>
<tr>
<th>Java</th>
<th>XML</th>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={BeanX.<jk>class</jk>})
<jk>class</jk> BeanWithArrayPropertiesWithTypeNames {
<jk>public</jk> BeanX[] <jf>b1</jf> = <jk>new</jk> BeanX[]{
<jk>new</jk> BeanX()
};
<jk>public</jk> Object[] <jf>b2</jf> = <jk>new</jk> BeanX[]{
<jk>new</jk> BeanX()
};
<jk>public</jk> Object[] <jf>b3</jf> = <jk>new</jk> Object[]{
<jk>new</jk> BeanX()
};
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;b1&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/b1&gt;
&lt;b2&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/b2&gt;
&lt;b3&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/b3&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={BeanX.<jk>class</jk>})
<jk>class</jk> BeanWith2dArrayPropertiesWithTypeNames {
<jk>public</jk> BeanX[][] <jf>b1</jf> = <jk>new</jk> BeanX[][]{{
<jk>new</jk> BeanX()
}};
<jk>public</jk> Object[][] <jf>b2</jf> = <jk>new</jk> BeanX[][]{{
<jk>new</jk> BeanX()
}};
<jk>public</jk> Object[][] <jf>b3</jf> = <jk>new</jk> Object[][]{{
<jk>new</jk> BeanX()
}};
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;b1&gt;
&lt;array&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/array&gt;
&lt;/b1&gt;
&lt;b2&gt;
&lt;array&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/array&gt;
&lt;/b2&gt;
&lt;b3&gt;
&lt;array&gt;
&lt;X&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/X&gt;
&lt;/array&gt;
&lt;/b3&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={BeanX.<jk>class</jk>})
<jk>class</jk> BeanWithMapPropertiesWithTypeNames {
<jk>public</jk> Map&lt;String,BeanX&gt; <jf>b1</jf> = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k1"</js>, <jk>new</jk> BeanX());
}};
<jk>public</jk> Map&lt;String,Object&gt; <jf>b2</jf> = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k2"</js>, <jk>new</jk> BeanX());
}}
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;b1&gt;
&lt;k1&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/k1&gt;
&lt;/b1&gt;
&lt;b2&gt;
&lt;k2 <xa>_type</xa>=<xs>'X'</xs>&gt;
&lt;fx&gt;<xv>foo</xv>&lt;/fx&gt;
&lt;/k2&gt;
&lt;/b2&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
<p>
Bean type names are also used for resolution when abstract fields are used.
The following examples show how they are used in a variety of circumstances.
</p>
<table class='styled w800'>
<tr>
<th>Java</th>
<th>XML</th>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={A.<jk>class</jk>})
<jk>class</jk> BeanWithAbstractFields {
<jk>public</jk> A <jf>a</jf> = <jk>new</jk> A();
<jk>public</jk> IA <jf>ia</jf> = <jk>new</jk> A();
<jk>public</jk> AA <jf>aa</jf> = <jk>new</jk> A();
<jk>public</jk> Object <jf>o</jf> = <jk>new</jk> A();
}
<jk>interface</jk> IA {}
<jk>abstract class</jk> AA <jk>implements</jk> IA {}
<ja>@Bean</ja>(typeName=<js>"A"</js>)
<jk>class</jk> A <jk>extends</jk> AA {
<jk>public</jk> String <jf>fa</jf> = <js>"foo"</js>;
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/a&gt;
&lt;ia <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/ia&gt;
&lt;aa <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/aa&gt;
&lt;o <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/o&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={A.<jk>class</jk>})
<jk>class</jk> BeanWithAbstractArrayFields {
<jk>public</jk> A[] <jf>a</jf> = <jk>new</jk> A[]{<jk>new</jk> A()};
<jk>public</jk> IA[] <jf>ia1</jf> = <jk>new</jk> A[]{<jk>new</jk> A()};
<jk>public</jk> IA[] <jf>ia2</jf> = <jk>new</jk> IA[]{<jk>new</jk> A()};
<jk>public</jk> AA[] <jf>aa1</jf> = <jk>new</jk> A[]{<jk>new</jk> A()};
<jk>public</jk> AA[] <jf>aa2</jf> = <jk>new</jk> AA[]{<jk>new</jk> A()};
<jk>public</jk> Object[] <jf>o1</jf> = <jk>new</jk> A[]{<jk>new</jk> A()};
<jk>public</jk> Object[] <jf>o2</jf> = <jk>new</jk> Object[]{<jk>new</jk> A()};
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/a&gt;
&lt;ia1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/ia1&gt;
&lt;ia2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/ia2&gt;
&lt;aa1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/aa1&gt;
&lt;aa2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/aa2&gt;
&lt;o1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/o1&gt;
&lt;o2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/o2&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={A.<jk>class</jk>})
<jk>class</jk> BeanWithAbstractMapFields {
<jk>public</jk> Map&lt;String,A&gt; <jf>a</jf> = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k1"</js>, <jk>new</jk> A());
}};
<jk>public</jk> Map&lt;String,AA&gt; <jf>b</jf> = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k2"</js>, <jk>new</jk> A());
}};
<jk>public</jk> Map&lt;String,Object&gt; <jf>c</jf> = <jk>new</jk> HashMap&lt;&gt;() {{
put(<js>"k3"</js>, <jk>new</jk> A());
}};
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;k1&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/k1&gt;
&lt;/a&gt;
&lt;b&gt;
&lt;k2 <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/k2&gt;
&lt;/b&gt;
&lt;c&gt;
&lt;k3 <xa>_type</xa>=<xs>'A'</xs>&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/k3&gt;
&lt;/c&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(dictionary={A.<jk>class</jk>})
<jk>class</jk> BeanWithAbstractMapArrayFields {
<jk>public</jk> Map&lt;String,A[]&gt; <jf>a</jf> = <jk>new</jk> LinkedHashMap&lt;&gt;() {{
put(<js>"a1"</js>, <jk>new</jk> A[]{<jk>new</jk> A()});
}};
<jk>public</jk> Map&lt;String,IA[]&gt; <jf>ia</jf> = <jk>new</jk> LinkedHashMap&lt;&gt;() {{
put(<js>"ia1"</js>, <jk>new</jk> A[]{<jk>new</jk> A()});
put(<js>"ia2"</js>, <jk>new</jk> IA[]{<jk>new</jk> A()});
}};
<jk>public</jk> Map&lt;String,AA[]&gt; <jf>aa</jf> = <jk>new</jk> LinkedHashMap&lt;&gt;() {{
put(<js>"aa1"</js>, <jk>new</jk> A[]{<jk>new</jk> A()});
put(<js>"aa2"</js>, <jk>new</jk> AA[]{<jk>new</jk> A()});
}};
<jk>public</jk> Map&lt;String,Object[]&gt; <jf>o</jf> = <jk>new</jk> LinkedHashMap&lt;&gt;() {{
put(<js>"o1"</js>, <jk>new</jk> A[]{<jk>new</jk> A()});
put(<js>"o2"</js>, <jk>new</jk> AA[]{<jk>new</jk> A()});
}};
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;a1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/a1&gt;
&lt;/a&gt;
&lt;ia&gt;
&lt;ia1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/ia1&gt;
&lt;ia2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/ia2&gt;
&lt;/ia&gt;
&lt;aa&gt;
&lt;aa1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/aa1&gt;
&lt;aa2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/aa2&gt;
&lt;/aa&gt;
&lt;o&gt;
&lt;o1&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/o1&gt;
&lt;o2&gt;
&lt;A&gt;
&lt;fa&gt;<xv>foo</xv>&lt;/fa&gt;
&lt;/A&gt;
&lt;/o2&gt;
&lt;/o&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
<p>
On a side note, characters that cannot be represented in XML 1.0 are encoded using a simple encoding.
Note in the examples below, some characters such as <js>'\n'</js>, <js>'\t</js>', and <js>'\r'</js>
can be represented as XML entities when used in text but not in element names. Other characters such as
<js>'\b'</js> and <js>'\f'</js> cannot be encoded in XML 1.0 at all without inventing our own notation.
Whitespace characters in element names are encoded as well as whitespace end characters in text.
</p>
<table class='styled w800'>
<tr>
<th>Java</th>
<th>XML</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> BeanWithSpecialCharacters {
<jk>public</jk> String <jf>a</jf> = <js>" \b\f\n\t\r "</js>;
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;<xv>_x0020_ _x0008__x000C_&amp;#x000a;&amp;#x0009;&amp;#x000d; _x0020_</xv>&lt;/a&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>" \b\f\n\t\r "</js>)
<jk>class</jk> BeanWithNamesWithSpecialCharacters {
<ja>@Beanp</ja>(name=<js>" \b\f\n\t\r "</js>)
<jk>public</jk> String <jf>a</jf> = <js>" \b\f\n\t\r "</js>;
}
</td>
<td class='code'><xt>
&lt;_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_&gt;
&lt;_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_&gt;
<xv>_x0020_ _x0008__x000C_&amp;#x000a;&amp;#x0009;&amp;#x000d; _x0020_</xv>
&lt;/_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_&gt;
&lt;/_x0020__x0020__x0008__x000C__x000A__x0009__x000D__x0020__x0020_&gt;
</xt></td>
</tr>
</table>
<p>
While it's true that these characters CAN be represented in XML 1.1, it's impossible to parse XML 1.1
text in Java without the XML containing an XML declaration.
Unfortunately, this, and the uselessness of the
<a href="https://docs.oracle.com/javase/8/docs/api/javax/xml/stream/XMLInputFactory.html?is-external=true#IS_REPLACING_ENTITY_REFERENCES" title="class or interface in javax.xml.stream"><code>XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES</code></a> setting in Java
forced us to make some hard design decisions that may not be the most elegant.
</p>
</div>
</div><!-- END: 2.26.4 - juneau-marshall.jm.XmlDetails.jm.XmlBeanTypeNameAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.XmlDetails.jm.XmlChildNameAnnotation' id='juneau-marshall.jm.XmlDetails.jm.XmlChildNameAnnotation'>2.26.5 - @Xml(childName) Annotation</a></h4>
<div class='topic'><!-- START: 2.26.5 - juneau-marshall.jm.XmlDetails.jm.XmlChildNameAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/xml/annotation/Xml.html#childName--"><code>@Xml(childName)</code></a> annotation can be used to
specify the name of XML child elements for bean properties of type collection or array.
</p>
<h5 class='figure'>Example</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>Without annotation</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(childName=<js>"X"</js>)
<jk>public</jk> String[] <jf>a</jf>;
<ja>@Xml</ja>(childName=<js>"Y"</js>)
<jk>public int</jk>[] <jf>b</jf>;
}
</td>
<td class='code'>
{
a: [<js>'foo'</js>,<js>'bar'</js>],
b: [123,456]
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;string&gt;<xv>foo</xv>&lt;/string&gt;
&lt;string&gt;<xv>bar</xv>&lt;/string&gt;
&lt;/a&gt;
&lt;b&gt;
&lt;number&gt;<xv>123</xv>&lt;/number&gt;
&lt;number&gt;<xv>456</xv>&lt;/number&gt;
&lt;/b&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;X&gt;<xv>foo</xv>&lt;/X&gt;
&lt;X&gt;<xv>bar</xv>&lt;/X&gt;
&lt;/a&gt;
&lt;b&gt;
&lt;Y&gt;<xv>123</xv>&lt;/Y&gt;
&lt;Y&gt;<xv>456</xv>&lt;/Y&gt;
&lt;/b&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(childName=<js>"child"</js>)
<jk>public int</jk>[] <jf>a</jf>;
}
</td>
<td class='code'>
{
a: [123,456]
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;string&gt;<xv>foo</xv>&lt;/string&gt;
&lt;string&gt;<xv>bar</xv>&lt;/string&gt;
&lt;/a&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;child&gt;<xv>foo</xv>&lt;/child&gt;
&lt;child&gt;<xv>bar</xv>&lt;/child&gt;
&lt;/a&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
</div>
</div><!-- END: 2.26.5 - juneau-marshall.jm.XmlDetails.jm.XmlChildNameAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.XmlDetails.jm.XmlFormatAnnotation' id='juneau-marshall.jm.XmlDetails.jm.XmlFormatAnnotation'>2.26.6 - @Xml(format) Annotation</a></h4>
<div class='topic'><!-- START: 2.26.6 - juneau-marshall.jm.XmlDetails.jm.XmlFormatAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/xml/annotation/Xml.html#format--"><code>@Xml(format)</code></a> annotation can be used to tweak
the XML format of a POJO.
The value is set to an enum value of type <a href="org/apache/juneau/xml/annotation/XmlFormat.html" title="enum in org.apache.juneau.xml.annotation"><code>XmlFormat</code></a>.
This annotation can be applied to both classes and bean properties.
</p>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#ATTR"><code>XmlFormat.ATTR</code></a> format can be applied to bean properties to
serialize them as XML attributes instead of elements.
Note that this only supports properties of simple types (e.g. strings, numbers, booleans).
</p>
<h5 class='figure'>Example</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>Without annotation</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>ATTR</jsf>)
<jk>public</jk> String <jf>a</jf>;
}
</td>
<td class='code'>
{
a: <js>'foo'</js>
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;<xv>foo</xv>&lt;/a&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object <xa>a</xa>=<xs>'foo'</xs>/&gt;
</xt></td>
</tr>
</table>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#ATTRS"><code>XmlFormat.ATTRS</code></a> format can be applied to bean classes to
force all bean properties to be serialized as XML attributes instead of child elements.
</p>
<h5 class='figure'>Example</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>Without annotation</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
<ja>@Xml</ja>(format=XmlFormat.<jsf>ATTRS</jsf>)
<jk>class</jk> MyBean {
<jk>public</jk> String <jf>a</jf>;
<jk>public int</jk> <jf>b</jf>;
}
</td>
<td class='code'>
{
a: <js>'foo'</js>,
b: 123
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;<xv>foo</xv>&lt;/a&gt;
&lt;b&gt;<xv>123</xv>&lt;/b&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object <xa>a</xa>=<xs>'foo'</xs> <xa>b</xa>=<xs>'123'</xs>/&gt;
</xt></td>
</tr>
</table>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#ELEMENT"><code>XmlFormat.ELEMENT</code></a> format can be applied to bean properties
to override the <a href="org/apache/juneau/xml/annotation/XmlFormat.html#ATTRS"><code>XmlFormat.ATTRS</code></a> format applied on the bean
class.
</p>
<h5 class='figure'>Example</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>Without annotation</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
<ja>@Xml</ja>(format=XmlFormat.<jsf>ATTRS</jsf>)
<jk>class</jk> MyBean {
<jk>public</jk> String <jf>a</jf>;
<ja>@Xml</ja>(format=XmlFormat.<jsf>ELEMENT</jsf>)
<jk>public int</jk> <jf>b</jf>;
}
</td>
<td class='code'>
{
a: <js>'foo'</js>,
b: 123
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;<xv>foo</xv>&lt;/a&gt;
&lt;b&gt;<xv>123</xv>&lt;/b&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object <xa>a</xa>=<xs>'foo'</xs></xs>&gt;
&lt;b&gt;<xv>123</xv>&lt;/b&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#ATTRS"><code>XmlFormat.ATTRS</code></a> format can be applied to a single bean
property of type <c>Map&lt;String,Object&gt;</c> to denote arbitrary XML attribute values on the
element.
These can be mixed with other <a href="org/apache/juneau/xml/annotation/XmlFormat.html#ATTR"><code>XmlFormat.ATTR</code></a> annotated
properties but there must not be an overlap in bean property names and map keys.
</p>
<h5 class='figure'>Example</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>Without annotation</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>ATTRS</jsf>)
<jk>public</jk> Map&lt;String,Object&gt; <jf>a</jf>;
<ja>@Xml</ja>(format=XmlFormat.<jsf>ATTR</jsf>)
<jk>public int</jk> <jf>b</jf>;
}
</td>
<td class='code'>
{
<jok>a</jok>: {
<jok>k1</jok>: <jov>'foo'</jov>,
<jok>k2</jok>: <jov>123</jov>,
},
<jok>b</jok>: <jov>456</jov>
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;k1&gt;<xv>foo</xv>&lt;/k1&gt;
&lt;k2 <xa>_type</xa>=<xs>'number'</xs>&gt;<xv>123</xv>&lt;/k2&gt;
&lt;/a&gt;
&lt;b&gt;<xv>456</xv>&lt;/b&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object <xa>k1</xa>=<xs>'foo'</xs> <xa>k2</xa>=<xs>'123'</xs> <xa>b</xa>=<xs>'456'</xs>/&gt;
</xt></td>
</tr>
</table>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#COLLAPSED"><code>XmlFormat.COLLAPSED</code></a> format can be applied to bean properties
of type array/Collection.
This causes the child objects to be serialized directly inside the bean element.
This format must be used in conjunction with <a href="org/apache/juneau/xml/annotation/Xml.html#childName--"><code>@Xml(childName)</code></a>
to differentiate which collection the values came from if you plan on parsing the output back into beans.
Note that child names must not conflict with other property names.
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>Without annotation</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(childName=<js>"A"</js>,format=XmlFormat.<jsf>COLLAPSED</jsf>)
<jk>public</jk> String[] <jf>a</jf>;
<ja>@Xml</ja>(childName=<js>"B"</js>,format=XmlFormat.<jsf>COLLAPSED</jsf>)
<jk>public int</jk>[] <jf>b</jf>;
}
</td>
<td class='code'>
{
a: [<js>'foo'</js>,<js>'bar'</js>],
b: [123,456]
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;string&gt;<xv>foo</xv>&lt;/string&gt;
&lt;string&gt;<xv>bar</xv>&lt;/string&gt;
&lt;/a&gt;
&lt;b&gt;
&lt;number&gt;<xv>123</xv>&lt;/number&gt;
&lt;number&gt;<xv>456</xv>&lt;/number&gt;
&lt;/b&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object&gt;
&lt;A&gt;<xv>foo</xv>&lt;/A&gt;
&lt;A&gt;<xv>bar</xv>&lt;/A&gt;
&lt;B&gt;<xv>123</xv>&lt;/B&gt;
&lt;B&gt;<xv>456</xv>&lt;/B&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#ELEMENTS"><code>XmlFormat.ELEMENTS</code></a> format can be applied to a single bean
property of either a simple type or array/Collection.
It allows free-form child elements to be formed.
All other properties on the bean MUST be serialized as attributes.
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>With annotation</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>ATTR</jsf>)
<jk>public</jk> String <jf>a</jf>;
<ja>@Xml</ja>(format=XmlFormat.<jsf>ELEMENTS</jsf>)
<jk>public</jk> String <jf>b</jf>;
}
</td>
<td class='code'>
{
a: <js>'foo'</js>,
b: <js>'bar'</js>
}
</td>
<td class='code'><xt>
&lt;object <xa>a</xa>=<xs>'foo'</xs>&gt;
&lt;string&gt;<xv>bar</xv>&lt;/string&gt;
&lt;/object&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>ATTR</jsf>)
<jk>public</jk> String <jf>a</jf>;
<ja>@Xml</ja>(format=XmlFormat.<jsf>ELEMENTS</jsf>)
<jk>public</jk> Object[] <jf>b</jf>;
}
</td>
<td class='code'>
{
a: <js>'foo'</js>,
b: [
<js>'bar'</js>,
<js>'baz'</js>,
123,
<jk>true</jk>,
<jk>null</jk>
]
}
</td>
<td class='code'><xt>
&lt;object <xa>a</xa>=<xs>'foo'</xs>&gt;
&lt;string&gt;<xv>bar</xv>&lt;/string&gt;
&lt;string&gt;<xv>baz</xv>&lt;/string&gt;
&lt;number&gt;<xv>123</xv>&lt;/number&gt;
&lt;boolean&gt;<xv>true</xv>&lt;/boolean&gt;
&lt;null/&gt;
&lt;/object&gt;
</xt></td>
</tr>
</table>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#MIXED"><code>XmlFormat.MIXED</code></a> format is similar to
<a href="org/apache/juneau/xml/annotation/XmlFormat.html#ELEMENTS"><code>XmlFormat.ELEMENTS</code></a> except elements names on primitive types
(string/number/boolean/null) are stripped from the output.
This format particularly useful when combined with bean dictionaries to produce mixed content.
The bean dictionary isn't used during serializationbut it is needed during parsing to resolve bean
types.
</p>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#MIXED_PWS"><code>XmlFormat.MIXED_PWS</code></a> format identical to
<a href="org/apache/juneau/xml/annotation/XmlFormat.html#MIXED"><code>XmlFormat.MIXED</code></a> except whitespace characters are preserved in
the output.
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>Without annotations</th>
<th>With annotations</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED</jsf>)
<ja>@Beanp</ja>(dictionary={MyBeanX.<jk>class</jk>, MyBeanY.<jk>class</jk>})
<jk>public</jk> Object[] <jf>a</jf>;
}
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBeanX {
<ja>@Xml</ja>(format=XmlFormat.<jsf>ATTR</jsf>)
<jk>public</jk> String <jf>b</jf>;
}
<ja>@Bean</ja>(typeName=<js>"Y"</js>)
<jk>class</jk> MyBeanY {
<ja>@Xml</ja>(format=XmlFormat.<jsf>ATTR</jsf>)
<jk>public</jk> String <jf>c</jf>;
}
</td>
<td class='code'>
{
a: [
<js>'foo'</js>,
{ _type:<js>'X'</js>, b:<js>'bar'</js> }
<js>'baz'</js>,
{ _type:<js>'Y'</js>, b:<js>'qux'</js> },
<js>'quux'</js>
]
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;
&lt;string&gt;<xv>foo</xv>&lt;/string&gt;
&lt;object&gt;
&lt;b&gt;<xv>bar</xv>&lt;/b&gt;
&lt;/object&gt;
&lt;string&gt;<xv>baz</xv>&lt;/string&gt;
&lt;object&gt;
&lt;b&gt;<xv>qux</xv>&lt;/b&gt;
&lt;/object&gt;
&lt;string&gt;<xv>quux</xv>&lt;/string&gt;
&lt;/a&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object&gt;<xv>foo</xv>&lt;X <xa>b</xa>=<xs>'bar'</xs>/&gt;<xv>baz</xv>&lt;Y <xa>c</xa>=<xs>'qux'</xs>/&gt;<xv>quux</xv>&lt;/object&gt;
</xt></td>
</tr>
</table>
<p>
Whitespace (tabs and newlines) are not added to MIXED child nodes in readable-output mode.
This helps ensures strings in the serialized output can be losslessly parsed back into their original
forms when they contain whitespace characters.
If the <a href="https://docs.oracle.com/javase/8/docs/api/javax/xml/stream/XMLInputFactory.html?is-external=true#IS_REPLACING_ENTITY_REFERENCES" title="class or interface in javax.xml.stream"><code>XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES</code></a> setting was not useless
in Java, we could support lossless readable XML for MIXED content.
But as of Java 8, it still does not work.
</p>
<p>
XML suffers from other deficiencies as well that affect MIXED content.
For example, <xt>&lt;X&gt;&lt;/X&gt;</xt> and <xt>&lt;X/&gt;</xt> are equivalent in XML and
indistinguishable by the Java XML parsers.
This makes it impossible to differentiate between an empty element and an element containing an empty
string.
This causes empty strings to get lost in translation.
To alleviate this, we use the constructs <js>"_xE000_"</js> to represent an empty string, and
<js>"_x0020_"</js> to represent leading and trailing spaces.
</p>
<p>
The examples below show how whitespace is handled under various circumstances:
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>XML</th>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT</jsf>)
<jk>public</jk> String <jf>a</jf> = <jk>null</jk>;
}
</td>
<td class='code'><xt>
&lt;X/&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT</jsf>)
<jk>public</jk> String <jf>a</jf> = <js>""</js>;
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_xE000_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT</jsf>)
<jk>public</jk> String <jf>a</jf> = <js>" "</js>;
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_x0020_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT</jsf>)
<jk>public</jk> String <jf>a</jf> = <js>" "</js>;
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_x0020__x0020_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT</jsf>)
<jk>public</jk> String <jf>a</jf> = <js>" foobar "</js>;
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_x0020_ foobar _x0020_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT_PWS</jsf>)
<jk>public</jk> String <jf>a</jf> = <jk>null</jk>;
}
</td>
<td class='code'><xt>
&lt;X/&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT_PWS</jsf>)
<jk>public</jk> String <jf>a</jf> = <js>""</js>;
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_xE000_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT_PWS</jsf>)
<jk>public</jk> String <jf>a</jf> = <js>" "</js>;
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv> </xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT_PWS</jsf>)
<jk>public</jk> String <jf>a</jf> = <js>" "</js>;
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv> </xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT_PWS</jsf>)
<jk>public</jk> String <jf>a</jf> = <js>" foobar "</js>;
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv> foobar </xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED</jsf>)
<jk>public</jk> String[] <jf>a</jf> = <jk>null</jk>;
}
</td>
<td class='code'><xt>
&lt;X/&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED</jsf>)
<jk>public</jk> String[] <jf>a</jf> = {<js>""</js>};
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_xE000_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED</jsf>)
<jk>public</jk> String[] <jf>a</jf> = {<js>" "</js>};
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_x0020_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED</jsf>)
<jk>public</jk> String[] <jf>a</jf> = {<js>" "</js>};
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_x0020__x0020_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED</jsf>)
<jk>public</jk> String[] <jf>a</jf> = {<js>" foobar "</js>};
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_x0020_ foobar _x0020_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED_PWS</jsf>)
<jk>public</jk> String[] <jf>a</jf> = <jk>null</jk>;
}
</td>
<td class='code'><xt>
&lt;X/&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED_PWS</jsf>)
<jk>public</jk> String[] <jf>a</jf> = {<js>""</js>};
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv>_xE000_</xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED_PWS</jsf>)
<jk>public</jk> String[] <jf>a</jf> = {<js>" "</js>};
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv> </xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED_PWS</jsf>)
<jk>public</jk> String[] <jf>a</jf> = {<js>" "</js>};
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv> </xv>&lt;/X&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<ja>@Bean</ja>(typeName=<js>"X"</js>)
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>MIXED_PWS</jsf>)
<jk>public</jk> String[] <jf>a</jf> = {<js>" foobar "</js>};
}
</td>
<td class='code'><xt>
&lt;X&gt;<xv> foobar </xv>&lt;/X&gt;
</xt></td>
</tr>
</table>
<p>
It should be noted that when using <jsf>MIXED</jsf>, you are not guaranteed to parse back the exact
same content since side-by-side strings in the content will end up concatenated when parsed.
</p>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#TEXT"><code>XmlFormat.TEXT</code></a> format is similar to
<a href="org/apache/juneau/xml/annotation/XmlFormat.html#MIXED"><code>XmlFormat.MIXED</code></a> except it's meant for solitary objects that
get serialized as simple child text nodes.
Any object that can be serialize to a <c>String</c> can be used.
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#TEXT_PWS"><code>XmlFormat.TEXT_PWS</code></a> is the same except whitespace is
preserved in the output.
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>Without annotations</th>
<th>With annotations</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>TEXT</jsf>)
<jk>public</jk> String <jf>a</jf>;
}
</td>
<td class='code'>
{
a: <js>'foo'</js>
}
</td>
<td class='code'><xt>
&lt;object&gt;
&lt;a&gt;<xv>foo</xv>&lt;/a&gt;
&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object&gt;<xv>foo</xv>&lt;/object&gt;
</xt></td>
</tr>
</table>
<p>
The <a href="org/apache/juneau/xml/annotation/XmlFormat.html#XMLTEXT"><code>XmlFormat.XMLTEXT</code></a> format is similar to
<a href="org/apache/juneau/xml/annotation/XmlFormat.html#TEXT"><code>XmlFormat.TEXT</code></a> except it's meant for strings containing XML
that should be serialized as-is to the document.
Any object that can be serialize to a <c>String</c> can be used.
During parsing, the element content gets parsed with the rest of the document and then re-serialized to
XML before being set as the property value.
This process may not be perfect (e.g. double quotes may be replaced by single quotes, etc...).
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>With TEXT annotation</th>
<th>With XMLTEXT annotation</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<ja>@Xml</ja>(format=XmlFormat.<jsf>XMLTEXT</jsf>)
<jk>public</jk> String <jf>a</jf>;
}
</td>
<td class='code'>
{
a: <js>'Some &lt;b&gt;XML&lt;/b&gt; text'</js>
}
</td>
<td class='code'><xt>
&lt;object&gt;<xv>Some &amp;lt;b&amp;gt;XML&amp;lt;/b&amp;gt; text</xv>&lt;/object&gt;
</xt></td>
<td class='code'><xt>
&lt;object&gt;<xv>Some <xt>&lt;b&gt;</xt>XML<xt>&lt;/b&gt;</xt> text</xv>&lt;/object&gt;
</xt></td>
</tr>
</table>
</div>
</div><!-- END: 2.26.6 - juneau-marshall.jm.XmlDetails.jm.XmlFormatAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.XmlDetails.jm.XmlNamespaces' id='juneau-marshall.jm.XmlDetails.jm.XmlNamespaces'>2.26.7 - Namespaces</a></h4>
<div class='topic'><!-- START: 2.26.7 - juneau-marshall.jm.XmlDetails.jm.XmlNamespaces -->
<div class='topic'>
<p>
Let's go back to the example of our original <c>Person</c> bean class but add some namespace annotations:
</p>
<h5 class='figure'>Sample Beans</h5>
<p class='bjava'>
<ja>@Xml</ja>(prefix=<js>"per"</js>)
<ja>@Bean</ja>(typeName=<js>"person"</js>)
<jk>public class</jk> Person {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>name</jf>;
<ja>@Swap</ja>(TemporalCalendarSwap.IsoInstant.<jk>class</jk>) <jk>public</jk> Calendar <jf>birthDate</jf>;
<jk>public</jk> List&lt;Address&gt; <jf>addresses</jf>;
<jc>// Getters/setters omitted</jc>
}
<ja>@Xml</ja>(prefix=<js>"addr"</js>)
<ja>@Bean</ja>(typeName=<js>"address"</js>)
<jk>public class</jk> Address {
<jc>// Bean properties</jc>
<ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public</jk> String <jf>street</jf>, <jf>city</jf>;
<ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public</jk> StateEnum <jf>state</jf>;
<ja>@Xml</ja>(prefix=<js>"mail"</js>) <jk>public int</jk> <jf>zip</jf>;
<jk>public boolean</jk> <jf>isCurrent</jf>;
<jc>// Getters/setters omitted</jc>
}
</p>
<p>
The namespace URLs can either be defined as part of the <a href="org/apache/juneau/xml/annotation/Xml.html" title="annotation in org.apache.juneau.xml.annotation"><code>@Xml</code></a>
annotation, or can be defined at the package level with the <a href="org/apache/juneau/xml/annotation/XmlSchema.html" title="annotation in org.apache.juneau.xml.annotation"><code>@XmlSchema</code></a>
annotation.
Below shows it defined at the package level:
</p>
<h5 class='figure'>package-info.java</h5>
<p class='bjava'>
<ja>@XmlSchema</ja>(
prefix=<js>"ab"</js>, <jc>// Default namespace</jc>
xmlNs={
<ja>@XmlNs</ja>(prefix=<js>"ab"</js>, namespaceURI=<js>"http://www.apache.org/addressBook/"</js>),
<ja>@XmlNs</ja>(prefix=<js>"per"</js>, namespaceURI=<js>"http://www.apache.org/person/"</js>),
<ja>@XmlNs</ja>(prefix=<js>"addr"</js>, namespaceURI=<js>"http://www.apache.org/address/"</js>),
<ja>@XmlNs</ja>(prefix=<js>"mail"</js>, namespaceURI=<js>"http://www.apache.org/mail/"</js>)
}
)
<jk>package</jk> org.apache.juneau.examples.addressbook;
</p>
<h5 class='figure'>Sample Code</h5>
<p class='bjava'>
Person <jv>person</jv> = <jk>new</jk> Person()
.name(<js>"John Smith"</js>)
.birthDate(<js>"1946-08-12T00:00:00Z"</js>)
.addresses(
<jk>new</jk> Address()
.street(<js>"100 Main Street"</js>)
.city(<js>"Anywhereville"</js>)
.state(<jsf>NY</jsf>)
.zip(12345)
.isCurrent(<jk>true</jk>);
);
<jc>// Create a new serializer with readable output, this time with namespaces enabled.</jc>
<jc>// Note that this is identical to XmlSerializer.DEFAULT_NS_SQ_READABLE.</jc>
XmlSerializer <jv>serializer</jv> = XmlSerializer.<jsm>create</jsm>().ns().ws().sq().build();
String <jv>xml</jv> = <jv>serializer</jv>.serialize(p);
</p>
<p>
Now when we run this code, we'll see namespaces added to our output:
</p>
<p class='bxml'>
<xt>&lt;per:person&gt;</xt>
<xt>&lt;per:name&gt;</xt>John Smith<xt>&lt;/per:name&gt;</xt>
<xt>&lt;per:birthDate&gt;</xt>1946-08-12T04:00:00Z<xt>&lt;/per:birthDate&gt;</xt>
<xt>&lt;per:addresses&gt;</xt>
<xt>&lt;addr:address&gt;</xt>
<xt>&lt;mail:street&gt;</xt>100 Main Street<xt>&lt;/mail:street&gt;</xt>
<xt>&lt;mail:city&gt;</xt>Anywhereville<xt>&lt;/mail:city&gt;</xt>
<xt>&lt;mail:state&gt;</xt>NY<xt>&lt;/mail:state&gt;</xt>
<xt>&lt;mail:zip&gt;</xt>12345<xt>&lt;/mail:zip&gt;</xt>
<xt>&lt;addr:isCurrent&gt;</xt>true<xt>&lt;/addr:isCurrent&gt;</xt>
<xt>&lt;/addr:address&gt;</xt>
<xt>&lt;/per:addresses&gt;</xt>
<xt>&lt;/per:person&gt;</xt>
</p>
<p>
Enabling the <dc>XmlSerializer.XML_addNamespaceUrisToRoot</dc> setting results
in the namespace URLs being added to the root node:
</p>
<p class='bxml'>
<xt>&lt;per:person</xt>
<xa>xmlns</xa>=<xs>'http://www.apache.org/2013/Juneau'</xs>
<xa>xmlns:per</xa>=<xs>'http://www.apache.org/person/'</xs>
<xa>xmlns:addr</xa>=<xs>'http://www.apache.org/address/'</xs>
<xa>xmlns:mail</xa>=<xs>'http://www.apache.org/mail/'</xs>
<xt>&gt;</xt>
<xt>&lt;per:name&gt;</xt>John Smith<xt>&lt;/per:name&gt;</xt>
<xt>&lt;per:birthDate&gt;</xt>1946-08-12T04:00:00Z<xt>&lt;/per:birthDate&gt;</xt>
<xt>&lt;per:addresses&gt;</xt>
<xt>&lt;addr:address&gt;</xt>
<xt>&lt;mail:street&gt;</xt>100 Main Street<xt>&lt;/mail:street&gt;</xt>
<xt>&lt;mail:city&gt;</xt>Anywhereville<xt>&lt;/mail:city&gt;</xt>
<xt>&lt;mail:state&gt;</xt>NY<xt>&lt;/mail:state&gt;</xt>
<xt>&lt;mail:zip&gt;</xt>12345<xt>&lt;/mail:zip&gt;</xt>
<xt>&lt;addr:isCurrent&gt;</xt>true<xt>&lt;/addr:isCurrent&gt;</xt>
<xt>&lt;/addr:address&gt;</xt>
<xt>&lt;/per:addresses&gt;</xt>
<xt>&lt;/per:person&gt;</xt>
</p>
<p>
We can simplify the output by setting the default namespace on the serializer so that all the elements do
not need to be prefixed:
</p>
<p class='bjava'>
<jc>// Create a new serializer with readable output, this time with namespaces enabled.</jc>
XmlSerializer <jv>serializer</jv> = XmlSerializer.<jsm>create</jsm>().ws().sq().ns()
.defaultNamespaceUri(<js>"http://www.apache.org/person/"</js>)
.build();
</p>
<p>
This produces the following equivalent where the elements don't need prefixes since they're already in the
default document namespace:
</p>
<p class='bxml'>
<xt>&lt;person</xt>
<xa>xmlns:juneau</xa>=<xs>'http://www.apache.org/2013/Juneau'</xs>
<xa>xmlns</xa>=<xs>'http://www.apache.org/person/'</xs>
<xa>xmlns:addr</xa>=<xs>'http://www.apache.org/address/'</xs>
<xa>xmlns:mail</xa>=<xs>'http://www.apache.org/mail/'</xs>
<xt>&gt;</xt>
<xt>&lt;name&gt;</xt>John Smith<xt>&lt;/name&gt;</xt>
<xt>&lt;birthDate&gt;</xt>1946-08-12T04:00:00Z<xt>&lt;/birthDate&gt;</xt>
<xt>&lt;addresses&gt;</xt>
<xt>&lt;addr:address&gt;</xt>
<xt>&lt;mail:street&gt;</xt>100 Main Street<xt>&lt;/mail:street&gt;</xt>
<xt>&lt;mail:city&gt;</xt>Anywhereville<xt>&lt;/mail:city&gt;</xt>
<xt>&lt;mail:state&gt;</xt>NY<xt>&lt;/mail:state&gt;</xt>
<xt>&lt;mail:zip&gt;</xt>12345<xt>&lt;/mail:zip&gt;</xt>
<xt>&lt;addr:isCurrent&gt;</xt>true<xt>&lt;/addr:isCurrent&gt;</xt>
<xt>&lt;/addr:address&gt;</xt>
<xt>&lt;/addresses&gt;</xt>
<xt>&lt;/person&gt;</xt>
</p>
<p>
By default, the XML serializer class will make a first-pass over the data structure to look for namespaces
defined on classes and bean properties.
In high-performance environments, you may want to consider disabling auto-detection and providing your
own explicit list of namespaces to the serializer to avoid this scanning step using
<a href="org/apache/juneau/xml/XmlSerializer.Builder.html#disableAutoDetectNamespaces--"><code>XmlSerializer.Builder.disableAutoDetectNamespaces()</code></a>.
</p>
<p>
The following code will produce the same output as before but will perform slightly better since it
avoids this pre-scan step.
</p>
<p class='bjava'>
<jc>// Create a new serializer with readable output, this time with namespaces enabled.</jc>
XmlSerializer <jv>serializer</jv> = XmlSerializer.<jsm>create</jsm>()
.ws()
.sq()
.autoDetectNamespaces(<jk>false</jk>)
.namespaces(<js>"{per:'http://www.apache.org/person/'}"</js>)
.build();
</p>
</div>
</div><!-- END: 2.26.7 - juneau-marshall.jm.XmlDetails.jm.XmlNamespaces -->
</div><!-- END: 2.26 - juneau-marshall.jm.XmlDetails -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlDetails' id='juneau-marshall.jm.HtmlDetails'>2.27 - HTML Details</a></h3>
<div class='topic'><!-- START: 2.27 - juneau-marshall.jm.HtmlDetails -->
<div class='topic'>
<p>
Juneau supports converting arbitrary POJOs to and from HTML.
Built on top of the existing XML parser, it also uses a STaX parser and creates POJOs directly without intermediate DOM objects.
</p>
<p>
The primary use case for HTML serialization is rendering POJOs in easy-to-read format in REST interfaces.
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlDetails.jm.HtmlMethodology' id='juneau-marshall.jm.HtmlDetails.jm.HtmlMethodology'>2.27.1 - HTML Methodology</a></h4>
<div class='topic'><!-- START: 2.27.1 - juneau-marshall.jm.HtmlDetails.jm.HtmlMethodology -->
<div class='topic'>
<p>
The following examples show how different data types are represented in HTML.
They mirror how the data structures are represented in JSON.
</p>
<h5 class='topic'>Simple types</h5>
<p>
The representation for simple types mirror those produced by the XML serializer.
Tags are added to help differentiate data types when they cannot be inferred through reflection.
These tags are ignored by browsers and treated as plain text.
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>HTML</th>
</tr>
<tr>
<td>string</td>
<td class='code'><js>'foo'</js></td>
<td class='code'><xt>&lt;string&gt;</xt>foo<xt>&lt;/string&gt;</xt></td>
</tr>
<tr>
<td>boolean</td>
<td class='code'><jk>true</jk></td>
<td class='code'><xt>&lt;boolean&gt;</xt>true<xt>&lt;/boolean&gt;</xt></td>
</tr>
<tr>
<td>integer</td>
<td class='code'>123</td>
<td class='code'><xt>&lt;number&gt;</xt>123<xt>&lt;/number&gt;</xt></td>
</tr>
<tr>
<td>float</td>
<td class='code'>1.23</td>
<td class='code'><xt>&lt;number&gt;</xt>1.23<xt>&lt;/number&gt;</xt></td>
</tr>
<tr>
<td>null</td>
<td class='code'><jk>null</jk></td>
<td class='code'><xt>&lt;null/&gt;</xt></td>
</tr>
</table>
<h5 class='topic'>Maps</h5>
<p>
Maps and beans are represented as tables.
</p>
<p>
The <xa>_type</xa> attribute is added to differentiate between objects (maps/beans) and arrays
(arrays/collections).
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>HTML</th>
</tr>
<tr>
<td class='code'>
Map&lt;String,String&gt;
</td>
<td class='code'>
{
k1: <js>'v1'</js>
k2: <jk>null</jk>
}
</td>
<td class='code'><xt>
&lt;table <xa>_type</xa>=<xs>'object'</xs>&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k1</xv>&lt;/td&gt;
&lt;td&gt;<xv>v1</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k2</xv>&lt;/td&gt;
&lt;td&gt;&lt;null/&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
Map&lt;String,Number&gt;
</td>
<td class='code'>
{
k1: 123,
k2: 1.23,
k3: <jk>null</jk>
}
</td>
<td class='code'><xt>
&lt;table <xa>_type</xa>=<xs>'object'</xs>&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k1</xv>&lt;/td&gt;
&lt;td&gt;<xv>123</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k2</xv>&lt;/td&gt;
&lt;td&gt;<xv>1.23</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k3</xv>&lt;/td&gt;
&lt;td&gt;&lt;null/&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
Map&lt;String,Object&gt;
</td>
<td class='code'>
{
k1: <js>'v1'</js>
k2: 123,
k3: 1.23,
k4: <jk>true</jk>,
k5: <jk>null</jk>
}
</td>
<td class='code'><xt>
&lt;table <xa>_type</xa>=<xs>'object'</xs>&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k1</xv>&lt;/td&gt;
&lt;td&gt;<xv>v1</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k2</xv>&lt;/td&gt;
&lt;td&gt;&lt;number&gt;<xv>123</xv>&lt;/number&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k3</xv>&lt;/td&gt;
&lt;td&gt;&lt;number&gt;<xv>1.23</xv>&lt;/number&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k4</xv>&lt;/td&gt;
&lt;td&gt;&lt;boolean&gt;<xv>true</xv>&lt;/boolean&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k5</xv>&lt;/td&gt;
&lt;td&gt;&lt;null/&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
</xt></td>
</tr>
</table>
<h5 class='topic'>Arrays</h5>
<p>
Collections and arrays are represented as ordered lists.
</p>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>HTML</th>
</tr>
<tr>
<td class='code'>
String[]
</td>
<td class='code'>
[
<js>'foo'</js>
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;ul&gt;
&lt;li&gt;<xv>foo</xv>&lt;/li&gt;
&lt;li&gt;&lt;null/&gt;&lt;/li&gt;
&lt;/ul&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
Number[]
</td>
<td class='code'>
[
123,
1.23,
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;ul&gt;
&lt;li&gt;<xv>123</xv>&lt;/li&gt;
&lt;li&gt;<xv>1.23</xv>&lt;/li&gt;
&lt;li&gt;&lt;null/&gt;&lt;/li&gt;
&lt;/ul&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
Object[]
</td>
<td class='code'>
[
<js>'foo'</js>,
123,
1.23,
<jk>true</jk>,
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;ul&gt;
&lt;li&gt;<xv>foo</xv>&lt;/li&gt;
&lt;li&gt;&lt;number&gt;<xv>123</xv>&lt;/number&gt;&lt;/li&gt;
&lt;li&gt;&lt;number&gt;<xv>1.23</xv>&lt;/number&gt;&lt;/li&gt;
&lt;li&gt;&lt;boolean&gt;<xv>true</xv>&lt;/boolean&gt;&lt;/li&gt;
&lt;li&gt;&lt;null/&gt;&lt;/li&gt;
&lt;/ul&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
String[][]
</td>
<td class='code'>
[
[<js>'foo'</js>, <jk>null</jk>],
<jk>null</jk>,
]
</td>
<td class='code'><xt>
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;<xv>foo</xv>&lt;/li&gt;
&lt;li&gt;&lt;null/&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;null/&gt;&lt;/li&gt;
&lt;/ul&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<jk>int</jk>[]
</td>
<td class='code'>
[
123
]
</td>
<td class='code'><xt>
&lt;ul&gt;
&lt;li&gt;<xv>123</xv>&lt;/li&gt;
&lt;/ul&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<jk>boolean</jk>[]
</td>
<td class='code'>
[
<jk>true</jk>
]
</td>
<td class='code'><xt>
&lt;ul&gt;
&lt;li&gt;<xv>true</xv>&lt;/li&gt;
&lt;/ul&gt;
</xt></td>
</tr>
</table>
<h5 class='topic'>Collections</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>HTML</th>
</tr>
<tr>
<td class='code'>
List&lt;String&gt;
</td>
<td class='code'>
[
<js>'foo'</js>
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;ul&gt;
&lt;li&gt;<xv>foo</xv>&lt;/li&gt;
&lt;li&gt;&lt;null/&gt;&lt;/li&gt;
&lt;/ul&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
List&lt;Number&gt;
</td>
<td class='code'>
[
123,
1.23,
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;ul&gt;
&lt;li&gt;<xv>123</xv>&lt;/li&gt;
&lt;li&gt;<xv>1.23</xv>&lt;/li&gt;
&lt;li&gt;&lt;null/&gt;&lt;/li&gt;
&lt;/ul&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
List&lt;Object&gt;
</td>
<td class='code'>
[
<js>'foo'</js>,
123,
1.23,
<jk>true</jk>,
<jk>null</jk>
]
</td>
<td class='code'><xt>
&lt;ul&gt;
&lt;li&gt;<xv>foo</xv>&lt;/li&gt;
&lt;li&gt;&lt;number&gt;<xv>123</xv>&lt;/number&gt;&lt;/li&gt;
&lt;li&gt;&lt;number&gt;<xv>1.23</xv>&lt;/number&gt;&lt;/li&gt;
&lt;li&gt;&lt;boolean&gt;<xv>true</xv>&lt;/boolean&gt;&lt;/li&gt;
&lt;li&gt;&lt;null/&gt;&lt;/li&gt;
&lt;/ul&gt;
</xt></td>
</tr>
</table>
<h5 class='topic'>Beans</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>HTML</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<jk>public</jk> String <jf>a</jf>;
<jk>public</jk> <jk>int</jk> <jf>b</jf>;
<jk>public</jk> Object <jf>c</jf>; <jc>// String value</jc>
<jk>public</jk> Object <jf>d</jf>; <jc>// Integer value</jc>
<jk>public</jk> MyBean2 <jf>e</jf>;
<jk>public</jk> String[] <jf>f</jf>;
<jk>public</jk> <jk>int</jk>[] <jf>g</jf>;
}
<jk>class</jk> MyBean2 {
String <jf>h</jf>;
}
</td>
<td class='code'>
{
<jok>a</jok>: <jov>'foo'</jov>,
<jok>b</jok>: <jov>123</jov>,
<jok>c</jok>: <jov>'bar'</jov>,
<jok>d</jok>: <jov>456</jov>,
<jok>e</jok>: {
<jok>h</jok>: <jov>'baz'</jov>
}
<jok>f</jok>: [<jov>'qux'</jov>]
<jok>g</jok>: [<jov>789</jov>]
}
</td>
<td class='code'><xt>
&lt;table <xa>_type</xa>=<xs>'object'</xs>&gt;
&lt;tr&gt;
&lt;td&gt;<xv>a</xv>&lt;/td&gt;
&lt;td&gt;<xv>foo</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>b</xv>&lt;/td&gt;
&lt;td&gt;<xv>123</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>c</xv>&lt;/td&gt;
&lt;td&gt;<xv>bar</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>d</xv>&lt;/td&gt;
&lt;td&gt;&lt;number&gt;<xv>456</xv>&lt;/number&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>e</xv>&lt;/td&gt;
&lt;td&gt;
&lt;table <xa>_type</xa>=<xs>'object'</xs>&gt;
&lt;tr&gt;
&lt;td&gt;<xv>h</xv>&lt;/td&gt;
&lt;td&gt;<xv>qux</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>f</xv>&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;<xv>baz</xv>&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>g</xv>&lt;/td&gt;
&lt;td&gt;
&lt;ul&gt;
&lt;li&gt;<xv>789</xv>&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
</xt></td>
</tr>
</table>
<h5 class='topic'>Beans with Map properties</h5>
<table class='styled w800'>
<tr>
<th>Data type</th>
<th>JSON example</th>
<th>HTML</th>
</tr>
<tr>
<td class='code'>
<jk>class</jk> MyBean {
<jk>public</jk> Map&lt;String,String&gt; <jf>a</jf>;
<jk>public</jk> Map&lt;String,Number&gt; <jf>b</jf>;
<jk>public</jk> Map&lt;String,Object&gt; <jf>c</jf>;
}
</td>
<td class='code'>
{
<jok>a</jok>: {
<jok>k1</jok>: <jov>'foo'</jov>
},
<jok>b</jok>: {
<jok>k2</jok>: <jov>123</jov>
},
<jok>c</jok>: {
<jok>k3</jok>: <jov>'bar'</jov>,
<jok>k4</jok>: <jov>456</jov>,
<jok>k5</jok>: <jov>true</jov>,
<jok>k6</jok>: <jov>null</jov>
}
}
</td>
<td class='code'><xt>
&lt;table <xa>_type</xa>=<xs>'object'</xs>&gt;
&lt;tr&gt;
&lt;td&gt;<xv>a</xv>&lt;/td&gt;
&lt;td&gt;
&lt;table _type='object'&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k1</xv>&lt;/td&gt;
&lt;td&gt;<xv>foo</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>b</xv>&lt;/td&gt;
&lt;td&gt;
&lt;table _type='object'&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k2</xv>&lt;/td&gt;
&lt;td&gt;<xv>123</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>c</xv>&lt;/td&gt;
&lt;td&gt;
&lt;table <xa>_type</xa>=<xs>'object'</xs>&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k3</xv>&lt;/td&gt;
&lt;td&gt;<xv>bar</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k4</xv>&lt;/td&gt;
&lt;td&gt;&lt;number&gt;<xv>456</xv>&lt;/number&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k5</xv>&lt;/td&gt;
&lt;td&gt;&lt;boolean&gt;<xv>true</xv>&lt;/boolean&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>k6</xv>&lt;/td&gt;
&lt;td&gt;&lt;null/&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
</xt></td>
</tr>
</table>
</div>
</div><!-- END: 2.27.1 - juneau-marshall.jm.HtmlDetails.jm.HtmlMethodology -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlDetails.jm.HtmlSerializers' id='juneau-marshall.jm.HtmlDetails.jm.HtmlSerializers'>2.27.2 - HTML Serializers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.27.2 - juneau-marshall.jm.HtmlDetails.jm.HtmlSerializers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a> class is used to serialize POJOs into HTML.
</p>
<p>
The <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a> class is the same but wraps the serialized POJO
inside a document template consisting of header, nav, aside, and footer sections.
</p>
<p>
The class hierarchy for the builder of this serializer is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanTraverseContext.Builder.html" title="class in org.apache.juneau"><code>BeanTraverseContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializer.Builder.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/xml/XmlSerializer.Builder.html" title="class in org.apache.juneau.xml"><code>XmlSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/html/HtmlSerializer.Builder.html" title="class in org.apache.juneau.html"><code>HtmlSerializer.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured serializers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/html/HtmlSerializer.html#DEFAULT"><code>HtmlSerializer.DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/html/HtmlSerializer.html#DEFAULT_SQ"><code>HtmlSerializer.DEFAULT_SQ</code></a>
<li class='jf'><a href="org/apache/juneau/html/HtmlSerializer.html#DEFAULT_SQ_READABLE"><code>HtmlSerializer.DEFAULT_SQ_READABLE</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/html/HtmlDocSerializer.html#DEFAULT"><code>HtmlDocSerializer.DEFAULT</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.27.2 - juneau-marshall.jm.HtmlDetails.jm.HtmlSerializers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlDetails.jm.HtmlParsers' id='juneau-marshall.jm.HtmlDetails.jm.HtmlParsers'>2.27.3 - HTML Parsers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.27.3 - juneau-marshall.jm.HtmlDetails.jm.HtmlParsers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/html/HtmlParser.html" title="class in org.apache.juneau.html"><code>HtmlParser</code></a> class is used to parse HTML into POJOs.
They can also parse the contents produced by <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a>.
</p>
<p>
The class hierarchy for the builder of this parser is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/Parser.Builder.html" title="class in org.apache.juneau.parser"><code>Parser.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/ReaderParser.Builder.html" title="class in org.apache.juneau.parser"><code>ReaderParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/html/HtmlParser.Builder.html" title="class in org.apache.juneau.html"><code>HtmlParser.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured parsers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/html/HtmlParser.html" title="class in org.apache.juneau.html"><code>HtmlParser</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/html/HtmlParser.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.27.3 - juneau-marshall.jm.HtmlDetails.jm.HtmlParsers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlDetails.jm.HtmlAnnotation' id='juneau-marshall.jm.HtmlDetails.jm.HtmlAnnotation'>2.27.4 - @Html Annotation</a></h4>
<div class='topic'><!-- START: 2.27.4 - juneau-marshall.jm.HtmlDetails.jm.HtmlAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/html/annotation/Html.html" title="annotation in org.apache.juneau.html.annotation"><code>@Html</code></a> annotation can be used to customize how POJOs are serialized to HTML on a per-class/field/method basis.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/html/annotation/Html.html" title="annotation in org.apache.juneau.html.annotation"><code>Html</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/html/annotation/Html.html#anchorText--"><code>anchorText</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/Html.html#format--"><code>format</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/Html.html#link--"><code>link</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/Html.html#noTableHeaders--"><code>noTableHeaders</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/Html.html#noTables--"><code>noTables</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/Html.html#render--"><code>render</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/html/annotation/Html.html#link--"><code>@Html(link)</code></a> annotation adds a hyperlink to a bean property when rendered as HTML.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>public class</jk> FileSpace {
<jc>// Add a hyperlink to this bean property.</jc>
<ja>@Html</ja>(link=<js>"servlet:/drive/{drive}"</js>)
<jk>public</jk> String getDrive() {...}
}
</p>
<p>
The <a href="org/apache/juneau/html/annotation/Html.html#anchorText--"><code>@Html(anchorText)</code></a> annotation is used to specify the anchor text of a hyperlink.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Produces &lt;a ...&gt;CLICK ME!&lt;/a&gt; when serialized to HTML.</jc>
<jk>public class</jk> FileSpace {
<jc>// Add a hyperlink to this bean property.</jc>
<ja>@Html</ja>(link=<js>"servlet:/drive/{drive}"</js>, anchorText=<js>"CLICK ME!"</js>)
<jk>public</jk> String getDrive() {...}
}
</p>
<p>
The <a href="org/apache/juneau/html/annotation/Html.html#format--"><code>@Html(format)</code></a> annotation is used to specify what format to use for HTML elements.
For example, the HTML beans defined in the <a href="org/apache/juneau/dto/html5/package-summary.html"><code>org.apache.juneau.dto.html5</code></a> package use <c>format=<jsf>XML</jsf></c> so that
the beans get serialized as standard XML:
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Parent class of all HTML DTO beans.</jc>
<ja>@Html</ja>(format=<jsf>XML</jsf>)
<jk>public abstract class</jk> HtmlElement {...}
</p>
<p>
The <a href="org/apache/juneau/html/annotation/Html.html#noTableHeaders--"><code>@Html(noTableHeaders)</code></a> annotation is used to prevent beans from being serialized with table headers.
</p>
<p>
The <a href="org/apache/juneau/html/annotation/Html.html#noTables--"><code>@Html(noTables)</code></a> annotation is used to force beans to be serialized as trees instead of tables
</p>
</div>
</div><!-- END: 2.27.4 - juneau-marshall.jm.HtmlDetails.jm.HtmlAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlDetails.jm.HtmlRenderAnnotation' id='juneau-marshall.jm.HtmlDetails.jm.HtmlRenderAnnotation'>2.27.5 - @Html(render) Annotation</a></h4>
<div class='topic'><!-- START: 2.27.5 - juneau-marshall.jm.HtmlDetails.jm.HtmlRenderAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/html/annotation/Html.html#render--"><code>@Html(render)</code></a> annotation allows for custom rendering of bean property values when serialized as HTML.
Using this class, you can alter the CSS style and HTML content of the bean property.
</p>
<p>
The following example shows two render classes that customize the appearance of the <c>pctFull</c> and
<c>status</c> columns in the code below:
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
<jc>// Our bean class</jc>
<jk>public class</jk> FileSpace {
<jk>private final</jk> String <jf>drive</jf>;
<jk>private final long</jk> <jf>total</jf>, <jf>available</jf>;
<jk>public</jk> FileSpace(String <jv>drive</jv>, <jk>long</jk> <jv>total</jv>, <jk>long</jk> <jv>available</jv>) {
<jk>this</jk>.<jf>drive</jf> = <jv>drive</jv>;
<jk>this</jk>.<jf>total</jf> = <jv>total</jv>;
<jk>this</jk>.<jf>available</jf> = <jv>available</jv>;
}
<ja>@Html</ja>(link=<js>"drive/{drive}"</js>)
<jk>public</jk> String getDrive() {
<jk>return</jk> <jf>drive</jf>;
}
<jk>public long</jk> getTotal() {
<jk>return</jk> <jf>total</jf>;
}
<jk>public long</jk> getAvailable() {
<jk>return</jk> <jf>available</jf>;
}
<ja>@Html</ja>(render=FileSpacePctRender.<jk>class</jk>)
<jk>public float</jk> getPctFull() {
<jk>return</jk> ((100 * <jf>available</jf>) / <jf>total</jf>);
}
<ja>@Html</ja>(render=FileSpaceStatusRender.<jk>class</jk>)
<jk>public</jk> FileSpaceStatus getStatus() {
<jk>float</jk> <jv>pf</jv> = getPctFull();
<jk>if</jk> (<jv>pf</jv> &lt; 80)
<jk>return</jk> FileSpaceStatus.<jsf>OK</jsf>;
<jk>if</jk> (<jv>pf</jv> &lt; 90)
<jk>return</jk> FileSpaceStatus.<jsf>WARNING</jsf>;
<jk>return</jk> FileSpaceStatus.<jsf>SEVERE</jsf>;
}
}
</p>
<p class='bjava'>
<jc>// Possible values for the getStatus() method</jc>
<jk>public enum</jk> FileSpaceStatus {
<jsf>OK</jsf>, <jsf>WARNING</jsf>, <jsf>SEVERE</jsf>;
}
</p>
<p class='bjava'>
<jc>// Custom render for getPctFull() method</jc>
<jk>public class</jk> FileSpacePctRender <jk>extends</jk> HtmlRender&lt;Float&gt; {
<ja>@Override</ja>
<jk>public</jk> String getStyle(SerializerSession <jv>session</jv>, Float <jv>value</jv>) {
<jk>if</jk> (<jv>value</jv> &lt; 80)
<jk>return</jk> <js>"background-color:lightgreen;text-align:center"</js>;
<jk>if</jk> (<jv>value</jv> &lt; 90)
<jk>return</jk> <js>"background-color:yellow;text-align:center"</js>;
<jk>return</jk> <js>"background-color:red;text-align:center;border:;animation:color_change 0.5s infinite alternate"</js>;
}
<ja>@Override</ja>
<jk>public</jk> Object getContent(SerializerSession <jv>session</jv>, Float <jv>value</jv>) {
<jk>if</jk> (<jv>value</jv> >= 90)
<jk>return</jk> <jsm>div</jsm>(
String.<jsm>format</jsm>(<js>"%.0f%%"</js>, <jv>value</jv>),
<jsm>style</jsm>(<js>"@keyframes color_change { from { background-color: red; } to { background-color: yellow; }"</js>)
);
<jk>return</jk> String.<jsm>format</jsm>(<js>"%.0f%%"</js>, <jv>value</jv>);
}
}
</p>
<p class='bjava'>
<jc>// Custom render for getStatus() method</jc>
<jk>public class</jk> FileSpaceStatusRender <jk>extends</jk> HtmlRender&lt;FileSpaceStatus&gt; {
<ja>@Override</ja>
<jk>public</jk> String getStyle(SerializerSession <jv>session</jv>, FileSpaceStatus <jv>value</jv>) {
<jk>return</jk> <js>"text-align:center"</js>;
}
<ja>@Override</ja>
<jk>public</jk> Object getContent(SerializerSession <jv>session</jv>, FileSpaceStatus <jv>value</jv>) {
<jk>switch</jk> (<jv>value</jv>) {
<jk>case</jk> <jsf>OK</jsf>: <jk>return</jk> <jsm>img</jsm>().src(URI.<jsm>create</jsm>(<js>"servlet:/htdocs/ok.png"</js>));
<jk>case</jk> <jsf>WARNING</jsf>: <jk>return</jk> <jsm>img</jsm>().src(URI.<jsm>create</jsm>(<js>"servlet:/htdocs/warning.png"</js>));
<jk>default</jk>: <jk>return</jk> <jsm>img</jsm>().src(URI.<jsm>create</jsm>(<js>"servlet:/htdocs/severe.png"</js>));
}
}
}
</p>
</div>
</div><!-- END: 2.27.5 - juneau-marshall.jm.HtmlDetails.jm.HtmlRenderAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlDetails.jm.HtmlDocSerializer' id='juneau-marshall.jm.HtmlDetails.jm.HtmlDocSerializer'>2.27.6 - HtmlDocSerializer</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.27.6 - juneau-marshall.jm.HtmlDetails.jm.HtmlDocSerializer -->
<div class='topic'>
<p>
<a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a> is an extension of <a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a>
that wraps serialized POJOs in a complete HTML document.
</p>
<p>
The class hierarchy for the builder of this serializer is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanTraverseContext.Builder.html" title="class in org.apache.juneau"><code>BeanTraverseContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializer.Builder.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/xml/XmlSerializer.Builder.html" title="class in org.apache.juneau.xml"><code>XmlSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/html/HtmlSerializer.Builder.html" title="class in org.apache.juneau.html"><code>HtmlSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/html/HtmlStrippedDocSerializer.Builder.html" title="class in org.apache.juneau.html"><code>HtmlStrippedDocSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/html/HtmlDocSerializer.Builder.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
This class is used extensively in the creation of POJO-based user interfaces in the REST API.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jd>/**
* Sample REST resource that prints out a simple "Hello world!" message.
*/</jd>
<ja>@Rest</ja>(path=<js>"/helloWorld"</js>)
<ja>@HtmlDocConfig</ja>(
navlinks={
<js>"up: request:/.."</js>,
<js>"options: servlet:/?method=OPTIONS"</js>
},
aside={
<js>"&lt;div style='max-width:400px' class='text'&gt;"</js>,
<js>" &lt;p&gt;This page shows a resource that simply response with a 'Hello world!' message&lt;/p&gt;"</js>,
<js>" &lt;p&gt;The POJO serialized is a simple String.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
The <a href="org/apache/juneau/html/HtmlDocSerializer.Builder.html#template-java.lang.Class-"><code>HtmlDocSerializer.Builder.template(Class)</code></a> setting defines
a template for the HTML page being generated.
The default template is described next.
</p>
</div>
</div><!-- END: 2.27.6 - juneau-marshall.jm.HtmlDetails.jm.HtmlDocSerializer -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlDetails.jm.BasicHtmlDocTemplate' id='juneau-marshall.jm.HtmlDetails.jm.BasicHtmlDocTemplate'>2.27.7 - BasicHtmlDocTemplate</a></h4>
<div class='topic'><!-- START: 2.27.7 - juneau-marshall.jm.HtmlDetails.jm.BasicHtmlDocTemplate -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/html/BasicHtmlDocTemplate.html" title="class in org.apache.juneau.html"><code>BasicHtmlDocTemplate</code></a> class defines a default template for HTML documents
created by <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a>.
</p>
<p>
The HTML document created by this template consists of the following structure:
</p>
<p class='bxml'>
<xt>&lt;html&gt;
&lt;head&gt;
&lt;style <xa>type</xa>=<xs>'text/css'</xs>&gt;
<xv>CSS styles and links to stylesheets</xv>
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header&gt;
<xv>Page header</xv>
&lt;/header&gt;
&lt;nav&gt;
<xv>Navigation links</xv>
&lt;/nav&gt;
&lt;aside&gt;
<xv>Side-bar text</xv>
&lt;/aside&gt;
&lt;article&gt;
<xv>Contents of serialized object</xv>
&lt;/article&gt;
&lt;footer&gt;
<xv>Footer message</xv>
&lt;/footer&gt;
&lt;/body&gt;
&lt;/html&gt;</xt>
</p>
</div>
</div><!-- END: 2.27.7 - juneau-marshall.jm.HtmlDetails.jm.BasicHtmlDocTemplate -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlDetails.jm.HtmlCustomTemplates' id='juneau-marshall.jm.HtmlDetails.jm.HtmlCustomTemplates'>2.27.8 - Custom Templates</a></h4>
<div class='topic'><!-- START: 2.27.8 - juneau-marshall.jm.HtmlDetails.jm.HtmlCustomTemplates -->
<div class='topic'>
<p>
Custom page templates can be created by implementing the <a href="org/apache/juneau/html/HtmlDocTemplate.html" title="interface in org.apache.juneau.html"><code>HtmlDocTemplate</code></a>
interface and associating it with your <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a> using the <a href="org/apache/juneau/html/HtmlDocSerializer.Builder.html#template-java.lang.Class-"><code>HtmlDocSerializer.Builder.template(Class)</code></a>
setting.
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/html/HtmlDocTemplate.html" title="interface in org.apache.juneau.html"><code>HtmlDocTemplate</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/html/HtmlDocTemplate.html#writeTo-org.apache.juneau.html.HtmlDocSerializerSession-org.apache.juneau.html.HtmlWriter-java.lang.Object-"><code>writeTo(HtmlDocSerializerSession,HtmlWriter,Object)</code></a>
</ul>
</li>
</ul>
<p>
The interface implementation is open-ended allowing you to define the contents of the page any way you wish.
</p>
</div>
</div><!-- END: 2.27.8 - juneau-marshall.jm.HtmlDetails.jm.HtmlCustomTemplates -->
</div><!-- END: 2.27 - juneau-marshall.jm.HtmlDetails -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.HtmlSchema' id='juneau-marshall.jm.HtmlSchema'>2.28 - HTML-Schema Support</a></h3>
<div class='topic'><!-- START: 2.28 - juneau-marshall.jm.HtmlSchema -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/html/HtmlSchemaSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSchemaSerializer</code></a> class is the HTML-equivalent to the
<a href="org/apache/juneau/json/JsonSchemaSerializer.html" title="class in org.apache.juneau.json"><code>JsonSchemaSerializer</code></a> class.
It's used to generate HTML versions of JSON-Schema documents that describe the output generated by the
<a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a> class.
</p>
<h5 class='figure'>Sample Beans</h5>
<p class='bjava'>
<jk>public class</jk> Person {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>name</jf>;
<jk>public</jk> Calendar <jf>birthDate</jf>;
<jk>public</jk> List&lt;Address&gt; <jf>addresses</jf>;
<jc>// Getters/setters omitted</jc>
}
<jk>public class</jk> Address {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>street</jf>, <jf>city</jf>;
<jk>public</jk> StateEnum <jf>state</jf>;
<jk>public int</jk> <jf>zip</jf>;
<jk>public boolean</jk> <jf>isCurrent</jf>;
<jc>// Getters/setters omitted</jc>
}
</p>
<p>
The code for creating our POJO model and generating HTML-Schema is shown below:
</p>
<p class='bjava'>
<jc>// Get the one of the default schema serializers.</jc>
HtmlSchemaSerializer <jv>serializer</jv> = HtmlSchemaSerializer.<jsf>DEFAULT_SIMPLE_READABLE</jsf>;
<jc>// Get the HTML Schema for the POJO.</jc>
String <jv>htmlSchema</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> Person());
<jc>// This also works.</jc>
<jv>htmlSchema</jv> = <jv>serializer</jv>.serialize(Person.<jk>class</jk>);
</p>
<p>
The result is the HTML table shown below:
</p>
<table class='bordered unstyled w800'>
<tr>
<td>type</td>
<td>object</td>
</tr>
<tr>
<td>properties</td>
<td>
<table>
<tr>
<td>name</td>
<td>
<table>
<tr>
<td>type</td>
<td>string</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>birthDate</td>
<td>
<table>
<tr>
<td>type</td>
<td>string</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>addresses</td>
<td>
<table>
<tr>
<td>type</td>
<td>array</td>
</tr>
<tr>
<td>items</td>
<td>
<table>
<tr>
<td>type</td>
<td>object</td>
</tr>
<tr>
<td>properties</td>
<td>
<table>
<tr>
<td>street</td>
<td>
<table>
<tr>
<td>type</td>
<td>string</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>city</td>
<td>
<table>
<tr>
<td>type</td>
<td>string</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>state</td>
<td>
<table>
<tr>
<td>type</td>
<td>string</td>
</tr>
<tr>
<td>enum</td>
<td>
<ul>
<li>AL</li>
<li>PA</li>
<li>NC</li>
</ul>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>zip</td>
<td>
<table>
<tr>
<td>type</td>
<td>integer</td>
</tr>
<tr>
<td>format</td>
<td>int32</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>isCurrent</td>
<td>
<table>
<tr>
<td>type</td>
<td>boolean</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div><!-- END: 2.28 - juneau-marshall.jm.HtmlSchema -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.UonDetails' id='juneau-marshall.jm.UonDetails'>2.29 - UON Details</a></h3>
<div class='topic'><!-- START: 2.29 - juneau-marshall.jm.UonDetails -->
<div class='topic'>
<p>
Juneau supports converting arbitrary POJOs to and from UON strings using ultra-efficient serializers
and parsers.
The serializer converts POJOs directly to UON strings without the need for intermediate DOM objects
using a highly-efficient state machine.
Likewise, the parser creates POJOs directly from UON strings without the need for intermediate DOM
objects.
</p>
<p>
Juneau uses UON (URL-Encoded Object Notation) for representing POJOs.
The UON specification can be found <a href='doc-files/rfc_uon.txt'>here</a>.
</p>
<p>
The following example shows JSON for a typical bean:
</p>
<h5 class='figure'>Sample Beans</h5>
<p class='bjava'>
<jk>public class</jk> Person {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>name</jf>;
<ja>@Swap</ja>(TemporalCalendarSwap.IsoInstant.<jk>class</jk>) <jk>public</jk> Calendar <jf>birthDate</jf>;
<jk>public</jk> List&lt;Address&gt; <jf>addresses</jf>;
<jc>// Getters/setters omitted</jc>
}
<jk>public class</jk> Address {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>street</jf>, <jf>city</jf>;
<jk>public</jk> StateEnum <jf>state</jf>;
<jk>public int</jk> <jf>zip</jf>;
<jk>public boolean</jk> <jf>isCurrent</jf>;
<jc>// Getters/setters omitted</jc>
}
</p>
<h5 class='figure'>Sample Code</h5>
<p class='bjava'>
Person <jv>person</jv> = <jk>new</jk> Person()
.name(<js>"John Smith"</js>)
.birthDate(<js>"1946-08-12T00:00:00Z"</js>)
.addresses(
<jk>new</jk> Address()
.street(<js>"100 Main Street"</js>)
.city(<js>"Anywhereville"</js>)
.state(<jsf>NY</jsf>)
.zip(12345)
.isCurrent(<jk>true</jk>);
);
</p>
<h5 class='figure'>UON</h5>
<p class='buon'>
(
<ua>name</ua>=<us>'John+Smith'</us>,
<ua>birthDate</ua>=<us>'1946-08-12T00:00:00Z'</us>,
<ua>addresses</ua>=@(
(
<ua>street</ua>=<us>'100 Main Street'</us>,
<ua>city</ua>=<us>Anywhereville</us>,
<ua>state</ua>=<us>NY</us>,
<ua>zip</ua>=<un>12345</un>,
<ua>isCurrent</ua>=<uk>true</uk>
)
)
)
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.UonDetails.jm.UonMethodology' id='juneau-marshall.jm.UonDetails.jm.UonMethodology'>2.29.1 - UON Methodology</a></h4>
<div class='topic'><!-- START: 2.29.1 - juneau-marshall.jm.UonDetails.jm.UonMethodology -->
<div class='topic'>
<h5 class='figure'>General methodology:</h5>
<table class='styled w800' style='border-collapse:collapse'>
<tr><th>Java type</th><th>JSON equivalent</th><th>UON</th></tr>
<tr>
<td>Maps/beans</td>
<td>OBJECT</td>
<td class='code'>
<ua>a1</ua>=(<ua>b1</ua>=<us>x1</us>,<ua>b2</ua>=<us>x2</us>)
<ua>a1</ua>=(<ua>b1</ua>=(<ua>c1</ua>=<us>x1</us>,<ua>c2</ua>=<us>x2</us>))
</td>
</tr>
<tr>
<td>Collections/arrays</td>
<td>ARRAY</td>
<td class='code'>
<ua>a1</ua>=@(<us>x1</us>,<us>x2</us>)
<ua>a1</ua>=@(@(<us>x1</us>,<us>x2</us>),@(<us>x3</us>,<us>x4</us>))
<ua>a1</ua>=@((<ua>b1</ua>=<us>x1</us>,<ua>b2</ua>=<us>x2</us>),(<ua>c1</ua>=<us>x1</us>,<ua>c2</ua>=<us>x2</us>))
</td>
</tr>
<tr>
<td>Booleans</td>
<td>BOOLEAN</td>
<td class='code'>
<ua>a1</ua>=<uk>true</uk>&amp;<ua>a2</ua>=<uk>false</uk>
</td>
</tr>
<tr>
<td>int/float/double/...</td>
<td>NUMBER</td>
<td class='code'>
<ua>a1</ua>=<un>123</un>&amp;<ua>a2</ua>=<un>1.23e1</un>
</td>
</tr>
<tr>
<td>null</td>
<td>NULL</td>
<td class='code'>
<ua>a1</ua>=<uk>null</uk>
</td>
</tr>
<tr>
<td>String</td>
<td>STRING</td>
<td class='code'>
<ua>a1</ua>=<us>foobar</us>
<ua>a1</ua>=<us>'true'</us>
<ua>a1</ua>=<us>'null'</us>
<ua>a1</ua>=<us>'123'</us>
<ua>a1</ua>=<us>' string with whitespace '</us>
<ua>a1</ua>=<us>'string with ~'escaped~' quotes'</us>
</td>
</tr>
</table>
<p>
Refer to the <a href='doc-files/rfc_uon.txt'>UON specification</a> for a complete set of syntax rules.
</p>
</div>
</div><!-- END: 2.29.1 - juneau-marshall.jm.UonDetails.jm.UonMethodology -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.UonDetails.jm.UonSerializers' id='juneau-marshall.jm.UonDetails.jm.UonSerializers'>2.29.2 - UON Serializers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.29.2 - juneau-marshall.jm.UonDetails.jm.UonSerializers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a> class is used to serialize POJOs into UON.
</p>
<p>
The class hierarchy for the builder of this serializer is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanTraverseContext.Builder.html" title="class in org.apache.juneau"><code>BeanTraverseContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializer.Builder.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/uon/UonSerializer.Builder.html" title="class in org.apache.juneau.uon"><code>UonSerializer.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured serializers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/uon/UonSerializer.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/uon/UonSerializer.html#DEFAULT_ENCODING"><code>DEFAULT_ENCODING</code></a>
<li class='jf'><a href="org/apache/juneau/uon/UonSerializer.html#DEFAULT_READABLE"><code>DEFAULT_READABLE</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.29.2 - juneau-marshall.jm.UonDetails.jm.UonSerializers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.UonDetails.jm.UonParsers' id='juneau-marshall.jm.UonDetails.jm.UonParsers'>2.29.3 - UON Parsers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.29.3 - juneau-marshall.jm.UonDetails.jm.UonParsers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a> class is used to parse UON into POJOs.
</p>
<p>
The class hierarchy for the builder of this parser is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/Parser.Builder.html" title="class in org.apache.juneau.parser"><code>Parser.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/ReaderParser.Builder.html" title="class in org.apache.juneau.parser"><code>ReaderParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/uon/UonParser.Builder.html" title="class in org.apache.juneau.uon"><code>UonParser.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured parsers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/uon/UonParser.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/uon/UonParser.html#DEFAULT_DECODING"><code>DEFAULT_DECODING</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.29.3 - juneau-marshall.jm.UonDetails.jm.UonParsers -->
</div><!-- END: 2.29 - juneau-marshall.jm.UonDetails -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.UrlEncodingDetails' id='juneau-marshall.jm.UrlEncodingDetails'>2.30 - URL-Encoding Details</a></h3>
<div class='topic'><!-- START: 2.30 - juneau-marshall.jm.UrlEncodingDetails -->
<div class='topic'>
<p>
Juneau supports converting arbitrary POJOs to and from URL-encoded strings using ultra-efficient serializers
and parsers.
The serializer converts POJOs directly to URL-encoded strings without the need for intermediate DOM objects
using a highly-efficient state machine.
Likewise, the parser creates POJOs directly from URL-encoded strings without the need for intermediate DOM
objects.
</p>
<p>
Juneau uses UON (URL-Encoded Object Notation) for representing POJOs as URL-Encoded values in key-value pairs.
The UON specification can be found <a href='doc-files/rfc_uon.txt'>here</a>.
</p>
<p>
The following example shows JSON for a typical bean:
</p>
<h5 class='figure'>Sample Beans</h5>
<p class='bjava'>
<jk>public class</jk> Person {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>name</jf>;
<ja>@Swap</ja>(TemporalCalendarSwap.IsoInstant.<jk>class</jk>) <jk>public</jk> Calendar <jf>birthDate</jf>;
<jk>public</jk> List&lt;Address&gt; <jf>addresses</jf>;
<jc>// Getters/setters omitted</jc>
}
<jk>public class</jk> Address {
<jc>// Bean properties</jc>
<jk>public</jk> String <jf>street</jf>, <jf>city</jf>;
<jk>public</jk> StateEnum <jf>state</jf>;
<jk>public int</jk> <jf>zip</jf>;
<jk>public boolean</jk> <jf>isCurrent</jf>;
<jc>// Getters/setters omitted</jc>
}
</p>
<h5 class='figure'>Sample Code</h5>
<p class='bjava'>
Person <jv>person</jv> = <jk>new</jk> Person()
.name(<js>"John Smith"</js>)
.birthDate(<js>"1946-08-12T00:00:00Z"</js>)
.addresses(
<jk>new</jk> Address()
.street(<js>"100 Main Street"</js>)
.city(<js>"Anywhereville"</js>)
.state(<jsf>NY</jsf>)
.zip(12345)
.isCurrent(<jk>true</jk>);
);
</p>
<h5 class='figure'>URL-Encoding</h5>
<p class='burlenc'>
<ua>name</ua>=<us>'John+Smith'</us>
&amp;<ua>birthDate</ua>=<us>'1946-08-12T00:00:00Z'</us>
&amp;<ua>addresses</ua>=@(
(
<ua>street</ua>=<us>'100 Main Street'</us>,
<ua>city</ua>=<us>Anywhereville</us>,
<ua>state</ua>=<us>NY</us>,
<ua>zip</ua>=<un>12345</un>,
<ua>isCurrent</ua>=<uk>true</uk>
)
)
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncMethodology' id='juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncMethodology'>2.30.1 - URL-Encoding Methodology</a></h4>
<div class='topic'><!-- START: 2.30.1 - juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncMethodology -->
<div class='topic'>
<h5 class='figure'>General methodology:</h5>
<table class='styled w800' style='border-collapse:collapse'>
<tr><th>Java type</th><th>JSON equivalent</th><th>UON</th></tr>
<tr>
<td>Maps/beans</td>
<td>OBJECT</td>
<td class='code'>
<ua>a1</ua>=(<ua>b1</ua>=<us>x1</us>,<ua>b2</ua>=<us>x2</us>)
<ua>a1</ua>=(<ua>b1</ua>=(<ua>c1</ua>=<us>x1</us>,<ua>c2</ua>=<us>x2</us>))
</td>
</tr>
<tr>
<td>Collections/arrays</td>
<td>ARRAY</td>
<td class='code'>
<ua>a1</ua>=@(<us>x1</us>,<us>x2</us>)
<ua>a1</ua>=@(@(<us>x1</us>,<us>x2</us>),@(<us>x3</us>,<us>x4</us>))
<ua>a1</ua>=@((<ua>b1</ua>=<us>x1</us>,<ua>b2</ua>=<us>x2</us>),(<ua>c1</ua>=<us>x1</us>,<ua>c2</ua>=<us>x2</us>))
</td>
</tr>
<tr>
<td>Booleans</td>
<td>BOOLEAN</td>
<td class='code'>
<ua>a1</ua>=<uk>true</uk>&amp;<ua>a2</ua>=<uk>false</uk>
</td>
</tr>
<tr>
<td>int/float/double/...</td>
<td>NUMBER</td>
<td class='code'>
<ua>a1</ua>=<un>123</un>&amp;<ua>a2</ua>=<un>1.23e1</un>
</td>
</tr>
<tr>
<td>null</td>
<td>NULL</td>
<td class='code'>
<ua>a1</ua>=<uk>null</uk>
</td>
</tr>
<tr>
<td>String</td>
<td>STRING</td>
<td class='code'>
<ua>a1</ua>=<us>foobar</us>
<ua>a1</ua>=<us>'true'</us>
<ua>a1</ua>=<us>'null'</us>
<ua>a1</ua>=<us>'123'</us>
<ua>a1</ua>=<us>' string with whitespace '</us>
<ua>a1</ua>=<us>'string with ~'escaped~' quotes'</us>
</td>
</tr>
</table>
<p>
Refer to the <a href='doc-files/rfc_uon.txt'>UON specification</a> for a complete set of syntax rules.
</p>
</div>
</div><!-- END: 2.30.1 - juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncMethodology -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncSerializers' id='juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncSerializers'>2.30.2 - URL-Encoding Serializers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.30.2 - juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncSerializers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a> class is used to serialize POJOs into URL-Encoding.
</p>
<p>
The class hierarchy for the builder of this serializer is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanTraverseContext.Builder.html" title="class in org.apache.juneau"><code>BeanTraverseContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializer.Builder.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/uon/UonSerializer.Builder.html" title="class in org.apache.juneau.uon"><code>UonSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.Builder.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured serializers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html#DEFAULT"><code>DEFAULT</code></a>
<li class='jf'><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html#DEFAULT_EXPANDED"><code>DEFAULT_EXPANDED</code></a>
<li class='jf'><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html#DEFAULT_PLAINTEXT"><code>DEFAULT_PLAINTEXT</code></a>
<li class='jf'><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html#DEFAULT_READABLE"><code>DEFAULT_READABLE</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.30.2 - juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncSerializers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncParsers' id='juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncParsers'>2.30.3 - URL-Encoding Parsers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.30.3 - juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncParsers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a> class is used to parse URL-Encoding into POJOs.
</p>
<p>
The class hierarchy for the builder of this parser is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/Parser.Builder.html" title="class in org.apache.juneau.parser"><code>Parser.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/ReaderParser.Builder.html" title="class in org.apache.juneau.parser"><code>ReaderParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/uon/UonParser.Builder.html" title="class in org.apache.juneau.uon"><code>UonParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingParser.Builder.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured parsers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/urlencoding/UrlEncodingParser.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.30.3 - juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncParsers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncodingAnnotation' id='juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncodingAnnotation'>2.30.4 - @UrlEncoding Annotation</a></h4>
<div class='topic'><!-- START: 2.30.4 - juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncodingAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/urlencoding/annotation/UrlEncoding.html" title="annotation in org.apache.juneau.urlencoding.annotation"><code>@UrlEncoding</code></a> annotation
is used to override the behavior of <a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a> on individual bean classes or properties.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/urlencoding/annotation/UrlEncoding.html" title="annotation in org.apache.juneau.urlencoding.annotation"><code>UrlEncoding</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/urlencoding/annotation/UrlEncoding.html#expandedParams--"><code>expandedParams</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/urlencoding/annotation/UrlEncoding.html#expandedParams--"><code>expandedParams</code></a> setting is
used to force bean properties of type array or Collection to be expanded into multiple key/value pairings.
</p>
</div>
</div><!-- END: 2.30.4 - juneau-marshall.jm.UrlEncodingDetails.jm.UrlEncodingAnnotation -->
</div><!-- END: 2.30 - juneau-marshall.jm.UrlEncodingDetails -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.MsgPackDetails' id='juneau-marshall.jm.MsgPackDetails'>2.31 - MessagePack Details</a></h3>
<div class='topic'><!-- START: 2.31 - juneau-marshall.jm.MsgPackDetails -->
<div class='topic'>
<p>
Juneau supports converting arbitrary POJOs to and from MessagePack using ultra-efficient serializers
and parsers.
</p>
<p>
MessagePack is a compact binary form of JSON.
The serialization support for MessagePack mirrors that of JSON.
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.MsgPackDetails.jm.MsgPackSerializers' id='juneau-marshall.jm.MsgPackDetails.jm.MsgPackSerializers'>2.31.1 - MessagePack Serializers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.31.1 - juneau-marshall.jm.MsgPackDetails.jm.MsgPackSerializers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/msgpack/MsgPackSerializer.html" title="class in org.apache.juneau.msgpack"><code>MsgPackSerializer</code></a> class is used to serialize POJOs into MessagePack.
</p>
<p>
The class hierarchy for the builder of this serializer is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanTraverseContext.Builder.html" title="class in org.apache.juneau"><code>BeanTraverseContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/OutputStreamSerializer.Builder.html" title="class in org.apache.juneau.serializer"><code>OutputStreamSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/msgpack/MsgPackSerializer.Builder.html" title="class in org.apache.juneau.msgpack"><code>MsgPackSerializer.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured serializers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/msgpack/MsgPackSerializer.html" title="class in org.apache.juneau.msgpack"><code>MsgPackSerializer</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/msgpack/MsgPackSerializer.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.31.1 - juneau-marshall.jm.MsgPackDetails.jm.MsgPackSerializers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.MsgPackDetails.jm.MsgPackParsers' id='juneau-marshall.jm.MsgPackDetails.jm.MsgPackParsers'>2.31.2 - MessagePack Parsers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.31.2 - juneau-marshall.jm.MsgPackDetails.jm.MsgPackParsers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/msgpack/MsgPackParser.html" title="class in org.apache.juneau.msgpack"><code>MsgPackParser</code></a> class is used to parse MessagePack into POJOs.
</p>
<p>
The class hierarchy for the builder of this parser is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/Parser.Builder.html" title="class in org.apache.juneau.parser"><code>Parser.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/InputStreamParser.Builder.html" title="class in org.apache.juneau.parser"><code>InputStreamParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/msgpack/MsgPackParser.Builder.html" title="class in org.apache.juneau.msgpack"><code>MsgPackParser.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured parsers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/msgpack/MsgPackParser.html" title="class in org.apache.juneau.msgpack"><code>MsgPackParser</code></a>
<ul class='javatreec'>
<li class='jf'><a href="org/apache/juneau/msgpack/MsgPackParser.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 2.31.2 - juneau-marshall.jm.MsgPackDetails.jm.MsgPackParsers -->
</div><!-- END: 2.31 - juneau-marshall.jm.MsgPackDetails -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.OpenApiDetails' id='juneau-marshall.jm.OpenApiDetails'>2.32 - OpenAPI Details</a><span class='update'>updated: 8.2.0</span></h3>
<div class='topic'><!-- START: 2.32 - juneau-marshall.jm.OpenApiDetails -->
<div class='topic'>
<p>
Juneau supports converting arbitrary POJOs to and from strings using OpenAPI-based schema rules.
</p>
<p>
The relevant classes for using OpenAPI-based serialization are:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> - Converts POJOs to strings.
<li class='jc'><a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a> - Converts strings to POJOs.
<li class='jc'><a href="org/apache/juneau/httppart/HttpPartSchema.html" title="class in org.apache.juneau.httppart"><code>HttpPartSchema</code></a> - Defines the schema for your POJO.
</ul>
<p>
The <a href="org/apache/juneau/httppart/HttpPartSchema.html" title="class in org.apache.juneau.httppart"><code>HttpPartSchema</code></a> class is used to define the formatting and
validations for a POJO.
It's used in conjunction with the serializer and parser to produce and consume HTTP parts based on
OpenAPI rules.
</p>
<p>
Later in the rest-server and rest-client sections, we also describe how the following annotations
can be applied to method parameters and class types to define the schema for various HTTP parts:
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a>
<li class='ja'><code>org.apache.juneau.http.annotation.ResponseHeader</code>
</ul>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiMethodology' id='juneau-marshall.jm.OpenApiDetails.jm.OpenApiMethodology'>2.32.1 - OpenAPI Methodology</a><span class='update'>updated: 8.2.0</span></h4>
<div class='topic'><!-- START: 2.32.1 - juneau-marshall.jm.OpenApiDetails.jm.OpenApiMethodology -->
<div class='topic'>
<p>
Unlike the other Juneau serializers and parsers that convert input and output directly to-and-from POJOs,
the OpenAPI serializers and parsers use intermediate objects based on the <c>type</c> and <c>format</c>
of the schema.
</p>
<p>
The following table shows the "natural" intermediate type of the object based on the <c>type/format</c>:
</p>
<table class='styled w800'>
<tr><th>Type</th><th>Format</th><th>Intermediate Java Type</th></tr>
<tr class='dark bb'>
<td rowspan='4'><c>string</c> or empty</td>
<td><c>byte<br>binary<br>binary-spaced</c></td>
<td><c><jk>byte</jk>[]</c></td>
</tr>
<tr class='dark bb'>
<td><c>date<br>date-time</c></td>
<td><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a></td>
</tr>
<tr class='dark bb'>
<td><c>uon</c></td>
<td>No intermediate type.<br>(serialized directly to/from POJO)</td>
</tr>
<tr class='dark bb'>
<td>empty</td>
<td><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a></td>
</tr>
<tr class='light bb'>
<td rowspan='1'><c>boolean</c></td>
<td>empty</td>
<td><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a></td>
</tr>
<tr class='dark bb'>
<td rowspan='2'><c>integer</c></td>
<td><c>int32</c></td>
<td><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang"><code>Integer</code></a></td>
</tr>
<tr class='dark bb'>
<td><c>int64</c></td>
<td><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a></td>
</tr>
<tr class='light bb'>
<td rowspan='2'><c>number</c></td>
<td><c>float</c></td>
<td><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html?is-external=true" title="class or interface in java.lang"><code>Float</code></a></td>
</tr>
<tr class='light bb'>
<td><c>double</c></td>
<td><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a></td>
</tr>
<tr class='dark bb'>
<td rowspan='2'><c>array</c></td>
<td>empty</td>
<td>Arrays of intermediate types on this list.</td>
</tr>
<tr class='dark bb'>
<td><c>uon</c></td>
<td>No intermediate type.<br>(serialized directly to/from POJO)</td>
</tr>
<tr class='light bb'>
<td rowspan='2'><c>object</c></td>
<td>empty</td>
<td><c>Map&lt;String,Object&gt;</c></td>
</tr>
<tr class='light bb'>
<td><c>uon</c></td>
<td>No intermediate type.<br>(serialized directly to/from POJO)</td>
</tr>
</table>
<p>
The valid POJO types for serializing/parsing are based on the intermediate types above.
As a general rule, any POJOs that are the intermediate type or transformable to or from
the intermediate type are valid POJO types.
</p>
<p>
For example, the following POJO type can be transformed to and from a byte array.
</p>
<p class='bjava'>
<jc>// Sample POJO class convertable to and from a byte[].</jc>
<jk>public class</jk> MyPojo {
<jc>// Constructor used by parser.</jc>
<jk>public</jk> MyPojo(<jk>byte</jk>[] <jv>value</jv>) {...}
<jc>// toX method used by serializer.</jc>
<jk>public byte</jk>[] toBytes() {...}
}
</p>
<p>
This example shows how that POJO can be converted to a BASE64-encoded string.
</p>
<p class='bjava'>
<jc>// Construct a POJO.</jc>
MyPojo <jv>myPojo</jv> = ...;
<jc>// Define a schema.</jc>
HttpPartSchema <jv>schema</jv> = HttpPartSchema.<jsm>tByte</jsm>().build();
<jc>// Convert POJO to BASE64-encoded string.</jc>
HttpPartSerializer <jv>serializer</jv> = OpenApiSerializer.<jsf>DEFAULT</jsf>;
String <jv>httpPart</jv> = <jv>serializer</jv>.serialize(<jv>schema</jv>, <jv>myPojo</jv>);
<jc>// Convert BASE64-encoded string back into a POJO.</jc>
HttpPartParser <jv>parser</jv> = OpenApiParser.<jsf>DEFAULT</jsf>;
<jv>myPojo</jv> = <jv>parser</jv>.parse(<jv>schema</jv>, <jv>httpPart</jv>, MyPojo.<jk>class</jk>);
</p>
<p>
In addition to defining format, the schema also allows for validations of the serialized form.
</p>
<p class='bjava'>
<jc>// Construct a POJO.</jc>
MyPojo <jv>myPojo</jv> = ...;
<jc>// Define a schema.</jc>
<jc>// Serialized string must be no smaller than 100 characters.</jc>
HttpPartSchema <jv>schema</jv> = HttpPartSchema.<jsm>tByte</jsm>().minLength(100).build();
<jc>// Convert POJO to BASE64-encoded string.</jc>
HttpPartSerializer <jv>serializer</jv> = OpenApiSerializer.<jsf>DEFAULT</jsf>;
String <jv>httpPart</jv>;
<jk>try</jk> {
<jv>httpPart</jv> = <jv>serializer</jv>.serialize(<jv>schema</jv>, <jv>myPojo</jv>);
} <jk>catch</jk> (SchemaValidationException <jv>e</jv>) {
<jc>// Oops, output too small.</jc>
}
<jc>// Convert BASE64-encoded string back into a POJO.</jc>
HttpPartParser <jv>parser</jv> = OpenApiParser.<jsf>DEFAULT</jsf>;
<jk>try</jk> {
<jv>myPojo</jv> = <jv>parser</jv>.parse(<jv>schema</jv>, <jv>httpPart</jv>, MyPojo.<jk>class</jk>);
} <jk>catch</jk> (SchemaValidationException <jv>e</jv>) {
<jc>// Oops, input too small.</jc>
}
</p>
<p>
It looks simple but the implementation is highly sophisticated being able to serialize and parse and validate using complex schemas.
</p>
<p>
The next sections go more into depth on serializing and parsing various POJO types.
</p>
</div>
</div><!-- END: 2.32.1 - juneau-marshall.jm.OpenApiDetails.jm.OpenApiMethodology -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers' id='juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers'>2.32.2 - OpenAPI Serializers</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.32.2 - juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> class is used to convert POJOs to HTTP parts.
</p>
<p>
The class hierarchy for the builder of this serializer is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanTraverseContext.Builder.html" title="class in org.apache.juneau"><code>BeanTraverseContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializer.Builder.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/uon/UonSerializer.Builder.html" title="class in org.apache.juneau.uon"><code>UonSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/oapi/OpenApiSerializer.Builder.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
Later we'll describe how to use HTTP-Part annotations to define OpenAPI schemas for serialization and parsing
of HTTP parts.
The following example is a preview showing an HTTP body defined as pipe-delimited list of comma-delimited numbers (e.g. <js>"1,2,3|4,5,6|7,8,9"</js>):
</p>
<p class='bjava'>
<ja>@RestPost</ja>(<js>"/2dLongArray"</js>)
<jk>public void</jk> post2dLongArray(
<ja>@Content</ja>(
schema=<ja>@Schema</ja>(
type=<js>"array"</js>,
collectionFormat=<js>"pipes"</js>,
items=<ja>@Items</ja>(
type=<js>"array"</js>,
collectionFormat=<js>"csv"</js>,
items=<ja>@SubItems</ja>(
type=<js>"integer"</js>,
format=<js>"int64"</js>,
minimum=<js>"0"</js>,
maximum=<js>"100"</js>
minLength=1,
maxLength=10
)
)
minLength=1,
maxLength=10
)
)
Long[][] body
) {...}
<jc>// Alternate shortened format.</jc>
<ja>@RestPost</ja>(<js>"/2dLongArray"</js>)
<jk>public void</jk> post2dLongArray(
<ja>@Content</ja>(
schema=<ja>@Schema</ja>(
t=<js>"array"</js>,
cf=<js>"pipes"</js>,
i=<ja>@Items</ja>(
t=<js>"array"</js>,
cf=<js>"csv"</js>,
i=<ja>@SubItems</ja>(
t=<js>"integer"</js>,
f=<js>"int64"</js>,
min=<js>"0"</js>,
max=<js>"100"</js>
minl=1,
maxl=10
)
)
minl=1,
maxl=10
)
)
Long[][] body
) {...}
</p>
<p>
Under-the-covers, this gets converted to the following schema object:
</p>
<p class='bjava'>
HttpPartSchema <jv>schema</jv> = HttpPartSchema.<jsm>create</jsm>()
.items(
HttpPartSchema.<jsm>create</jsm>()
.type(<js>"array"</js>)
.collectionFormat(<js>"pipes"</js>)
.items(
HttpPartSchema.<jsm>create</jsm>()
.type(<js>"array"</js>)
.collectionFormat(<js>"csv"</js>)
.items(
HttpPartSchema.<jsm>create</jsm>()
.type(<js>"integer"</js>)
.format(<js>"int64"</js>)
.minimum(0)
.maximum(100)
.minLength(1)
.maxLength(10)
)
)
)
.build();
</p>
<p>
Various convenience methods exist for shortening this code.
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpPartSchema.*;
HttpPartSchema <jv>schema</jv> = <jsm>tArrayPipes</jsm>(
<jsm>tArrayCsv</jsm>(
<jsm>tInt64</jsm>().minimum(0).maximum(100).minLength(1).maxLength(10)
)
).build();
</p>
<p>
The following code shows how the schema above can be used to create our pipe+csv list of numbers:
</p>
<p class='bjava'>
<jc>// Our POJO being serialized.</jc>
Long[][] <jv>input</jv> = ....
<jc>// Convert POJO to a string.</jc>
<jk>try</jk> {
String <jv>httpPart</jv> = OpenApi.<jsm>of</jsm>(<jv>schema</jv>, <jv>input</jv>);
} <jk>catch</jk> (SchemaValidationException <jv>e</jv>) {
<jc>// Oops, one of the restrictions were not met.</jc>
}
</p>
<p>
As a general rule, any POJO convertible to the intermediate type for the <c>type/format</c> of the schema can
be serialized using the OpenAPI serializer.
Here are the rules of POJO types allowed for various type/format combinations:
</p>
<table class='styled w800'>
<tr><th>Type</th><th>Format</th><th>Valid parameter types</th></tr>
<tr class='dark bb'>
<td rowspan='4'><c>string</c> or empty</td>
<td><c>byte<br>binary<br>binary-spaced</c></td>
<td>
<ul>
<li><c><jk>byte</jk>[]</c> (default)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a> - Read into String and then converted using <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true#getBytes--" title="class or interface in java.lang"><code>String.getBytes()</code></a>.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - Converted to String and then converted using <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true#getBytes--" title="class or interface in java.lang"><code>String.getBytes()</code></a>.
<li>Any POJO transformable to a <c><jk>byte</jk>[]</c> via the following methods:
<ul>
<li><c><jk>public byte</jk>[] toBytes() {...}</c>
<li><c><jk>public byte</jk>[]</jk> toFoo() {...}</c> (any method name starting with "to")
</ul>
<li>Any POJO transformable to a <c><jk>byte</jk>[]</c> via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>.
</ul>
</td>
</tr>
<tr class='dark bb'>
<td><c>date<br>date-time</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a> (default)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a>
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a> via the following methods:
<ul>
<li><c><jk>public</jk> Calendar toCalendar() {...}</c>
<li><c><jk>public</jk> Calendar toFoo() {...}</c> (any method name starting with "to")
</ul>
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a> via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>.
</ul>
</td>
</tr>
<tr class='dark bb'>
<td><c>uon</c></td>
<td>
<ul>
<li>Any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Serializable POJO</a> type.
</ul>
</td>
</tr>
<tr class='dark bb'>
<td>empty</td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> (default)
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> via the following methods:
<ul>
<li><c><jk>public</jk> String toString() {...}</c>
</ul>
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>.
</ul>
</td>
</tr>
<tr class='light bb'>
<td rowspan='1'><c>boolean</c></td>
<td>empty</td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a> (default)
<li><jk>boolean</jk>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> - Converted to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a>.
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a> via the following methods:
<ul>
<li><c><jk>public</jk> Boolean toBoolean() {...}</c>
<li><c><jk>public</jk> Boolean toFoo() {...}</c> (any method name starting with "to")
</ul>
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a> via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>.
</ul>
</td>
</tr>
<tr class='dark bb'>
<td rowspan='2'><c>integer</c></td>
<td><c>int32</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang"><code>Integer</code></a> (default)
<li><jk>int</jk>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> - Converted to an <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a>.
<li>Any POJO transformable to an <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang"><code>Integer</code></a> via the following methods:
<ul>
<li><c><jk>public</jk> Integer toInteger() {...}</c>
<li><c><jk>public</jk> Integer toFoo() {...}</c> (any method name starting with "to")
</ul>
<li>Any POJO transformable to an <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang"><code>Integer</code></a> via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>.
</ul>
</td>
</tr>
<tr class='dark bb'>
<td><c>int64</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a> (default)
<li><jk>long</jk>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> - Converted to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a>.
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a> via the following methods:
<ul>
<li><c><jk>public</jk> Long toLong() {...}</c>
<li><c><jk>public</jk> Long toFoo() {...}</c> (any method name starting with "to")
</ul>
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a> via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>.
</ul>
</td>
</tr>
<tr class='light bb'>
<td rowspan='2'><c>number</c></td>
<td><c>float</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html?is-external=true" title="class or interface in java.lang"><code>Float</code></a> (default)
<li><jk>float</jk>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> - Converted to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html?is-external=true" title="class or interface in java.lang"><code>Float</code></a>.
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html?is-external=true" title="class or interface in java.lang"><code>Float</code></a> via the following methods:
<ul>
<li><c><jk>public</jk> Float toFloat() {...}</c>
<li><c><jk>public</jk> Float toFoo() {...}</c> (any method name starting with "to")
</ul>
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html?is-external=true" title="class or interface in java.lang"><code>Float</code></a> via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>.
</ul>
</td>
</tr>
<tr class='light bb'>
<td><c>double</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a> (default)
<li><jk>double</jk>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> - Converted to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a>.
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a> via the following methods:
<ul>
<li><c><jk>public</jk> Double toDouble() {...}</c>
<li><c><jk>public</jk> Double toFoo() {...}</c> (any method name starting with "to")
</ul>
<li>Any POJO transformable to a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a> via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>.
</ul>
</td>
</tr>
<tr class='dark bb'>
<td rowspan='2'><c>array</c></td>
<td>empty</td>
<td>
<ul>
<li>Arrays or Collections of any defaults on this list.
<li>Any POJO transformable to arrays of the default types (e.g. <c>Integer[]</c>, <c>Boolean[][]</c>, etc...).
<br>For example:
<ul>
<li><c><jk>public</jk> Boolean[][] toFoo() {...}</c> (any method name starting with "to")
</ul>
<li>Any POJO transformable to arrays of the default types via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>
</ul>
</td>
</tr>
<tr class='dark bb'>
<td><c>uon</c></td>
<td>
<ul>
<li>Any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Serializable POJO</a> type.
</ul>
</td>
</tr>
<tr class='light bb'>
<td rowspan='2'><c>object</c></td>
<td>empty</td>
<td>
<ul>
<li><c>Map&lt;String,Object&gt;</c> (default)
<li>Beans with properties of anything on this list.
<li>Any POJO transformable to a map via an <a href="org/apache/juneau/swap/ObjectSwap.html" title="class in org.apache.juneau.swap"><code>ObjectSwap</code></a>
</ul>
</td>
</tr>
<tr class='light bb'>
<td><c>uon</c></td>
<td>
<ul>
<li>Any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Serializable POJO</a> type.
</ul>
</td>
</tr>
</table>
<p>
For arrays, an example of "Any POJO transformable to arrays of the default types" is:
</p>
<p class='bjava'>
<jc>// Sample POJO class convertable to a Long[][].</jc>
<jk>public class</jk> MyPojo {
<jc>// toX method used by serializer.</jc>
<jk>public</jk> Long[][] to2dLongs() {...}
}
</p>
<p>
In the example above, our POJO class can be used to create our pipe-delimited list of comma-delimited numbers:
</p>
<p class='bjava'>
<jc>// Our POJO being serialized.</jc>
MyPojo <jv>input</jv> = ....
<jc>// Convert POJO to a string.</jc>
<jk>try</jk> {
String <jv>httpPart</jv> = OpenApi.<jsm>of</jsm>(<jv>schema</jv>, <jv>input</jv>);
} <jk>catch</jk> (SchemaValidationException <jv>e</jv>) {
<jc>// Oops, one of the restrictions were not met.</jc>
}
</p>
<p>
The <c>object</c> type is not officially part of the OpenAPI standard.
However, Juneau supports serializing Maps and beans to HTTP parts using UON notation.
</p>
<p>
The following shows an example of a bean with several properties of various types.
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jk>private static byte</jk>[] <jsf>FOOB</jsf> = <js>"foo"</js>.getBytes();
<jk>public</jk> String <jf>f1</jf> = <js>"foo"</js>;
<jk>public byte</jk>[] <jf>f2</jf> = <jsf>FOOB</jsf>;
<jk>public byte</jk>[] <jf>f3</jf> = <jsf>FOOB</jsf>;
<jk>public byte</jk>[] <jf>f4</jf> = <jsf>FOOB</jsf>;
<jk>public</jk> Calendar <jf>f5</jf> = <jsm>parseIsoCalendar</jsm>(<js>"2012-12-21T12:34:56Z"</js>);
<jk>public</jk> String <jf>f6</jf> = <js>"foo"</js>;
<jk>public int</jk> <jf>f7</jf> = 1;
<jk>public</jk> Long <jf>f8</jf> = 2l;
<jk>public float</jk> <jf>f9</jf> = 1.0;
<jk>public</jk> Double <jf>f10</jf> = 1.0;
<jk>public</jk> Boolean <jf>f11</jf> = <jk>true</jk>;
<jk>public</jk> Object <jf>fExtra</jf> = "1";
}
</p>
<p>
We define the following schema:
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.httppart.HttpPartSchema.*;
HttpPartSchema <jv>schema</jv> = tObject()
.prop(<js>"f1"</js>, <jsm>tString</jsm>())
.prop(<js>"f2"</js>, <jsm>tByte</jsm>())
.prop(<js>"f3"</js>, <jsm>tBinary</jsm>())
.prop(<js>"f4"</js>, <jsm>tBinarySpaced</jsm>())
.prop(<js>"f5"</js>, <jsm>tDateTime</jsm>())
.prop(<js>"f6"</js>, <jsm>tUon</jsm>())
.prop(<js>"f7"</js>, <jsm>tInteger</jsm>())
.prop(<js>"f8"</js>, <jsm>tInt64</jsm>())
.prop(<js>"f9"</js>, <jsm>tNumber</jsm>())
.prop(<js>"f10"</js>, <jsm>tDouble</jsm>())
.prop(<js>"f11"</js>, <jsm>tBoolean</jsm>())
.ap(<jsm>tInteger</jsm>())
.build();
</p>
<p>
Then we serialize our bean:
</p>
<p class='bjava'>
String <jv>httpPart</jv> = OpenApi.<jsm>of</jsm>(<jv>schema</jv>, <jk>new</jk> MyBean());
</p>
<p>
The results of this serialization is shown below:
</p>
<p class='buon'>
(
f1=foo,
f2=Zm9v,
f3=666F6F,
f4='66 6F 6F',
f5=2012-12-21T12:34:56Z,
f6=foo,
f7=1,
f8=2,
f9=1.0,
f10=1.0,
f11=true,
fExtra=1
)
</p>
<p>
The following is an example of a bean with various array property types:
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jk>private static byte</jk>[] <jsf>FOOB</jsf> = <js>"foo"</js>.getBytes();
<jk>public</jk> String[] <jf>f1</jf> = {<js>"a,b"</js>,<jk>null</jk>},
<jk>public byte</jk>[][] <jf>f2</jf> = <jk>new byte</jk>[][]{<jsf>FOOB</jsf>,<jk>null</jk>},
<jk>public byte</jk>[][] <jf>f3</jf> = <jk>new byte</jk>[][]{<jsf>FOOB</jsf>,<jk>null</jk>},
<jk>public byte</jk>[][] <jf>f4</jf> = <jk>new byte</jk>[][]{<jsf>FOOB</jsf>,<jk>null</jk>},
<jk>public</jk> Calendar[] <jf>f5</jf> = <jk>new</jk> Calendar[]{<jsm>parseIsoCalendar</jsm>(<js>"2012-12-21T12:34:56Z"</js>),<jk>null</jk>},
<jk>public</jk> String[] <jf>f6</jf> = {<js>"a"</js>,<js>"b"</js>,<jk>null</jk>},
<jk>public int</jk>[] <jf>f7</jf> = <jk>new int</jk>[]{1,2,<jk>null</jk>},
<jk>public</jk> Integer[] <jf>f8</jf> = <jk>new</jk> Integer[]{3,4,<jk>null</jk>},
<jk>public float</jk>[] <jf>f9</jf> = <jk>new float</jk>[]{1f,2f,<jk>null</jk>},
<jk>public</jk> Float[] <jf>f10</jf> = <jk>new</jk> Float[]{3f,4f,<jk>null</jk>},
<jk>public</jk> Boolean[] <jf>f11</jf> = <jk>new</jk> Boolean[]{<jk>true</jk>,<jk>false</jk>,<jk>null</jk>},
<jk>public</jk> Object[] <jf>fExtra</jf> = <jk>new</jk> Object[]{1,<js>"2"</js>,<jk>null</jk>};
}
</p>
<p>
For this bean, we define the following schema:
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.httppart.HttpPartSchema.*;
HttpPartSchema <jv>schema</jv> = <jsm>tObject</jsm>()
.prop(<js>"f1"</js>, <jsm>tArray</jsm>(<jsm>tString</jsm>()))
.prop(<js>"f2"</js>, <jsm>tArray</jsm>(<jsm>tByte</jsm>()))
.prop(<js>"f3"</js>, <jsm>tArray</jsm>(<jsm>tBinary</jsm>()))
.prop(<js>"f4"</js>, <jsm>tArray</jsm>(<jsm>tBinarySpaced</jsm>()))
.prop(<js>"f5"</js>, <jsm>tArray</jsm>(<jsm>tDateTime</jsm>()))
.prop(<js>"f6"</js>, <jsm>tArray</jsm>(<jsm>tUon</jsm>()))
.prop(<js>"f7"</js>, <jsm>tArray</jsm>(<jsm>tInteger</jsm>()))
.prop(<js>"f8"</js>, <jsm>tArray</jsm>(<jsm>tInt64</jsm>()))
.prop(<js>"f9"</js>, <jsm>tArray</jsm>(<jsm>tNumber</jsm>()))
.prop(<js>"f10"</js>, <jsm>tArray</jsm>(<jsm>tDouble</jsm>()))
.prop(<js>"f11"</js>, <jsm>tArray</jsm>(<jsm>tBoolean</jsm>()))
.ap(<jsm>tArray</jsm>(<jsm>tInteger</jsm>()))
.build();
</p>
<p>
Serializing this bean produces the following output:
</p>
<p class='buon'>
(
f1=@('a,b',null),
f2=@(Zm9v,null),
f4=@(2012-12-21T12:34:56Z,null),
f5=@(666F6F,null),
f6=@('66 6F 6F',null),
f7=@(a,b,null),
f8=@(1,2,null),
f9=@(3,4,null),
f10=@(1.0,2.0,null),
f11=@(3.0,4.0,null),
f12=@(true,false,null),
fExtra=@(1,2,null)
)
</p>
<ul class='notes'>
<li class='note'>
Array properties can also use CSV/SSV/PIPES for array notation.
<br>Various notations can be mixed throughout.
<li class='note'>
Schemas and POJOs can be defined arbitrarily deep.
<li class='note'>
Schemas are optional.
They can be skipped or partially defined.
<li class='note'>
We make our best attempt to convert the input to the matching type.
However, you will get <c>SerializeExceptions</c> if you attempt an impossible conversion.
(e.g. trying to serialize the string "foo" as a boolean).
</ul>
</div>
</div><!-- END: 2.32.2 - juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiParsers' id='juneau-marshall.jm.OpenApiDetails.jm.OpenApiParsers'>2.32.3 - OpenAPI Parsers</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 2.32.3 - juneau-marshall.jm.OpenApiDetails.jm.OpenApiParsers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a> class is used to convert HTTP parts back into POJOs.
</p>
<p>
The class hierarchy for the builder of this parser is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/Parser.Builder.html" title="class in org.apache.juneau.parser"><code>Parser.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/ReaderParser.Builder.html" title="class in org.apache.juneau.parser"><code>ReaderParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/uon/UonParser.Builder.html" title="class in org.apache.juneau.uon"><code>UonParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/oapi/OpenApiParser.Builder.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following is the previous example of a schema that defines the format of a pipe-delimited list of comma-delimited numbers (e.g. <js>"1,2,3|4,5,6|7,8,9"</js>):
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.httppart.HttpPartSchema.*;
HttpPartSchema <jv>schema</jv> = <jsm>tArrayPipes</jsm>(
<jsm>tArrayCsv</jsm>(
<jsm>tInt64</jsm>().min(0).max(100).minl(1).maxl(10)
)
).build();
</p>
<p>
The following code shows how the schema above can be used to parse our input into a POJO:
</p>
<p class='bjava'>
<jc>// Our input being parsed.</jc>
String <jv>input</jv> = <js>"1,2,3|4,5,6|7,8,9"</js>
<jc>// Convert string to a POJO.</jc>
<jk>try</jk> {
Long[][] <jv>pojo</jv> = OpenApi.<jsm>to</jsm>(<jv>schema</jv>, <jv>input</jv>, Long[][].<jk>class</jk>);
} <jk>catch</jk> (SchemaValidationException <jv>e</jv>) {
<jc>// Oops, one of the restrictions were not met.</jc>
}
</p>
<p>
As a general rule, any POJO convertible from the intermediate type for the <c>type/format</c> of the schema can
be parsed using the OpenAPI parser.
Here are the rules of POJO types allowed for various type/format combinations:
</p>
<table class='styled w800'>
<tr><th>Type</th><th>Format</th><th>Valid parameter types</th></tr>
<tr class='dark bb'>
<td rowspan='4'><c>string</c> or empty</td>
<td><c>byte<br>binary<br>binary-spaced</c></td>
<td>
<ul>
<li><c><jk>byte</jk>[]</c> (default)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a> - Returns a <a href="https://docs.oracle.com/javase/8/docs/api/java/io/ByteArrayInputStream.html?is-external=true" title="class or interface in java.io"><code>ByteArrayInputStream</code></a>.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a> - Returns a <a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStreamReader.html?is-external=true" title="class or interface in java.io"><code>InputStreamReader</code></a> wrapped around a <a href="https://docs.oracle.com/javase/8/docs/api/java/io/ByteArrayInputStream.html?is-external=true" title="class or interface in java.io"><code>ByteArrayInputStream</code></a>.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> - Constructed using <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true#String-byte:A-" title="class or interface in java.lang"><code>String.String(byte[])</code></a>.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - Returns the default <c><jk>byte</jk>[]</c>.
<li>Any POJO transformable from a <c><jk>byte</jk>[]</c> (via constructors or static create methods).
</ul>
</td>
</tr>
<tr class='dark bb'>
<td><c>date<br>date-time</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a> (default)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/GregorianCalendar.html?is-external=true" title="class or interface in java.util"><code>GregorianCalendar</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> - Converted using <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true#toString--" title="class or interface in java.util"><code>Calendar.toString()</code></a>.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - Returns the default <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a>.
<li>Any POJO transformable from a <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a> (via constructors or static create methods).
</ul>
</td>
</tr>
<tr class='dark bb'>
<td><c>uon</c></td>
<td>
<ul>
<li>Any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Parsable POJO</a> type.
</ul>
</td>
</tr>
<tr class='dark bb'>
<td>empty</td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> (default)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - Returns the default <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a>.
<li>Any POJO transformable from a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> (via constructors, static create methods, or swaps).
</ul>
</td>
</tr>
<tr class='light bb'>
<td rowspan='1'><c>boolean</c></td>
<td>empty</td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a> (default)
<li><jk>boolean</jk>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - Returns the default <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a>.
<li>Any POJO transformable from a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang"><code>Boolean</code></a> (via constructors, static create methods, or swaps).
</ul>
</td>
</tr>
<tr class='dark bb'>
<td rowspan='2'><c>integer</c></td>
<td><c>int32</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang"><code>Integer</code></a> (default)
<li>Any subclass of <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Number.html?is-external=true" title="class or interface in java.lang"><code>Number</code></a>
<li>Any primitive number: (e.g <jk>int</jk>, <jk>float</jk>...)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - Returns the default <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang"><code>Integer</code></a>.
<li>Any POJO transformable from an <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang"><code>Integer</code></a> (via constructors, static create methods, or swaps).
</ul>
</td>
</tr>
<tr class='dark bb'>
<td><c>int64</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a> (default)
<li>Any subclass of <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Number.html?is-external=true" title="class or interface in java.lang"><code>Number</code></a>
<li>Any primitive number: (e.g <jk>int</jk>, <jk>float</jk>...)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - Returns the default <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a>.
<li>Any POJO transformable from an <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang"><code>Long</code></a> (via constructors, static create methods, or swaps).
</ul>
</td>
</tr>
<tr class='light bb'>
<td rowspan='2'><c>number</c></td>
<td><c>float</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html?is-external=true" title="class or interface in java.lang"><code>Float</code></a> (default)
<li>Any subclass of <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Number.html?is-external=true" title="class or interface in java.lang"><code>Number</code></a>
<li>Any primitive number: (e.g <jk>int</jk>, <jk>float</jk>...)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - Returns the default <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html?is-external=true" title="class or interface in java.lang"><code>Float</code></a>.
<li>Any POJO transformable from an <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Float.html?is-external=true" title="class or interface in java.lang"><code>Float</code></a> (via constructors, static create methods, or swaps).
</ul>
</td>
</tr>
<tr class='light bb'>
<td><c>double</c></td>
<td>
<ul>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a> (default)
<li>Any subclass of <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Number.html?is-external=true" title="class or interface in java.lang"><code>Number</code></a>
<li>Any primitive number: (e.g <jk>int</jk>, <jk>float</jk>...)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - Returns the default <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a>.
<li>Any POJO transformable from an <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang"><code>Double</code></a> (via constructors, static create methods, or swaps).
</ul>
</td>
</tr>
<tr class='dark bb'>
<td rowspan='2'><c>array</c></td>
<td>empty</td>
<td>
<ul>
<li>Arrays or Collections of anything on this list.
<li>Any POJO transformable from arrays of the default types (e.g. <c>Integer[]</c>, <c>Boolean[][]</c>, etc...).
</ul>
</td>
</tr>
<tr class='dark bb'>
<td><c>uon</c></td>
<td>
<ul>
<li>Any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Parsable POJO</a> type.
</ul>
</td>
</tr>
<tr class='light bb'>
<td rowspan='2'><c>object</c></td>
<td>empty</td>
<td>
<ul>
<li><c>Map&lt;String,Object&gt;</c> (default)
<li>Beans with properties of anything on this list.
<li>Maps with string keys.
</ul>
</td>
</tr>
<tr class='light bb'>
<td><c>uon</c></td>
<td>
<ul>
<li>Any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Parsable POJO</a> type.
</ul>
</td>
</tr>
</table>
<p>
Additionally, any of the type above can also be wrapped as <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html?is-external=true" title="class or interface in java.util"><code>Optionals</code></a>.
</p>
<p>
For arrays, an example of "Any POJO transformable from arrays of the default types" is:
</p>
<p class='bjava'>
<jc>// Sample POJO class convertable from a Long[][].</jc>
<jk>public class</jk> MyPojo {
<jc>// Constructor used by parser.</jc>
<jk>public</jk> MyPojo(Long[][] <jv>from2dLongs</jv>) {...}
}
</p>
<p>
In the example above, our POJO class can be constructed from our pipe-delimited list of comma-delimited numbers:
</p>
<p class='bjava'>
<jc>// Our input being parsed.</jc>
String <jv>input</jv> = <js>"1,2,3|4,5,6|7,8,9"</js>
<jc>// Convert string to a POJO.</jc>
<jk>try</jk> {
MyPojo <jv>pojo</jv> = OpenApi.<jsm>to</jsm>(<jv>schema</jv>, <jv>input</jv>, MyPojo.<jk>class</jk>);
} <jk>catch</jk> (SchemaValidationException <jv>e</jv>) {
<jc>// Oops, one of the restrictions were not met.</jc>
}
</p>
<p>
Just like serialization, the <c>object</c> type is not officially part of the OpenAPI standard but
Juneau supports parsing HTTP parts in UON notation to Maps and beans.
</p>
<p>
The following shows an example of a bean with several properties of various types.
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jk>public</jk> String <jf>f1</jf>;
<jk>public byte</jk>[] <jf>f2</jf>;
<jk>public byte</jk>[] <jf>f3</jf>;
<jk>public byte</jk>[] <jf>f4</jf>;
<jk>public</jk> Calendar <jf>f5</jf>;
<jk>public</jk> String <jf>f6</jf>;
<jk>public int</jk> <jf>f7</jf>;
<jk>public</jk> Long <jf>f8</jf>;
<jk>public float</jk> <jf>f9</jf>;
<jk>public</jk> Double <jf>f10</jf>;
<jk>public</jk> Boolean <jf>f11</jf>;
<jk>public</jk> Object <jf>fExtra</jf>;
}
</p>
<p>
We define the following schema again:
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.httppart.HttpPartSchema.*;
HttpPartSchema <jv>schema</jv> = <jsm>tObject</jsm>()
.prop(<js>"f1"</js>, <jsm>tString</jsm>())
.prop(<js>"f2"</js>, <jsm>tByte</jsm>())
.prop(<js>"f3"</js>, <jsm>tBinary</jsm>())
.prop(<js>"f4"</js>, <jsm>tBinarySpaced</jsm>())
.prop(<js>"f5"</js>, <jsm>tDateTime</jsm>())
.prop(<js>"f6"</js>, <jsm>tUon</jsm>())
.prop(<js>"f7"</js>, <jsm>tInteger</jsm>())
.prop(<js>"f8"</js>, <jsm>tInt64</jsm>())
.prop(<js>"f9"</js>, <jsm>tNumber</jsm>())
.prop(<js>"f10"</js>, <jsm>tDouble</jsm>())
.prop(<js>"f11"</js>, <jsm>tBoolean</jsm>())
.ap(<jsm>tInteger</jsm>())
.build();
</p>
<p>
Then we parse our input into our POJO:
</p>
<p class='bjava'>
String <jv>input</jv> =
<js>"(f1=foo,f2=Zm9v,f3=666F6F,f4='66 6F 6F',f5=2012-12-21T12:34:56Z,f6=foo,"</js>
+ <js>"f7=1,f8=2,f9=1.0,f10=1.0,f11=true,fExtra=1)"</js>;
MyBean <jv>bean</jv> = OpenApi.<jsm>to</jsm>(<jv>schema</jv>, <jv>input</jv>, MyBean.<jk>class</jk>);
</p>
<p>
Note that serializing into generic <c>Object</c> properties would have produced similar results:
</p>
<p class='bjava'>
<jk>public class</jk> MyBean {
<jk>public</jk> Object <jf>f1</jf>;
<jk>public</jk> Object <jf>f2</jf>;
<jk>public</jk> Object <jf>f3</jf>;
<jk>public</jk> Object <jf>f4</jf>;
<jk>public</jk> Object <jf>f5</jf>;
<jk>public</jk> Object <jf>f6</jf>;
<jk>public</jk> Object <jf>f7</jf>;
<jk>public</jk> Object <jf>f8</jf>;
<jk>public</jk> Object <jf>f9</jf>;
<jk>public</jk> Object <jf>f10</jf>;
<jk>public</jk> Object <jf>f11</jf>;
<jk>public</jk> Object <jf>fExtra</jf>;
}
</p>
<p>
We can also parse into Maps as well:
</p>
<p class='bjava'>
String <jv>input</jv> =
<js>"(f1=foo,f2=Zm9v,f3=666F6F,f4='66 6F 6F',f5=2012-12-21T12:34:56Z,f6=foo,"</js>
+ <js>"f7=1,f8=2,f9=1.0,f10=1.0,f11=true,fExtra=1)"</js>;
JsonMap <jv>map</jv> = OpenApi.<jsm>to</jsm>(<jv>schema</jv>, <jv>input</jv>, JsonMap.<jk>class</jk>);
</p>
<ul class='notes'>
<li class='note'>
Array properties can also use CSV/SSV/PIPES for array notation.
<br>Various notations can be mixed throughout.
<li class='note'>
Schemas and POJOs can be defined arbitrarily deep.
<li class='note'>
Schemas are optional.
They can be skipped or partially defined.
<li class='note'>
We make our best attempt to convert the output to the matching type.
However, you will get <c>ParseExceptions</c> if you attempt an impossible conversion.
(e.g. trying to parse the string "foo" into a boolean).
</ul>
</div>
</div><!-- END: 2.32.3 - juneau-marshall.jm.OpenApiDetails.jm.OpenApiParsers -->
</div><!-- END: 2.32 - juneau-marshall.jm.OpenApiDetails -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall.jm.BestPractices' id='juneau-marshall.jm.BestPractices'>2.33 - Best Practices</a></h3>
<div class='topic'><!-- START: 2.33 - juneau-marshall.jm.BestPractices -->
<div class='topic'>
<ol class='spaced-list'>
<li>
Reuse instances of serializers and parsers whenever possible.
<br>They are designed to be thread safe and maintain internal caches of bean metadata to increase performance.
<li>
The <a href="org/apache/juneau/BeanTraverseContext.Builder.html#detectRecursions--"><code>BeanTraverseContext.Builder.detectRecursions()</code></a>
option can cause a performance penalty of
around 20%.
<br>Therefore, it's recommended that this option be used only when necessary.
<li>
In general, JSON serialization and parsing is about 20% faster than XML.
JSON is also more compact than XML.
<br>MessagePack is fastest and most compact of all.
<li>
The RDF parsers are SLOW.
<br>RDF simply isn't efficient with node traversal, so creating tree structures out of RDF models
is highly inefficient.
<li>
The <a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a> methods that take in <a href="org/apache/juneau/ClassMeta.html" title="class in org.apache.juneau"><code>ClassMeta</code></a>
parameters are slightly faster than methods that
take in <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html?is-external=true" title="class or interface in java.lang"><code>Class</code></a> or <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> parameters, since the latter methods involve
hash lookups to resolve to <a href="org/apache/juneau/ClassMeta.html" title="class in org.apache.juneau"><code>ClassMeta</code></a> parameters.
</ol>
</div>
</div><!-- END: 2.33 - juneau-marshall.jm.BestPractices -->
</div><!-- END: 2 - juneau-marshall -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-marshall-rdf' id='juneau-marshall-rdf'>3 - juneau-marshall-rdf</a></h2>
<div class='topic'><!-- START: 3 - juneau-marshall-rdf -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-marshall-rdf<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-marshall-rdf-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.marshaller.rdf_9.0.0.jar
</p>
<p>
The <c>juneau-marshall-rdf</c> library provides additional serializers and parsers for RDF.
These rely on the Apache Jena library to provide support for the following languages:
</p>
<ul>
<li>RDF/XML
<li>RDF/XML-Abbrev
<li>N-Triple
<li>Turtle
<li>N3
</ul>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-marshall-rdf.jmr.RdfDetails' id='juneau-marshall-rdf.jmr.RdfDetails'>3.1 - RDF Details</a></h3>
<div class='topic'><!-- START: 3.1 - juneau-marshall-rdf.jmr.RdfDetails -->
<div class='topic'>
<p>
Juneau supports serializing and parsing arbitrary POJOs to and from the following RDF formats:
</p>
<ul>
<li>RDF/XML
<li>Abbreviated RDF/XML
<li>N-Triple
<li>Turtle
<li>N3
</ul>
<p>
The serializers and parsers work identically to those in <c>juneau-marshall</c> but are
packaged separately so that you don't need to pull in the Jena dependency unless you need it.
</p>
<p class='bjava'>
<jc>// A simple bean</jc>
<jk>public class</jk> Person {
<jk>public</jk> String <jf>name</jf> = <js>"John Smith"</js>;
<jk>public int</jk> <jf>age</jf> = 21;
}
<jc>// Serialize a bean to JSON, XML, or HTML</jc>
Person <jv>person</jv> = <jk>new</jk> Person();
<jc>// Produces:
// &lt;rdf:RDF
// xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
// xmlns:jp="http://www.apache.org/juneaubp/"
// xmlns:j="http://www.apache.org/juneau/"&gt;
// &lt;rdf:Description&gt;
// &lt;jp:name&gt;John Smith&lt;/jp:name&gt;
// &lt;jp:age&gt;21&lt;/jp:age&gt;
// &lt;/rdf:Description&gt;
// &lt;/rdf:RDF&gt;</jc>
String <jv>rdfXml</jv> = RdfXmlAbbrev.<jsm>of</jsm>(<jv>person</jv>);
<jc>// Produces:
// @prefix jp: &lt;http://www.apache.org/juneaubp/&gt; .
// @prefix j: &lt;http://www.apache.org/juneau/&gt; .
// [] jp:age "21" ;
// jp:name "John Smith" .</jc>
String <jv>rdfN3</jv> = N3.<jsm>of</jsm>(<jv>person</jv>);
<jc>// Produces:
// _:A3bf53c85X3aX157cf407e2dX3aXX2dX7ffd &lt;http://www.apache.org/juneaubp/name&gt; "John Smith" .
// _:A3bf53c85X3aX157cf407e2dX3aXX2dX7ffd &lt;http://www.apache.org/juneaubp/age&gt; "21" .</jc>
String <jv>rdfNTriple</jv> = NTriple.<jsm>of</jsm>(<jv>person</jv>);
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.Serializers' id='juneau-marshall-rdf.jmr.RdfDetails.jmr.Serializers'>3.1.1 - RDF Serializers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 3.1.1 - juneau-marshall-rdf.jmr.RdfDetails.jmr.Serializers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/jena/RdfSerializer.html" title="class in org.apache.juneau.jena"><code>RdfSerializer</code></a> class is the top-level class for all Jena-based serializers.
Language-specific serializers are defined as inner subclasses of the <c>RdfSerializer</c> class:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/jena/RdfSerializer.html" title="class in org.apache.juneau.jena"><code>RdfSerializer</code></a>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/jena/RdfXmlSerializer.html" title="class in org.apache.juneau.jena"><code>RdfXmlSerializer</code></a>
<li class='jc'><a href="org/apache/juneau/jena/RdfXmlAbbrevSerializer.html" title="class in org.apache.juneau.jena"><code>RdfXmlAbbrevSerializer</code></a>
<li class='jc'><a href="org/apache/juneau/jena/N3Serializer.html" title="class in org.apache.juneau.jena"><code>N3Serializer</code></a>
<li class='jc'><a href="org/apache/juneau/jena/NTripleSerializer.html" title="class in org.apache.juneau.jena"><code>NTripleSerializer</code></a>
<li class='jc'><a href="org/apache/juneau/jena/TurtleSerializer.html" title="class in org.apache.juneau.jena"><code>TurtleSerializer</code></a>
</ul>
</li>
</ul>
<p>
The class hierarchy for the builder of this serializer is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanTraverseContext.Builder.html" title="class in org.apache.juneau"><code>BeanTraverseContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializer.Builder.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/jena/RdfSerializer.Builder.html" title="class in org.apache.juneau.jena"><code>RdfSerializer.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured serializers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/jena/RdfSerializer.html" title="class in org.apache.juneau.jena"><code>RdfSerializer</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/jena/RdfXmlSerializer.html" title="class in org.apache.juneau.jena"><code>RdfXmlSerializer</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/jena/RdfXmlSerializer.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/jena/RdfXmlAbbrevSerializer.html" title="class in org.apache.juneau.jena"><code>RdfXmlAbbrevSerializer</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/jena/RdfXmlAbbrevSerializer.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/jena/N3Serializer.html" title="class in org.apache.juneau.jena"><code>N3Serializer</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/jena/N3Serializer.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/jena/NTripleSerializer.html" title="class in org.apache.juneau.jena"><code>NTripleSerializer</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/jena/NTripleSerializer.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/jena/TurtleSerializer.html" title="class in org.apache.juneau.jena"><code>TurtleSerializer</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/jena/TurtleSerializer.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Abbreviated RDF/XML is currently the most widely accepted and readable RDF syntax, so the examples shown here
will use that format.
</p>
</div>
</div><!-- END: 3.1.1 - juneau-marshall-rdf.jmr.RdfDetails.jmr.Serializers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.Parsers' id='juneau-marshall-rdf.jmr.RdfDetails.jmr.Parsers'>3.1.2 - RDF Parsers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 3.1.2 - juneau-marshall-rdf.jmr.RdfDetails.jmr.Parsers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/jena/RdfParser.html" title="class in org.apache.juneau.jena"><code>RdfParser</code></a> class is the top-level class for all Jena-based parsers.
Language-specific parsers are defined as inner subclasses of the <c>RdfParser</c> class:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/jena/RdfParser.html" title="class in org.apache.juneau.jena"><code>RdfParser</code></a>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/jena/RdfXmlParser.html" title="class in org.apache.juneau.jena"><code>RdfXmlParser</code></a>
<li class='jc'><a href="org/apache/juneau/jena/NTripleParser.html" title="class in org.apache.juneau.jena"><code>NTripleParser</code></a>
<li class='jc'><a href="org/apache/juneau/jena/TurtleParser.html" title="class in org.apache.juneau.jena"><code>TurtleParser</code></a>
<li class='jc'><a href="org/apache/juneau/jena/N3Parser.html" title="class in org.apache.juneau.jena"><code>N3Parser</code></a>
</ul>
</li>
</ul>
<p>
The <c>RdfParser.Xml</c> parser handles both regular and abbreviated RDF/XML.
</p>
<p>
The class hierarchy for the builder of this parser is:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/BeanContextable.Builder.html" title="class in org.apache.juneau"><code>BeanContextable.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/Parser.Builder.html" title="class in org.apache.juneau.parser"><code>Parser.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/parser/ReaderParser.Builder.html" title="class in org.apache.juneau.parser"><code>ReaderParser.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/jena/RdfParser.Builder.html" title="class in org.apache.juneau.jena"><code>RdfParser.Builder</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
Refer to the builder javadocs for configurable settings.
</p>
<p>
The following pre-configured parsers are provided for convenience:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/jena/RdfParser.html" title="class in org.apache.juneau.jena"><code>RdfParser</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/jena/RdfXmlParser.html" title="class in org.apache.juneau.jena"><code>RdfXmlParser</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/jena/RdfXmlParser.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/jena/N3Parser.html" title="class in org.apache.juneau.jena"><code>N3Parser</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/jena/N3Parser.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/jena/NTripleParser.html" title="class in org.apache.juneau.jena"><code>NTripleParser</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/jena/NTripleParser.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/jena/TurtleParser.html" title="class in org.apache.juneau.jena"><code>TurtleParser</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/jena/TurtleParser.html#DEFAULT"><code>DEFAULT</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div><!-- END: 3.1.2 - juneau-marshall-rdf.jmr.RdfDetails.jmr.Parsers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.RdfAnnotation' id='juneau-marshall-rdf.jmr.RdfDetails.jmr.RdfAnnotation'>3.1.3 - @Rdf Annotation</a></h4>
<div class='topic'><!-- START: 3.1.3 - juneau-marshall-rdf.jmr.RdfDetails.jmr.RdfAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/jena/annotation/Rdf.html" title="annotation in org.apache.juneau.jena.annotation"><code>@Rdf</code></a> annotation
is used to override the behavior of the RDF serializers and parsers on individual bean classes or properties.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/jena/annotation/Rdf.html" title="annotation in org.apache.juneau.jena.annotation"><code>Rdf</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/jena/annotation/Rdf.html#beanUri--"><code>beanUri</code></a>
<li class='jma'><a href="org/apache/juneau/jena/annotation/Rdf.html#collectionFormat--"><code>collectionFormat</code></a>
<li class='jma'><a href="org/apache/juneau/jena/annotation/Rdf.html#namespace--"><code>namespace</code></a>
<li class='jma'><a href="org/apache/juneau/jena/annotation/Rdf.html#prefix--"><code>prefix</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 3.1.3 - juneau-marshall-rdf.jmr.RdfDetails.jmr.RdfAnnotation -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.Namespaces' id='juneau-marshall-rdf.jmr.RdfDetails.jmr.Namespaces'>3.1.4 - Namespaces</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 3.1.4 - juneau-marshall-rdf.jmr.RdfDetails.jmr.Namespaces -->
<div class='topic'>
<p>
You'll notice in the previous example that Juneau namespaces are used to represent bean property names.
These are used by default when namespaces are not explicitly specified.
</p>
<p>
The <c>juneau</c> namespace is used for generic names for objects that don't have namespaces
associated with them.
</p>
<p>
The <c>juneaubp</c> namespace is used on bean properties that don't have namespaces associated with
them.
</p>
<p>
The easiest way to specify namespaces is through annotations.
In this example, we're going to associate the prefix <c>'per'</c> to our bean class and all properties
of this class.
We do this by adding the following annotation to our class:
</p>
<p class='bjava'>
<ja>@Rdf</ja>(prefix=<js>"per"</js>)
<jk>public class</jk> Person {
</p>
<p>
In general, the best approach is to define the namespace URIs at the package level using a
<c>package-info.java</c> class, like so:
</p>
<p class='bjava'>
<jc>// RDF namespaces used in this package</jc>
<ja>@RdfSchema</ja>(
prefix=<js>"ab"</js>,
rdfNs={
<ja>@RdfNs</ja>(prefix=<js>"ab"</js>, namespaceURI=<js>"http://www.apache.org/addressBook/"</js>),
<ja>@RdfNs</ja>(prefix=<js>"per"</js>, namespaceURI=<js>"http://www.apache.org/person/"</js>),
<ja>@RdfNs</ja>(prefix=<js>"addr"</js>, namespaceURI=<js>"http://www.apache.org/address/"</js>),
<ja>@RdfNs</ja>(prefix=<js>"mail"</js>, namespaceURI=<js>"http://www.apache.org/mail/"</js>)
}
)
<jk>package</jk> org.apache.juneau.sample.addressbook;
<jk>import</jk> org.apache.juneau.xml.annotation.*;
</p>
<p>
This assigns a default prefix of <js>"ab"</js> for all classes and properties within the project, and
specifies various other prefixes used within this project.
</p>
<p>
Now when we rerun the sample code, we'll get the following:
</p>
<p class='bxml'>
<xt>&lt;rdf:RDF</xt>
<xa>xmlns:rdf</xa>=<xs>"http://www.w3.org/1999/02/22-rdf-syntax-ns#"</xs>
<xa>xmlns:j</xa>=<xs>"http://www.apache.org/juneau/"</xs>
<xa>xmlns:jp</xa>=<xs>"http://www.apache.org/juneaubp/"</xs>
<xa>xmlns:per</xa>=<xs>"http://www.apache.org/person/"</xs><xt>&gt;</xt>
<xt>&lt;rdf:Description&gt;</xt>
<xt>&lt;per:id&gt;</xt>1<xt>&lt;/per:id&gt;</xt>
<xt>&lt;per:name&gt;</xt>John Smith<xt>&lt;/per:name&gt;</xt>
<xt>&lt;/rdf:Description&gt;</xt>
<xt>&lt;/rdf:RDF&gt;</xt>
</p>
<p>
Namespace auto-detection is enabled on serializers by default.
This causes the serializer to make a first-pass over the data structure to look for namespaces.
In high-performance environments, you may want to consider disabling auto-detection and providing an
explicit list of namespaces to the serializer to avoid this scanning step using <a href="org/apache/juneau/xml/XmlSerializer.Builder.html#disableAutoDetectNamespaces--"><code>XmlSerializer.Builder.disableAutoDetectNamespaces()</code></a>.
</p>
<p class='bjava'>
<jc>// Create a new serializer but manually specify the namespaces.</jc>
RdfSerializer <jv>serializer</jv> = RdfSerializer.<jsm>create</jsm>()
.xmlabbrev()
.rdfxml_tab(3)
.disableAutoDetectNamespaces()
.namespaces(<js>"{per:'http://www.apache.org/person/'}"</js>)
.build();
</p>
<p>
This code change will produce the same output as before but will perform slightly better since it doesn't
have to crawl the POJO tree before serializing the result.
</p>
</div>
</div><!-- END: 3.1.4 - juneau-marshall-rdf.jmr.RdfDetails.jmr.Namespaces -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.UriProperties' id='juneau-marshall-rdf.jmr.RdfDetails.jmr.UriProperties'>3.1.5 - URI Properties</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 3.1.5 - juneau-marshall-rdf.jmr.RdfDetails.jmr.UriProperties -->
<div class='topic'>
<p>
Bean properties of type <c>java.net.URI</c> or <c>java.net.URL</c> have special meaning to the
RDF serializer.
They are interpreted as resource identifiers.
</p>
<p>
In the following code, we're adding 2 new properties.
The first property is annotated with <ja>@Beanp</ja> to identify that this property is the resource
identifier for this bean.
The second un-annotated property is interpreted as a reference to another resource.
</p>
<p class='bjava'>
<jk>public class</jk> Person {
<jc>// Bean properties</jc>
<ja>@Rdf</ja>(beanUri=<jk>true</jk>)
<jk>public</jk> URI <jf>uri</jf>;
<jk>public</jk> URI <jf>addressBookUri</jf>;
...
<jc>// Normal constructor</jc>
<jk>public</jk> Person(<jk>int</jk> <jv>id</jv>, String <jv>name</jv>, String <jv>uri</jv>, String <jv>addressBookUri</jv>) <jk>throws</jk> URISyntaxException {
<jk>this</jk>.<jf>id</jf> = <jv>id</jv>;
<jk>this</jk>.<jf>name</jf> = <jv>name</jv>;
<jk>this</jk>.<jf>uri</jf> = <jk>new</jk> URI(<jv>uri</jv>);
<jk>this</jk>.<jf>addressBookUri</jf> = <jk>new</jk> URI(<jv>addressBookUri</jv>);
}
}
</p>
<p>
We alter our code to pass in values for these new properties.
</p>
<p class='bjava'>
<jc>// Create our bean.</jc>
Person <jv>person</jv> = <jk>new</jk> Person(1, <js>"John Smith"</js>, <js>"http://sample/addressBook/person/1"</js>,
<js>"http://sample/addressBook"</js>);
</p>
<p>
Now when we run the sample code, we get the following:
</p>
<p class='bxml'>
<xt>&lt;rdf:RDF</xt>
<xa>xmlns:rdf</xa>=<xs>"http://www.w3.org/1999/02/22-rdf-syntax-ns#"</xs>
<xa>xmlns:j</xa>=<xs>"http://www.apache.org/juneau/"</xs>
<xa>xmlns:jp</xa>=<xs>"http://www.apache.org/juneaubp/"</xs>
<xa>xmlns:per</xa>=<xs>"http://www.apache.org/person/"</xs><xt>&gt;</xt>
<xt>&lt;rdf:Description <b><xa>rdf:about</xa>=<xs>"http://sample/addressBook/person/1"</xs></b>&gt;</xt>
<xt>&lt;per:addressBookUri</xt> <xa>rdf:resource</xa>=<xs>"http://sample/addressBook"</xs><xt>/&gt;</xt>
<xt>&lt;per:id&gt;</xt>1<xt>&lt;/per:id&gt;</xt>
<xt>&lt;per:name&gt;</xt>John Smith<xt>&lt;/per:name&gt;</xt>
<xt>&lt;/rdf:Description&gt;</xt>
<xt>&lt;/rdf:RDF&gt;</xt>
</p>
<p>
The <a href="org/apache/juneau/annotation/Uri.html" title="annotation in org.apache.juneau.annotation"><code>@Uri</code></a> annotation can also be used on classes and properties
to identify them as URLs when they're not instances of <c>java.net.URI</c> or <c>java.net.URL</c>
(not needed if <c><ja>@Rdf</ja>(beanUri=<jk>true</jk>)</c> is already specified).
</p>
<p>
The following properties would have produced the same output as before.
Note that the <ja>@URI</ja> annotation is only needed on the second property.
</p>
<p class='bjava'>
<jk>public class</jk> Person {
<jc>// Bean properties</jc>
<ja>@Rdf</ja>(beanUri=<jk>true</jk>) <jk>public</jk> String <jf>uri</jf>;
<ja>@URI</ja> <jk>public</jk> String <jf>addressBookUri</jf>;
</p>
<p>
Also take note of the <a href="org/apache/juneau/serializer/Serializer.Builder.html#uriResolution-org.apache.juneau.UriResolution-"><code>Serializer.Builder.uriResolution(UriResolution)</code></a>,
<a href="org/apache/juneau/serializer/Serializer.Builder.html#uriRelativity-org.apache.juneau.UriRelativity-"><code>Serializer.Builder.uriRelativity(UriRelativity)</code></a>, and
and <a href="org/apache/juneau/serializer/Serializer.Builder.html#uriContext-org.apache.juneau.UriContext-"><code>Serializer.Builder.uriContext(UriContext)</code></a>
settings that can be specified on the serializer to resolve relative and context-root-relative URIs to
fully-qualified URIs.
</p>
<p>
This can be useful if you want to keep the URI authority and context root information out of the bean logic
layer.
</p>
<p>
The following code produces the same output as before but the URIs on the beans are relative.
</p>
<p class='bjava'>
<jc>// Create a new serializer with readable output.</jc>
RdfSerializer <jv>serializer</jv> = RdfSerializer.<jsm>create</jsm>()
.xmlabbrev()
.rdfxml_tab(3);
.relativeUriBase(<js>"http://myhost/sample"</js>);
.absolutePathUriBase(<js>"http://myhost"</js>)
.build();
<jc>// Create our bean.</jc>
Person <jv>person</jv> = <jk>new</jk> Person(1, <js>"John Smith"</js>, <js>"person/1"</js>, <js>"/"</js>);
<jc>// Serialize the bean to RDF/XML.</jc>
String <jv>rdfXml</jv> = <jv>serializer</jv>.serialize(<jv>person</jv>);
</p>
</div>
</div><!-- END: 3.1.5 - juneau-marshall-rdf.jmr.RdfDetails.jmr.UriProperties -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.RootProperty' id='juneau-marshall-rdf.jmr.RdfDetails.jmr.RootProperty'>3.1.6 - Root Property</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 3.1.6 - juneau-marshall-rdf.jmr.RdfDetails.jmr.RootProperty -->
<div class='topic'>
<p>
For all RDF languages, the POJO objects get broken down into simple triplets.
Unfortunately, for tree-structured data like the POJOs shown above, this causes the root node of the tree
to become lost.
There is no easy way to identify that <c>person/1</c> is the root node in our tree once in triplet
form, and in some cases it's impossible.
</p>
<p>
By default, the <a href="org/apache/juneau/jena/RdfParser.html" title="class in org.apache.juneau.jena"><code>RdfParser</code></a> class handles this by scanning all the nodes and
identifying the nodes without incoming references.
However, this is inefficient, especially for large models.
And in cases where the root node is referenced by another node in the model by URL, it's not possible to
locate the root at all.
</p>
<p>
To resolve this issue, the property <dc>RdfSerializer.RDF_addRootProperty</dc>
was introduced.
When enabled, this adds a special <c>root</c> attribute to the root node to make it easy to locate
by the parser.
</p>
<p>
To enable, set the <jsf>RDF_addRootProperty</jsf> property to <jk>true</jk> on the serializer:
</p>
<p class='bjava'>
<jc>// Create a new serializer.</jc>
RdfSerializer <jv>serializer</jv> = RdfSerializer.<jsm>create</jsm>()
.xmlabbrev()
.rdfxml_tab(3),
.addRootProperty()
.build();
</p>
<p>
Now when we rerun the sample code, we'll see the added <c>root</c> attribute on the root resource.
</p>
<p class='bxml'>
<xt>&lt;rdf:RDF</xt>
<xa>xmlns:rdf</xa>=<xs>"http://www.w3.org/1999/02/22-rdf-syntax-ns#"</xs>
<xa>xmlns:j</xa>=<xs>"http://www.apache.org/juneau/"</xs>
<xa>xmlns:jp</xa>=<xs>"http://www.apache.org/juneaubp/"</xs>
<xa>xmlns:per</xa>=<xs>"http://www.apache.org/person/"</xs>
<xa>xmlns:mail</xa>=<xs>"http://www.apache.org/mail/"</xs>
<xa>xmlns:addr</xa>=<xs>"http://www.apache.org/address/"</xs><xt>&gt;</xt>
<xt>&lt;rdf:Description <xa>rdf:about</xa>=<xs>"http://sample/addressBook/person/1"</xs>&gt;</xt>
<b><xt>&lt;j:root&gt;</xt>true<xt>&lt;/j:root&gt;</xt></b>
<xt>&lt;per:addressBookUri</xt> <xa>rdf:resource</xa>=<xs>"http://sample/addressBook"</xs><xt>/&gt;</xt>
<xt>&lt;per:id&gt;</xt>1<xt>&lt;/per:id&gt;</xt>
<xt>&lt;per:name&gt;</xt>John Smith<xt>&lt;/per:name&gt;</xt>
<xt>&lt;per:addresses&gt;</xt>
<xt>&lt;rdf:Seq&gt;</xt>
<xt>&lt;rdf:li&gt;</xt>
<xt>&lt;rdf:Description <xa>rdf:about</xa>=<xs>"http://sample/addressBook/address/1"</xs>&gt;</xt>
<xt>&lt;addr:personUri <xa>rdf:resource</xa>=<xs>"http://sample/addressBook/person/1"</xs>/&gt;</xt>
<xt>&lt;addr:id&gt;</xt>1<xt>&lt;/addr:id&gt;</xt>
<xt>&lt;mail:street&gt;</xt>100 Main Street<xt>&lt;/mail:street&gt;</xt>
<xt>&lt;mail:city&gt;</xt>Anywhereville<xt>&lt;/mail:city&gt;</xt>
<xt>&lt;mail:state&gt;</xt>NY<xt>&lt;/mail:state&gt;</xt>
<xt>&lt;mail:zip&gt;</xt>12345<xt>&lt;/mail:zip&gt;</xt>
<xt>&lt;addr:isCurrent&gt;</xt>true<xt>&lt;/addr:isCurrent&gt;</xt>
<xt>&lt;/rdf:Description&gt;</xt>
<xt>&lt;/rdf:li&gt;</xt>
<xt>&lt;/rdf:Seq&gt;</xt>
<xt>&lt;/per:addresses&gt;</xt>
<xt>&lt;/rdf:Description&gt;</xt>
<xt>&lt;/rdf:RDF&gt;</xt>
</p>
</div>
</div><!-- END: 3.1.6 - juneau-marshall-rdf.jmr.RdfDetails.jmr.RootProperty -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-marshall-rdf.jmr.RdfDetails.jmr.TypedLiterals' id='juneau-marshall-rdf.jmr.RdfDetails.jmr.TypedLiterals'>3.1.7 - Typed Literals</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 3.1.7 - juneau-marshall-rdf.jmr.RdfDetails.jmr.TypedLiterals -->
<div class='topic'>
<p>
XML-Schema data-types can be added to non-<c>String</c> literals through the
<dc>RdfSerializer.RDF_addLiteralTypes</dc> setting.
</p>
<p>
To enable, set the <jsf>RDF_addLiteralTypes</jsf> property to <jk>true</jk> on the serializer:
</p>
<p class='bjava'>
<jc>// Create a new serializer (revert back to namespace autodetection).</jc>
RdfSerializer <jv>serializer</jv> = RdfSerializer.<jsm>create</jsm>()
.xmlabbrev()
.rdfxml_tab(3),
.addLiteralTypes()
.build();
</p>
<p>
Now when we rerun the sample code, we'll see the added <c>root</c> attribute on the root resource.
</p>
<p class='bxml'>
<xt>&lt;rdf:RDF</xt>
<xa>xmlns:rdf</xa>=<xs>"http://www.w3.org/1999/02/22-rdf-syntax-ns#"</xs>
<xa>xmlns:j</xa>=<xs>"http://www.apache.org/juneau/"</xs>
<xa>xmlns:jp</xa>=<xs>"http://www.apache.org/juneaubp/"</xs>
<xa>xmlns:per</xa>=<xs>"http://www.apache.org/person/"</xs>
<xa>xmlns:mail</xa>=<xs>"http://www.apache.org/mail/"</xs>
<xa>xmlns:addr</xa>=<xs>"http://www.apache.org/address/"</xs><xt>&gt;</xt>
<xt>&lt;rdf:Description <xa>rdf:about</xa>=<xs>"http://sample/addressBook/person/1"</xs>&gt;</xt>
<xt>&lt;per:addressBookUri</xt> <xa>rdf:resource</xa>=<xs>"http://sample/addressBook"</xs><xt>/&gt;</xt>
<xt>&lt;per:id</xt> <b><xa>rdf:datatype</xa>=<xs>"http://www.w3.org/2001/XMLSchema#int"</xs></b><xt>&gt;</xt>1<xt>&lt;/per:id&gt;</xt>
<xt>&lt;per:name&gt;</xt>John Smith<xt>&lt;/per:name&gt;</xt>
<xt>&lt;per:addresses&gt;</xt>
<xt>&lt;rdf:Seq&gt;</xt>
<xt>&lt;rdf:li&gt;</xt>
<xt>&lt;rdf:Description <xa>rdf:about</xa>=<xs>"http://sample/addressBook/address/1"</xs>&gt;</xt>
<xt>&lt;addr:personUri <xa>rdf:resource</xa>=<xs>"http://sample/addressBook/person/1"</xs>/&gt;</xt>
<xt>&lt;addr:id</xt> <b><xa>rdf:datatype</xa>=<xs>"http://www.w3.org/2001/XMLSchema#int"</xs></b>&gt;</xt>1<xt>&lt;/addr:id&gt;</xt>
<xt>&lt;mail:street&gt;</xt>100 Main Street<xt>&lt;/mail:street&gt;</xt>
<xt>&lt;mail:city&gt;</xt>Anywhereville<xt>&lt;/mail:city&gt;</xt>
<xt>&lt;mail:state&gt;</xt>NY<xt>&lt;/mail:state&gt;</xt>
<xt>&lt;mail:zip</xt> <b><xa>rdf:datatype</xa>=<xs>"http://www.w3.org/2001/XMLSchema#int"</xs></b>&gt;</xt>12345<xt>&lt;/mail:zip&gt;</xt>
<xt>&lt;addr:isCurrent</xt> <b><xa>rdf:datatype</xa>=<xs>"http://www.w3.org/2001/XMLSchema#boolean"</xs></b>&gt;</xt>true<xt>&lt;/addr:isCurrent&gt;</xt>
<xt>&lt;/rdf:Description&gt;</xt>
<xt>&lt;/rdf:li&gt;</xt>
<xt>&lt;/rdf:Seq&gt;</xt>
<xt>&lt;/per:addresses&gt;</xt>
<xt>&lt;/rdf:Description&gt;</xt>
<xt>&lt;/rdf:RDF&gt;</xt>
</p>
</div>
</div><!-- END: 3.1.7 - juneau-marshall-rdf.jmr.RdfDetails.jmr.TypedLiterals -->
</div><!-- END: 3.1 - juneau-marshall-rdf.jmr.RdfDetails -->
</div><!-- END: 3 - juneau-marshall-rdf -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-dto' id='juneau-dto'>4 - juneau-dto</a></h2>
<div class='topic'><!-- START: 4 - juneau-dto -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-dto<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-dto-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.dto_9.0.0.jar
</p>
<p>
The <c>juneau-dto</c> library contains several predefined POJOs for generating commonly-used document types.
This section describes support for these POJOs.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-dto.jd.Html5' id='juneau-dto.jd.Html5'>4.1 - HTML5</a></h3>
<div class='topic'><!-- START: 4.1 - juneau-dto.jd.Html5 -->
<div class='topic'>
<p>
The Juneau HTML5 DTOs are simply beans with fluent-style setters that allow you to quickly construct HTML
fragments as Java objects. These object can then be serialized to HTML using one of the existing HTML
serializers, or to other languages such as JSON using the JSON serializers.
</p>
<p>
The <a href="org/apache/juneau/dto/html5/HtmlBuilder.html" title="class in org.apache.juneau.dto.html5"><code>HtmlBuilder</code></a> class is a utility class with predefined static methods
that allow you to easily construct DTO instances in a minimal amount of code.
</p>
<p>
The following examples show how to create common HTML DOM objects.
</p>
<table class='styled w800'>
<tr>
<th>Java code</th>
<th>HTML</th>
</tr>
<tr>
<td class='code'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
Object <jv>mytable</jv> =
<jsm>table</jsm>(
<jsm>tr</jsm>(
<jsm>th</jsm>(<js>"c1"</js>),
<jsm>th</jsm>(<js>"c2"</js>)
),
<jsm>tr</jsm>(
<jsm>td</jsm>(<js>"v1"</js>),
<jsm>td</jsm>(<js>"v2"</js>)
)
);
String <jv>html</jv> = Html.<jsm>of</jsm>(<jv>mytablE</jv>);
</td>
<td class='code'><xt>
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;<xv>c1</xv>&lt;/th&gt;
&lt;th&gt;<xv>c2</xv>&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;<xv>v1</xv>&lt;/td&gt;
&lt;td&gt;<xv>v2</xv>&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
Object <jv>mydiv</jv> =
<jsm>div</jsm>().align(<js>"center"</js>).onmouseover(<js>"alert(\"boo!\");"</js>)
.children(
<jsm>p</jsm>(<js>"Juneau supports "</js>, <jsm>b</jsm>(<jsm>i</jsm>(<js>"mixed"</js>)), <js>" content!"</js>)
);
String <jv>html</jv> = Html.<jsm>of</jsm>(<jv>mydiv</jv>);
</td>
<td class='code'><xt>
&lt;div <xa>align</xa>=<xs>'center'</xs> <xa>onmouseover</xa>=<xs>'alert("boo!");'</xs>&gt;
&lt;p&gt;<xv>Juneau supports </xv>&lt;b&gt;&lt;i&gt;<xv>mixed</xv>&lt;/i&gt;&lt;/b&gt; <xv>content!</xv>&lt;/p&gt;
&lt;/table&gt;
</xt></td>
</tr>
<tr>
<td class='code'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
Object <jv>myform</jv> =
<jsm>form</jsm>().action(<js>"/submit"</js>).method(<js>"POST"</js>)
.children(
<js>"Position (1-10000): "</js>, <jsm>input</jsm>(<js>"number"</js>).name(<js>"pos"</js>).value(1), <jsm>br</jsm>(),
<js>"Limit (1-10000): "</js>, <jsm>input</jsm>(<js>"number"</js>).name(<js>"limit"</js>).value(100), <jsm>br</jsm>(),
<jsm>button</jsm>(<js>"submit"</js>, <js>"Submit"</js>),
<jsm>button</jsm>(<js>"reset"</js>, <js>"Reset"</js>)
);
String <jv>html</jv> = Html.<jsm>of</jsm>(<jv>myform</jv>);
</td>
<td class='code'><xt>
&lt;form <xa>action</xa>=<xs>'/submit'</xs> <xa>method</xa>=<xs>'POST'</xs>&gt;
<xv>Position (1-10000):</xv> &lt;input <xa>name</xa>=<xs>'pos'</xs> <xa>type</xa>=<xs>'number'</xs>
<xa>value</xa>=<xs>'1'</xs>/&gt;&lt;br/&gt;
<xv>Limit (1-10000):</xv> &lt;input <xa>name</xa>=<xs>'pos'</xs> <xa>type</xa>=<xs>'number'</xs>
<xa>value</xa>=<xs>'100'</xs>/&gt;&lt;br/&gt;
&lt;button <xa>type</xa>=<xs>'submit'</xs>&gt;<xv>Submit</xv>&lt;/button&gt;
&lt;button <xa>type</xa>=<xs>'reset'</xs>&gt;<xv>Reset</xv>&lt;/button&gt;
&lt;/form&gt;
</xt></td>
</tr>
</table>
<p>
Using the HTML5 DTOs, you should be able to construct any valid HTML5 from full document bodies
to any possible fragments.
</p>
<p>
The <a href="org/apache/juneau/html/HtmlParser.html" title="class in org.apache.juneau.html"><code>HtmlParser</code></a> class can be used convert these HTML documents back
into POJOs.
</p>
<p>
Other serializers and parsers (e.g. <a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a>) can be used to
represent these POJOs in languages other than HTML.
</p>
<h5 class='toc'>Additional Information - org.apache.juneau.dto.html5</h5>
<ol class='toc'>
<li><p><a class='doclink' href='org/apache/juneau/dto/html5/package-summary.html#Overview'>Overview</a></p>
<ol>
<li><p><a class='doclink' href='org/apache/juneau/dto/html5/package-summary.html#Serialize'>Generating HTML5</a></p>
<li><p><a class='doclink' href='org/apache/juneau/dto/html5/package-summary.html#Parse'>Parsing HTML5</a></p>
<li><p><a class='doclink' href='org/apache/juneau/dto/html5/package-summary.html#Templates'>HTML5 Templates</a></p>
</ol>
</ol>
</div>
</div><!-- END: 4.1 - juneau-dto.jd.Html5 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-dto.jd.Atom' id='juneau-dto.jd.Atom'>4.2 - Atom</a></h3>
<div class='topic'><!-- START: 4.2 - juneau-dto.jd.Atom -->
<div class='topic'>
<p>
The Juneau ATOM feed DTOs are simply beans with fluent-style setters.
The following code shows a feed being created programmatically using the
<a href="org/apache/juneau/dto/atom/AtomBuilder.html" title="class in org.apache.juneau.dto.atom"><code>AtomBuilder</code></a> class.
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.atom.AtomBuilder.*;
Feed <jv>feed</jv> =
<jsm>feed</jsm>(<js>"tag:juneau.apache.org"</js>, <js>"Juneau ATOM specification"</js>, <js>"2016-01-02T03:04:05Z"</js>)
.setSubtitle(<jsm>text</jsm>(<js>"html"</js>).setText(<js>"Describes &lt;em&gt;stuff&lt;/em&gt; about Juneau"</js>))
.setLinks(
<jsm>link</jsm>(<js>"alternate"</js>, <js>"text/html"</js>, <js>"http://juneau.apache.org"</js>).setHreflang(<js>"en"</js>),
<jsm>link</jsm>(<js>"self"</js>, <js>"application/atom+xml"</js>, <js>"http://juneau.apache.org/feed.atom"</js>)
)
.setRights(<js>"Copyright (c) ..."</js>)
.setGenerator(
<jsm>generator</jsm>(<js>"Juneau"</js>).setUri(<js>"http://juneau.apache.org/"</js>).setVersion(<js>"1.0"</js>)
)
.setEntries(
<jsm>entry</jsm>(<js>"tag:juneau.sample.com,2013:1.2345"</js>, <js>"Juneau ATOM specification snapshot"</js>, <js>"2016-01-02T03:04:05Z"</js>)
.setLinks(
<jsm>link</jsm><js>"alternate"</js>, <js>"text/html"</js>, <js>"http://juneau.apache.org/juneau.atom"</js>),
<jsm>link</jsm>(<js>"enclosure"</js>, <js>"audio/mpeg"</js>, <js>"http://juneau.apache.org/audio/juneau_podcast.mp3"</js>).setLength(1337)
)
.setPublished(<js>"2016-01-02T03:04:05Z"</js>)
.setAuthors(
<jsm>person</jsm>(<js>"Jane Smith"</js>).setUri(<js>"http://juneau.apache.org/"</js>).setEmail(<js>"janesmith@apache.org"</js>)
)
.setContributors(
<jsm>person</jsm>(<js>"John Smith"</js>)
)
.setContent(
<jsm>content</jsm>(<js>"xhtml"</js>)
.setLang(<js>"en"</js>)
.setBase(<js>"http://www.apache.org/"</js>)
.setText(<js>"&lt;div&gt;&lt;p&gt;&lt;i&gt;[Update: Juneau supports ATOM.]&lt;/i&gt;&lt;/p&gt;&lt;/div&gt;"</js>)
)
);
</p>
<p>
To serialize this to ATOM, use the <a href="org/apache/juneau/xml/XmlSerializer.html" title="class in org.apache.juneau.xml"><code>XmlSerializer</code></a> class:
</p>
<h5 class='figure'>Example with no namespaces</h5>
<p class='bjava'>
<jc>// Create a serializer with readable output, no namespaces yet.</jc>
XmlSerializer <jv>serializer</jv> = XmlSerializer.<jsm>create</jsm>().sq().ws().build();
<jc>// Serialize to ATOM/XML</jc>
String <jv>atomXml</jv> = <jv>serializer</jv>.serialize(<jv>feed</jv>);
</p>
<h5 class='figure'>Results</h5>
<p class='bxml'>
<xt>&lt;feed&gt;</xt>
<xt>&lt;id&gt;</xt>
tag:juneau.apache.org
<xt>&lt;/id&gt;</xt>
<xt>&lt;link</xt> <xa>href</xa>=<xs>'http://juneau.apache.org/'</xs> <xa>rel</xa>=<xs>'alternate'</xs>
<xa>type</xa>=<xs>'text/html'</xs> <xa>hreflang</xa>=<xs>'en'</xs>/<xt>&gt;</xt>
<xt>&lt;link</xt> <xa>href</xa>=<xs>'http://juneau.apache.org/feed.atom'</xs> <xa>rel</xa>=<xs>'self'</xs>
<xa>type</xa>=<xs>'application/atom+xml'</xs>/<xt>&gt;</xt>
<xt>&lt;rights&gt;</xt>
Copyright (c) ...
<xt>&lt;/rights&gt;</xt>
<xt>&lt;title</xt> <xa>type</xa>=<xs>'text'</xs>&gt;</xt>
Juneau ATOM specification
<xt>&lt;/title&gt;</xt>
<xt>&lt;updated&gt;</xt>2016-01-02T03:04:05Z<xt>&lt;/updated&gt;</xt>
<xt>&lt;generator</xt> <xa>uri</xa>=<xs>'http://juneau.apache.org/'</xs> <xa>version</xa>=<xs>'1.0'</xs><xt>&gt;</xt>
Juneau
<xt>&lt;/generator&gt;</xt>
<xt>&lt;subtitle</xt> <xa>type</xa>=<xs>'html'</xs><xt>&gt;</xt>
Describes <xt>&lt;em&gt;</xt>stuff<xt>&lt;/em&gt;</xt> about Juneau
<xt>&lt;/subtitle&gt;</xt>
<xt>&lt;entry&gt;</xt>
<xt>&lt;author&gt;</xt>
<xt>&lt;name&gt;</xt>Jane Smith<xt>&lt;/name&gt;</xt>
<xt>&lt;uri&gt;</xt>http://juneau.apache.org/<xt>&lt;/uri&gt;</xt>
<xt>&lt;email&gt;</xt>janesmith@apache.org<xt>&lt;/email&gt;</xt>
<xt>&lt;/author&gt;</xt>
<xt>&lt;contributor&gt;</xt>
<xt>&lt;name&gt;</xt>John Smith<xt>&lt;/name&gt;</xt>
<xt>&lt;/contributor&gt;</xt>
<xt>&lt;id&gt;</xt>
tag:juneau.apache.org
<xt>&lt;/id&gt;</xt>
<xt>&lt;link</xt> <xa>href</xa>=<xs>'http://juneau.apache.org/juneau.atom'</xs>
<xa>rel</xa>=<xs>'alternate'</xs> <xa>type</xa>=<xs>'text/html'</xs>/<xt>&gt;</xt>
<xt>&lt;link</xt> <xa>href</xa>=<xs>'http://juneau.apache.org/audio/juneau_podcast.mp3'</xs>
<xa>rel</xa>=<xs>'enclosure'</xs> <xa>type</xa>=<xs>'audio/mpeg'</xs> <xa>length</xa>=<xs>'12345'</xs>/<xt>&gt;</xt>
<xt>&lt;title&gt;</xt>
Juneau ATOM specification snapshot
<xt>&lt;/title&gt;</xt>
<xt>&lt;updated&gt;</xt>2016-01-02T03:04:05Z<xt>&lt;/updated&gt;</xt>
<xt>&lt;content</xt> <xa>base</xa>=<xs>'http://www.apache.org/'</xs> <xa>lang</xa>=<xs>'en'</xs>
<xa>type</xa>=<xs>'xhtml'</xs><xt>&gt;</xt>
<xt>&lt;div</xt> <xa>xmlns</xa>=<xs>"http://www.w3.org/1999/xhtml"</xs>
<xt>&gt;&lt;p&gt;&lt;i&gt;</xt>[Update: Juneau supports ATOM.]<xt>&lt;/i&gt;&lt;/p&gt;&lt;/div&gt;</xt>
<xt>&lt;/content&gt;</xt>
<xt>&lt;published&gt;</xt>2016-01-02T03:04:05Z<xt>&lt;/published&gt;</xt>
<xt>&lt;/entry&gt;</xt>
<xt>&lt;/feed&gt;</xt>
</p>
<p>
The <a href="org/apache/juneau/xml/XmlParser.html" title="class in org.apache.juneau.xml"><code>XmlParser</code></a> class can be used convert these Atom documents back into POJOs.
</p>
<p>
Other serializers and parsers (e.g. <a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a>) can be used to
represent these POJOs in languages other than XML.
</p>
<h5 class='toc'>Additional Information - org.apache.juneau.dto.atom</h5>
<ol class='toc'>
<li><p><a class='doclink' href='org/apache/juneau/dto/atom/package-summary.html#Overview'>Overview</a></p>
<ol>
<li><p><a class='doclink' href='org/apache/juneau/dto/atom/package-summary.html#Serialize'>Serializing ATOM feeds</a></p>
<ol>
<li><p><a class='doclink' href='org/apache/juneau/dto/atom/package-summary.html#AtomJson'>ATOM/JSON</a></p>
<li><p><a class='doclink' href='org/apache/juneau/dto/atom/package-summary.html#AtomRdfXml'>ATOM/RDF/XML</a></p>
<li><p><a class='doclink' href='org/apache/juneau/dto/atom/package-summary.html#AtomHtml'>ATOM/HTML</a></p>
</ol>
<li><p><a class='doclink' href='org/apache/juneau/dto/atom/package-summary.html#Parse'>Parsing ATOM feeds</a></p>
</ol>
</ol>
</div>
</div><!-- END: 4.2 - juneau-dto.jd.Atom -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-dto.jd.Swagger' id='juneau-dto.jd.Swagger'>4.3 - Swagger</a></h3>
<div class='topic'><!-- START: 4.3 - juneau-dto.jd.Swagger -->
<div class='topic'>
<p>
The Juneau Swagger DTOs are simply beans with fluent-style setters that allow you to quickly construct
Swagger documents as Java objects.
These object can then be serialized to JSON using one of the existing JSON serializers, or to other
languages such as XML or HTML using the other serializers.
</p>
<p>
The <a href="org/apache/juneau/dto/swagger/SwaggerBuilder.html" title="class in org.apache.juneau.dto.swagger"><code>SwaggerBuilder</code></a> class is a utility class with predefined static
methods that allow you to easily construct DTO instances in a minimal amount of code.
</p>
<p>
The following is an example Swagger document from the
<a href='http://petstore.swagger.io/'>Swagger website</a>.
</p>
<p class='bjson'>
{
<jok>"swagger"</jok>: <jov>"2.0"</jov>,
<jok>"info"</jok>: {
<jok>"title"</jok>: <jov>"Swagger Petstore"</jov>,
<jok>"description"</jok>: <jov>"This is a sample server Petstore server."</jov>,
<jok>"version"</jok>: <jov>"1.0.0"</jov>,
<jok>"termsOfService"</jok>: <jov>"http://swagger.io/terms/"</jov>,
<jok>"contact"</jok>: {
<jok>"email"</jok>: <jov>"apiteam@swagger.io"</jov>
},
<jok>"license"</jok>: {
<jok>"name"</jok>: <jov>"Apache 2.0"</jov>,
<jok>"url"</jok>: <jov>"http://www.apache.org/licenses/LICENSE-2.0.html"</jov>
}
},
<jok>"host"</jok>: <jov>"petstore.swagger.io"</jov>,
<jok>"basePath"</jok>: <jov>"/v2"</jov>,
<jok>"tags"</jok>: [
{
<jok>"name"</jok>: <jov>"pet"</jov>,
<jok>"description"</jok>: <jov>"Everything about your Pets"</jov>,
<jok>"externalDocs"</jok>: {
<jok>"description"</jok>: <jov>"Find out more"</jov>,
<jok>"url"</jok>: <jov>"http://swagger.io"</jov>
}
}
],
<jok>"schemes"</jok>: [
<jov>"http"</jov>
],
<jok>"paths"</jok>: {
<jok>"/pet"</jok>: {
<jok>"post"</jok>: {
<jok>"tags"</jok>: [
<jov>"pet"</jov>
],
<jok>"summary"</jok>: <jov>"Add a new pet to the store"</jov>,
<jok>"description"</jok>: <jov>""</jov>,
<jok>"operationId"</jok>: <jov>"addPet"</jov>,
<jok>"consumes"</jok>: [
<jov>"application/json"</jov>,
<jov>"text/xml"</jov>
],
<jok>"produces"</jok>: [
<jov>"application/json"</jov>,
<jov>"text/xml"</jov>
],
<jok>"parameters"</jok>: [
{
<jok>"in"</jok>: <jov>"body"</jov>,
<jok>"name"</jok>: <jov>"body"</jov>,
<jok>"description"</jok>: <jov>"Pet object that needs to be added to the store"</jov>,
<jok>"required"</jok>: <jov>true</jov>
}
],
<jok>"responses"</jok>: {
<jok>"405"</jok>: {
<jok>"description"</jok>: <jov>"Invalid input"</jov>
}
}
}
}
}
}
</p>
<p>
This document can be generated by the following Java code:
</p>
<p class='bjava'>
<jk>static import</jk> org.apache.juneau.dto.swagger.SwaggerBuilder.*;
Swagger <jv>swagger</jv> = <jsm>swagger</jsm>()
.setSwagger(<js>"2.0"</js>)
.setInfo(
<jsm>info</jsm>(<js>"Swagger Petstore"</js>, <js>"1.0.0"</js>)
.setDescription(<js>"This is a sample server Petstore server."</js>)
.setTermsOfService(<js>"http://swagger.io/terms/"</js>)
.setContact(
<jsm>contact</jsm>().setEmail(<js>"apiteam@swagger.io"</js>)
)
.setLicense(
<jsm>license</jsm>(<js>"Apache 2.0"</js>).setUrl(<js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>)
)
)
.setHost(<js>"petstore.swagger.io"</js>)
.setBasePath(<js>"/v2"</js>)
.setTags(
<jsm>tag</jsm>(<js>"pet"</js>).setDescription(<js>"Everything about your Pets"</js>)
.setExternalDocs(
<jsm>externalDocumentation</jsm>(<js>"http://swagger.io"</js>, <js>"http://swagger.io"</js>)
)
)
.setSchemes(<js>"http"</js>)
.setPath(<js>"/pet"</js>, <js>"post"</js>,
<jsm>operation</jsm>()
.setTags(<js>"pet"</js>)
.setSummary(<js>"Add a new pet to the store"</js>)
.setDescription(<js>""</js>)
.setOperationId(<js>"addPet"</js>)
.setConsumes(MediaType.<jsf>JSON</jsf>, MediaType.<jsf>XML</jsf>)
.setProduces(MediaType.<jsf>JSON</jsf>, MediaType.<jsf>XML</jsf>)
.setParameters(
<jsm>parameterInfo</jsm>(<js>"body"</js>, <js>"body"</js>)
.setDescription(<js>"Pet object that needs to be added to the store"</js>)
.setRequired(<jk>true</jk>)
)
.setResponse(405, <jsm>responseInfo</jsm>(<js>"Invalid input"</js>))
);
<jc>// Serialize using JSON serializer.</jc>
String <jv>swaggerJson</jv> = Json.<jsm>of</jsm>(<jv>swagger</jv>);
<jc>// Or just use toString().</jc>
String <jv>swaggerJson</jv> = <jv>swagger</jv>.toString();
</p>
<p>
Methods that take in beans and collections of beans can also take in JSON representations
of those objects.
</p>
<p class='bjava'>
<jc>// Pass in a JSON object representation of an Info object.</jc>
<jv>swagger</jv>.info(<js>"{title:'Swagger Petstore',...}"</js>);
</p>
<p>
Properties can also be accessed via the <a href="org/apache/juneau/dto/swagger/SwaggerElement.html#get-java.lang.String-java.lang.Class-"><code>SwaggerElement.get(String,Class)</code></a>
and <a href="org/apache/juneau/dto/swagger/SwaggerElement.html#set-java.lang.String-java.lang.Object-"><code>SwaggerElement.set(String,Object)</code></a> methods.
These methods can also be used to set and retrieve non-Swagger attributes such as
<js>"$ref"</js> (which is not a part of the Swagger spec but is part of the JSON Schema spec).
</p>
<p class='bjava'>
<jc>// Set a non-standard attribute.</jc>
<jv>swagger</jv>.set(<js>"$ref"</js>, <js>"http://foo.com"</js>);
<jc>// Retrieve a non-standard attribute.</jc>
URI <jv>ref</jv> = <jv>swagger</jv>.get(<js>"$ref"</js>, URI.<jk>class</jk>);
</p>
<p>
Swagger docs can be parsed back into Swagger beans using the following code:
</p>
<p class='bjava'>
Swagger <jv>swagger</jv> = JsonParser.<jsf>DEFAULT</jsf>.parse(<jv>swaggerJson</jv>, Swagger.<jk>class</jk>);
</p>
</div>
</div><!-- END: 4.3 - juneau-dto.jd.Swagger -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-dto.jd.SwaggerUi' id='juneau-dto.jd.SwaggerUi'>4.4 - Swagger UI</a></h3>
<div class='topic'><!-- START: 4.4 - juneau-dto.jd.SwaggerUi -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/dto/swagger/ui/SwaggerUI.html" title="class in org.apache.juneau.dto.swagger.ui"><code>SwaggerUI</code></a> class is a DTO class for generating Swagger user interfaces
from <a href="org/apache/juneau/dto/swagger/Swagger.html" title="class in org.apache.juneau.dto.swagger"><code>Swagger</code></a> beans.
</p>
<p>
The <c>PetStore</c> example described later provides an example of auto-generated Swagger JSON:
</p>
<img class='bordered w900' src='doc-files/jd.SwaggerUI.json.png'>
<p>
Using <a href="org/apache/juneau/dto/swagger/ui/SwaggerUI.html" title="class in org.apache.juneau.dto.swagger.ui"><code>SwaggerUI</code></a>, we're able to render that JSON as a Swagger user interface
when the request is asking for HTML:
</p>
<img class='bordered w900' src='doc-files/jd.SwaggerUI.html.png'>
<p>
The class itself is nothing more than a POJO swap that swaps out <a href="org/apache/juneau/dto/swagger/Swagger.html" title="class in org.apache.juneau.dto.swagger"><code>Swagger</code></a> beans
with <a href="org/apache/juneau/dto/html5/Div.html" title="class in org.apache.juneau.dto.html5"><code>Div</code></a> elements:
</p>
<p class='bjava'>
<jk>public class</jk> SwaggerUI <jk>extends</jk> ObjectSwap&lt;Swagger,Div&gt; {
<ja>@Override</ja>
<jk>public</jk> MediaType[] forMediaTypes() {
<jc>// Only use this swap when the Accept type is HTML.</jc>
<jk>return new</jk> MediaType[] {MediaType.<jsf>HTML</jsf>};
}
<ja>@Override</ja>
<jk>public</jk> Div swap(BeanSession <jv>beanSession</jv>, Swagger <jv>swagger</jv>) <jk>throws</jk> Exception {
...
}
}
</p>
<p>
The <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> class (describe later) shows how this swap is used in the REST interface to
generate the Swagger UI shown above:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
<jc>// Allow OPTIONS requests to be simulated using ?method=OPTIONS query parameter.</jc>
allowedMethodParams=<js>"OPTIONS"</js>,
...
)
<ja>@BeanConfig</ja>(
<jc>// POJO swaps to apply to all serializers/parsers.</jc>
swaps={
<jc>// Use the SwaggerUI swap when rendering Swagger beans.</jc>
SwaggerUI.<jk>class</jk>
}
)
<jk>public abstract class</jk> BasicRestServlet <jk>extends</jk> RestServlet <jk>implements</jk> BasicRestConfig {
<jd>/**
* [OPTIONS /*] - Show resource options.
*/</jd>
<ja>@RestOp</ja>(
method=<jsf>OPTIONS</jsf>,
path=<js>"/*"</js>,
summary=<js>"Swagger documentation"</js>,
description=<js>"Swagger documentation for this resource."</js>
)
<ja>@HtmlDocConfig</ja>(
<jc>// Override the nav links for the swagger page.</jc>
navlinks={
<js>"back: servlet:/"</js>,
<js>"json: servlet:/?method=OPTIONS&amp;Accept=text/json&amp;plainText=true"</js>
},
<jc>// Never show aside contents of page inherited from class.</jc>
aside="<js>NONE"</js>
)
<jk>public</jk> Swagger getOptions(RestRequest <jv>req</jv>) {
<jc>// Localized Swagger for this resource is available through the RestRequest object.</jc>
<jk>return</jk> <jv>req</jv>.getSwagger();
}
}
</p>
</div>
</div><!-- END: 4.4 - juneau-dto.jd.SwaggerUi -->
</div><!-- END: 4 - juneau-dto -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-config' id='juneau-config'>5 - juneau-config</a></h2>
<div class='topic'><!-- START: 5 - juneau-config -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-config<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-config-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.config_9.0.0.jar
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.Overview' id='juneau-config.jc.Overview'>5.1 - Overview</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 5.1 - juneau-config.jc.Overview -->
<div class='topic'>
<p>
The <c>juneau-config</c> library contains a powerful API for creating and using INI-style config files.
</p>
<h5 class='figure'>Example configuration file:</h5>
<p class='bini'>
<cc># A set of entries</cc>
<cs>[Section1]</cs>
<cc># An integer</cc>
<ck>key1</ck> = <cv>1</cv>
<cc># A boolean</cc>
<ck>key2</ck> = <cv>true</cv>
<cc># An array</cc>
<ck>key3</ck> = <cv>1,2,3</cv>
<cc># A POJO</cc>
<ck>key4</ck> = <cv>http://bar</cv>
</p>
<p>
Config files are accessed through the <a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a> class which
are created through the <a href="org/apache/juneau/config/Config.Builder.html" title="class in org.apache.juneau.config"><code>Config.Builder</code></a> class.
Builder creator methods are provided on the <c>Config</c> class:
</p>
<p class='bjava'>
<jc>// Create a Config object</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>().name(<js>"MyConfig.cfg"</js>).build();
<jc>// Shortcut</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).build();
</p>
<p>
Once instantiated, reading values from the config are simple:
</p>
<p class='bjava'>
<jc>// Read values from section #1</jc>
<jk>int</jk> <jv>key1</jv> = <jv>config</jv>.get(<js>"Section1/key1"</js>).asInteger().orElse(-1);
<jk>boolean</jk> <jv>key2</jv> = <jv>config</jv>.get(<js>"Section1/key2"</js>).asBoolean().orElse(<jk>false</jk>);
<jk>int</jk>[] <jv>key3</jv> = <jv>config</jv>.get(<js>"Section1/key3"</js>).as(<jk>int</jk>[].<jk>class</jk>).orElse(<jk>null</jk>);
URL <jv>key4</jv> = <jv>config</jv>.get(<js>"Section1/key4"</js>).as(URL.<jk>class</jk>).orElse(<jk>null</jk>);
</p>
<p>
The config language may look simple but it is a very powerful feature with many capabilities including:
</p>
<ul class='spaced-list'>
<li>
Support for storing and retrieving any of the following data types:
<ul>
<li>Primitives
<li>POJOs
<li>Beans
<li>Arrays, Maps, and Collections of anything
<li>Binary data
</ul>
<li>
Transactional modifications with commit/rollback capabilities.
<li>
A listener API.
<li>
Filesystem watcher integration allowing changes on the file system to be reflected in real-time.
<li>
Modifications through the Config class (e.g. add/remove/modify sections and keys, add/remove comments and whitespace, etc...)
<b>DO NOT</b> cause loss of formatting in the file.
<br>All existing whitespace and comments are preserved for you!
<li>
Value encoding for added security.
<li>
Support for SVL variables.
<li>
Directly populate beans from config sections.
<li>
Accessing config sections through Java interface proxies.
<li>
An extensible storage API allows you to write your own config storage (e.g. storage in databases or the cloud).
</ul>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.Overview.jc.SyntaxRules' id='juneau-config.jc.Overview.jc.SyntaxRules'>5.1.1 - Syntax Rules</a></h4>
<div class='topic'><!-- START: 5.1.1 - juneau-config.jc.Overview.jc.SyntaxRules -->
<div class='topic'>
<ul class='spaced-list'>
<li>
Each config file contains zero or more sections containing zero or more entries:
<p class='bini'>
<cs>[Section1]</cs>
<ck>key1</ck> = <cv>1</cv>
<cs>[Section2]</cs>
<ck>key1</ck> = <cv>2</cv>
</p>
<li>
Unicode escapes can be used in values.
<p class='bini'>
<ck>key1</ck> = <cv>\u0070\u0075\u0062\u006c\u0069\u0063</cv>
</p>
<li>
Comment lines start with the <js>'#'</js> character and can be placed on lines before sections and entries:
<p class='bini'>
<cc># A comment about this section</cc>
<cs>[Section1]</cs>
<cc># A comment about this entry</cc>
<ck>key1</ck> = <cv>1</cv>
</p>
<li>
Comments can also be placed on the same line as entries:
<p class='bini'>
<ck>key1</ck> = <cv>1</cv> <cc># A comment about this entry</cc>
</p>
<li>
Values containing <js>'#'</js> must be escaped to prevent identification as a comment character:
<p class='bini'>
<ck>valueContainingPound</ck> = <cv>Value containing \u0023 character</cv>
</p>
<br>Likewise, <js>'\'</js> should be escaped to prevent confusion with unicode escapes.
<li>
Values containing newlines can span multiple lines.
<br>Subsequent lines start with a tab character.
<p class='bini'>
<ck>multiLineValue</ck> =
<cv>line 1,</cv>
<cv>line 2,</cv>
<cv>line 3</cv>
</p>
<br>When retrieved, the above translates to <js>"line1,\nline2,\nline3"</js>.
<li>
Leading and trailing whitespace on values are ignored.
<li>
Whitespace is not ignored within multi-line values (except for the leading tab character on each line).
<li>
Blank lines can be used anywhere in the file.
<p class='bini'>
<cc># A comment line</cc>
<cc># Another comment line</cc>
<cs>[Section1]</cs>
...
</p>
<li>
Values located before any sections are considered part of the no-name section, meaning
they are accessed simply by key and not section/key.
<p class='bini'>
<cc># Top of file</cc>
<cc># Use config.getString("key1") to retrieve.</cc>
<ck>key1</ck> = <cv>val1</cv>
<cc># The first section</cc>
<cs>[Section1]</cs>
<cc># Use config.getString("Section1/key2") to retrieve.</cc>
<ck>key2</ck> = <cv>val2</cv>
</p>
<li>
Section and key names must be at least one character long and not consist of any of the following
characters:
<p class='bini'>
/ \ [ ] = #
</p>
<li>
Whitespace in section and key names is technically allowed but discouraged.
</ul>
</div>
</div><!-- END: 5.1.1 - juneau-config.jc.Overview.jc.SyntaxRules -->
</div><!-- END: 5.1 - juneau-config.jc.Overview -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ReadingEntries' id='juneau-config.jc.ReadingEntries'>5.2 - Reading Entries</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 5.2 - juneau-config.jc.ReadingEntries -->
<div class='topic'>
<p>
Configuration files can contain entries for anything from primitive types up to complex hierarchies of POJOs consisting of maps, collections, and/or beans.
</p>
<p>
Entries are accessed via the <a href="org/apache/juneau/config/Config.html#get-java.lang.String-"><code>Config.get(String)</code></a> method which returns the following bean:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Entry.html" title="class in org.apache.juneau.config"><code>Entry</code></a>
<ul class='spaced-list'>
<li>Primary methods
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#get--"><code>get()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#isNotEmpty--"><code>isNotEmpty()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#isPresent--"><code>isPresent()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#orElse-java.lang.String-"><code>orElse(String)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#orElseGet-java.util.function.Supplier-"><code>orElseGet(Supplier)</code></a>
</ul>
</li>
<li>Conversion methods
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#as-java.lang.Class-"><code>as(Class)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#as-org.apache.juneau.parser.Parser-java.lang.Class-"><code>as(Parser,Class)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#as-org.apache.juneau.parser.Parser-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>as(Parser,Type,Type...)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#as-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>as(Type,Type...)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asBoolean--"><code>asBoolean()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asBytes--"><code>asBytes()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asDouble--"><code>asDouble()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asFloat--"><code>asFloat()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asInteger--"><code>asInteger()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asList--"><code>asList()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asList-org.apache.juneau.parser.Parser-"><code>asList(Parser)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asLong--"><code>asLong()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asMap--"><code>asMap()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asMap-org.apache.juneau.parser.Parser-"><code>asMap(Parser)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asString--"><code>asString()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#asStringArray--"><code>asStringArray()</code></a>
</ul>
</li>
<li>Metadata methods
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#getComment--"><code>getComment()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#getKey--"><code>getKey()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#getModifiers--"><code>getModifiers()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#getPreLines--"><code>getPreLines()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Entry.html#getValue--"><code>getValue()</code></a>
</ul>
</li>
</ul>
</li>
</ul>
<p>
The most common case for configuration values are primitives.
</p>
<p class='bini'>
<cc># A string</cc>
<ck>key1</ck> = <cv>foo</cv>
<cc># A boolean</cc>
<ck>key2</ck> = <cv>true</cv>
<cc># An integer</cc>
<ck>key3</ck> = <cv>123</cv>
<cc># A long</cc>
<ck>key4</ck> = <cv>10000000000</cv>
<cc># Doubles</cc>
<ck>key5</ck> = <cv>6.67e−11</cv>
<ck>key6</ck> = <cv>Infinity</cv>
</p>
<p>
On integers and longs, <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga.
</p>
<p class='bini'>
<ck>key1</ck> = <cv>100K</cv> <cc># Same as 1024000</cc>
<ck>key2</ck> = <cv>100M</cv> <cc># Same as 104857600</cc>
</p>
<p>
Numbers can also use hexadecimal and octal notation:
</p>
<p class='bini'>
<ck>hex1</ck> = <cv>0x12FE</cv>
<ck>hex2</ck> = <cv>0X12FE</cv>
<ck>octal1</ck> = <cv>01234</cv>
</p>
<p>
Strings with newlines are treated as multi-line values that get broken into separate lines:
</p>
<p class='bini'>
<ck>key1</ck> = <cv>This is a particularly long sentence that we want to split</cv>
<cv>onto separate lines</cv>.
</p>
<p>
Typically, multi-line values are started on the next line for clarity like so:
</p>
<p class='bini'>
<ck>key1</ck> =
<cv>This is a particularly long sentence that we want to split</cv>
<cv>onto separate lines</cv>.
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ReadingEntries.jc.Pojos' id='juneau-config.jc.ReadingEntries.jc.Pojos'>5.2.1 - POJOs</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 5.2.1 - juneau-config.jc.ReadingEntries.jc.Pojos -->
<div class='topic'>
<p>
Entries can also be read as POJOs. In theory, any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>parsable</a> POJO type can be represented
as a config value.
However in practice, we're typically talking about the following:
</p>
<ul>
<li>Objects convertible from Strings.
<li>Beans.
</ul>
<p>
An example of an object convertible from a String was already shown in an example above.
In that case, it was a URL which has a public constructor that takes in a String:
</p>
<p class='bini'>
<cc># A POJO</cc>
<ck>key4</ck> = <cv>http://bar</cv>
</p>
<p class='bjava'>
<jc>// Read values from section #1</jc>
URL <jv>key4</jv> = <jv>config</jv>.get(<js>"Section1/key4"</js>).as(URL.<jk>class</jk>).orElse(<jk>null</jk>);
</p>
<p>
Beans are represented as <a class='doclink' href='#juneau-marshall.jm.JsonDetails.jm.SimplifiedJson'>Simplified JSON</a> by default:
</p>
<p class='bini'>
<jc>// Contact information</jc>
<cs>[ContactInfo]</cs>
<ck>address</ck> =
<cv>{
street: '123 Main Street',
city: 'Anywhere',
state: 'NY',
zip: 12345
}</cv>
</p>
<p class='bjava'>
<jc>// Example bean</jc>
<jk>public class</jk> Address {
<jk>public</jk> String <jf>street</jf>, <jf>city</jf>;
<jk>public</jk> StateEnum <jf>state</jf>;
<jk>public int</jk> <jf>zip</jf>;
}
<jc>// Example usage</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).build();
Address <jv>myAddress</jv> = <jv>config</jv>.get(<js>"ContactInfo/address"</js>).as(Address.<jk>class</jk>).orElse(<jk>null</jk>);
</p>
<p>
The default serializer and parser is registered on the Config through the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.Builder.html" title="class in org.apache.juneau.config"><code>Config.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.Builder.html#serializer-org.apache.juneau.serializer.WriterSerializer-"><code>serializer(WriterSerializer)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.Builder.html#parser-org.apache.juneau.parser.ReaderParser-"><code>parser(ReaderParser)</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 5.2.1 - juneau-config.jc.ReadingEntries.jc.Pojos -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ReadingEntries.jc.Arrays' id='juneau-config.jc.ReadingEntries.jc.Arrays'>5.2.2 - Arrays</a></h4>
<div class='topic'><!-- START: 5.2.2 - juneau-config.jc.ReadingEntries.jc.Arrays -->
<div class='topic'>
<p>
The <c>asStringArray()</c> method allows you to retrieve comma-delimited lists of values:
<p class='bini'>
<ck>key1</ck> = <cv>foo, bar, baz</cv>
</p>
<p class='bjava'>
String[] <jv>key1</jv> = <jv>config</jv>.get(<js>"key1"</js>).asStringArray().orElse(<jk>null</jk>);
</p>
<p>
String arrays can also be represented in JSON when the registered parser is a JSON parser:
</p>
<p class='bini'>
<ck>key1</ck> = <cv>['foo','bar','baz']</cv>
</p>
<p class='bjava'>
String[] <jv>key1</jv> = <jv>config</jv>.get(<js>"key1"</js>).asStringArray().orElse(<jk>null</jk>);
</p>
<p>
Primitive arrays can also be retrieved using the <c>as()</c> and <c>to()</c> methods:
</p>
<p class='bini'>
<ck>key1</ck> = <cv>[1,2,3]</cv>
</p>
<p class='bjava'>
<jk>int</jk>[] <jv>key1</jv> = <jv>config</jv>.get(<js>"key1"</js>).as(<jk>int</jk>[].<jk>class</jk>).orElse(<jk>null</jk>);
</p>
<p>
Arrays of POJOs can also be retrieved using the methods as well:
</p>
<p class='bini'>
<ck>addresses</ck> =
<cv>[
{
street: '123 Main Street',
city: 'Anywhere',
state: 'NY',
zip: 12345
}</cv>,
<cv>{
street: '456 Main Street',
city: 'Anywhere',
state: 'NY',
zip: 12345
}
]</cv>
</p>
<p class='bjava'>
Address[] <jv>addresses</jv> = <jv>config</jv>.get(<js>"addresses"</js>).as(Address[].<jk>class</jk>).orElse(<jk>null</jk>);
</p>
</div>
</div><!-- END: 5.2.2 - juneau-config.jc.ReadingEntries.jc.Arrays -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ReadingEntries.jc.JCFObjects' id='juneau-config.jc.ReadingEntries.jc.JCFObjects'>5.2.3 - Java Collection Framework Objects</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 5.2.3 - juneau-config.jc.ReadingEntries.jc.JCFObjects -->
<div class='topic'>
<p>
Entries can also be read as Java Collection Framework objects.
The <c>Type,Type...</c> arguments allow you to specify the component types for maps and collections.
<c>List</c> class arguments can be followed by zero or one arguments representing the entry types.
<c>Map</c> class arguments can be followed by zero or two arguments representing the key and value types.
The arguments can be chained to produce any data structure consisting of maps, collections, or POJOs.
</p>
<p>
Examples are shown below:
</p>
<ul class='spaced-list'>
<li><c>to(List.<jk>class</jk>)</c>
<br>Produces: <c>List&lt;?&gt;</c>
<li><c>to(LinkedList.<jk>class</jk>)</c>
<br>Produces: <c>LinkedList&lt;?&gt;</c>
<li><c>to(HashSet.<jk>class</jk>, Integer.<jk>class</jk>)</c>
<br>Produces: <c>HashSet&lt;Integer&gt;</c>
<li><c>to(Map.<jk>class</jk>)</c>
<br>Produces: <c>Map&lt;?,?&gt;</c>
<li><c>to(HashMap.<jk>class</jk>)</c>
<br>Produces: <c>HashMap&lt;?,?&gt;</c>
<li><c>to(LinkedHashMap.<jk>class</jk>, String.<jk>class</jk>, MyBean.<jk>class</jk>)</c>
<br>Produces: <c>LinkedHashMap&lt;String,MyBean&gt;</c>
<li><c>to(HashMap.<jk>class</jk>, Integer.<jk>class</jk>, ArrayList.<jk>class</jk>, MyBean[].<jk>class</jk>)</c>
<br>Produces: <c>LinkedHashMap&lt;Integer,ArrayList&lt;MyBean[]&gt;&gt;</c>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bini'>
<ck>addresses</ck> =
<cv>[
{
street: '123 Main Street',
city: 'Anywhere',
state: 'NY',
zip: 12345
}</cv>,
<cv>{
street: '456 Main Street',
city: 'Anywhere',
state: 'NY',
zip: 12345
}
]</cv>
</p>
<p class='bjava'>
List&lt;Address&gt; <jv>addresses</jv> = <jv>config</jv>.get(<js>"addresses"</js>).as(ArrayList.<jk>class</jk>, Address.<jk>class</jk>).orElse(<jk>null</jk>);
</p>
<p>
Oftentimes, it might be useful to parse into the <a href="org/apache/juneau/collections/JsonList.html" title="class in org.apache.juneau.collections"><code>JsonList</code></a> and <a href="org/apache/juneau/collections/JsonMap.html" title="class in org.apache.juneau.collections"><code>JsonMap</code></a>
classes that provide the various convenience methods for working with JSON-like data structures:
</p>
<p class='bjava'>
JsonMap <jv>map</jv> = <jv>config</jv>.get(<js>"key1"</js>).asMap().orElse(<jk>null</jk>);
JsonList <jv>list</jv> = <jv>config</jv>.get(<js>"key2"</js>).asList().orElse(<jk>null</jk>);
</p>
</div>
</div><!-- END: 5.2.3 - juneau-config.jc.ReadingEntries.jc.JCFObjects -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ReadingEntries.jc.BinaryData' id='juneau-config.jc.ReadingEntries.jc.BinaryData'>5.2.4 - Binary Data</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 5.2.4 - juneau-config.jc.ReadingEntries.jc.BinaryData -->
<div class='topic'>
<p>
Entries can also be accessed as binary data.
Binary data can be represented in 3 formats:
</p>
<ul class='spaced-list'>
<li>BASE-64 (default)
<br>Example: <c><js>"Zm9vYmFycw=="</js></c>
<li>Hexadecimal
<br>Example: <c><js>"666F6F62617273"</js></c>
<li>Spaced hexadecimal
<br>Example: <c><js>"66 6F 6F 62 61 72 73"</js></c>
</ul>
<p>
The binary data format is controlled via the following setting:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.Builder.html" title="class in org.apache.juneau.config"><code>Config.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.Builder.html#binaryFormat-org.apache.juneau.BinaryFormat-"><code>binaryFormat(BinaryFormat)</code></a>
</ul>
</li>
</ul>
<p>
For example:
</p>
<p class='bini'>
<ck>key</ck> = <cv>Zm9vYmFycw==</cv>
</p>
<p class='bjava'>
<jk>byte</jk>[] <jv>bytes</jv> = <jv>config</jv>.get(<js>"key"</js>).asBytes().orElse(<jk>null</jk>);
</p>
<p>
Binary lines can be split up into separate lines for readability:
</p>
<p class='bini'>
<ck>key</ck> =
<cv>Zm9vYm
Fycw==</cv>
</p>
<p>
Binary data line wrapping can be controlled via the following setting:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.Builder.html" title="class in org.apache.juneau.config"><code>Config.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.Builder.html#binaryLineLength-int-"><code>binaryLineLength(int)</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 5.2.4 - juneau-config.jc.ReadingEntries.jc.BinaryData -->
</div><!-- END: 5.2 - juneau-config.jc.ReadingEntries -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.Variables' id='juneau-config.jc.Variables'>5.3 - Variables</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 5.3 - juneau-config.jc.Variables -->
<div class='topic'>
<p>
Config files can contain variables that get resolved dynamically using the previously-described <a href="org/apache/juneau/svl/VarResolver.html" title="class in org.apache.juneau.svl"><code>VarResolver</code></a> API.
</p>
<h5 class='figure'>Example:</h5>
<p class='bini'>
<cc>#--------------------------</cc>
<cc># My section</cc>
<cc>#--------------------------</cc>
<cs>[MySection]</cs>
<cc># A system property</cc>
<ck>locale</ck> = <cv>$S{java.locale, en_US}</cv>
<cc># An environment variable</cc>
<ck>path</ck> = <cv>$E{PATH, unknown}</cv>
<cc># Another value in this config file</cc>
<ck>anotherLocale</ck> = <cv>$C{MySection/locale}</cv>
<cc># Look for system property, or env var if that doesn't exist, or a default value if that doesn't exist.</cc>
<ck>nested</ck> = <cv>$S{mySystemProperty,$E{MY_ENV_VAR,$C{MySection/anotherLocale}}}</cv>
<cc># A POJO with embedded variables</cc>
<ck>aBean</ck> = <cv>{foo:'$S{foo}',baz:$C{MySection/anInt}}</cv>
</p>
<p class='bjava'>
Config <jv>config</jv> = Config.<jsm>create</jsm>().build();
Locale <jv>locale</jv> = <jv>config</jv>.get(<js>"MySection/locale"</js>).as(Locale.<jk>class</jk>).orElse(<jk>null</jk>);
String <jv>path</jv> = <jv>config</jv>.get(<js>"MySection/path"</js>).asString().orElse(<jk>null</jk>);
<jk>int</jk> <jv>sameAsAnInt</jv> = <jv>config</jv>.get(<js>"MySection/sameAsAnInt"</js>).asInteger().orElse(<jk>null</jk>);
ABean <jv>bean</jv> = <jv>config</jv>.get(<js>"MySection/aBean"</js>).as(ABean.<jk>class</jk>).orElse(<jk>null</jk>);
</p>
<p>
By default, <c>Configs</c> use the <a href="org/apache/juneau/svl/VarResolver.html#DEFAULT"><code>VarResolver.DEFAULT</code></a> variable resolver
which provides support for the following variables and constructs:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/svl/vars/SystemPropertiesVar.html" title="class in org.apache.juneau.svl.vars"><code>SystemPropertiesVar</code></a> - <c>$S{key[,default]}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/EnvVariablesVar.html" title="class in org.apache.juneau.svl.vars"><code>EnvVariablesVar</code></a> - <c>$E{key[,default]}</c>
<li class='jc'><a href="org/apache/juneau/config/vars/ConfigVar.html" title="class in org.apache.juneau.config.vars"><code>ConfigVar</code></a> - <c>$C{key[,default]}</c>
</ul>
<p>
The variable resolver is controlled via the following setting:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.Builder.html" title="class in org.apache.juneau.config"><code>Config.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.Builder.html#varResolver-org.apache.juneau.svl.VarResolver-"><code>varResolver(VarResolver)</code></a>
</ul>
</li>
</ul>
<p>
Additionally, the following method can be used to retrieve a <c>Config</c> with a different variable resolver:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.html#resolving-org.apache.juneau.svl.VarResolverSession-"><code>resolving(VarResolverSession)</code></a>
</ul>
</li>
</ul>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.Variables.jc.LogicVariables' id='juneau-config.jc.Variables.jc.LogicVariables'>5.3.1 - Logic Variables</a></h4>
<div class='topic'><!-- START: 5.3.1 - juneau-config.jc.Variables.jc.LogicVariables -->
<div class='topic'>
<p>
The default variable resolver also provides the following logic variables for performing simple logical operations:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/svl/vars/IfVar.html" title="class in org.apache.juneau.svl.vars"><code>IfVar</code></a> - <c>$IF{arg,then[,else]}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/SwitchVar.html" title="class in org.apache.juneau.svl.vars"><code>SwitchVar</code></a> - <c>$SW{arg,pattern1:then1[,pattern2:then2...]}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/CoalesceVar.html" title="class in org.apache.juneau.svl.vars"><code>CoalesceVar</code></a> - <c>$CO{arg1[,arg2...]}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/PatternMatchVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternMatchVar</code></a> - <c>$PM{arg,pattern}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/NotEmptyVar.html" title="class in org.apache.juneau.svl.vars"><code>NotEmptyVar</code></a> - <c>$NE{arg}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/UpperCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>UpperCaseVar</code></a> - <c>$UC{arg}</c>
<li class='jc'><a href="org/apache/juneau/svl/vars/LowerCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>LowerCaseVar</code></a> - <c>$LC{arg}</c>
</ul>
<p>
The <c>$IF</c> variable can be used for simple if/else logic:
</p>
<p class='bini'>
<cc># Value set to 'foo' if myBooleanProperty is true</cc>
<ck>key1</ck> =
<cv>$IF{
$S{myBooleanProperty},
foo
}</cv>
<cc># Value set to 'foo' if myBooleanProperty is true, 'bar' if false.</cc>
<ck>key2</ck> =
<cv>$IF{
$S{myBooleanProperty},
foo,
bar
}</cv>
<cc># Value set to key1 value if myBooleanProperty is true, key2 value if false.</cc>
<ck>key3</ck> =
<cv>$IF{
$S{myBooleanProperty},
$C{key1},
$C{key2}
}</cv>
</p>
<p>
The <c>$SW</c> variable can be used for switch blocks based on pattern matching:
</p>
<p class='bini'>
<cc># Shell command depends on the OS</cc>
<ck>shellCommand</ck> =
<cv>$SW{
$LC{$S{os.name}},
*win*: bat,
linux: bash,
*: sh
}</cv>
</p>
<p>
The <c>$CO</c> variable can be used for coalescing of values (finding the first non-null/empty match):
</p>
<p class='bini'>
<cc># Debug flag can be enabled by system property or environment variable.</cc>
<ck>debug</ck> =
<cv>$CO{
$S{debug},
$E{DEBUG},
false
}</cv>
</p>
<p>
The <c>$PM</c> variable can be used for calculating boolean values:
</p>
<p class='bini'>
<cc># Debug flag can be enabled by system property or environment variable.</cc>
<ck>isWindows</ck> =
<cv>$PM{
$LC{$S{os.name}},
*win*
}</cv>
</p>
</div>
</div><!-- END: 5.3.1 - juneau-config.jc.Variables.jc.LogicVariables -->
</div><!-- END: 5.3 - juneau-config.jc.Variables -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ModdedEntries' id='juneau-config.jc.ModdedEntries'>5.4 - Modded/Encoded Entries</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 5.4 - juneau-config.jc.ModdedEntries -->
<div class='topic'>
<p>
The following method can be used to associates entry modifiers to a config:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.Builder.html" title="class in org.apache.juneau.config"><code>Config.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/config/Config.Builder.html#mods-org.apache.juneau.config.mod.Mod...-"><code>mods(Mod...)</code></a>
</ul>
</li>
</ul>
<p>
Mods are used to modify values before being persisted. This can be used to
replace or encode sensitive information. They are denoted by a single
character that gets appended between angle brackets on the property name (e.g. <ck>key&lt;X&gt;</ck>).
Multiple modifiers can be denoted by multiple characters (e.g. <ck>key&lt;XYZ&gt;</ck>) and
are applied/removed in the order denoted.
</p>
<p>
The framework comes built-in with a simple <a href="org/apache/juneau/config/mod/XorEncodeMod.html" title="class in org.apache.juneau.config.mod"><code>xor-encode</code></a> mod tied
to the <js>'*'</js> character. The following shows how it is used:
</p>
<p class='bini'>
<cs>[MyHost]</cs>
<ck>url</ck> = <cv>http://localhost:9080/foo</cv>
<ck>user</ck> = <cv>me</cv>
<ck>password&lt;*&gt;</ck> = <cv>{AwwJVhwUQFZEMg==}</cv>
</p>
<p>
Custom encoders can be used to provide your own encoding support by implementing the <a href="org/apache/juneau/config/mod/Mod.html" title="class in org.apache.juneau.config.mod"><code>Mod</code></a> class.
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/config/mod/Mod.html" title="class in org.apache.juneau.config.mod"><code>Mod</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/mod/Mod.html#apply-java.lang.String-"><code>apply(String)</code></a>
<li class='jm'><a href="org/apache/juneau/config/mod/Mod.html#remove-java.lang.String-"><code>remove(String)</code></a>
<li class='jm'><a href="org/apache/juneau/config/mod/Mod.html#isApplied-java.lang.String-"><code>isApplied(String)</code></a>
</ul>
</li>
</ul>
<p>
Unmodified values are encoded when the file is saved using the <a href="org/apache/juneau/config/Config.html#commit--"><code>Config.commit()</code></a> method.
They can also be encoded immediately by calling <a href="org/apache/juneau/config/Config.html#applyMods--"><code>Config.applyMods()</code></a> which can typically
be done during JVM startup to immediately encode any unencoded passwords in the file.
</p>
</div>
</div><!-- END: 5.4 - juneau-config.jc.ModdedEntries -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.Sections' id='juneau-config.jc.Sections'>5.5 - Sections</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 5.5 - juneau-config.jc.Sections -->
<div class='topic'>
<p>
Config sections can be retrieved in-bulk using the
<a href="org/apache/juneau/config/Config.html#getSection-java.lang.String-"><code>Config.getSection(String)</code></a> method. It returns the following bean:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Section.html" title="class in org.apache.juneau.config"><code>Section</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Section.html#asBean-java.lang.Class-"><code>asBean(Class)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Section.html#asBean-java.lang.Class-boolean-"><code>asBean(Class,boolean)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Section.html#asInterface-java.lang.Class-"><code>asInterface(Class)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Section.html#asMap--"><code>asMap()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Section.html#isPresent--"><code>isPresent()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Section.html#writeToBean-java.lang.Object-boolean-"><code>writeToBean(Object,boolean)</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/config/Section.html#asMap--"><code>asMap()</code></a>
method allows you to access a section as simple key/value pairs.
</p>
<h5 class='figure'>Example:</h5>
<p class='bini'>
<jc>// Example config file</jc>
<cs>[MyAddress]</cs>
<ck>street</ck> = <cv>123 Main Street</cv>
<ck>city</ck> = <cv>Anywhere</cv>
<ck>state</ck> = <cv>NY</cv>
<ck>zip</ck> = <cv>12345</cv>
</p>
<p class='bjava'>
<jc>// Example usage</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).build();
JsonMap <jv>map</jv> = <jv>config</jv>.getSection(<js>"MyAddress"</js>).asMap().get();
String <jv>street</jv> = <jv>map</jv>.getString(<js>"street"</js>);
String <jv>city</jv> = <jv>map</jv>.getString(<js>"city"</js>);
String <jv>state</jv> = <jv>map</jv>.getString(<js>"state"</js>);
<jk>int</jk> <jv>zip</jv> = <jv>map</jv>.getInt(<js>"zip"</js>);
</p>
<p>
Maps created this way are snapshot copies of the section at the time of the method call.
</p>
<p>
Config files can also be used to directly populate beans using
<a href="org/apache/juneau/config/Section.html#asBean-java.lang.Class-"><code>asBean()</code></a> or <a href="org/apache/juneau/config/Section.html#writeToBean-java.lang.Object-boolean-"><code>writeToBean()</code></a>.
</p>
<h5 class='figure'>Example:</h5>
<p class='bini'>
<jc>// Example config file</jc>
<cs>[MyAddress]</cs>
<ck>street</ck> = <cv>123 Main Street</cv>
<ck>city</ck> = <cv>Anywhere</cv>
<ck>state</ck> = <cv>NY</cv>
<ck>zip</ck> = <cv>12345</cv>
</p>
<p class='bjava'>
<jc>// Example bean</jc>
<jk>public class</jk> Address {
<jk>public</jk> String <jf>street</jf>, <jf>city</jf>;
<jk>public</jk> StateEnum <jf>state</jf>;
<jk>public int</jk> <jf>zip</jf>;
}
<jc>// Example usage</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).build();
Address <jv>myAddress</jv> = <jv>config</jv>.getSection(<js>"MyAddress"</js>).as(Address.<jk>class</jk>).orElse(<jk>null</jk>);
</p>
<p>
Like maps, beans created this way are snapshot copies of the section at the time of the method call.
</p>
<p>
Config sections can also be accessed via interface proxies using
<a href="org/apache/juneau/config/Section.html#asInterface-java.lang.Class-"><code>Section.asInterface(Class)</code></a>.
</p>
<p>
While section maps and beans retrieve copies of the configuration data at the time of the method
call, section interfaces can also be use to set values in the underlying configuration.
</p>
<h5 class='figure'>Example:</h5>
<p class='bini'>
<jc>// Example config file</jc>
<cs>[MySection]</cs>
<ck>string</ck> = <cv>foo</cv>
<ck>int</ck> = <cv>123</cv>
<ck>enum</ck> = <cv>ONE</cv>
<ck>bean</ck> = <cv>{foo:'bar',baz:123}</cv>
<ck>int3dArray</ck> = <cv>[[[123,null],null],null]</cv>
<ck>bean1d3dListMap</ck> = <cv>{key:[[[[{foo:'bar',baz:123}]]]]}</cv>
</p>
<p class='bjava'>
<jc>// Example interface.</jc>
<jc>// Setters are optional.</jc>
<jk>public interface</jk> MyConfigInterface {
String getString();
<jk>void</jk> setString(String <jv>value</jv>);
<jk>int</jk> getInt();
<jk>void</jk> setInt(<jk>int</jk> <jv>value</jv>);
MyEnum getEnum();
<jk>void</jk> setEnum(MyEnum <jv>value</jv>);
MyBean getBean();
<jk>void</jk> setBean(MyBean <jv>value</jv>);
<jk>int</jk>[][][] getInt3dArray();
<jk>void</jk> setInt3dArray(<jk>int</jk>[][][] <jv>value</jv>);
Map&lt;String,List&lt;MyBean[][][]&gt;&gt; getBean1d3dListMap();
<jk>void</jk> setBean1d3dListMap(Map&lt;String,List&lt;MyBean[][][]&gt;&gt; <jv>value</jv>);
}
<jc>// Example usage.</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).build();
MyConfigInterface <jv>intf</jv> = <jv>config</jv>.getSection(<js>"MySection"</js>).asInterface(MyConfigInterface.<jk>class</jk>).get();
<jc>// Read a value.</jc>
<jk>int</jk> <jv>myInt</jv> = <jv>intf</jv>.getInt();
<jc>// Write a value.</jc>
<jv>intf</jv>.setBean(<jk>new</jk> MyBean());
<jc>// Commit your changes to the store.</jc>
<jv>config</jv>.commit();
</p>
</div>
</div><!-- END: 5.5 - juneau-config.jc.Sections -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.SettingValues' id='juneau-config.jc.SettingValues'>5.6 - Setting Values</a></h3>
<div class='topic'><!-- START: 5.6 - juneau-config.jc.SettingValues -->
<div class='topic'>
<p>
The following methods allow you to add, remove, and modify entries and sections in a config file:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.html#set-java.lang.String-java.lang.Object-"><code>set(String,Object)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#set-java.lang.String-java.lang.Object-org.apache.juneau.serializer.Serializer-"><code>set(String,Object,Serializer)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#set-java.lang.String-java.lang.Object-org.apache.juneau.serializer.Serializer-java.lang.String-java.lang.String-java.util.List-"><code>set(String,Object,Serializer,String,String,List)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#set-java.lang.String-java.lang.String-"><code>set(String,String)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#remove-java.lang.String-"><code>remove(String)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#setSection-java.lang.String-java.util.List-"><code>setSection(String,List)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#setSection-java.lang.String-java.util.List-java.util.Map-"><code>setSection(String,List,Map)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#removeSection-java.lang.String-"><code>removeSection(String)</code></a>
</ul>
</li>
</ul>
<p class='bjava'>
<jc>// Construct the sample config file programmatically</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).build()
.set(<js>"key1"</js>, 1)
.set(<js>"key2"</js>, <jk>true</jk>)
.set(<js>"key3"</js>, <jk>new int</jk>[]{1,2,3})
.set(<js>"key4"</js>, <jk>new</jk> URI(<js>"http://foo"</js>))
.set(<js>"Section1/key1"</js>, 2)
.set(<js>"Section1/key2"</js>, <jk>false</jk>)
.set(<js>"Section1/key3"</js>, <jk>new int</jk>[]{4,5,6})
.set(<js>"Section1/key4"</js>, <jk>new</jk> URI(<js>"http://bar"</js>))
.commit();
</p>
<p>
The method <a href="org/apache/juneau/config/Config.html#set-java.lang.String-java.lang.Object-org.apache.juneau.serializer.Serializer-java.lang.String-java.lang.String-java.util.List-"><code>Config.set(String,Object,Serializer,String,String,List)</code></a> can be used
for adding comments and pre-lines to entries, and specifying encoded values.
</p>
<p class='bjava'>
<jc>// Set an encoded value with some comments.</jc>
<jv>config</jv>.set(<js>"key1"</js>, 1, <jk>null</jk>, <js>"*"</js>, <js>"Same-line comment"</js>,
Arrays.asList(
<js>"# Comment 1"</js>, <js>""</js>, <js>"# Comment 2"</js>
)
);
</p>
<p class='bini'>
<cc># Comment 1</cc>
<cc># Comment 2</cc>
<ck>key1</ck> = <cv>1</cv> <cc># Same-line comment</cc>
</p>
<p>
The last 4 arguments in <a href="org/apache/juneau/config/Config.html#set-java.lang.String-java.lang.Object-org.apache.juneau.serializer.Serializer-java.lang.String-java.lang.String-java.util.List-"><code>Config.set(String,Object,Serializer,String,String,List)</code></a>
are optional in that if you pass <jk>null</jk>, the current value will not be overwritten.
To unset the same-line comment, you should pass in a blank string.
To remove pre-lines, you should pass in an empty list.
</p>
<p>
Sections can be added with optional pre-lines using the <c>setSection</c> methods:
</p>
<p class='bjava'>
<jc>// Set an encoded value with some comments.</jc>
<jv>config</jv>.setSection(<js>"NewSection"</js>,
Arrays.asList(
<js>"# Section comment 1"</js>, <js>""</js>, <js>"# Section comment 2"</js>
)
);
</p>
<p class='bini'>
<cc># Section comment 1</cc>
<cc># Section comment 2</cc>
<cs>[NewSection]</cs>
</p>
<p>
Changes made to the configuration are transactional in nature.
They are kept in memory until you call the <a href="org/apache/juneau/config/Config.html#commit--"><code>Config.commit()</code></a> method.
Until then, you still see the modified values when you call any of the getters but the modified values
exist only in memory.
</p>
<p>
Changes can be rolled back using the <a href="org/apache/juneau/config/Config.html#rollback--"><code>Config.rollback()</code></a> method.
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.SettingValues.jc.FileSystemChanges' id='juneau-config.jc.SettingValues.jc.FileSystemChanges'>5.6.1 - File System Changes</a></h4>
<div class='topic'><!-- START: 5.6.1 - juneau-config.jc.SettingValues.jc.FileSystemChanges -->
<div class='topic'>
<p>
In general, external file modifications will be detected immediately in the <c>Config</c>
object when a watcher thread is enabled (explained later).
Otherwise, they are detected when a commit is performed.
</p>
<p>
The <c>Config</c> object maintains an in-memory record of all changes that have been applied to it
through getters and setters.
When the underlying file changes, the new contents are loaded and the in-memory changes are then
applied to the new configuration.
This provides the benefits of real-time updates of configurations while not losing any changes made in the JVM.
</p>
<p>
If the <c>commit()</c> method is called on the <c>Config</c> objects after the file system
contents have been modified, we will then reload the configuration from the file system, apply the
changes, and then try to save to the file system again (up to 10 times).
</p>
<p>
If the same entry is both internally and externally modified, the external modification will be
overwritten (although both change events will be seen by listeners).
</p>
</div>
</div><!-- END: 5.6.1 - juneau-config.jc.SettingValues.jc.FileSystemChanges -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.SettingValues.jc.CustomEntrySerialization' id='juneau-config.jc.SettingValues.jc.CustomEntrySerialization'>5.6.2 - Custom Entry Serialization</a></h4>
<div class='topic'><!-- START: 5.6.2 - juneau-config.jc.SettingValues.jc.CustomEntrySerialization -->
<div class='topic'>
<p>
Setter methods that take in a <c>Serializer</c> can be used to provide custom serialization of entries
instead of using the predefined serializer.
</p>
<p class='bjava'>
<jc>// Set an XML value instead of JSON.</jc>
<jv>config</jv>.set(<js>"key1"</js>, <jv>myAddress</jv>, XmlSerializer.<jsf>DEFAULT_SQ_READABLE</jsf>);
</p>
<p class='bini'>
<ck>key1</ck> =
<cv>&lt;address&gt;
&lt;street&gt;123 Main Street&lt;/street&gt;
&lt;city&gt;Anywhere&lt;/city&gt;
&lt;state&gt;NY&lt;/state&gt;
&lt;zip&gt;12345&lt;/zip&gt;
&lt;/address&gt;</cv>
</p>
<p>
The value can then be retrieved using the equivalent parser:
</p>
<p class='bjava'>
Address <jv>myAddress</jv> = <jv>config</jv>.get(<js>"key1"</js>).as(XmlParser.<jsf>DEFAULT</jsf>, Address.<jk>class</jk>).orElse(<jk>null</jk>);
</p>
</div>
</div><!-- END: 5.6.2 - juneau-config.jc.SettingValues.jc.CustomEntrySerialization -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.SettingValues.jc.BulkSettingValues' id='juneau-config.jc.SettingValues.jc.BulkSettingValues'>5.6.3 - Setting Values in Bulk</a></h4>
<div class='topic'><!-- START: 5.6.3 - juneau-config.jc.SettingValues.jc.BulkSettingValues -->
<div class='topic'>
<p>
The following methods can be used to bulk-load configuration values:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.html#setSection-java.lang.String-java.util.List-java.util.Map-"><code>setSection(String,List,Map)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#load-java.util.Map-"><code>load(Map)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#load-java.io.Reader-boolean-"><code>load(Reader,boolean)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#load-java.lang.String-boolean-"><code>load(String,boolean)</code></a>
</ul>
</li>
</ul>
<p>
Changes can then be committed using the <a href="org/apache/juneau/config/Config.html#commit--"><code>Config.commit()</code></a> method.
</p>
</div>
</div><!-- END: 5.6.3 - juneau-config.jc.SettingValues.jc.BulkSettingValues -->
</div><!-- END: 5.6 - juneau-config.jc.SettingValues -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.Listeners' id='juneau-config.jc.Listeners'>5.7 - Listeners</a></h3>
<div class='topic'><!-- START: 5.7 - juneau-config.jc.Listeners -->
<div class='topic'>
<p>
Configuration change events can be listened for using the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.html#addListener-org.apache.juneau.config.event.ConfigEventListener-"><code>addListener(ConfigEventListener)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#removeListener-org.apache.juneau.config.event.ConfigEventListener-"><code>removeListener(ConfigEventListener)</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/config/event/ConfigEventListener.html" title="interface in org.apache.juneau.config.event"><code>ConfigEventListener</code></a> interface consists of the following method:
</p>
<ul class='javatree'>
<li class='jic'><a href="org/apache/juneau/config/event/ConfigEventListener.html" title="interface in org.apache.juneau.config.event"><code>ConfigEventListener</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/event/ConfigEventListener.html#onConfigChange-org.apache.juneau.config.event.ConfigEvents-"><code>onConfigChange(ConfigEvents)</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/config/event/ConfigEvent.html" title="class in org.apache.juneau.config.event"><code>ConfigEvent</code></a> class provides access to all the information about the updated entry:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/event/ConfigEvent.html" title="class in org.apache.juneau.config.event"><code>ConfigEvent</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/event/ConfigEvent.html#getType--"><code>getType()</code></a>
<li class='jm'><a href="org/apache/juneau/config/event/ConfigEvent.html#getSection--"><code>getSection()</code></a>
<li class='jm'><a href="org/apache/juneau/config/event/ConfigEvent.html#getKey--"><code>getKey()</code></a>
<li class='jm'><a href="org/apache/juneau/config/event/ConfigEvent.html#getValue--"><code>getValue()</code></a>
<li class='jm'><a href="org/apache/juneau/config/event/ConfigEvent.html#getModifiers--"><code>getModifiers()</code></a>
<li class='jm'><a href="org/apache/juneau/config/event/ConfigEvent.html#getComment--"><code>getComment()</code></a>
<li class='jm'><a href="org/apache/juneau/config/event/ConfigEvent.html#getPreLines--"><code>getPreLines</code></a>
</ul>
</li>
</ul>
<p>
The listener method is triggered:
</p>
<ul class='spaced-list'>
<li>After <a href="org/apache/juneau/config/Config.html#commit--"><code>Config.commit()</code></a> is called.
<li>When the file changes on the file system.
</ul>
<p>
In both cases, the listener is triggered after the changes have been committed.
</p>
<p class='bjava'>
<jk>final</jk> Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).build();
<jc>// Add a listener for changes to MySection/key1</jc>
<jv>config</jv>.addListener(
<jk>new</jk> ConfigEventListener() {
<ja>@Override</ja>
<jk>public void</jk> onConfigChange(ConfigEvents <jv>events</jv>) {
<jk>for</jk> (ConfigEvent <jv>event</jv> : <jv>events</jv>) {
<jk>if</jk> (<jv>event</jv>.getType() == <jsf>SET_ENTRY</jsf>) {
String <jv>section</jv> = <jv>event</jv>.getSection();
String <jv>key</jv> = <jv>event</jv>.getKey();
<jk>if</jk> (<jv>section</jv>.equals(<js>"MySection"</js>) &amp;&amp; <jv>key</jv>.equals(<js>"key1"</js>)) {
<jc>// Get the new value from the event.</jc>
String <jv>newVal</jv> = <jv>event</jv>.getValue();
<jc>// Or get the new value from the config (since the change has already been committed).</jc>
<jv>newVal</jv> = <jv>config</jv>.getString(<js>"MySection/key1"</js>);
}
}
}
}
}
)
</p>
</div>
</div><!-- END: 5.7 - juneau-config.jc.Listeners -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.SerializingConfigs' id='juneau-config.jc.SerializingConfigs'>5.8 - Serializing</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 5.8 - juneau-config.jc.SerializingConfigs -->
<div class='topic'>
<p>
The following methods are used for serializing <c>Config</c> objects back into INI files:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.html#writeTo-java.io.Writer-"><code>writeTo(Writer)</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#toString--"><code>toString()</code></a>
</ul>
</li>
</ul>
<p>
Both methods are thread safe.
</p>
</div>
</div><!-- END: 5.8 - juneau-config.jc.SerializingConfigs -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ConfigImports' id='juneau-config.jc.ConfigImports'>5.9 - Imports</a><span class='update'>updated: 8.1.0</span></h3>
<div class='topic'><!-- START: 5.9 - juneau-config.jc.ConfigImports -->
<div class='topic'>
<p>
Configurations can import values from other configurations using the following syntax:
</p>
<p class='bini'>
<cc># Import values from configuration 'ParentConfig'</cc>
<ci>&lt;ParentConfig&gt;</ci>
<cc># Our normal section</cc>
<cs>[Section1]</cs>
...
</p>
<p>
A configuration can contain zero or more imports anywhere in the file.
However, for clarity, imports should normally be placed in the default section of the configuration file.
The resolved configuration is retrieved from the configuration store used for the child configuration.
</p>
<p>
Configuration imports can be nested arbitrarily deep.
</p>
<h5 class='figure'>Example:</h5>
<p class='bini'>
<cc># MyConfig contents</cc>
<ci>&lt;ParentConfig1&gt;</ci>
</p>
<p class='bini'>
<cc># ParentConfig1 contents</cc>
<ci>&lt;ParentConfig2&gt;</ci>
</p>
<p class='bini'>
<cc># ParentConfig2 contents</cc>
<cs>[Foo]</cs>
<ck>bar</ck> = <cv>baz</cv>
</p>
<p class='bjava'>
<jc>// Java code</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig"</js>).build();
String <jv>foo</jv> = <jv>config</jv>.get(<js>"Foo/bar"</js>).get(); <jc>// == "baz"</jc>
</p>
<p>
Values can be overridden by child configurations.
</p>
<h5 class='figure'>Example:</h5>
<p class='bini'>
<cc># MyConfig contents</cc>
<ci>&lt;ParentConfig1&gt;</ci>
<cs>[Foo]</cs>
<ck>bar</ck> = <cv>baz</cv>
</p>
<p class='bini'>
<cc># ParentConfig1 contents</cc>
<ci>&lt;ParentConfig2&gt;</ci>
<cs>[Foo]</cs>
<ck>bar</ck> = <cv>qux</cv>
</p>
<p class='bini'>
<cc># ParentConfig2 contents</cc>
<cs>[Foo]</cs>
<ck>bar</ck> = <cv>quux</cv>
</p>
<p class='bjava'>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig"</js>).build();
String <jv>foo</jv> = <jv>config</jv>.get(<js>"Foo/bar"</js>).get(); <jc>// == "baz"</jc>
</p>
<p>
Changes made to imported configurations are automatically reflected in the child configuration and
partake in the listener API as if the entries were part of the child configuration.
Only non-overridden values trigger listener events. For example, if an imported configuration
defines a value for <js>"Foo/bar"</js> and the child configuration does not, modifications to
<js>"Foo/bar"</js> value in the parent configuration will trigger a listener event in the child config.
However, if the child configuration does also specify a value for <js>"Foo/bar"</js>, a change to the parent
<js>"Foo/bar"</js> will NOT trigger a listener event because the value ends up not being changed from
the perspective of the child configuration.
</p>
<p>
Values can be overwritten in child configurations but the values will only be set in that configuration
and not the imported configuration.
</p>
<p>
Dynamically adding an import will cause change events to be generated for imported values.
</p>
<p class='bini'>
<cc># MyConfig contents starting empty</cc>
</p>
<p class='bini'>
<cc># ParentConfig contents</cc>
<cs>[Foo]</cs>
<ck>bar</ck> = <cv>baz</cv>
</p>
<p class='bjava'>
<jc>// Create our configuration.</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig"</js>).build();
<jc>// Create a listener that sets a flag if "Foo/bar" is set.</jc>
<jk>final boolean</jk>[] <jv>triggered</jv> = <jk>new boolean</jk>[1];
ConfigEventListener <jv>listener</jv> = <jk>new</jk> ConfigEventListener() {
<jk>public void</jk> onConfigChange(ConfigEvents <jv>events</jv>) {
<jv>triggered</jv>[0] = <jv>events</jv>.isKeyModified(<js>"Foo"</js>, <js>"bar"</js>));
}
};
<jv>config</jv>.addListener(<jv>listener</jv>);
<jc>// Dynamically add an import to ParentConfig in the default section.</jc>
<jv>config</jv>.setImport(<js>""</js>, <js>"ParentConfig"</js>);
<jv>config</jv>.commit();
<jc>// The new import statement should have triggered a config changes for imported values.</jc>
<jsm>assertTrue</jsm>(<jv>triggered</jv>[0]);
</p>
<p>
Dynamically removing an import has the same effect as removing keys and generates <jsf>REMOVE_ENTRY</jsf> events.
</p>
<p>
Note that when dynamically adding or removing imports, overridden keys in the child config will be filtered
from the change events.
</p>
</div>
</div><!-- END: 5.9 - juneau-config.jc.ConfigImports -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ConfigStores' id='juneau-config.jc.ConfigStores'>5.10 - Config Stores</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 5.10 - juneau-config.jc.ConfigStores -->
<div class='topic'>
<p>
Configuration files are stored in entities called Stores.
</p>
<p>
The methods that need to be implemented on a store are:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/config/store/ConfigStore.html" title="class in org.apache.juneau.config.store"><code>ConfigStore</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/store/ConfigStore.html#read-java.lang.String-"><code>read(String)</code></a>
<li class='jm'><a href="org/apache/juneau/config/store/ConfigStore.html#write-java.lang.String-java.lang.String-java.lang.String-"><code>write(String,String,String)</code></a>
<li class='jm'><a href="org/apache/juneau/config/store/ConfigStore.html#update-java.lang.String-java.lang.String-"><code>update(String,String)</code></a>
</ul>
</li>
</ul>
<p>
Read is self-explanatory:
</p>
<p class='bjava'>
<jk>public</jk> String read(String <jv>name</jv>) {
<jc>// Return the contents of the specified configuration.</jc>
}
</p>
<p>
Write is slightly trickier:
</p>
<p class='bjava'>
<jk>public</jk> String write(String <jv>name</jv>, String <jv>oldContents</jv>, String <jv>newContents</jv>) {
<jc>// If the old contents match the current stored contents, the new contents will get stored,
// and the method returns null indicating success.
// If the old contents DO NOT match the current stored contents (i.e. it was modified in some way),
// the new contents are NOT stored, and the method returns the current stored contents.
// If the old contents are null, then just always write the new contents.</jc>
}
</p>
<p>
The update method is called whenever the stored file gets modified externally:
</p>
<p class='bjava'>
<jk>public</jk> String update(String <jv>name</jv>, String <jv>newContents</jv>) {
<jc>// Do something with the updated contents.</jc>
}
</p>
<p>
Two configuration stores are provided by default:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/store/FileStore.html" title="class in org.apache.juneau.config.store"><code>FileStore</code></a> - File-system storage.
<li class='jc'><a href="org/apache/juneau/config/store/MemoryStore.html" title="class in org.apache.juneau.config.store"><code>MemoryStore</code></a> - In-memory storage.
</ul>
<p>
The store is defined on the <c>Config</c> object via the following setting:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.Builder.html" title="class in org.apache.juneau.config"><code>Config.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.Builder.html#store-org.apache.juneau.config.store.ConfigStore-"><code>store(ConfigStore)</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a config with in-memory storage.</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).store(ConfigMemoryStore.<jsf>DEFAULT</jsf>).build();
</p>
<p>
The default store used is <a href="org/apache/juneau/config/store/FileStore.html#DEFAULT"><code>FileStore.DEFAULT</code></a> which defines
the execution directory as the file system directory to store and retrieve files.
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ConfigStores.jc.MemoryStore' id='juneau-config.jc.ConfigStores.jc.MemoryStore'>5.10.1 - MemoryStore</a></h4>
<div class='topic'><!-- START: 5.10.1 - juneau-config.jc.ConfigStores.jc.MemoryStore -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/config/store/MemoryStore.html" title="class in org.apache.juneau.config.store"><code>MemoryStore</code></a> class is simply an in-memory storage
location for configuration files.
There is no hard persistence and is used primarily for testing purposes.
</p>
<p>
However, the implementation provides a good idea on how stores work (especially the write method):
</p>
<p class='bjava'>
<jk>public class</jk> MemoryStore <jk>extends</jk> ConfigStore {
<jc>// Some methods ommitted.</jc>
<jk>private final</jk> ConcurrentHashMap&lt;String,String&gt; <jf>cache</jf> = <jk>new</jk> ConcurrentHashMap&lt;&gt;();
<ja>@Override</ja> <jc>/* ConfigStore */</jc>
<jk>public synchronized</jk> String read(String <jv>name</jv>) {
<jk>return</jk> <jsm>emptyIfNull</jsm>(<jf>cache</jf>.get(<jv>name</jv>));
}
<ja>@Override</ja> <jc>/* ConfigStore */</jc>
<jk>public synchronized</jk> String write(String <jv>name</jv>, String <jv>expectedContents</jv>, String <jv>newContents</jv>) {
<jc>// This is a no-op.</jc>
<jk>if</jk> (<jsm>isEquals</jsm>(<jv>expectedContents</jv>, <jv>newContents</jv>))
<jk>return null</jk>;
String <jv>currentContents</jv> = read(<jv>name</jv>);
<jk>if</jk> (<jv>expectedContents</jv> != <jk>null</jk> &amp;&amp; ! <jsm>isEquals</jsm>(<jv>currentContents</jv>, <jv>expectedContents</jv>))
<jk>return</jk> currentContents;
update(<jv>name</jv>, <jv>newContents</jv>);
<jc>// Success!</jc>
<jk>return null</jk>;
}
<ja>@Override</ja> <jc>/* ConfigStore */</jc>
<jk>public synchronized</jk> MemoryStore update(String <jv>name</jv>, String <jv>newContents</jv>) {
<jf>cache</jf>.put(<jv>name</jv>, <jv>newContents</jv>);
<jk>super</jk>.update(<jv>name</jv>, <jv>newContents</jv>); <jc>// Trigger any listeners.</jc>
<jk>return this</jk>;
}
}
</p>
</div>
</div><!-- END: 5.10.1 - juneau-config.jc.ConfigStores.jc.MemoryStore -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ConfigStores.jc.FileStore' id='juneau-config.jc.ConfigStores.jc.FileStore'>5.10.2 - FileStore</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 5.10.2 - juneau-config.jc.ConfigStores.jc.FileStore -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/config/store/FileStore.html" title="class in org.apache.juneau.config.store"><code>FileStore</code></a> is the typical store used for configuration files.
It provides the following configurable settings:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/store/FileStore.Builder.html" title="class in org.apache.juneau.config.store"><code>FileStore.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/store/FileStore.Builder.html#charset-java.nio.charset.Charset-"><code>charset(Charset)</code></a>
<li class='jm'><a href="org/apache/juneau/config/store/FileStore.Builder.html#directory-java.io.File-"><code>directory(File)</code></a>
<li class='jm'><a href="org/apache/juneau/config/store/FileStore.Builder.html#updateOnWrite--"><code>updateOnWrite()</code></a>
<li class='jm'><a href="org/apache/juneau/config/store/FileStore.Builder.html#enableWatcher--"><code>enableWatcher()</code></a>
<li class='jm'><a href="org/apache/juneau/config/store/FileStore.Builder.html#watcherSensitivity-org.apache.juneau.config.store.WatcherSensitivity-"><code>watcherSensitivity(WatcherSensitivity)</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a config store with a watcher thread and high sensitivity.</jc>
FileStore <jv>fileStore</jv> = FileStore
.<jsm>create</jsm>()
.directory(<js>"configs"</js>)
.useWatcher()
.watcherSensitivity(<jsf>HIGH</jsf>)
.build();
<jc>// Create a config using the store defined above.</jc>
Config <jv>config</jv> = Config
.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>)
.store(<jv>fileStore</jv>)
.build();
</p>
</div>
</div><!-- END: 5.10.2 - juneau-config.jc.ConfigStores.jc.FileStore -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ConfigStores.jc.CustomStores' id='juneau-config.jc.ConfigStores.jc.CustomStores'>5.10.3 - Custom ConfigStores</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 5.10.3 - juneau-config.jc.ConfigStores.jc.CustomStores -->
<div class='topic'>
<p>
The <c>ConfigStore</c> API has been written to allow easy development of custom configuration storage classes.
</p>
<p>
The example below shows a starting point for an implementation based on polling a relational database.
The source can be found here: <a href="org/apache/juneau/examples/core/config/store/SqlStore.html" title="class in org.apache.juneau.examples.core.config.store"><code>SqlStore</code></a>.
Completing it is left as an exercise:
</p>
<h5 class='figure'>Example Store Class:</h5>
<p class='bjava'>
<jk>public class</jk> SqlStore <jk>extends</jk> ConfigStore {
<jk>private final</jk> String <jf>jdbcUrl</jf>;
<jk>private final</jk> String <jf>tableName</jf>, <jf>nameColumn</jf>, <jf>valueColumn</jf>;
<jk>private final</jk> Timer <jf>watcher</jf>;
<jk>private final</jk> ConcurrentHashMap&låt;String,String> <jf>cache</jf> = <jk>new</jk> ConcurrentHashMap<>();
<jk>protected</jk> SqlStore(ConfigStore.Builder <jv>builder</jv>) {
<jk>super</jk>(<jv>builder</jv>);
<jk>this</jk>.<jf>jdbcUrl</jf> = <jv>builder</jv>.<jf>jdbcUrl</jf>;
<jk>this</jk>.<jf>tableName</jf> = <jv>builder</jv>.<jf>tableName</jf>;
<jk>this</jk>.<jf>nameColumn</jf> = <jv>builder</jv>.<jf>nameColumn</jf>;
<jk>this</jk>.<jf>valueColumn</jf> = <jv>builder</jv>.<jf>valueColumn</jf>;
<jk>int</jk> <jv>pollInterval</jv> = <jv>builder</jv>.<jf>pollInterval</jf>;
TimerTask <jv>timerTask</jv> = <jk>new</jk> TimerTask() {
<ja>@Override</ja>
<jk>public void</jk> run() {
SqlStore.<jk>this</jk>.poll();
}
};
<jk>this</jk>.<jf>watcher</jf> = <jk>new</jk> Timer(<js>"MyTimer"</js>);
<jf>watcher</jf>.scheduleAtFixedRate(<jv>timerTask</jv>, 0, <jv>pollInterval</jv> * 1000);
}
<jk>synchronized void</jk> poll() {
<jc>// Loop through all our entries and find the latest values.</jc>
<jk>for</jk> (Map.Entry&lt;String,String> <jv>e</jv> : <jf>cache</jf>.entrySet()) {
String <jv>name</jv> = <jv>e</jv>.getKey();
String <jv>cacheContents</jv> = <jv>e</jv>.getValue();
String <jv>newContents</jv> = getDatabaseValue(<jv>name</jv>);
<jc>// Change detected!</jc>
<jk>if</jk> (! <jv>cacheContents</jv>.equals(<jv>newContents</jv>))
update(<jv>name</jv>, <jv>newContents</jv>);
}
}
<jc>// Reads the value from the database.</jc>
<jk>protected</jk> String getDatabaseValue(String <jv>name</jv>) {
<jc>// Implement me!</jc>
<jk>return null</jk>;
}
<ja>@Override</ja> <jc>/* ConfigStore */</jc>
<jk>public boolean</jk> exists(String <jv>name</jv>) {
<jc>// Implement me!</jc>
<jk>return false</jk>;
}
<ja>@Override</ja> <jc>/* ConfigStore */</jc>
<jk>public synchronized</jk> String read(String <jv>name</jv>) {
String <jv>contents</jv> = <jf>cache</jf>.get(<jv>name</jv>);
<jk>if</jk> (<jv>contents</jv> == <jk>null</jk>) {
<jv>contents</jv> = getDatabaseValue(<jv>name</jv>);
update(<jv>name</jv>, <jv>contents</jv>);
}
<jk>return</jk> <jv>contents</jv>;
}
<ja>@Override</ja> <jc>/* ConfigStore */</jc>
<jk>public synchronized</jk> String write(String <jv>name</jv>, String <jv>expectedContents</jv>, String <jv>newContents</jv>) {
<jc>// This is a no-op.</jc>
<jk>if</jk> (StringUtils.<jsm>eq</jsm>(<jv>expectedContents</jv>, <jv>newContents</jv>))
<jk>return null</jk>;
String <jv>currentContents</jv> = read(<jv>name</jv>);
<jk>if</jk> (<jv>expectedContents</jv> != <jk>null</jk> && StringUtils.<jsm>ne</jsm>(<jv>currentContents</jv>, <jv>expectedContents</jv>))
<jk>return</jk> <jv>currentContents</jv>;
update(<jv>name</jv>, <jv>newContents</jv>);
<jc>// Success!</jc>
<jk>return null</jk>;
}
<ja>@Override</ja> <jc>/* ConfigStore */</jc>
<jk>public synchronized</jk> SqlStore update(String <jv>name</jv>, String <jv>newContents</jv>) {
<jf>cache</jf>.put(<jv>name</jv>, <jv>newContents</jv>);
<jk>super</jk>.update(<jv>name</jv>, <jv>newContents</jv>); <jc>// Trigger any listeners.</jc>
<jk>return this</jk>;
}
<ja>@Override</ja> <jc>/* Closeable */</jc>
<jk>public synchronized void</jk> close() {
<jk>if</jk> (<jf>watcher</jf> != <jk>null</jk>)
<jf>watcher</jf>.cancel();
}
}
</p>
</div>
</div><!-- END: 5.10.3 - juneau-config.jc.ConfigStores.jc.CustomStores -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ConfigStores.jc.StoreListeners' id='juneau-config.jc.ConfigStores.jc.StoreListeners'>5.10.4 - ConfigStore Listeners</a></h4>
<div class='topic'><!-- START: 5.10.4 - juneau-config.jc.ConfigStores.jc.StoreListeners -->
<div class='topic'>
<p>
The <c>ConfigStore</c> class has the following listener methods:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/config/store/ConfigStore.html" title="class in org.apache.juneau.config.store"><code>ConfigStore</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/store/ConfigStore.html#register-java.lang.String-org.apache.juneau.config.store.ConfigStoreListener-"><code>register(String,ConfigStoreListener)</code></a>
<li class='jm'><a href="org/apache/juneau/config/store/ConfigStore.html#unregister-java.lang.String-org.apache.juneau.config.store.ConfigStoreListener-"><code>unregister(String,ConfigStoreListener)</code></a>
</ul>
</li>
</ul>
<p>
Note that this is a different listener than <a href="org/apache/juneau/config/event/ConfigEventListener.html" title="interface in org.apache.juneau.config.event"><code>ConfigEventListener</code></a>.
In this case, we're just listening for changed files:
</p>
<ul class='javatree'>
<li class='jic'><a href="org/apache/juneau/config/store/ConfigStoreListener.html" title="interface in org.apache.juneau.config.store"><code>ConfigStoreListener</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/store/ConfigStoreListener.html#onChange-java.lang.String-"><code>onChange(String)</code></a>
</ul>
</li>
</ul>
<p>
This listener is used by the <c>Config</c> class to listen for changes on the file system so that it can be
updated in real-time.
</p>
</div>
</div><!-- END: 5.10.4 - juneau-config.jc.ConfigStores.jc.StoreListeners -->
</div><!-- END: 5.10 - juneau-config.jc.ConfigStores -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ReadOnlyConfigs' id='juneau-config.jc.ReadOnlyConfigs'>5.11 - Read-only Configs</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 5.11 - juneau-config.jc.ReadOnlyConfigs -->
<div class='topic'>
<p>
The following settings can be used to create read-only <c>Config</c> objects:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.Builder.html" title="class in org.apache.juneau.config"><code>Config.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.Builder.html#readOnly--"><code>readOnly()</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a read-only config</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).readOnly().build();
</p>
<p>
This causes all methods that make modifications to throw <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/UnsupportedOperationException.html?is-external=true" title="class or interface in java.lang"><code>UnsupportedOperationException</code></a>.
</p>
</div>
</div><!-- END: 5.11 - juneau-config.jc.ReadOnlyConfigs -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.ClosingConfigs' id='juneau-config.jc.ClosingConfigs'>5.12 - Closing Configs</a></h3>
<div class='topic'><!-- START: 5.12 - juneau-config.jc.ClosingConfigs -->
<div class='topic'>
<p>
In general, it's good practice to close Config if you're only creating them temporarily so that
their listeners get unregistered from the underlying storage APIs.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a transient config.</jc>
Config <jv>config</jv> = Config.<jsm>create</jsm>(<js>"MyConfig.cfg"</js>).build();
<jc>// Do stuff with it.</jc>
<jc>// Then close the config to unregister the listeners.</jc>
<jv>config</jv>.close();
</p>
</div>
</div><!-- END: 5.12 - juneau-config.jc.ClosingConfigs -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-config.jc.SystemDefaultConfig' id='juneau-config.jc.SystemDefaultConfig'>5.13 - System Default Config</a><span class='update'>created: 8.0.0, updated: 8.1.0</span></h3>
<div class='topic'><!-- START: 5.13 - juneau-config.jc.SystemDefaultConfig -->
<div class='topic'>
<p>
Each JVM has a system default config. This is a configuration file that serves as the default
configuration for the system. It's accessed using the following static methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/config/Config.html#getSystemDefault--"><code>getSystemDefault()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#setSystemDefault-org.apache.juneau.config.Config-"><code>setSystemDefault(Config)</code></a>
</ul>
</li>
</ul>
<p>
If you do not specify a system default config, one will be automatically searched for.
The search is done in the following order:
</p>
<ol class='spaced-list'>
<li>
If the system property <js>"juneau.configFile"</js> is set, we search for this file in first the home
directory and then the classpath.
<li>
In the home directory:
<ol>
<li><c>&lt;jar-name&gt;.cfg</c>
<li>Any file that end with <c>.cfg</c>. First one matched alphabetically is used.
</ol>
<li>
In the context classpath root package (i.e. inside the jar itself):
<ol>
<li><c>&lt;jar-name&gt;.cfg</c>
<li><c>juneau.cfg</c>
<li><c>default.cfg</c>
<li><c>application.cfg</c>
<li><c>app.cfg</c>
<li><c>settings.cfg</c>
<li><c>application.properties</c>
</ol>
</ol>
<p>
Later in the section on REST resources, we describe how to associate configurations with REST resources
using the <a href="org/apache/juneau/rest/annotation/Rest.html#config--"><code>@Rest(config)</code></a> annotation.
The system default configuration can be referenced with the keyword <c>SYSTEM_DEFAULT</c> like so:
</p>
<p class='bjava'>
<jc>// Always use system default.</jc>
<ja>@Rest</ja>(config=<js>"SYSTEM_DEFAULT"</js>)
<jc>// Use system property if set or the system default if not.</jc>
<ja>@Rest</ja>(config=<js>"$S{juneau.configFile,SYSTEM_DEFAULT}"</js>)
</p>
<p>
By default, all properties in the system default configuration are automatically set as system properties.
This can be disabled by setting the system property <js>"juneau.disableAutoSystemProps"</js> to <js>"true"</js>.
</p>
</div>
</div><!-- END: 5.13 - juneau-config.jc.SystemDefaultConfig -->
</div><!-- END: 5 - juneau-config -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-assertions' id='juneau-assertions'>6 - juneau-assertions</a><span class='update'>created: <b>9.0.0</b></span></h2>
<div class='topic'><!-- START: 6 - juneau-assertions -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-assertions<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-assertions-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.assertions_9.0.0.jar
</p>
<p>
The <a href="org/apache/juneau/assertions/package-summary.html"><code>org.apache.juneau.assertions</code></a> package in Juneau is a powerful API for performing fluent style assertions.
It is used to implement built-in assertion methods on both the server and client side APIs.
But it can also be used standalone for testing.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-assertions.ja.Overview' id='juneau-assertions.ja.Overview'>6.1 - Overview</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 6.1 - juneau-assertions.ja.Overview -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/assertions/package-summary.html"><code>org.apache.juneau.assertions</code></a> package in Juneau is a powerful API for performing fluent style assertions.
It is used throughout the REST client and server APIs for performing inline assertions on REST requests and responses.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a basic REST client with JSON support and download a bean.</jc>
MyBean <jv>bean</jv> = RestClient.<jsm>create</jsm>()
.simpleJson()
.build()
.get(<jsf>URI</jsf>)
.run()
.assertStatus().asCode().is(200)
.assertHeader(<js>"Content-Type"</js>).isMatches(<js>"application/json*"</js>)
.getContent().assertValue().asString().isContains(<js>"OK"</js>)
.getContent().as(MyBean.<jk>class</jk>);
</p>
<ul class='notes'>
<li class='note'>The REST API is described later in the documentation.</i>
</ul>
<p>
The assertions API is designed to be used in both code (as it's done in the REST APIs) or for standalone
use in unit tests.
</p>
<p>
The <a href="org/apache/juneau/assertions/Assertions.html" title="class in org.apache.juneau.assertions"><code>Assertions</code></a> class provides various static methods for invoking assertions on a variety
of object types for simplified unit testing.
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/assertions/Assertions.html" title="class in org.apache.juneau.assertions"><code>Assertions</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertAny-T-"><code>assertAny(T)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertArray-E:A-"><code>assertArray(E[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertBean-T-"><code>assertBean(V)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertBeanList-java.util.List-"><code>assertBeanList(List)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertBoolean-java.lang.Boolean-"><code>assertBoolean(Boolean)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertBooleanArray-boolean:A-"><code>assertBooleanArray(boolean[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertByteArray-byte:A-"><code>assertByteArray(byte[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertBytes-byte:A-"><code>assertBytes(byte[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertBytes-java.io.InputStream-"><code>assertBytes(InputStream)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertCharArray-char:A-"><code>assertCharArray(char[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertCollection-java.util.Collection-"><code>assertCollection(Collection)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertComparable-T-"><code>assertComparable(T)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertDate-java.util.Date-"><code>assertDate(Date)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertDoubleArray-double:A-"><code>assertDoubleArray(double[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertFloatArray-float:A-"><code>assertFloatArray(float[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertIntArray-int:A-"><code>assertIntArray(int[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertInteger-java.lang.Integer-"><code>assertInteger(Integer)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertList-java.util.List-"><code>assertList(List)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertLong-java.lang.Long-"><code>assertLong(Long)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertLongArray-long:A-"><code>assertLongArray(long[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertMap-java.util.Map-"><code>assertMap(Map)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertObject-T-"><code>assertObject(T)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertOptional-java.util.Optional-"><code>assertOptional(Optional)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertReader-java.io.Reader-"><code>assertReader(Reader)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertShortArray-short:A-"><code>assertShortArray(short[])</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertString-java.lang.Object-"><code>assertString(Object)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertStringList-java.util.List-"><code>assertStringList(List)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertThrowable-T-"><code>assertThrowable(V)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertThrown-org.apache.juneau.utils.Snippet-"><code>assertThrown(Snippet)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertVersion-org.apache.juneau.Version-"><code>assertVersion(Version)</code></a>
<li class='jm'><a href="org/apache/juneau/assertions/Assertions.html#assertZonedDateTime-java.time.ZonedDateTime-"><code>assertZonedDateTime(ZonedDateTime)</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.assertions.Assertions.*;
<jk>import static</jk> org.apache.juneau.assertions.AssertionPredicates.*;
<jc>// Check the contents of a string.</jc>
<jsm>assertString</jsm>(<js>"foo, bar"</js>)
.asSplit(<js>","</js>)
.asTrimmed()
.isHas(<js>"foo"</js>, <js>"bar"</js>);
<jc>// Extract a subset of properties from a list of beans and compare using Simplified JSON.</jc>
List&lt;MyBean&gt; <jv>myListOfBeans</jv> = ...;
<jsm>assertBeanList</jsm>(<jv>myListOfBeans</jv>)
.asPropertyMap(<js>"a,b"</js>)
.asJson().is(<js>"[{a:1,b:'foo'}]"</js>);
<jc>// Perform an arbitrary Predicate check against a bean.</jc>
MyBean <jv>myBeans</jv> = ...;
<jsm>assertBean</jsm>(<jv>myBeans</jv>)
.is(<jv>x</jv> -> <jsm>isValidCheck</jsm>(<jv>x</jv>))
<jc>// Check that a list of strings has less than 10 entries and the first</jc>
<jc>// 3 entries are [foo, bar*, null] using assertion predicates.</jc>
List&lt;String&gt; <jv>myListOfStrings</jv> = ...;
<jsm>assertStringList</jsm>(<jv>myListOfStrings</jv>)
.asSize().isLt(10)
.asFirst(3)
.isEach(<jsm>eq</jsm>(<js>"foo"</js>),<jsm>match</jsm>(<js>"bar*"</js>),<jsm>isNull</jsm>())
<jc>// Check that an exception is thrown and is the specified type and has the specified message.</jc>
<jsm>assertThrown</jsm>(()-><jv>myBean</jv>.runBadMethod())
.exists()
.isExactType(RuntimeException.<jk>class</jk>)
.asMessage().is(<js>"foo"</js>);
</p>
<p>
Assertions have 3 categories of methods:
</p>
<ul>
<li>Testing methods.
<li>Transform methods.
<li>Configuration methods.
</ul>
<p>
Testing methods perform an assertion on the specified value and throws a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/AssertionError.html?is-external=true" title="class or interface in java.lang"><code>AssertionError</code></a> if
the test fails. Otherwise, the method returns the original assertion object to allow you to chain the command.
Testing methods start with <c>is</c>.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Test a string.</jc>
<jsm>assertString</jsm>(<jv>myString</jv>)
.isNotNull() <jc>// Perform test and returns original FluentStringAssertion.</jc>
.isNotEmpty(); <jc>// Perform test and returns original FluentStringAssertion.</jc>
</p>
<p>
Transform methods allow you to convert assertions of one type to another type or to convert the tested value to
some other form wrapped in another assertion. Transform methods start with <c>as</c>.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Customize the behavior of an assertion.</jc>
<jsm>assertString</jsm>(<jv>myString</jv>)
.asString() <jc>// Converts to a FluentIntegerAssertion.</jc>
.isLt(100) <jc>// Runs test and returns original FluentStringAssertion.</jc>
.asUc() <jc>// Converts string to uppercase and returns a new FluentStringAssertion.</jc>
.isContains(<js>"FOO"</js>); <jc>// Runs test and returns original FluentStringAssertion.</jc>
</p>
<p>
Configuration methods allow you to tailor the behavior of assertions when they fail. They always return the same assertion object.
Transformed assertions inherit the configurations of the created-by assertions. Configuration methods start with <c>set</c>.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Customize the behavior of an assertion.</jc>
<jsm>assertString</jsm>(<jv>myString</jv>)
.setMsg(<js>"My string was null. Value was {VALUE}."</js>) <jc>// Custom error message when error occurs.</jc>
.setOut(<jv>myPrintWriter</jv>) <jc>// Print error message to a separate writer.</jc>
.setThrowable(MyAssertionThrowable.<jk>class</jk>) <jc>// Throw a customized assertion exception.</jc>
.isNotNull();
</p>
<p>
The following shows the class hierarchy for the <a href="org/apache/juneau/assertions/IntegerAssertion.html" title="class in org.apache.juneau.assertions"><code>IntegerAssertion</code></a> class showing the general
design pattern for assertion classes:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/assertions/Assertion.html" title="class in org.apache.juneau.assertions"><code>Assertion</code></a> - Base class for all assertion objects containing common configuration methods.
<ul>
<li class='jac'><a href="org/apache/juneau/assertions/FluentAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentAssertion&lt;R&gt;</code></a> - Parent class for all fluent assertions.
<ul>
<li class='jac'><a href="org/apache/juneau/assertions/FluentObjectAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentObjectAssertion&lt;T,R&gt;</code></a> - Tests and transforms for general POJOs.
<ul>
<li class='jac'><a href="org/apache/juneau/assertions/FluentComparableAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentComparableAssertion&lt;T <jk>extends</jk> Comparable,R&gt;</code></a> - Tests and transforms for Comparables.
<ul>
<li class='jac'><a href="org/apache/juneau/assertions/FluentIntegerAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentIntegerAssertion&lt;R&gt;</code></a> - Tests and transforms for Integers.
<ul>
<li class='jac'><a href="org/apache/juneau/assertions/IntegerAssertion.html" title="class in org.apache.juneau.assertions"><code>IntegerAssertion</code></a> - Assertion that returns itself.
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>
In the design, the "Fluent" classes (e.g. <a href="org/apache/juneau/assertions/FluentIntegerAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentIntegerAssertion</code></a>) allow you to specify the object
that gets returned when the test method is executed. When used in the <c>RestClient</c> class for example, the return
object is the <a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a> object so that you can perform multiple fluent operations against that object.
The "Normal" classes (e.g. <a href="org/apache/juneau/assertions/IntegerAssertion.html" title="class in org.apache.juneau.assertions"><code>IntegerAssertion</code></a>) are simply subclasses of the fluent equivalent
which return the assertion itself, meaning the test method returns the original <a href="org/apache/juneau/assertions/IntegerAssertion.html" title="class in org.apache.juneau.assertions"><code>IntegerAssertion</code></a>
so that multiple tests can be performed per assertion.
</p>
<p>
For more information about the capabilities of the Assertions API, refer to the methods on the <a href="org/apache/juneau/assertions/Assertions.html" title="class in org.apache.juneau.assertions"><code>Assertions</code></a> methods
above.
</p>
</div>
</div><!-- END: 6.1 - juneau-assertions.ja.Overview -->
</div><!-- END: 6 - juneau-assertions -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-rest-common' id='juneau-rest-common'>7 - juneau-rest-common</a><span class='update'>created: <b>9.0.0</b></span></h2>
<div class='topic'><!-- START: 7 - juneau-rest-common -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-rest-common<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-rest-common-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.rest.common_9.0.0.jar
</p>
<p>
The <a href="org/apache/juneau/http/package-summary.html"><code>org.apache.juneau.http</code></a> package contains a slew of useful extensions to the Apache HttpComponents libraries
and define APIs used extensively in the REST server and client APIs.
</p>
<ul class='javatree'>
<li class='jp'><a href="org/apache/juneau/http/package-summary.html"><code>org.apache.juneau.http</code></a> - Utility classes used for HTTP parts/headers/entities.
<li class='jp'><a href="org/apache/juneau/http/annotation/package-summary.html"><code>org.apache.juneau.http.annotation</code></a> - Swagger-based annotations used on both server-side APIs and client-side proxy interfaces.
<li class='jp'><a href="org/apache/juneau/http/entity/package-summary.html"><code>org.apache.juneau.http.entity</code></a> - HTTP entity classes.
<li class='jp'><a href="org/apache/juneau/http/header/package-summary.html"><code>org.apache.juneau.http.header</code></a> - HTTP header classes.
<li class='jp'><a href="org/apache/juneau/http/part/package-summary.html"><code>org.apache.juneau.http.part</code></a> - HTTP query/form-data/path classes.
<li class='jp'><a href="org/apache/juneau/http/remote/package-summary.html"><code>org.apache.juneau.http.remote</code></a> - Remote proxy interface API
<li class='jp'><a href="org/apache/juneau/http/resource/package-summary.html"><code>org.apache.juneau.http.resource</code></a> - HTTP resource classes.
<li class='jp'><a href="org/apache/juneau/http/response/package-summary.html"><code>org.apache.juneau.http.response</code></a> - HTTP response classes.
</ul>
<p>
These APIs extend from the Apache HttpComponents libraries and can be used with libraries based on it such
as Apache HttpClient. The REST Client API described later is built on top of Apache HttpClient and many
of the classes defined in this package make up integral components of that API. Likewise, the APIs
defined here are also used in the REST Server APIs also described later.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-common.jrc.org.apache.juneau.http' id='juneau-rest-common.jrc.org.apache.juneau.http'>7.1 - org.apache.juneau.http</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 7.1 - juneau-rest-common.jrc.org.apache.juneau.http -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/header/package-summary.html"><code>org.apache.juneau.http.header</code></a> package contains various convenience classes for creating
standard HTTP components using static imports.
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/http/HttpHeaders.html" title="class in org.apache.juneau.http"><code>HttpHeaders</code></a> - Utility class for standard HTTP headers.
<li class='jc'><a href="org/apache/juneau/http/HttpParts.html" title="class in org.apache.juneau.http"><code>HttpParts</code></a> - Utility class for standard HTTP parts.
<li class='jc'><a href="org/apache/juneau/http/HttpEntities.html" title="class in org.apache.juneau.http"><code>HttpEntities</code></a> - Utility class for standard HTTP entities.
<li class='jc'><a href="org/apache/juneau/http/HttpResources.html" title="class in org.apache.juneau.http"><code>HttpResources</code></a> - Utility class for standard HTTP resources.
<li class='jc'><a href="org/apache/juneau/http/HttpResponses.html" title="class in org.apache.juneau.http"><code>HttpResponses</code></a> - Utility class for standard HTTP resources.
</ul>
<h5 class='topic'>HttpHeaders</h5>
<p>
The <a href="org/apache/juneau/http/HttpHeaders.html" title="class in org.apache.juneau.http"><code>HttpHeaders</code></a> class contains many convenience static methods and fields for working with standard HTTP request and response headers
and header lists.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpHeaders.*;
HeaderList <jv>headers</jv> =
<jsm>headerList</jsm>( <jc>// Arbitrary list of headers</jc>
<jsf>CONTENTTYPE_TEXT_XML</jsf>, <jc>// Static constants</jc>
<jsm>contentType</jsm>(<js>"text/xml"</js>) <jc>// Predefined headers</jc>
<jsm>contentType</jsm>(() -&gt; <js>"text/xml"</js>) <jc>// Predefined headers with supplied values</jc>
<jsm>stringHeader</jsm>(<js>"Content-Type"</js>, <js>"text/xml"</js>) <jc>// Freeform headers</jc>
<jsm>stringHeader</jsm>(<js>"Content-Type"</js>, () -&gt; <js>"text/xml"</js>) <jc>// Freeform headers with supplied values</jc>
);
</p>
<p>
This class is vast in scope and covers all request and response headers defined in RFC2616.
</p>
<p>
In addition to the predefined headers, various methods are provided for free-form headers. Each accepts
either static values or values from <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html?is-external=true" title="class or interface in java.util.function"><code>Suppliers</code></a>:
</p>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#basicHeader-java.lang.String-java.lang.Object-"><code>basicHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#booleanHeader-java.lang.String-java.lang.String-"><code>booleanHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#csvHeader-java.lang.String-java.lang.String-"><code>csvHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#dateHeader-java.lang.String-java.lang.String-"><code>dateHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#entityTagsHeader-java.lang.String-java.lang.String-"><code>entityTagsHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#entityTagHeader-java.lang.String-java.lang.String-"><code>entityTagHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#integerHeader-java.lang.String-java.lang.String-"><code>integerHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#longHeader-java.lang.String-java.lang.String-"><code>longHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#mediaRangesHeader-java.lang.String-java.lang.String-"><code>mediaRangesHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#mediaTypeHeader-java.lang.String-java.lang.String-"><code>mediaTypeHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#stringHeader-java.lang.String-java.lang.String-"><code>stringHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#serializedHeader-java.lang.String-java.lang.Object-"><code>serializedHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#stringRangesHeader-java.lang.String-java.lang.String-"><code>stringRangesHeader</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#uriHeader-java.lang.String-java.lang.String-"><code>uriHeader</code></a>
</ul>
<p>
The <a href="org/apache/juneau/http/HttpHeaders.html#serializedHeader-java.lang.String-java.lang.Object-"><code>serializedHeader</code></a> methods allows for headers
serialized using schema-based serializers such as the OpenAPI serializer.
</p>
<p>
Static methods are also provided for instantiating <a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>-annotated or
other HttpComponent-defined header classes:
</p>
<ul class='javatree'>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#header-java.lang.Class-java.lang.String-java.lang.Object-"><code>header(Class,String,Object)</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#header-java.lang.Class-java.lang.Object-"><code>header(Class,String,Object)</code></a>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpHeaders.*;
ContentType <jv>contentType</jv> = <jsm>header</jsm>(ContentType.<jk>class</jk>, <js>"text/xml"</js>);
</p>
<p>
Lists of headers can be produced with the following methods:
</p>
<ul class='javatree'>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#headerList--"><code>headerList()</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#headerList-org.apache.http.Header...-"><code>headerList(Header...)</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#headerList-java.util.List-"><code>headerList(List&lt;Header&gt;)</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpHeaders.html#headerList-java.lang.String...-"><code>headerList(String...)</code></a>
</ul>
<p>
The capabilities of the <a href="org/apache/juneau/http/header/HeaderList.html" title="class in org.apache.juneau.http.header"><code>HeaderList</code></a> class is described later.
</p>
<h5 class='topic'>HttpParts</h5>
<p>
The <a href="org/apache/juneau/http/HttpParts.html" title="class in org.apache.juneau.http"><code>HttpParts</code></a> class contains convenience static methods for generating query/form-data/path parts and part lists.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpParts.*;
PartList <jv>formData</jv> =
<jsm>partList</jsm>( <jc>// Arbitrary list of parts</jc>
<jsm>stringPart</jsm>(<js>"Name"</js>, <js>"Bill"</js>) <jc>// Freeform part</jc>
<jsm>integerPart</jsm>(<js>"Age"</js>, () -> <jsm>calculateAge</jsm>()) <jc>// Freeform part with supplied value</jc>
);
</p>
<p>
The following methods are provided for creating parts. Each accepts
either static values or values from <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html?is-external=true" title="class or interface in java.util.function"><code>Suppliers</code></a>:
</p>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#basicPart-java.lang.String-java.lang.Object-"><code>basicPart</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#booleanPart-java.lang.String-java.lang.Boolean-"><code>booleanPart</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#csvArrayPart-java.lang.String-java.lang.String...-"><code>csvArrayPart</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#datePart-java.lang.String-java.time.ZonedDateTime-"><code>datePart</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#integerPart-java.lang.String-java.lang.Integer-"><code>integerPart</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#longPart-java.lang.String-java.lang.Long-"><code>longPart</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#serializedPart-java.lang.String-java.lang.Object-"><code>serializedPart</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#stringPart-java.lang.String-java.lang.String-"><code>stringPart</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#uriPart-java.lang.String-java.net.URI-"><code>uriPart</code></a>
</ul>
<p>
The <a href="org/apache/juneau/http/HttpParts.html#serializedPart-java.lang.String-java.lang.Object-"><code>serializedPart</code></a> methods allows for parts
serialized using schema-based serializers such as the OpenAPI serializer.
</p>
<p>
Lists of parts can be produced with the following methods:
</p>
<ul class='javatree'>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#partList--"><code>partList()</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#partList-java.util.List-"><code>partList(List&lt;NameValuePair&gt;)</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#partList-org.apache.http.NameValuePair...-"><code>partList(NameValuePair...)</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpParts.html#partList-java.lang.Object...-"><code>partList(Object...)</code></a>
</ul>
<p>
The capabilities of the <a href="org/apache/juneau/http/part/PartList.html" title="class in org.apache.juneau.http.part"><code>PartList</code></a> class is described later.
</p>
<h5 class='topic'>HttpEntities</h5>
<p>
The <a href="org/apache/juneau/http/HttpEntities.html" title="class in org.apache.juneau.http"><code>HttpEntities</code></a> class contains convenience static methods for generating HTTP message entities.
Returned objects extend from <code>org.apache.http.HttpEntity</code> but provides the following additional features:
</p>
<ul class='spaced-list'>
<li>
Caching.
<li>
Fluent setters.
<li>
Fluent assertions.
<li>
Externally-supplied/dynamic content.
</ul>
<p>
The following methods are provided for creating entities. Each accepts
either static values or values from <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html?is-external=true" title="class or interface in java.util.function"><code>Suppliers</code></a> and returns builders:
</p>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/http/HttpEntities.html#byteArrayEntity-byte:A-"><code>byteArrayEntity</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpEntities.html#fileEntity-java.io.File-"><code>fileEntity</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpEntities.html#readerEntity-java.io.Reader-"><code>readerEntity</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpEntities.html#serializedEntity-java.lang.Object-org.apache.juneau.serializer.Serializer-"><code>serializedEntity</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpEntities.html#streamEntity-java.io.InputStream-"><code>streamEntity</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpEntities.html#stringEntity-java.lang.String-"><code>stringEntity</code></a>
</ul>
<p>
HTTP entities are automatically supported in both the server and client REST APIs for requests and responses.
</p>
<h5 class='topic'>HttpResources</h5>
<p>
The <a href="org/apache/juneau/http/HttpResources.html" title="class in org.apache.juneau.http"><code>HttpResources</code></a> class contains convenience static methods for generating HTTP message resources.
Returned objects extend from <a href="org/apache/juneau/http/resource/HttpResource.html" title="interface in org.apache.juneau.http.resource"><code>HttpResource</code></a> which extends from <code>org.apache.juneau.http.HttpEntity</code> but with
additional arbitrary headers.
</p>
<p>
The following methods are provided for creating entities. Each accepts
either static values or values from <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html?is-external=true" title="class or interface in java.util.function"><code>Suppliers</code></a> and are in the form of builders.
</p>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/http/HttpResources.html#byteArrayResource-byte:A-"><code>byteArrayResource</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResources.html#fileResource-java.io.File-"><code>fileResource</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResources.html#readerResource-java.io.Reader-"><code>readerResource</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResources.html#streamResource-java.io.InputStream-"><code>streamResource</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResources.html#stringResource-java.lang.String-"><code>stringResource</code></a>
</ul>
<p>
The most common location where resources are used are as returned types of REST operation methods described later.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpResources.*;
<ja>@RestDelete</ja>(path=<js>"/{id}"</js>)
<jk>public</jk> HttpResource helloWold(...) {
<jk>return</jk> <jsm>stringResource</jsm>(<js>"Hello!"</js>).contentType(<js>"text/plain"</js>).build();
}
</p>
<h5 class='topic'>HttpResponses</h5>
<p>
The <a href="org/apache/juneau/http/HttpResponses.html" title="class in org.apache.juneau.http"><code>HttpResponses</code></a> class contains convenience static methods for standard HTTP responses.
Returned objects extend from <code>org.apache.http.HttpResponse</code> and are in the form of builders.
</p>
<p>
The following methods are provided for creating entities:
</p>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#Z:Z_continue--"><code>_continue</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#accepted--"><code>accepted</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#alreadyReported--"><code>alreadyReported</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#badRequest--"><code>badRequest</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#conflict--"><code>conflict</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#created--"><code>created</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#earlyHints--"><code>earlyHints</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#expectationFailed--"><code>expectationFailed</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#failedDependency--"><code>failedDependency</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#forbidden--"><code>forbidden</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#found-java.lang.String-"><code>found</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#gone--"><code>gone</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#httpVersionNotSupported--"><code>httpVersionNotSupported</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#imUsed--"><code>imUsed</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#insufficientStorage--"><code>insufficientStorage</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#internalServerError--"><code>internalServerError</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#lengthRequired--"><code>lengthRequired</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#locked--"><code>locked</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#loopDetected--"><code>loopDetected</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#methodNotAllowed--"><code>methodNotAllowed</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#misdirectedRequest--"><code>misdirectedRequest</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#movedPermanently-java.lang.String-"><code>movedPermanently</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#multipleChoices--"><code>multipleChoices</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#multiStatus--"><code>multiStatus</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#networkAuthenticationRequired--"><code>networkAuthenticationRequired</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#noContent--"><code>noContent</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#nonAuthoritiveInformation--"><code>nonAuthoritiveInformation</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#notAcceptable--"><code>notAcceptable</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#notExtended--"><code>notExtended</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#notFound--"><code>notFound</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#notImplemented--"><code>notImplemented</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#notModified--"><code>notModified</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#ok--"><code>ok</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#partialContent--"><code>partialContent</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#payloadTooLarge--"><code>payloadTooLarge</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#permanentRedirect-java.lang.String-"><code>permanentRedirect</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#preconditionFailed--"><code>preconditionFailed</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#preconditionRequired--"><code>preconditionRequired</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#processing--"><code>processing</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#rangeNotSatisfiable--"><code>rangeNotSatisfiable</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#requestHeaderFieldsTooLarge--"><code>requestHeaderFieldsTooLarge</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#resetContent--"><code>resetContent</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#seeOther-java.lang.String-"><code>seeOther</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#serviceUnavailable--"><code>serviceUnavailable</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#switchingProtocols--"><code>switchingProtocols</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#temporaryRedirect-java.lang.String-"><code>temporaryRedirect</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#tooManyRequests--"><code>tooManyRequests</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#unauthorized--"><code>unauthorized</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#unavailableForLegalReasons--"><code>unavailableForLegalReasons</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#unprocessableEntity--"><code>unprocessableEntity</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#unsupportedMediaType--"><code>unsupportedMediaType</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#upgradeRequired--"><code>upgradeRequired</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#uriTooLong--"><code>uriTooLong</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#useProxy--"><code>useProxy</code></a>
<li class='jm'><a href="org/apache/juneau/http/HttpResponses.html#variantAlsoNegotiates--"><code>variantAlsoNegotiates</code></a>
</ul>
<p>
The most common location where these responses are used are in REST operation methods described later.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpResponses.*;
<jk>import static</jk> org.apache.juneau.http.HttpHeaders.*;
<ja>@RestDelete</ja>(path=<js>"/{id}"</js>)
<jk>public</jk> Ok doDelete(...) <jk>throws</jk> Unauthorized {
<jk>if</jk> (<jc>/* user not authorized*/</jc>)
<jk>throw</jk> <jsm>unauthorized</jsm>().build();
<jk>return</jk> <jsm>ok</jsm>().content(<js>"OK"</js>).header(<jsm>contentType</jsm>(<js>"text/plain"</js>)).build();
}
</p>
</div>
</div><!-- END: 7.1 - juneau-rest-common.jrc.org.apache.juneau.http -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-common.jrc.org.apache.juneau.http.annotation' id='juneau-rest-common.jrc.org.apache.juneau.http.annotation'>7.2 - org.apache.juneau.http.annotation</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 7.2 - juneau-rest-common.jrc.org.apache.juneau.http.annotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/package-summary.html"><code>org.apache.juneau.http.annotation</code></a> package contains annotations for defining both server and client side
APIs. The server-side APIs also use it for producing auto-generated Swagger documentation through
the REST API itself.
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Contact.html" title="annotation in org.apache.juneau.http.annotation"><code>Contact</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/HasFormData.html" title="annotation in org.apache.juneau.http.annotation"><code>HasFormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/HasQuery.html" title="annotation in org.apache.juneau.http.annotation"><code>HasQuery</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/License.html" title="annotation in org.apache.juneau.http.annotation"><code>License</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>Request</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/StatusCode.html" title="annotation in org.apache.juneau.http.annotation"><code>StatusCode</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Tag.html" title="annotation in org.apache.juneau.http.annotation"><code>Tag</code></a>
</ul>
<p>
These annotations are used in a variety of places in the server and client side REST interfaces, especially for
remote proxies.
</p>
</div>
</div><!-- END: 7.2 - juneau-rest-common.jrc.org.apache.juneau.http.annotation -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-common.jrc.org.apache.juneau.http.header' id='juneau-rest-common.jrc.org.apache.juneau.http.header'>7.3 - org.apache.juneau.http.header</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 7.3 - juneau-rest-common.jrc.org.apache.juneau.http.header -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/header/package-summary.html"><code>org.apache.juneau.http.header</code></a> package contains implementations of <c>org.apache.http.Header</c> for all common HTTP
headers.
</p>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/header/Accept.html" title="class in org.apache.juneau.http.header"><code>Accept</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/AcceptCharset.html" title="class in org.apache.juneau.http.header"><code>AcceptCharset</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/AcceptEncoding.html" title="class in org.apache.juneau.http.header"><code>AcceptEncoding</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/AcceptLanguage.html" title="class in org.apache.juneau.http.header"><code>AcceptLanguage</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/AcceptRanges.html" title="class in org.apache.juneau.http.header"><code>AcceptRanges</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Age.html" title="class in org.apache.juneau.http.header"><code>Age</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Allow.html" title="class in org.apache.juneau.http.header"><code>Allow</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Authorization.html" title="class in org.apache.juneau.http.header"><code>Authorization</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/CacheControl.html" title="class in org.apache.juneau.http.header"><code>CacheControl</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ClientVersion.html" title="class in org.apache.juneau.http.header"><code>ClientVersion</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Connection.html" title="class in org.apache.juneau.http.header"><code>Connection</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentDisposition.html" title="class in org.apache.juneau.http.header"><code>ContentDisposition</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentEncoding.html" title="class in org.apache.juneau.http.header"><code>ContentEncoding</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentLanguage.html" title="class in org.apache.juneau.http.header"><code>ContentLanguage</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentLength.html" title="class in org.apache.juneau.http.header"><code>ContentLength</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentLocation.html" title="class in org.apache.juneau.http.header"><code>ContentLocation</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentRange.html" title="class in org.apache.juneau.http.header"><code>ContentRange</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentType.html" title="class in org.apache.juneau.http.header"><code>ContentType</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Date.html" title="class in org.apache.juneau.http.header"><code>Date</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Debug.html" title="class in org.apache.juneau.http.header"><code>Debug</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ETag.html" title="class in org.apache.juneau.http.header"><code>ETag</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Expect.html" title="class in org.apache.juneau.http.header"><code>Expect</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Expires.html" title="class in org.apache.juneau.http.header"><code>Expires</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Forwarded.html" title="class in org.apache.juneau.http.header"><code>Forwarded</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/From.html" title="class in org.apache.juneau.http.header"><code>From</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Host.html" title="class in org.apache.juneau.http.header"><code>Host</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfMatch.html" title="class in org.apache.juneau.http.header"><code>IfMatch</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfModifiedSince.html" title="class in org.apache.juneau.http.header"><code>IfModifiedSince</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfNoneMatch.html" title="class in org.apache.juneau.http.header"><code>IfNoneMatch</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfRange.html" title="class in org.apache.juneau.http.header"><code>IfRange</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfUnmodifiedSince.html" title="class in org.apache.juneau.http.header"><code>IfUnmodifiedSince</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/LastModified.html" title="class in org.apache.juneau.http.header"><code>LastModified</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Location.html" title="class in org.apache.juneau.http.header"><code>Location</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/MaxForwards.html" title="class in org.apache.juneau.http.header"><code>MaxForwards</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/NoTrace.html" title="class in org.apache.juneau.http.header"><code>NoTrace</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Origin.html" title="class in org.apache.juneau.http.header"><code>Origin</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Pragma.html" title="class in org.apache.juneau.http.header"><code>Pragma</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ProxyAuthenticate.html" title="class in org.apache.juneau.http.header"><code>ProxyAuthenticate</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ProxyAuthorization.html" title="class in org.apache.juneau.http.header"><code>ProxyAuthorization</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Range.html" title="class in org.apache.juneau.http.header"><code>Range</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Referer.html" title="class in org.apache.juneau.http.header"><code>Referer</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/RetryAfter.html" title="class in org.apache.juneau.http.header"><code>RetryAfter</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Server.html" title="class in org.apache.juneau.http.header"><code>Server</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/TE.html" title="class in org.apache.juneau.http.header"><code>TE</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Thrown.html" title="class in org.apache.juneau.http.header"><code>Thrown</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Trailer.html" title="class in org.apache.juneau.http.header"><code>Trailer</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/TransferEncoding.html" title="class in org.apache.juneau.http.header"><code>TransferEncoding</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Upgrade.html" title="class in org.apache.juneau.http.header"><code>Upgrade</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/UserAgent.html" title="class in org.apache.juneau.http.header"><code>UserAgent</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Vary.html" title="class in org.apache.juneau.http.header"><code>Vary</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Via.html" title="class in org.apache.juneau.http.header"><code>Via</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Warning.html" title="class in org.apache.juneau.http.header"><code>Warning</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/WwwAuthenticate.html" title="class in org.apache.juneau.http.header"><code>WwwAuthenticate</code></a>
</ul>
<p>
These headers extend from the following classes that provide data-type specific functionality:
</p>
<ul class='javatree'>
<li class='jic'><code>org.apache.http.NameValuePair</code>
<ul>
<li class='jic'><code>org.apache.http.Header</code>
<ul>
<li class='jc'><a href="org/apache/juneau/http/header/BasicHeader.html" title="class in org.apache.juneau.http.header"><code>BasicHeader</code></a>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/header/BasicBooleanHeader.html" title="class in org.apache.juneau.http.header"><code>BasicBooleanHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicCsvHeader.html" title="class in org.apache.juneau.http.header"><code>BasicCsvHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicDateHeader.html" title="class in org.apache.juneau.http.header"><code>BasicDateHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicEntityTagHeader.html" title="class in org.apache.juneau.http.header"><code>BasicEntityTagHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicEntityTagsHeader.html" title="class in org.apache.juneau.http.header"><code>BasicEntityTagsHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicIntegerHeader.html" title="class in org.apache.juneau.http.header"><code>BasicIntegerHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicLongHeader.html" title="class in org.apache.juneau.http.header"><code>BasicLongHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicMediaRangesHeader.html" title="class in org.apache.juneau.http.header"><code>BasicMediaRangesHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicMediaTypeHeader.html" title="class in org.apache.juneau.http.header"><code>BasicMediaTypeHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicStringHeader.html" title="class in org.apache.juneau.http.header"><code>BasicStringHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicStringRangesHeader.html" title="class in org.apache.juneau.http.header"><code>BasicStringRangesHeader</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/BasicUriHeader.html" title="class in org.apache.juneau.http.header"><code>BasicUriHeader</code></a>
</ul>
</ul>
</ul>
</ul>
<p>
These subclasses provide various convenience methods to allow for easy fluent-style coding.
</p>
<h5 class='figure'>Examples</h5>
<p class='bjava'>
<jc>// Validates the response body content is not expired.</jc>
<jv>restClient</jv>
.get(<jsf>URL</jsf>)
.run()
.getHeader(<js>"Expires"</js>).asDateHeader().assertZonedDateTime().isLessThan(<jk>new</jk> Date());
</p>
<h5 class='topic'>HeaderList</h5>
<p>
The <a href="org/apache/juneau/http/header/HeaderList.html" title="class in org.apache.juneau.http.header"><code>HeaderList</code></a> class is a thread-safe immutable list of HTTP headers.
</p>
<h5 class='figure'>Example</h5>
<p class='bjava'>
<jc>// Construct using builder.</jc>
HeaderList <jv>headers</jv> = HeaderList
.<jsm>create</jsm>()
.append(Accept.<jsm>of</jsm>(<js>"text/xml"</js>))
.append(<js>"Content-Type"</js>, ()-&gt;<jsm>getDynamicContentTypeFromSomewhere</jsm>())
.build();
<jc>// Construct using convenience creator.</jc>
HeaderList <jv>headers</jv> = HeaderList.<jsm>of</jsm>(Accept.<jsf>TEXT_XML</jsf>, ContentType.<jsf>TEXT_XML</jsf>);
</p>
<p>
Header lists are immutable but can be appended to using the <a href="org/apache/juneau/http/header/HeaderList.html#copy--"><code>copy()</code></a> method:
</p>
<p class='bjava'>
<jv>headers</jv> = <jv>headers</jv>
.copy()
.append(AcceptEncoding.<jsm>of</jsm>(<js>"identity"</js>))
.build();
</p>
<p>
Static methods are provided on <a href="org/apache/juneau/http/HttpHeaders.html" title="class in org.apache.juneau.http"><code>HttpHeaders</code></a> to further simplify creation of header lists.
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpHeaders.*;
HeaderList <jv>headers</jv> = <jsm>headerList</jsm>(<jsm>accept</jsm>(<js>"text/xml"</js>), <jsm>contentType</jsm>(<js>"text/xml"</js>));
</p>
<p>
The builder class supports setting default header values (i.e. add a header to the list if it isn't otherwise in the list).
Note that this is different from simply setting a value twice as using default values will not overwrite existing
headers.
<br>The following example notes the distinction:
</p>
<p class='bjava'>
<jv>headers</jv> = HeaderList
.<jsm>create</jsm>()
.set(Accept.<jsf>TEXT_PLAIN</jsf>)
.set(Accept.<jsf>TEXT_XML</jsf>)
.build();
<jsm>assertObject</jsm>(<jv>headers</jv>).isString(<js>"[Accept: text/xml]"</js>);
<jv>headers</jv> = HeaderList
.create()
.set(Accept.<jsf>TEXT_PLAIN</jsf>)
.setDefault(Accept.<jsf>TEXT_XML</jsf>)
.build();
<jsm>assertObject</jsm>(<jv>headers</jv>).isString(<js>"[Accept: text/plain]"</js>);
</p>
<p>
Various methods are provided for iterating over the headers in this list to avoid array copies.
</p>
<ul class='javatree'>
<li class='jm'><a href="org/apache/juneau/http/header/HeaderList.html#forEach-java.util.function.Consumer-"><code>forEach(Consumer)</code></a> / <a href="org/apache/juneau/http/header/HeaderList.html#forEach-java.lang.String-java.util.function.Consumer-"><code>forEach(String,Consumer)</code></a> / <a href="org/apache/juneau/http/header/HeaderList.html#forEach-java.util.function.Predicate-java.util.function.Consumer-"><code>forEach(Predicate,Consumer)</code></a> - Use consumers to process headers.
<li class='jm'><a href="org/apache/juneau/http/header/HeaderList.html#iterator--"><code>iterator()</code></a> / <a href="org/apache/juneau/http/header/HeaderList.html#iterator-java.lang.String-"><code>iterator(String)</code></a> - Use an <code>HeaderIterator</code> to process headers.
<li class='jm'><a href="org/apache/juneau/http/header/HeaderList.html#stream--"><code>stream()</code></a> / <a href="org/apache/juneau/http/header/HeaderList.html#stream-java.lang.String-"><code>stream(String)</code></a> - Use a stream.
</ul>
<p>
In general, try to use these over the <a href="org/apache/juneau/http/header/HeaderList.html#getAll--"><code>getAll()</code></a> / <a href="org/apache/juneau/http/header/HeaderList.html#getAll-java.lang.String-"><code>getAll(String)</code></a> methods that require array copies.
</p>
<p>
The <a href="org/apache/juneau/http/header/HeaderList.html#get-java.lang.String-"><code>get(String)</code></a> method is special in that it will collapse multiple headers with the same name into
a single comma-delimited list (see <a href='https://tools.ietf.org/html/rfc2616#section-4.2'>RFC 2616 Section 4.2</a> for rules).
</p>
<p>
The <a href="org/apache/juneau/http/header/HeaderList.html#get-java.lang.Class-"><code>get(Class)</code></a> and <a href="org/apache/juneau/http/header/HeaderList.html#get-java.lang.String-java.lang.Class-"><code>get(String,Class)</code></a> methods are provided for working with <a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>-annotated
beans.
</p>
<h5 class='figure'>Example</h5>
<p class='bjava'>
ContentType <jv>contentType</jv> = <jv>headers</jv>.get(ContentType.<jk>class</jk>);
</p>
<p>
By default, header names are treated as case-insensitive. This can be changed using the <a href="org/apache/juneau/http/header/HeaderList.Builder.html#caseSensitive--"><code>caseSensitive()</code></a>
method.
</p>
<p>
A <a href="org/apache/juneau/svl/VarResolver.html" title="class in org.apache.juneau.svl"><code>VarResolver</code></a> can be associated with this builder to create header values with embedded variables that
are resolved at runtime.
</p>
<h5 class='figure'>Example</h5>
<p class='bjava'>
<jc>// Create a header list with dynamically-resolving values pulled from a system property.</jc>
System.<jsm>setProperty</jsm>(<js>"foo"</js>, <js>"bar"</js>);
HeaderList <jv>headers</jv> = HeaderList
.<jsm>create</jsm>()
.resolving()
.append(<js>"X1"</js>, <js>"$S{foo}"</js>)
.append(<js>"X2"</js>, ()-&gt;<js>"$S{foo}"</js>)
.build();
<jsm>assertObject</jsm>(<jv>headers</jv>).isString(<js>"[X1: bar, X2: bar]"</js>);
</p>
<p>
The <a href="org/apache/juneau/http/header/HeaderList.html" title="class in org.apache.juneau.http.header"><code>HeaderList</code></a> object can be extended to defined pre-packaged lists of headers which can be used in various
annotations throughout the framework.
</p>
<h5 class='figure'>Example</h5>
<p class='bjava'>
<jc>// A predefined list of headers.</jc>
<jk>public class</jk> MyHeaderList <jk>extends</jk> HeaderList {
<jk>public</jk> MyHeaderList() {
<jk>super</jk>(Accept.<jsf>TEXT_XML</jsf>, ContentType.<jsf>TEXT_XML</jsf>);
}
}
<jc>// Use it on a remote proxy to add headers on all requests.</jc>
<ja>@Remote</ja>(path=<js>"/petstore"</js>, headerList=MyHeaderList.<jk>class</jk>)
<jk>public interface</jk> PetStore {
<ja>@RemotePost</ja>(<js>"/pets"</js>)
Pet addPet(
<ja>@Content</ja> CreatePet <jv>createPet</jv>,
<ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
<ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
);
}
</p>
</div>
</div><!-- END: 7.3 - juneau-rest-common.jrc.org.apache.juneau.http.header -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-common.jrc.org.apache.juneau.http.part' id='juneau-rest-common.jrc.org.apache.juneau.http.part'>7.4 - org.apache.juneau.http.part</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 7.4 - juneau-rest-common.jrc.org.apache.juneau.http.part -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/part/package-summary.html"><code>org.apache.juneau.http.part</code></a> package contains implementations of <c>org.apache.http.NameValuePair</c> to
be used for query/form-data/path parts and part lists.
</p>
<ul class='javatree'>
<li class='jic'><code>org.apache.http.NameValuePair</code>
<ul>
<li class='jc'><a href="org/apache/juneau/http/part/BasicPart.html" title="class in org.apache.juneau.http.part"><code>BasicPart</code></a>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/part/BasicBooleanPart.html" title="class in org.apache.juneau.http.part"><code>BasicBooleanPart</code></a>
<li class='jc'><a href="org/apache/juneau/http/part/BasicCsvArrayPart.html" title="class in org.apache.juneau.http.part"><code>BasicCsvArrayPart</code></a>
<li class='jc'><a href="org/apache/juneau/http/part/BasicDatePart.html" title="class in org.apache.juneau.http.part"><code>BasicDatePart</code></a>
<li class='jc'><a href="org/apache/juneau/http/part/BasicIntegerPart.html" title="class in org.apache.juneau.http.part"><code>BasicIntegerPart</code></a>
<li class='jc'><a href="org/apache/juneau/http/part/BasicLongPart.html" title="class in org.apache.juneau.http.part"><code>BasicLongPart</code></a>
<li class='jc'><a href="org/apache/juneau/http/part/BasicPartIterator.html" title="class in org.apache.juneau.http.part"><code>BasicPartIterator</code></a>
<li class='jc'><a href="org/apache/juneau/http/part/BasicStringPart.html" title="class in org.apache.juneau.http.part"><code>BasicStringPart</code></a>
<li class='jc'><a href="org/apache/juneau/http/part/BasicUriPart.html" title="class in org.apache.juneau.http.part"><code>BasicUriPart</code></a>
</ul>
</ul>
</ul>
<h5 class='topic'>PartList</h5>
<p>
The <a href="org/apache/juneau/http/part/PartList.html" title="class in org.apache.juneau.http.part"><code>PartList</code></a> class is a thread-safe immutable list of HTTP parts (form-data, query-parameters, path-parameters).
</p>
<h5 class='figure'>Example</h5>
<p class='bjava'>
PartList <jv>parts</jv> = PartList
.<jsm>create</jsm>()
.append(MyPart.<jsm>of</jsm>(<js>"foo"</js>))
.append(<js>"Bar"</js>, ()-&gt;<jsm>getDynamicValueFromSomewhere</jsm>())
.build();
</p>
<p>
Convenience creators are provided for creating lists with minimal code:
</p>
<p class='bjava'>
PartList <jv>parts</jv> = PartList.<jsm>of</jsm>(BasicIntegerPart.<jsm>of</jsm>(<js>"foo"</js>, 1));
</p>
<p>
Part lists are immutable but can be appended to using the <a href="org/apache/juneau/http/part/PartList.html#copy--"><code>copy()</code></a> method:
</p>
<p class='bjava'>
<jv>parts</jv> = <jv>parts</jv>
.copy()
.append(BasicIntegerPart.<jsm>of</jsm>(<js>"foo"</js>, 1))
.build();
</p>
<p>
Static methods are provided on <a href="org/apache/juneau/http/HttpParts.html" title="class in org.apache.juneau.http"><code>HttpParts</code></a> to further simplify creation of part lists.
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpParts.*;
PartList <jv>parts</jv> = <jsm>partList</jsm>(<jsm>integerPart</jsm>(<js>"foo"</js>, 1), <jsm>booleanPart</jsm>(<js>"bar"</js>, <jk>false</jk>));
</p>
<p>
The builder class supports setting default part values (i.e. add a part to the list if it isn't otherwise in the list).
Note that this is different from simply setting a value twice as using default values will not overwrite existing
parts.
<br>The following example notes the distinction:
</p>
<p class='bjava'>
<jv>parts</jv> = PartList
.<jsm>create</jsm>()
.set(<js>"Foo"</js>, <js>"bar"</js>)
.set(<js>"Foo"</js>, <js>"baz"</js>)
.build();
<jsm>assertObject</jsm>(<jv>parts</jv>).isString(<js>"foo=baz"</js>);
<jv>parts</jv> = PartList
.create()
.set(<js>"Foo"</js>, <js>"bar"</js>)
.setDefault(<js>"Foo"</js>, <js>"baz"</js>)
.build();
<jsm>assertObject</jsm>(<jv>parts</jv>).isString(<js>"foo=bar"</js>);
</p>
<p>
Various methods are provided for iterating over the parts in this list to avoid array copies.
</p>
<ul class='javatree'>
<li class='jm'><a href="org/apache/juneau/http/part/PartList.html#forEach-java.util.function.Consumer-"><code>forEach(Consumer)</code></a> / <a href="org/apache/juneau/http/part/PartList.html#forEach-java.lang.String-java.util.function.Consumer-"><code>forEach(String,Consumer)</code></a> / <a href="org/apache/juneau/http/part/PartList.html#forEach-java.util.function.Predicate-java.util.function.Consumer-"><code>forEach(Predicate,Consumer)</code></a> - Use consumers to process parts.
<li class='jm'><a href="org/apache/juneau/http/part/PartList.html#iterator--"><code>iterator()</code></a> / <a href="org/apache/juneau/http/part/PartList.html#iterator-java.lang.String-"><code>iterator(String)</code></a> - Use an <code>PartIterator</code> to process parts.
<li class='jm'><a href="org/apache/juneau/http/part/PartList.html#stream--"><code>stream()</code></a> / <a href="org/apache/juneau/http/part/PartList.html#stream-java.lang.String-"><code>stream(String)</code></a> - Use a stream.
</ul>
<p>
In general, try to use these over the <a href="org/apache/juneau/http/part/PartList.html#getAll--"><code>getAll()</code></a> / <a href="org/apache/juneau/http/part/PartList.html#getAll-java.lang.String-"><code>getAll(String)</code></a> methods that require array copies.
</p>
<p>
Similar to the way multiple headers can be collapsed into a single value, the <a href="org/apache/juneau/http/part/PartList.html#get-java.lang.String-"><code>get(String)</code></a> method is special in that it will collapse multiple parts with the same name into
a single comma-delimited list.
</p>
<p>
The <a href="org/apache/juneau/http/part/PartList.html#get-java.lang.Class-"><code>get(Class)</code></a> and <a href="org/apache/juneau/http/part/PartList.html#get-java.lang.String-java.lang.Class-"><code>get(String,Class)</code></a> methods are provided for working with <a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a> / <a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a> / <a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>-annotated
beans.
</p>
<h5 class='figure'>Example</h5>
<p class='bjava'>
MyQueryBean <jv>foo</jv> = <jv>parts</jv>.get(MyQueryBean.<jk>class</jk>);
</p>
<p>
A <a href="org/apache/juneau/svl/VarResolver.html" title="class in org.apache.juneau.svl"><code>VarResolver</code></a> can be associated with this builder to create part values with embedded variables that
are resolved at runtime.
</p>
<h5 class='figure'>Example</h5>
<p class='bjava'>
<jc>// Create a part list with dynamically-resolving values pulled from a system property.</jc>
System.<jsm>setProperty</jsm>(<js>"foo"</js>, <js>"bar"</js>);
PartList <jv>parts</jv> = PartList
.<jsm>create</jsm>()
.resolving()
.append(<js>"X1"</js>, <js>"$S{foo}"</js>)
.append(<js>"X2"</js>, ()-&gt;<js>"$S{foo}"</js>)
.build();
<jsm>assertObject</jsm>(<jv>parts</jv>).isString(<js>"X1=bar&amp;X2=bar"</js>);
</p>
<p>
The <a href="org/apache/juneau/http/part/PartList.html" title="class in org.apache.juneau.http.part"><code>PartList</code></a> object can be extended to defined pre-packaged lists of parts which can be used in various
annotations throughout the framework.
</p>
<h5 class='figure'>Example</h5>
<p class='bjava'>
<jc>// A predefined list of parts.</jc>
<jk>public class</jk> MyPartList <jk>extends</jk> PartList {
<jk>public</jk> MyPartList() {
<jk>super</jk>(BasicIntegerPart.<jsm>of</jsm>(<js>"foo"</js>,1), BasicBooleanPart.<jsm>of</jsm>(<js>"bar"</js>,<jk>false</jk>));
}
}
</p>
</div>
</div><!-- END: 7.4 - juneau-rest-common.jrc.org.apache.juneau.http.part -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-common.jrc.org.apache.juneau.http.entity' id='juneau-rest-common.jrc.org.apache.juneau.http.entity'>7.5 - org.apache.juneau.http.entity</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 7.5 - juneau-rest-common.jrc.org.apache.juneau.http.entity -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/entity/package-summary.html"><code>org.apache.juneau.http.entity</code></a> package contains implementations of <c>org.apache.http.HttpEntity</c>.
</p>
<ul class='javatree'>
<li class='jic'><code>org.apache.http.HttpEntity</code>
<ul>
<li class='jc'><a href="org/apache/juneau/http/entity/BasicHttpEntity.html" title="class in org.apache.juneau.http.entity"><code>BasicHttpEntity</code></a>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/entity/ByteArrayEntity.html" title="class in org.apache.juneau.http.entity"><code>ByteArrayEntity</code></a>
<li class='jc'><a href="org/apache/juneau/http/entity/FileEntity.html" title="class in org.apache.juneau.http.entity"><code>FileEntity</code></a>
<li class='jc'><a href="org/apache/juneau/http/entity/InputStreamEntity.html" title="class in org.apache.juneau.http.entity"><code>InputStreamEntity</code></a>
<li class='jc'><a href="org/apache/juneau/http/entity/ReaderEntity.html" title="class in org.apache.juneau.http.entity"><code>ReaderEntity</code></a>
<li class='jc'><a href="org/apache/juneau/http/entity/SerializedEntity.html" title="class in org.apache.juneau.http.entity"><code>SerializedEntity</code></a>
<li class='jc'><a href="org/apache/juneau/http/entity/StringEntity.html" title="class in org.apache.juneau.http.entity"><code>StringEntity</code></a>
</ul>
</ul>
</ul>
<h5 class='topic'>HttpEntityBuilder</h5>
<p>
HTTP entities are created through builders created in the <code>org.apache.juneau.http.HttpEnties</code> class or individual <c>create()</c> methods
defined in the subclasses above. The builder contains the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html" title="class in org.apache.juneau.http.entity"><code>HttpEntityBuilder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#cached--"><code>cached()</code></a>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#chunked--"><code>chunked()</code></a>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#chunked-boolean-"><code>chunked(boolean)</code></a>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#content-java.lang.Object-"><code>content(Object)</code></a>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#content-java.util.function.Supplier-"><code>content(Supplier)</code></a>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#contentEncoding-org.apache.juneau.http.header.ContentEncoding-"><code>contentEncoding(ContentEncoding)</code></a>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#contentEncoding-java.lang.String-"><code>contentEncoding(String)</code></a>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#contentLength-long-"><code>contentLength(long)</code></a>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#contentType-org.apache.juneau.http.header.ContentType-"><code>contentType(ContentType)</code></a>
<li class='jm'><a href="org/apache/juneau/http/entity/HttpEntityBuilder.html#contentType-java.lang.String-"><code>contentType(String)</code></a>
</ul>
</ul>
<h5 class='figure'>Example</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpEntities.*;
<jk>byte</jk>[] <jv>payload</jv> = {...};
<jc>// Create via type builder.</jc>
HttpEntity <jv>entity</jv> = ByteArrayEntity
.<jsm>create</jsm>()
.content(<jv>payload</jv>)
.contentType(ContentType.<jsf>APPLICATION_OCTET_STREAM</jsf>)
.build();
<jc>// Create via HttpEntities.</jc>
HttpEntity <jv>entity</jv> = <jsm>byteArrayEntity</jsm>(<jv>payload</jv>, ContentType.<jsf>APPLICATION_OCTET_STREAM</jsf>).build();
</p>
</div>
</div><!-- END: 7.5 - juneau-rest-common.jrc.org.apache.juneau.http.entity -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-common.jrc.org.apache.juneau.http.resource' id='juneau-rest-common.jrc.org.apache.juneau.http.resource'>7.6 - org.apache.juneau.http.resource</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 7.6 - juneau-rest-common.jrc.org.apache.juneau.http.resource -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/resource/package-summary.html"><code>org.apache.juneau.http.resource</code></a> package contains implementations of <a href="org/apache/juneau/http/resource/HttpResource.html" title="interface in org.apache.juneau.http.resource"><code>HttpResource</code></a> which are extensions of <c>org.apache.http.HttpEntity</c> with
arbitrary headers added.
</p>
<ul class='javatree'>
<li class='jic'><code>org.apache.http.HttpEntity</code>
<ul>
<li class='jic'><a href="org/apache/juneau/http/resource/HttpResource.html" title="interface in org.apache.juneau.http.resource"><code>HttpResource</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/http/resource/BasicResource.html" title="class in org.apache.juneau.http.resource"><code>BasicResource</code></a>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/resource/ByteArrayResource.html" title="class in org.apache.juneau.http.resource"><code>ByteArrayResource</code></a>
<li class='jc'><a href="org/apache/juneau/http/resource/FileResource.html" title="class in org.apache.juneau.http.resource"><code>FileResource</code></a>
<li class='jc'><a href="org/apache/juneau/http/resource/InputStreamResource.html" title="class in org.apache.juneau.http.resource"><code>InputStreamResource</code></a>
<li class='jc'><a href="org/apache/juneau/http/resource/ReaderResource.html" title="class in org.apache.juneau.http.resource"><code>ReaderResource</code></a>
<li class='jc'><a href="org/apache/juneau/http/resource/StringResource.html" title="class in org.apache.juneau.http.resource"><code>StringResource</code></a>
</ul>
</ul>
</ul>
</ul>
<h5 class='topic'>HttpResourceBuilder</h5>
<p>
HTTP entities are created through builders created in the <a href="org/apache/juneau/http/HttpResources.html" title="class in org.apache.juneau.http"><code>HttpResources</code></a> class or individual <c>create()</c> methods
defined in the subclasses above. The builder contains the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html" title="class in org.apache.juneau.http.resource"><code>HttpResourceBuilder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#cached--"><code>cached()</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#chunked--"><code>chunked()</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#chunked-boolean-"><code>chunked(boolean)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#content-java.lang.Object-"><code>content(Object)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#content-java.util.function.Supplier-"><code>content(Supplier)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#contentEncoding-org.apache.juneau.http.header.ContentEncoding-"><code>contentEncoding(ContentEncoding)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#contentEncoding-java.lang.String-"><code>contentEncoding(String)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#contentLength-long-"><code>contentLength(long)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#contentType-org.apache.juneau.http.header.ContentType-"><code>contentType(ContentType)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#contentType-java.lang.String-"><code>contentType(String)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#copyFrom-org.apache.http.HttpResponse-"><code>copyFrom(HttpResponse)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#getEntity--"><code>getEntity()</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#getHeaders--"><code>getHeaders()</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#header-org.apache.http.Header-"><code>header(Header)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#header-java.lang.String-java.lang.String-"><code>header(String,String)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#headers-org.apache.http.Header...-"><code>headers(Header...)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#headers-org.apache.juneau.http.header.HeaderList-"><code>headers(HeaderList)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#headers-java.util.List-"><code>headers(List&lt;Header&gt;)</code></a>
<li class='jm'><a href="org/apache/juneau/http/resource/HttpResourceBuilder.html#getHeaders--"><code>getHeaders()</code></a>
</ul>
</ul>
<h5 class='figure'>Example</h5>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.http.HttpResources.*;
<jk>byte</jk>[] <jv>payload</jv> = {...};
<jc>// Create via type builder.</jc>
HttpResource <jv>resource</jv> = ByteArrayResource
.<jsm>create</jsm>()
.content(<jv>payload</jv>)
.contentType(ContentType.<jsf>APPLICATION_OCTET_STREAM</jsf>)
.build();
<jc>// Create via HttpResources.</jc>
HttpResource <jv>resource</jv> = <jsm>byteArrayResource</jsm>(<jv>payload</jv>, ContentType.<jsf>APPLICATION_OCTET_STREAM</jsf>).build();
</p>
</div>
</div><!-- END: 7.6 - juneau-rest-common.jrc.org.apache.juneau.http.resource -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-common.jrc.org.apache.juneau.http.response' id='juneau-rest-common.jrc.org.apache.juneau.http.response'>7.7 - org.apache.juneau.http.response</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 7.7 - juneau-rest-common.jrc.org.apache.juneau.http.response -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/response/package-summary.html"><code>org.apache.juneau.http.response</code></a> package contains predefined <c>org.apache.http.HttpResponse</c> implementations for most standard HTTP
responses.
</p>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/response/Accepted.html" title="class in org.apache.juneau.http.response"><code>Accepted</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/AlreadyReported.html" title="class in org.apache.juneau.http.response"><code>AlreadyReported</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/BadRequest.html" title="class in org.apache.juneau.http.response"><code>BadRequest</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Conflict.html" title="class in org.apache.juneau.http.response"><code>Conflict</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Continue.html" title="class in org.apache.juneau.http.response"><code>Continue</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Created.html" title="class in org.apache.juneau.http.response"><code>Created</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/EarlyHints.html" title="class in org.apache.juneau.http.response"><code>EarlyHints</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/ExpectationFailed.html" title="class in org.apache.juneau.http.response"><code>ExpectationFailed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/FailedDependency.html" title="class in org.apache.juneau.http.response"><code>FailedDependency</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Forbidden.html" title="class in org.apache.juneau.http.response"><code>Forbidden</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Found.html" title="class in org.apache.juneau.http.response"><code>Found</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Gone.html" title="class in org.apache.juneau.http.response"><code>Gone</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/HttpVersionNotSupported.html" title="class in org.apache.juneau.http.response"><code>HttpVersionNotSupported</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/IMUsed.html" title="class in org.apache.juneau.http.response"><code>IMUsed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/InsufficientStorage.html" title="class in org.apache.juneau.http.response"><code>InsufficientStorage</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/InternalServerError.html" title="class in org.apache.juneau.http.response"><code>InternalServerError</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/LengthRequired.html" title="class in org.apache.juneau.http.response"><code>LengthRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Locked.html" title="class in org.apache.juneau.http.response"><code>Locked</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/LoopDetected.html" title="class in org.apache.juneau.http.response"><code>LoopDetected</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MethodNotAllowed.html" title="class in org.apache.juneau.http.response"><code>MethodNotAllowed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MisdirectedRequest.html" title="class in org.apache.juneau.http.response"><code>MisdirectedRequest</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MovedPermanently.html" title="class in org.apache.juneau.http.response"><code>MovedPermanently</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MultipleChoices.html" title="class in org.apache.juneau.http.response"><code>MultipleChoices</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MultiStatus.html" title="class in org.apache.juneau.http.response"><code>MultiStatus</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NetworkAuthenticationRequired.html" title="class in org.apache.juneau.http.response"><code>NetworkAuthenticationRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NoContent.html" title="class in org.apache.juneau.http.response"><code>NoContent</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NonAuthoritiveInformation.html" title="class in org.apache.juneau.http.response"><code>NonAuthoritiveInformation</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotAcceptable.html" title="class in org.apache.juneau.http.response"><code>NotAcceptable</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotExtended.html" title="class in org.apache.juneau.http.response"><code>NotExtended</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotFound.html" title="class in org.apache.juneau.http.response"><code>NotFound</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotImplemented.html" title="class in org.apache.juneau.http.response"><code>NotImplemented</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotModified.html" title="class in org.apache.juneau.http.response"><code>NotModified</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Ok.html" title="class in org.apache.juneau.http.response"><code>Ok</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PartialContent.html" title="class in org.apache.juneau.http.response"><code>PartialContent</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PayloadTooLarge.html" title="class in org.apache.juneau.http.response"><code>PayloadTooLarge</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PermanentRedirect.html" title="class in org.apache.juneau.http.response"><code>PermanentRedirect</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PreconditionFailed.html" title="class in org.apache.juneau.http.response"><code>PreconditionFailed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PreconditionRequired.html" title="class in org.apache.juneau.http.response"><code>PreconditionRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Processing.html" title="class in org.apache.juneau.http.response"><code>Processing</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/RangeNotSatisfiable.html" title="class in org.apache.juneau.http.response"><code>RangeNotSatisfiable</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/RequestHeaderFieldsTooLarge.html" title="class in org.apache.juneau.http.response"><code>RequestHeaderFieldsTooLarge</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/ResetContent.html" title="class in org.apache.juneau.http.response"><code>ResetContent</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/SeeOther.html" title="class in org.apache.juneau.http.response"><code>SeeOther</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/ServiceUnavailable.html" title="class in org.apache.juneau.http.response"><code>ServiceUnavailable</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/SwitchingProtocols.html" title="class in org.apache.juneau.http.response"><code>SwitchingProtocols</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/TemporaryRedirect.html" title="class in org.apache.juneau.http.response"><code>TemporaryRedirect</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/TooManyRequests.html" title="class in org.apache.juneau.http.response"><code>TooManyRequests</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Unauthorized.html" title="class in org.apache.juneau.http.response"><code>Unauthorized</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UnavailableForLegalReasons.html" title="class in org.apache.juneau.http.response"><code>UnavailableForLegalReasons</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UnprocessableEntity.html" title="class in org.apache.juneau.http.response"><code>UnprocessableEntity</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UnsupportedMediaType.html" title="class in org.apache.juneau.http.response"><code>UnsupportedMediaType</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UpgradeRequired.html" title="class in org.apache.juneau.http.response"><code>UpgradeRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UriTooLong.html" title="class in org.apache.juneau.http.response"><code>UriTooLong</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UseProxy.html" title="class in org.apache.juneau.http.response"><code>UseProxy</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/VariantAlsoNegotiates.html" title="class in org.apache.juneau.http.response"><code>VariantAlsoNegotiates</code></a>
</ul>
<p>
These are built upon existing HttpComponents APIs:
</p>
<ul class='javatree'>
<li class='jic'><code>org.apache.http.HttpMessage</code>
<ul>
<li class='jic'><code>org.apache.http.HttpResponse</code>
<ul>
<li class='jc'><a href="org/apache/juneau/http/response/BasicHttpResponse.html" title="class in org.apache.juneau.http.response"><code>BasicHttpResponse</code></a> - 100-399 response codes
<li class='jc'><a href="org/apache/juneau/http/response/BasicHttpException.html" title="class in org.apache.juneau.http.response"><code>BasicHttpException</code></a> - 400+ response codes
</ul>
</ul>
</ul>
<p>
The most common location where these responses are used are in REST operation methods described later.
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestDelete</ja>(path=<js>"/{id}"</js>)
<jk>public</jk> Ok doDelete(<ja>@Path</ja> <jk>int</jk> <jv>id</jv>) <jk>throws</jk> NotFound, Unauthorized {
<jf>pojoService</jf>.delete(<jf>pojoService</jf>.find(<jv>id</jv>).orElseThrow(NotFound::<jk>new</jk>));
<jk>return</jk> Ok.OK;
}
</p>
<p>
The following classes are also provided for constructing your own custom responses:
</p>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/response/BasicHttpException.html" title="class in org.apache.juneau.http.response"><code>BasicHttpException</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/BasicHttpResponse.html" title="class in org.apache.juneau.http.response"><code>BasicHttpResponse</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/HttpExceptionBuilder.html" title="class in org.apache.juneau.http.response"><code>HttpExceptionBuilder</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html" title="class in org.apache.juneau.http.response"><code>HttpResponseBuilder</code></a>
</ul>
<h5 class='topic'>HttpResponseBuilder / HttpExceptionBuilder</h5>
<p>
HTTP responses are created through builders created in the <a href="org/apache/juneau/http/HttpResponses.html" title="class in org.apache.juneau.http"><code>HttpResponses</code></a> class or individual <c>create()</c> methods
defined in the basic classes above. The builder contains the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html" title="class in org.apache.juneau.http.response"><code>HttpResponseBuilder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#content-org.apache.http.HttpEntity-"><code>content(HttpEntity)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#content-java.lang.String-"><code>content(String)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#copyFrom-org.apache.http.HttpResponse-"><code>copyFrom(HttpResponse)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#getHeaders--"><code>getHeaders()</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#getStatusLine--"><code>getStatusLine()</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#header-org.apache.http.Header-"><code>header(Header)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#header-java.lang.String-java.lang.String-"><code>header(String,String)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#headers-org.apache.http.Header...-"><code>headers(Header...)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#headers-org.apache.juneau.http.header.HeaderList-"><code>headers(HeaderList)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#headers-java.util.List-"><code>headers(List&lt;Header&gt;)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#locale-java.util.Locale-"><code>locale(Locale)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#location-java.lang.String-"><code>location(String)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#location-java.net.URI-"><code>location(URI)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#protocolVersion-org.apache.http.ProtocolVersion-"><code>protocolVersion(ProtocolVersion)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#reasonPhrase-java.lang.String-"><code>reasonPhrase(String)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#reasonPhraseCatalog-org.apache.http.ReasonPhraseCatalog-"><code>reasonPhraseCatalog(ReasonPhraseCatalog)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#statusCode-int-"><code>statusCode(int)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#statusLine-org.apache.juneau.http.BasicStatusLine-"><code>statusLine(BasicStatusLine)</code></a>
<li class='jm'><a href="org/apache/juneau/http/response/HttpResponseBuilder.html#unmodifiable--"><code>unmodifiable()</code></a>
</ul>
</ul>
</div>
</div><!-- END: 7.7 - juneau-rest-common.jrc.org.apache.juneau.http.response -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-common.jrc.org.apache.juneau.http.remote' id='juneau-rest-common.jrc.org.apache.juneau.http.remote'>7.8 - org.apache.juneau.http.remote</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 7.8 - juneau-rest-common.jrc.org.apache.juneau.http.remote -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/remote/package-summary.html"><code>org.apache.juneau.http.remote</code></a> package contains the annotations used for defining client-side remote proxies.
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>Remote</code></a>
<li class='ja'><a href="org/apache/juneau/http/remote/RemoteGet.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteGet</code></a>
<li class='ja'><a href="org/apache/juneau/http/remote/RemotePut.html" title="annotation in org.apache.juneau.http.remote"><code>RemotePut</code></a>
<li class='ja'><a href="org/apache/juneau/http/remote/RemotePost.html" title="annotation in org.apache.juneau.http.remote"><code>RemotePost</code></a>
<li class='ja'><a href="org/apache/juneau/http/remote/RemoteDelete.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteDelete</code></a>
<li class='ja'><a href="org/apache/juneau/http/remote/RemoteOp.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteOp</code></a>
</ul>
<p>
See <a class='doclink' href='#juneau-rest-client.jrc.Proxies'>Proxies</a> for more information on use of these annotations.
</p>
</div>
</div><!-- END: 7.8 - juneau-rest-common.jrc.org.apache.juneau.http.remote -->
</div><!-- END: 7 - juneau-rest-common -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server' id='juneau-rest-server'>8 - juneau-rest-server</a><span class='update'>updated: <b>9.0.0</b></span></h2>
<div class='topic'><!-- START: 8 - juneau-rest-server -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-rest-server<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-rest-server-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.rest.server_9.0.0.jar
</p>
<p>
The <l>juneau-rest-server</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, <a href="org/apache/juneau/rest/servlet/RestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>RestServlet</code></a> is nothing but a specialized
<code>HttpServlet</code>, and the <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> and
<a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a> classes are nothing more than specialized
<code>HttpServletRequest</code> and <code>HttpServletResponse</code> 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>
<h5 class='topic'>Features</h5>
<ul class='spaced-list'>
<li>
Deployable in standard Servlet containers.
<li>
Deployable in Spring Boot environments with full support for injected beans.
<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>
Support for parsing all HTTP parts (headers, query, formData, path variables) using Swagger formatting rules and validations.
<br>Not limited to simple POJOs but rather you can represent arbitrarily-complex POJOs in any HTTP part using UON notation.
<li>
Auto-created Swagger JSON and Swagger UI available through OPTIONS requests of resources.
<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>&amp;Accept=text/xml</l>).
<li>Ability to pass HTTP content on PUT/POST requests as a URL GET parameter
(e.g. <l>&amp;content=(foo=bar)</l>).
<li>Ability to simulate non-GET requests using a <l>&amp;method</l> GET parameter
(e.g. <l>&amp;method=POST</l>).
<li>Ability to force <js>"text/plain"</js> on response using GET parameter <l>&amp;plainText=true</l>.
</ul>
<li>
Ability to implement overloaded HTTP methods through the use of the <l>&amp;method</l> attribute
(e.g. <l>&amp;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 <l>juneau-examples-rest</l>.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Overview' id='juneau-rest-server.jrs.Overview'>8.1 - Overview</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.1 - juneau-rest-server.jrs.Overview -->
<div class='topic'>
<p>
A REST resource is simply a Java class annotated with <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a>.
The most common case is a class that extends <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a>, which itself is simply an
extension of <code>HttpServlet</code> which allows it to be deployed as a servlet.
</p>
<p>
Juneau has two sample applications for demonstrating how to use the REST API, one using Jetty and one using
Spring Boot:
</p>
<ul class='javatree'>
<li class='jp'><a href="org/apache/juneau/examples/rest/jetty/package-summary.html"><code>org.apache.juneau.examples.rest.jetty</code></a>
<li class='jp'><a href="org/apache/juneau/examples/rest/springboot/package-summary.html"><code>org.apache.juneau.examples.rest.springboot</code></a>
</ul>
<p>
The <a href="org/apache/juneau/examples/rest/springboot/package-summary.html"><code>org.apache.juneau.examples.rest.springboot</code></a> application is described in the section <a class='doclink' href='#juneau-rest-server-springboot.jrss.Overview'>SpringBoot Overview</a>.
</p>
<p>
The Jetty application consists of the following application class that registers our top-level servlet:
</p>
<p class='bjava'>
<jk>public class</jk> App {
<jk>public static void</jk> main(String[] <jv>args</jv>) <jk>throws</jk> Exception {
JettyMicroservice
.<jsm>create</jsm>()
.args(<jv>args</jv>)
.servlet(RootResources.<jk>class</jk>)
.build()
.start()
.startConsole()
.join();
}
}
</p>
<p>
The root resources class is an example of a router page that is used to attach children to:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
title=<js>"Root resources"</js>,
description=<js>"Example of a router resource page."</js>,
children={
HelloWorldResource.<jk>class</jk>,
DtoExamples.<jk>class</jk>,
UtilityBeansResource.<jk>class</jk>,
HtmlBeansResource.<jk>class</jk>,
ConfigResource.<jk>class</jk>,
ShutdownResource.<jk>class</jk>
}
)
<ja>@HtmlDocConfig</ja>(
widgets={
ContentTypeMenuItem.<jk>class</jk>
},
navlinks={
<js>"api: servlet:/api"</js>,
<js>"stats: servlet:/stats"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/RootResources.java"</js>
},
aside={
<js>"&lt;div class='text'&gt;"</js>,
<js>" &lt;p&gt;This is an example of a 'router' page that serves as a jumping-off point to child resources.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Resources can be nested arbitrarily deep through router pages.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Note the &lt;span class='link'&gt;API&lt;/span&gt; link provided that lets you see the generated swagger doc for this page.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Also note the &lt;span class='link'&gt;STATS&lt;/span&gt; link to view runtime statistics on this page.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Also note the &lt;span class='link'&gt;SOURCE&lt;/span&gt; link to view the source code for the page.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;All content on pages in the UI are serialized POJOs. In this case, it's a serialized array of beans with 2 properties, 'name' and 'description'.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Other features (such as this aside) are added through annotations.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
},
asideFloat=<js>"RIGHT"</js>
)
<ja>@SerializerConfig</ja>(
<jc>// For testing purposes, we want to use single quotes in all the serializers so it's easier to do simple
// String comparisons.
// You can apply any of the Serializer/Parser/BeanContext settings this way.</jc>
quoteChar=<js>"'"</js>
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicRestServletGroup <jk>implements</jk> BasicUniversalJenaConfig {
<jc>// IMPORTANT! If you don't need RDF support, change the parent interface to BasicUniversalConfig.
// It allows you to remove the Jena prerequisite.</jc>
<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L;
}
</p>
<p>
This is what it looks like in a browser:
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrs.Overview.RootResources.png'>
<h5 class='figure'>JSON representation</h5>
<img class='bordered w800' src='doc-files/jrs.Overview.RootResources.json.png'>
<p>
The <a href="org/apache/juneau/examples/rest/HelloWorldResource.html" title="class in org.apache.juneau.examples.rest"><code>HelloWorldResource</code></a> class is our basic example of a child REST resource:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
title=<js>"Hello World"</js>,
description=<js>"An example of the simplest-possible resource"</js>,
path=<js>"/helloWorld"</js>
)
<ja>@HtmlDocConfig</ja>(
aside={
<js>"&lt;div style='max-width:400px' class='text'&gt;"</js>,
<js>" &lt;p&gt;This page shows a resource that simply response with a 'Hello world!' message&lt;/p&gt;"</js>,
<js>" &lt;p&gt;The POJO serialized is a simple String.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig {
<ja>@RestGet</ja>(path=<js>"/*"</js>, summary=<js>"Responds with \"Hello world!\""</js>)
<jk>public</jk> String sayHello() {
<jk>return</jk> <js>"Hello world!"</js>;
}
}
</p>
<p>
This is what it looks like in a browser:
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrs.Overview.HelloWorldResource.png'>
<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>
</div>
</div><!-- END: 8.1 - juneau-rest-server.jrs.Overview -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.AnnotatedClasses' id='juneau-rest-server.jrs.AnnotatedClasses'>8.2 - @Rest-Annotated Classes</a><span class='update'>updated: 8.1.2,<b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.2 - juneau-rest-server.jrs.AnnotatedClasses -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a> annotation is the primary way of defining
and configuring REST resource classes.
The functionality of the class itself is covered in detail in the topics below.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#allowedHeaderParams--"><code>allowedHeaderParams</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#allowedMethodHeaders--"><code>allowedMethodHeaders</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#allowedMethodParams--"><code>allowedMethodParams</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#beanStore--"><code>beanStore</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#builder--"><code>builder</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#callLogger--"><code>callLogger</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#children--"><code>children</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#clientVersionHeader--"><code>clientVersionHeader</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#config--"><code>config</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#consumes--"><code>consumes</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#contextClass--"><code>contextClass</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#converters--"><code>converters</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#debug--"><code>debug</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#debugEnablement--"><code>debugEnablement</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#debugOn--"><code>debugOn</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultAccept--"><code>defaultAccept</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultCharset--"><code>defaultCharset</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultContentType--"><code>defaultContentType</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultRequestAttributes--"><code>defaultRequestAttributes</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultRequestHeaders--"><code>defaultRequestHeaders</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultResponseHeaders--"><code>defaultResponseHeaders</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#description--"><code>description</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#disableContentParam--"><code>disableContentParam</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#encoders--"><code>encoders</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#fileFinder--"><code>fileFinder</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#guards--"><code>guards</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#maxInput--"><code>maxInput</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#messages--"><code>messages</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#on--"><code>on</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#onClass--"><code>onClass</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#parsers--"><code>parsers</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#partParser--"><code>partParser</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#partSerializer--"><code>partSerializer</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#path--"><code>path</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#produces--"><code>produces</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#renderResponseStackTraces--"><code>renderResponseStackTraces</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#responseProcessors--"><code>responseProcessors</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#restChildrenClass--"><code>restChildrenClass</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#restOpArgs--"><code>restOpArgs</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#restOpContextClass--"><code>restOpContextClass</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#restOperationsClass--"><code>restOperationsClass</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#roleGuard--"><code>roleGuard</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#rolesDeclared--"><code>rolesDeclared</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#serializers--"><code>serializers</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#siteName--"><code>siteName</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#staticFiles--"><code>staticFiles</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#swagger--"><code>swagger</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#swaggerProvider--"><code>swaggerProvider</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#title--"><code>title</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#uriAuthority--"><code>uriAuthority</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#uriContext--"><code>uriContext</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#uriRelativity--"><code>uriRelativity</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#uriResolution--"><code>uriResolution</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a> annotation in inheritable from parents and interfaces of resource classes.
When multiple annotations are defined at different levels, the annotation values are combined.
This is a particularly useful feature because it allows you to define your own configured parent
resource classes that can be extended by all your child resources so that they all share common
settings.
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.PredefinedClasses' id='juneau-rest-server.jrs.AnnotatedClasses.jrs.PredefinedClasses'>8.2.1 - Predefined Classes</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.2.1 - juneau-rest-server.jrs.AnnotatedClasses.jrs.PredefinedClasses -->
<div class='topic'>
<p>
The following example represents the bare-minimum needed
for deploying a top-level REST endpoint with basic JSON marshalling support:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/mypath"</js>,
serializers=JsonSerializer.<jk>class</jk>,
parsers=JsonParser.<jk>class</jk>
)
<jk>public class</jk> MyResource <jk>extends</jk> RestServlet {
<ja>@RestGet</ja>(path=<js>"/"</js>)
<jk>public</jk> Object getPojo() {
...
}
}
</p>
<p>
The <a href="org/apache/juneau/rest/servlet/RestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>RestServlet</code></a> class provides all the logic for starting up your REST
application when the servlet container calls <a href="org/apache/juneau/rest/servlet/RestServlet.html#init-javax.servlet.ServletConfig-"><code>init(ServletConfig)</code></a>.
On startup, it scans your class for annotations and sets up
all of your serializers and parsers. It then does this recursively for all child resources.
</p>
<p>
Users will typically not extend directly from <a href="org/apache/juneau/rest/servlet/RestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>RestServlet</code></a>. Instead, several classes are provided by the framework to provide additional
functionality and to handle different use-cases. Users will typically extend from one of these <c>Basic*</c> classes:
</p>
<ul class='javatree'>
<li class='jac'><code>HttpServlet</code>
<ul>
<li class='jac'><a href="org/apache/juneau/rest/servlet/RestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>RestServlet</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> <jk>implements</jk> <a href="org/apache/juneau/rest/servlet/BasicRestOperations.html" title="interface in org.apache.juneau.rest.servlet"><code>BasicRestOperations</code></a>, <a href="org/apache/juneau/rest/config/BasicJsonConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicJsonConfig</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/rest/servlet/BasicRestServletGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServletGroup</code></a> <jk>implements</jk> <a href="org/apache/juneau/rest/servlet/BasicGroupOperations.html" title="interface in org.apache.juneau.rest.servlet"><code>BasicGroupOperations</code></a>
</ul>
</li>
<li class='jac'><a href="org/apache/juneau/rest/springboot/SpringRestServlet.html" title="class in org.apache.juneau.rest.springboot"><code>SpringRestServlet</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/rest/springboot/BasicSpringRestServlet.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServlet</code></a> <jk>implements</jk> <a href="org/apache/juneau/rest/servlet/BasicRestOperations.html" title="interface in org.apache.juneau.rest.servlet"><code>BasicRestOperations</code></a>, <a href="org/apache/juneau/rest/config/BasicJsonConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicJsonConfig</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/rest/springboot/BasicSpringRestServletGroup.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServletGroup</code></a> <jk>implements</jk> <a href="org/apache/juneau/rest/servlet/BasicGroupOperations.html" title="interface in org.apache.juneau.rest.servlet"><code>BasicGroupOperations</code></a>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class='jac'><a href="org/apache/juneau/rest/servlet/RestObject.html" title="class in org.apache.juneau.rest.servlet"><code>RestObject</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/rest/servlet/BasicRestObject.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObject</code></a> <jk>implements</jk> <a href="org/apache/juneau/rest/servlet/BasicRestOperations.html" title="interface in org.apache.juneau.rest.servlet"><code>BasicRestOperations</code></a>, <a href="org/apache/juneau/rest/config/BasicJsonConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicJsonConfig</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/rest/servlet/BasicRestObjectGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObjectGroup</code></a> <jk>implements</jk> <a href="org/apache/juneau/rest/servlet/BasicGroupOperations.html" title="interface in org.apache.juneau.rest.servlet"><code>BasicGroupOperations</code></a>
</ul>
</li>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/rest/servlet/RestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>RestServlet</code></a>
class itself is not configured with any serializers or parsers. However, it does
provide several convenience methods to be aware of:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/rest/servlet/RestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>RestServlet</code></a>
<ul class='spaced-list'>
<li>Predefined lifecycle hook methods:
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#onInit-org.apache.juneau.rest.RestContext.Builder-"><code>onInit()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#onPostInit-org.apache.juneau.rest.RestContext-"><code>onPostInit()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#onPostInitChildFirst-org.apache.juneau.rest.RestContext-"><code>onPostInitChildFirst()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#onStartCall-javax.servlet.http.HttpServletRequest-javax.servlet.http.HttpServletResponse-"><code>onStartCall()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#onPreCall-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>onPreCall()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#onPostCall-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>onPostCall()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#onEndCall-javax.servlet.http.HttpServletRequest-javax.servlet.http.HttpServletResponse-"><code>onEndCall()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#onDestroy-org.apache.juneau.rest.RestContext-"><code>onDestroy()</code></a>
</ul>
</li>
<li>Logging methods:
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#log-java.util.logging.Level-java.lang.String-java.lang.Object...-"><code>log(Level,String,Object...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#log-java.util.logging.Level-java.lang.Throwable-java.lang.String-java.lang.Object...-"><code>log(Level,Throwable,String,Object...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#log-java.lang.String-"><code>log(String)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#log-java.lang.String-java.lang.Throwable-"><code>log(String,Throwable)</code></a>
</ul>
</li>
<li>Other methods:
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#getContext--"><code>getContext()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#getPath--"><code>getPath()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#getRequest--"><code>getRequest()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/servlet/RestServlet.html#getResponse--"><code>getResponse()</code></a>
</ul>
</li>
</ul>
</li>
</ul>
<p>
The <c>Basic*</c> classes implement the <a href="org/apache/juneau/rest/servlet/BasicRestOperations.html" title="interface in org.apache.juneau.rest.servlet"><code>BasicRestOperations</code></a> interface
which defines common endpoints for swagger documentation, statistics, and serving static files:
</p>
<p class='bjava'>
<jk>public interface</jk> BasicRestOperations {
<ja>@RestGet</ja>(path=<js>"/api/*"</js>)
<jk>public</jk> <a href="org/apache/juneau/dto/swagger/Swagger.html" title="class in org.apache.juneau.dto.swagger"><code>Swagger</code></a> <a href="org/apache/juneau/rest/servlet/BasicRestOperations.html#getSwagger-org.apache.juneau.rest.RestRequest-"><code>getSwagger</code></a>(<a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> <jv>req</jv>);
<ja>@RestGet</ja>(path=<js>"/htdocs/*"</js>)
<jk>public</jk> <a href="org/apache/juneau/http/resource/HttpResource.html" title="interface in org.apache.juneau.http.resource"><code>HttpResource</code></a> <a href="org/apache/juneau/rest/servlet/BasicRestOperations.html#getHtdoc-java.lang.String-java.util.Locale-"><code>getHtdoc</code></a>(<ja>@Path</ja> String <jv>path</jv>, Locale <jv>locale</jv>);
<ja>@RestGet</ja>(path=<js>"favicon.ico"</js>)
<jk>public</jk> <a href="org/apache/juneau/http/resource/HttpResource.html" title="interface in org.apache.juneau.http.resource"><code>HttpResource</code></a> <a href="org/apache/juneau/rest/servlet/BasicRestOperations.html#getFavIcon--"><code>getFavIcon</code></a>();
<ja>@RestGet</ja>(path=<js>"/stats"</js>)
<jk>public</jk> <a href="org/apache/juneau/rest/stats/RestContextStats.html" title="class in org.apache.juneau.rest.stats"><code>RestContextStats</code></a> <a href="org/apache/juneau/rest/servlet/BasicRestOperations.html#getStats-org.apache.juneau.rest.RestRequest-"><code>getStats</code></a>(<a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> <jv>req</jv>);
<ja>@RestOp</ja>(method=<jsf>ANY</jsf>, path=<js>"/error"</js>)
<jk>public void</jk> <a href="org/apache/juneau/rest/servlet/BasicRestOperations.html#error--"><code>error</code></a>();
}
</p>
<p>
The <c>Basic*</c> classes also implement <a href="org/apache/juneau/rest/config/BasicJsonConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicJsonConfig</code></a> interface which
provides basic JSON marshalling support. Other config interfaces are available as
well to quickly provide different types of marshalling support. Note that these interfaces
do not define any methods but rather simply provide a set of commonly-used annotations so that
you don't need to define them on all your classes.
</p>
<ul class='javatreec'>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicJsonConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicJsonConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicJsonHtmlConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicJsonHtmlConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicSimpleJsonConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicSimpleJsonConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicOpenApiConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicOpenApiConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicUniversalConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicUniversalConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicUniversalJenaConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicUniversalJenaConfig</code></a>
</ul>
<p>
For example, if you want to provide a resource that supports all languages in Juneau,
simply add the <a href="org/apache/juneau/rest/config/BasicUniversalConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicUniversalConfig</code></a> interface like so:
</p>
<p class='bjava'>
<ja>@Rest</ja>(...)
<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
...
}
</p>
<p>
The <c>*Group</c> classes implement the <a href="org/apache/juneau/rest/servlet/BasicGroupOperations.html" title="interface in org.apache.juneau.rest.servlet"><code>BasicGroupOperations</code></a> interface which provides an additional REST endpoint for listing and navigating child resources:
</p>
<p class='bjava'>
<jk>public interface</jk> BasicGroupOperations {
<ja>@RestGet</ja>(path=<js>"/"</js>)
<jk>public</jk> <a href="org/apache/juneau/rest/beans/ChildResourceDescriptions.html" title="class in org.apache.juneau.rest.beans"><code>ChildResourceDescriptions</code></a> <a href="org/apache/juneau/rest/servlet/BasicGroupOperations.html#getChildren-org.apache.juneau.rest.RestRequest-"><code>getChildren</code></a>(<a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> <jv>req</jv>);
}
</p>
<p>
The <c>*Spring*</c> classes are meant to be used in Spring Boot environments so that you can
take full advantage of the Spring Framework for injecting dependencies on child resources
and helper classes.
</p>
<p>
The <c>*Object*</c> classes provide the same functionality as the servlet
classes but do not extend from <code>HttpServlet</code>.
This becomes important in Spring Boot environments where you may want to
define child resources as Spring Beans but don't want Spring Boot to auto-detect
them as servlets to be deployed as top-level resources. This is less important
in standard servlet containers that don't auto-deploy servlets. In those
environments, you can also use servlet classes for child resources.
</p>
<p>
The following is a breakdown of which classes you will use in different cases:
</p>
<ul class='spaced-list'>
<li>Top level resources in a servlet container:
<ul class='javatreec'>
<li class='jac'><a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a>
<li class='jac'><a href="org/apache/juneau/rest/servlet/BasicRestServletGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServletGroup</code></a>
</ul>
</li>
<li>Top level resources in a Spring Boot environment:
<ul class='javatreec'>
<li class='jac'><a href="org/apache/juneau/rest/springboot/BasicSpringRestServlet.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServlet</code></a>
<li class='jac'><a href="org/apache/juneau/rest/springboot/BasicSpringRestServletGroup.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServletGroup</code></a>
</ul>
</li>
<li>Child resources:
<ul class='javatreec'>
<li class='jac'><a href="org/apache/juneau/rest/servlet/BasicRestObject.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObject</code></a>
<li class='jac'><a href="org/apache/juneau/rest/servlet/BasicRestObjectGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObjectGroup</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 8.2.1 - juneau-rest-server.jrs.AnnotatedClasses.jrs.PredefinedClasses -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.ChildResources' id='juneau-rest-server.jrs.AnnotatedClasses.jrs.ChildResources'>8.2.2 - Child Resources</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.2.2 - juneau-rest-server.jrs.AnnotatedClasses.jrs.ChildResources -->
<div class='topic'>
<p>
Child Resources are REST servlets or objects that are linked to parent resources through the
<a href="org/apache/juneau/rest/annotation/Rest.html#children--"><code>@Rest(children)</code></a> annotation.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jd>/** Parent Resource */</jd>
<ja>@Rest</ja>(
path=<js>"/parent"</js>,
children={MyChildResource.<jk>class</jk>}
)
<jk>public</jk> MyRootResources <jk>extends</jk> BasicRestServletGroup <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p class='bjava'>
<jd>/** Child Resource */</jd>
<ja>@Rest</ja>(
path=<js>"/child"</js> <jc>// Path relative to parent resource.</jc>
)
<jc>// Note that we don't need to extend from RestServlet.</jc>
<jk>public</jk> MyChildResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
The path of the child resource gets appended to the path of the parent resource.
So in the example above, the child resource is accessed through the URL <l>/parent/child</l>.
</p>
<p>
One advantage of using child resources is that they do not need to be declared in the JEE <l>web.xml</l>
file.
Initialization of and access to the child resources occurs through the parent resource.
Children can be nested arbitrary deep to create complex REST interfaces with a single top-level REST servlet.
</p>
<p>
As explained earlier, child REST objects typically extend from <a href="org/apache/juneau/rest/servlet/BasicRestObject.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObject</code></a> or <a href="org/apache/juneau/rest/servlet/BasicRestObjectGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObjectGroup</code></a>
and not from one of the servlet classes. They also technically don't even need to extend from those classes
and can instead just be a normal class annotated with the bare-minimum <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a> and <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestOp</code></a>
annotations.
</p>
</div>
</div><!-- END: 8.2.2 - juneau-rest-server.jrs.AnnotatedClasses.jrs.ChildResources -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.PathVariables' id='juneau-rest-server.jrs.AnnotatedClasses.jrs.PathVariables'>8.2.3 - Path Variables</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.2.3 - juneau-rest-server.jrs.AnnotatedClasses.jrs.PathVariables -->
<div class='topic'>
<p>
The path can contain variables that get resolved to <a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>@Path</code></a> parameters
or access through the <a href="org/apache/juneau/rest/RestRequest.html#getPathParams--"><code>RestRequest.getPathParams()</code></a> method.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/myResource/{foo}/{bar}"</js>
)
<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<ja>@RestPost</ja>(<js>"/{baz}"</js>)
<jk>public void</jk> String doX(<ja>@Path</ja> String <jv>foo</jv>, <ja>@Path</ja> <jk>int</jk> <jv>bar</jv>) {
...
}
}
</p>
<p>
Variables can be used on either top-level or child resources and can be defined on multiple levels.
Path variables resolved in parent resource paths are also available to the child resources.
</p>
<div class='info'>
All variables in the path must be specified or else the target will not resolve and a <c>404</c> will result.
</div>
</div>
</div><!-- END: 8.2.3 - juneau-rest-server.jrs.AnnotatedClasses.jrs.PathVariables -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.Deployment' id='juneau-rest-server.jrs.AnnotatedClasses.jrs.Deployment'>8.2.4 - Deployment</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.2.4 - juneau-rest-server.jrs.AnnotatedClasses.jrs.Deployment -->
<div class='topic'>
<p>
REST resources are deployed in the following ways:
</p>
<ul class='spaced-list'>
<li>Deployed in a J2EE container as a servlet.
<li>Deployed in a Spring Boot environment as a servlet.
<li>Deployed as a child of another REST resource.
</ul>
<p>
When deployed in a J2EE container, you MUST extend from one of the servlet classes.
</p>
<ul class='notes'>
<li class='note'>
When deployed as a child of another resource, you MAY extend from one of the servlet classes but it's
not necessary.</b>
The only requirement is that the class be annotated with <ja>@Rest</ja> and have one of the following constructors
if they aren't already Spring Beans:
<ul class='javatreec'>
<li class='jm'><c><jk>public</jk> T()</c>
<li class='jm'><c><jk>public</jk> T(RestContext.Builder)</c>
</ul>
</li>
</ul>
<p>
Deployment in a servlet container is typically done by adding a servlet entry for the top-level resources to the JEE <l>web.xml</l>.
</p>
<p>
Deployment in a Spring Boot environment involves defining your top-level resources as Spring Beans.
Top-level resources must extend from <a href="org/apache/juneau/rest/springboot/BasicSpringRestServlet.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServlet</code></a> or <a href="org/apache/juneau/rest/springboot/BasicSpringRestServletGroup.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServletGroup</code></a>
so that Juneau can hook into the injection framework provided by Spring. Child resource CAN be defined as injected Spring Beans
as well but it is not a requirement.
</p>
<h5 class='figure'>Example Spring Boot Configuration</h5>
<p class='bjava'>
<ja>@SpringBootApplication</ja>
<ja>@Controller</ja>
<jk>public class</jk> SpringBootAppConfig {
<ja>@Bean</ja>
<jk>public</jk> MyRootResources getRootResources() {
...
}
<ja>@Bean</ja>
<jk>public</jk> MyChildResource getMyChildResource() {
...
}
<ja>@Bean</ja>
<jk>public</jk> ServletRegistrationBean&lt;Servlet&gt; getRootServlet(RootResources <jv>rootResources</jv>) {
<jk>return new</jk> ServletRegistrationBean&lt;&gt;(<jv>rootResources</jv>, <js>"/*"</js>);
}
}
</p>
</div>
</div><!-- END: 8.2.4 - juneau-rest-server.jrs.AnnotatedClasses.jrs.Deployment -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.AnnotatedClasses.jrs.LifecycleHooks' id='juneau-rest-server.jrs.AnnotatedClasses.jrs.LifecycleHooks'>8.2.5 - Lifecycle Hooks</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.2.5 - juneau-rest-server.jrs.AnnotatedClasses.jrs.LifecycleHooks -->
<div class='topic'>
<p>
Lifecycle hooks allow you to hook into lifecycle events of the servlet/resource creation and REST calls.
</p>
<p>
For example, if you want to add an initialization method to your resource:
</p>
<p class='bjava'>
<ja>@Rest</ja>(...)
<jk>public class</jk> MyResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig {
<jc>// Our database.</jc>
<jk>private</jk> Map&lt;Integer,Object&gt; <jf>myDatabase</jf>;
<ja>@RestHook</ja>(<jsf>INIT</jsf>)
<jk>public void</jk> initMyDatabase(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
<jf>myDatabase</jf> = <jk>new</jk> LinkedHashMap&lt;&gt;();
}
}
</p>
<p>
Or if you want to intercept REST calls:
</p>
<p class='bjava'>
<ja>@Rest</ja>(...)
<jk>public class</jk> MyResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig {
<jc>// Add a request attribute to all incoming requests.</jc>
<ja>@RestHook</ja>(<jsf>PRE_CALL</jsf>)
<jk>public void</jk> onPreCall(RestRequest <jv>req</jv>) {
<jv>req</jv>.setAttribute(<js>"foo"</js>, <js>"bar"</js>);
}
}
</p>
<p>
The hook events can be broken down into two categories:
</p>
<ul class='javatree'>
<li class='je'><a href="org/apache/juneau/rest/annotation/HookEvent.html" title="enum in org.apache.juneau.rest.annotation"><code>HookEvent</code></a>
<ul class='spaced-list'>
<li>Resource lifecycle events:
<ul class='javatree'>
<li class='jf'><a href="org/apache/juneau/rest/annotation/HookEvent.html#INIT"><code>INIT</code></a> - Right before initialization.
<li class='jf'><a href="org/apache/juneau/rest/annotation/HookEvent.html#POST_INIT"><code>POST_INIT</code></a> - Right after initialization.
<li class='jf'><a href="org/apache/juneau/rest/annotation/HookEvent.html#POST_INIT_CHILD_FIRST"><code>POST_INIT_CHILD_FIRST</code></a> - Right after initialization but run child methods first.
<li class='jf'><a href="org/apache/juneau/rest/annotation/HookEvent.html#DESTROY"><code>DESTROY</code></a> - Right before servlet destroy.
</ul>
</li>
<li>REST call lifecycle events:
<ul class='javatree'>
<li class='jf'><a href="org/apache/juneau/rest/annotation/HookEvent.html#START_CALL"><code>START_CALL</code></a> - At the beginning of a REST call.
<li class='jf'><a href="org/apache/juneau/rest/annotation/HookEvent.html#PRE_CALL"><code>PRE_CALL</code></a> - Right before the <ja>@RestOp</ja> method is invoked.
<li class='jf'><a href="org/apache/juneau/rest/annotation/HookEvent.html#POST_CALL"><code>POST_CALL</code></a> - Right after the <ja>@RestOp</ja> method is invoked.
<li class='jf'><a href="org/apache/juneau/rest/annotation/HookEvent.html#END_CALL"><code>END_CALL</code></a> - At the end of the REST call after the response has been flushed.
</ul>
</li>
</ul>
</li>
</ul>
<ul class='seealso'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestHook.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestHook</code></a>
</ul>
</div>
</div><!-- END: 8.2.5 - juneau-rest-server.jrs.AnnotatedClasses.jrs.LifecycleHooks -->
</div><!-- END: 8.2 - juneau-rest-server.jrs.AnnotatedClasses -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpAnnotatedMethods' id='juneau-rest-server.jrs.RestOpAnnotatedMethods'>8.3 - @RestOp-Annotated Methods</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.3 - juneau-rest-server.jrs.RestOpAnnotatedMethods -->
<div class='topic'>
<p>
REST Java methods are identified on REST servlets using the
<a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestOp</code></a> annotation.
The annotation allows the framework to identify the available REST methods through reflection.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#clientVersion--"><code>clientVersion</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#consumes--"><code>consumes</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#contextClass--"><code>contextClass</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#converters--"><code>converters</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#debug--"><code>debug</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultAccept--"><code>defaultAccept</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultCharset--"><code>defaultCharset</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultContentType--"><code>defaultContentType</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultRequestAttributes--"><code>defaultRequestAttributes</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultRequestFormData--"><code>defaultRequestFormData</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultRequestHeaders--"><code>defaultRequestHeaders</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultRequestQueryData--"><code>defaultRequestQueryData</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultResponseHeaders--"><code>defaultResponseHeaders</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#description--"><code>description</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#encoders--"><code>encoders</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#guards--"><code>guards</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#matchers--"><code>matchers</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#maxInput--"><code>maxInput</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#method--"><code>method</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#on--"><code>on</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#parsers--"><code>parsers</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#path--"><code>path</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#produces--"><code>produces</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#roleGuard--"><code>roleGuard</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#rolesDeclared--"><code>rolesDeclared</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#serializers--"><code>serializers</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#summary--"><code>summary</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#swagger--"><code>swagger</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#value--"><code>value</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestOp</ja>(method=<jsf>GET</jsf>, path=<js>"/"</js>)
<jk>public</jk> String sayHello() {
<jk>return</jk> <js>"Hello world!"</js>;
}
</p>
<p>
The following specialized annotations are also provided for specific HTTP methods:
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestGet.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestGet</code></a>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestPut.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestPut</code></a>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestPost.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestPost</code></a>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestDelete.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestDelete</code></a>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestGet</ja>(path=<js>"/"</js>)
<jk>public</jk> String sayHello() {
<jk>return</jk> <js>"Hello world!"</js>;
}
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.InferredHttpMethodsAndPaths' id='juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.InferredHttpMethodsAndPaths'>8.3.1 - Inferred HTTP Methods and Paths</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.3.1 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.InferredHttpMethodsAndPaths -->
<div class='topic'>
<p>
When the <c>name</c> and/or <c>path</c> values are not specified, their values are inferred
from the Java method name.
</p>
<p>
The HTTP method can be inferred from the Java method by starting the method name with any of the following:
</p>
<ul>
<li><c>get</c>
<li><c>put</c>
<li><c>post</c>
<li><c>delete</c>
<li><c>options</c>
<li><c>head</c>
<li><c>trace</c>
<li><c>patch</c>
</ul>
<p>
If <c>path</c> is not defined, it's inferred from the Java method name (minus the prefix above).
</p>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Method="GET", path="/foo"</jc>
<ja>@RestOp</ja>
<jk>public</jk> String getFoo() {...}
</p>
<p class='bjava'>
<jc>// Method="DELETE", path="/foo"</jc>
<ja>@RestOp</ja>
<jk>public</jk> String deleteFoo() {...}
</p>
<p class='bjava'>
<jc>// Method="GET", path="/foo"</jc>
<jc>// "GET" is default</jc>
<ja>@RestOp</ja>
<jk>public</jk> String foo() {...}
</p>
<p class='bjava'>
<jc>// Method="GET", path="/"</jc>
<ja>@RestOp</ja>(path=<js>"/"</js>)
<jk>public</jk> String foo() {...}
</p>
<p class='bjava'>
<jc>// Method="GET", path="/"</jc>
<ja>@RestOp</ja>
<jk>public</jk> String get() {...}
</p>
<p class='bjava'>
<jc>// Method="POST", path="/"</jc>
<ja>@RestOp</ja>
<jk>public</jk> String post() {...}
</p>
<p>
If <c>name</c> and <c>path</c> are both specified, the Java method name can be anything.
</p>
</div>
</div><!-- END: 8.3.1 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.InferredHttpMethodsAndPaths -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodParameters' id='juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodParameters'>8.3.2 - Java Method Parameters</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.3.2 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodParameters -->
<div class='topic'>
<p>
Java methods can contain any of the following parameters in any order:
</p>
<ul class='spaced-list'>
<li>
<b>Parameters based on class types:</b>
<ul class='spaced-list'>
<li>Request objects:
<ul class='javatreec'>
<li class='jic'><code>AsyncContext</code>
<li class='jc'><a href="org/apache/juneau/rest/arg/CookieList.html" title="class in org.apache.juneau.rest.arg"><code>CookieList</code></a>
<li class='je'><code>DispatcherType</code>
<li class='jc'><a href="org/apache/juneau/httppart/HttpPartParserSession.html" title="interface in org.apache.juneau.httppart"><code>HttpPartParserSession</code></a>
<li class='jc'><a href="org/apache/juneau/httppart/HttpPartSerializerSession.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializerSession</code></a>
<li class='jic'><code>HttpServletRequest</code>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a>
<li class='jac'><a href="org/apache/juneau/parser/InputStreamParser.html" title="class in org.apache.juneau.parser"><code>InputStreamParser</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html?is-external=true" title="class or interface in java.util"><code>Locale</code></a>
<li class='jc'><a href="org/apache/juneau/cp/Messages.html" title="class in org.apache.juneau.cp"><code>Messages</code></a>
<li class='jac'><a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a>
<li class='jic'><a href="https://docs.oracle.com/javase/8/docs/api/java/security/Principal.html?is-external=true" title="class or interface in java.security"><code>Principal</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a>
<li class='jac'><a href="org/apache/juneau/parser/ReaderParser.html" title="class in org.apache.juneau.parser"><code>ReaderParser</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestAttributes.html" title="class in org.apache.juneau.rest.httppart"><code>RequestAttributes</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestContent.html" title="class in org.apache.juneau.rest.httppart"><code>RequestContent</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestFormParams.html" title="class in org.apache.juneau.rest.httppart"><code>RequestFormParams</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestHeaders.html" title="class in org.apache.juneau.rest.httppart"><code>RequestHeaders</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestPathParams.html" title="class in org.apache.juneau.rest.httppart"><code>RequestPathParams</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestQueryParams.html" title="class in org.apache.juneau.rest.httppart"><code>RequestQueryParams</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html?is-external=true" title="class or interface in java.util"><code>ResourceBundle</code></a>
<li class='jc'><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>
<li class='jic'><code>ServletInputStream</code>
<li class='jc'><a href="org/apache/juneau/dto/swagger/Swagger.html" title="class in org.apache.juneau.dto.swagger"><code>Swagger</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html?is-external=true" title="class or interface in java.util"><code>TimeZone</code></a>
<li class='jc'><a href="org/apache/juneau/UriContext.html" title="class in org.apache.juneau"><code>UriContext</code></a>
<li class='jc'><a href="org/apache/juneau/UriResolver.html" title="class in org.apache.juneau"><code>UriResolver</code></a>
<li class='jc'><a href="org/apache/juneau/svl/VarResolverSession.html" title="class in org.apache.juneau.svl"><code>VarResolverSession</code></a>
</ul>
</li>
<li>Response objects:
<ul class='javatreec'>
<li class='jic'><code>HttpServletResponse</code>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html?is-external=true" title="class or interface in java.io"><code>OutputStream</code></a>
<li class='jc'><a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a>
<li class='jic'><code>ServletOutputStream</code>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/io/Writer.html?is-external=true" title="class or interface in java.io"><code>Writer</code></a>
</ul>
</li>
<li>Session objects:
<ul class='javatreec'>
<li class='jic'><code>HttpSession</code>
<li class='jc'><a href="org/apache/juneau/rest/RestSession.html" title="class in org.apache.juneau.rest"><code>RestSession</code></a>
<li class='jc'><a href="org/apache/juneau/rest/util/UrlPath.html" title="class in org.apache.juneau.rest.util"><code>UrlPath</code></a>
<li class='jc'><a href="org/apache/juneau/rest/util/UrlPathMatch.html" title="class in org.apache.juneau.rest.util"><code>UrlPathMatch</code></a>
<li class='jc'><a href="org/apache/juneau/cp/BeanStore.html" title="class in org.apache.juneau.cp"><code>BeanStore</code></a>
<li class='jc'><a href="org/apache/juneau/rest/RestOpSession.html" title="class in org.apache.juneau.rest"><code>RestOpSession</code></a>
</ul>
</li>
<li>Parsed request header values:
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/header/Accept.html" title="class in org.apache.juneau.http.header"><code>Accept</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/AcceptCharset.html" title="class in org.apache.juneau.http.header"><code>AcceptCharset</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/AcceptEncoding.html" title="class in org.apache.juneau.http.header"><code>AcceptEncoding</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/AcceptLanguage.html" title="class in org.apache.juneau.http.header"><code>AcceptLanguage</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/AcceptRanges.html" title="class in org.apache.juneau.http.header"><code>AcceptRanges</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Authorization.html" title="class in org.apache.juneau.http.header"><code>Authorization</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/CacheControl.html" title="class in org.apache.juneau.http.header"><code>CacheControl</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ClientVersion.html" title="class in org.apache.juneau.http.header"><code>ClientVersion</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Connection.html" title="class in org.apache.juneau.http.header"><code>Connection</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentDisposition.html" title="class in org.apache.juneau.http.header"><code>ContentDisposition</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentEncoding.html" title="class in org.apache.juneau.http.header"><code>ContentEncoding</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentLength.html" title="class in org.apache.juneau.http.header"><code>ContentLength</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ContentType.html" title="class in org.apache.juneau.http.header"><code>ContentType</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Date.html" title="class in org.apache.juneau.http.header"><code>Date</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Debug.html" title="class in org.apache.juneau.http.header"><code>Debug</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Expect.html" title="class in org.apache.juneau.http.header"><code>Expect</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Forwarded.html" title="class in org.apache.juneau.http.header"><code>Forwarded</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/From.html" title="class in org.apache.juneau.http.header"><code>From</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Host.html" title="class in org.apache.juneau.http.header"><code>Host</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfMatch.html" title="class in org.apache.juneau.http.header"><code>IfMatch</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfModifiedSince.html" title="class in org.apache.juneau.http.header"><code>IfModifiedSince</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfNoneMatch.html" title="class in org.apache.juneau.http.header"><code>IfNoneMatch</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfRange.html" title="class in org.apache.juneau.http.header"><code>IfRange</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/IfUnmodifiedSince.html" title="class in org.apache.juneau.http.header"><code>IfUnmodifiedSince</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/MaxForwards.html" title="class in org.apache.juneau.http.header"><code>MaxForwards</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/NoTrace.html" title="class in org.apache.juneau.http.header"><code>NoTrace</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Origin.html" title="class in org.apache.juneau.http.header"><code>Origin</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Pragma.html" title="class in org.apache.juneau.http.header"><code>Pragma</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/ProxyAuthorization.html" title="class in org.apache.juneau.http.header"><code>ProxyAuthorization</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Range.html" title="class in org.apache.juneau.http.header"><code>Range</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Referer.html" title="class in org.apache.juneau.http.header"><code>Referer</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/TE.html" title="class in org.apache.juneau.http.header"><code>TE</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Thrown.html" title="class in org.apache.juneau.http.header"><code>Thrown</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Upgrade.html" title="class in org.apache.juneau.http.header"><code>Upgrade</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/UserAgent.html" title="class in org.apache.juneau.http.header"><code>UserAgent</code></a>
<li class='jc'><a href="org/apache/juneau/http/header/Warning.html" title="class in org.apache.juneau.http.header"><code>Warning</code></a>
</ul>
</li>
<li>Context values:
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a>
<li class='jc'><a href="org/apache/juneau/rest/logger/CallLogger.html" title="class in org.apache.juneau.rest.logger"><code>CallLogger</code></a>
<li class='jc'><a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>
<li class='jic'><a href="org/apache/juneau/rest/debug/DebugEnablement.html" title="interface in org.apache.juneau.rest.debug"><code>DebugEnablement</code></a>
<li class='jc'><a href="org/apache/juneau/encoders/EncoderSet.html" title="class in org.apache.juneau.encoders"><code>EncoderSet</code></a>
<li class='jic'><a href="org/apache/juneau/cp/FileFinder.html" title="interface in org.apache.juneau.cp"><code>FileFinder</code></a>
<li class='jc'><a href="org/apache/juneau/jsonschema/JsonSchemaGenerator.html" title="class in org.apache.juneau.jsonschema"><code>JsonSchemaGenerator</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Logger.html?is-external=true" title="class or interface in java.util"><code>Logger</code></a>
<li class='jc'><a href="org/apache/juneau/rest/stats/MethodExecStore.html" title="class in org.apache.juneau.rest.stats"><code>MethodExecStore</code></a>
<li class='jc'><a href="org/apache/juneau/parser/ParserSet.html" title="class in org.apache.juneau.parser"><code>ParserSet</code></a>
<li class='jc'><a href="org/apache/juneau/rest/RestChildren.html" title="class in org.apache.juneau.rest"><code>RestChildren</code></a>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>
<li class='jc'><a href="org/apache/juneau/rest/stats/RestContextStats.html" title="class in org.apache.juneau.rest.stats"><code>RestContextStats</code></a>
<li class='jc'><a href="org/apache/juneau/rest/RestOpContext.html" title="class in org.apache.juneau.rest"><code>RestOpContext</code></a>
<li class='jc'><a href="org/apache/juneau/rest/RestOperations.html" title="class in org.apache.juneau.rest"><code>RestOperations</code></a>
<li class='jc'><a href="org/apache/juneau/serializer/SerializerSet.html" title="class in org.apache.juneau.serializer"><code>SerializerSet</code></a>
<li class='jic'><a href="org/apache/juneau/rest/staticfile/StaticFiles.html" title="interface in org.apache.juneau.rest.staticfile"><code>StaticFiles</code></a>
<li class='jc'><a href="org/apache/juneau/rest/stats/ThrownStore.html" title="class in org.apache.juneau.rest.stats"><code>ThrownStore</code></a>
</ul>
</li>
</ul>
<li><b>Annotated parameters (either on the parameter or parameter type):</b>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Attr.html" title="annotation in org.apache.juneau.rest.annotation"><code>Attr</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/HasFormData.html" title="annotation in org.apache.juneau.http.annotation"><code>HasFormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/HasQuery.html" title="annotation in org.apache.juneau.http.annotation"><code>HasQuery</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/StatusCode.html" title="annotation in org.apache.juneau.http.annotation"><code>StatusCode</code></a>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Method.html" title="annotation in org.apache.juneau.rest.annotation"><code>Method</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>Request</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a>
</ul>
</li>
</ul>
<p>
In Spring Boot environments, any available Spring Beans can also be passed in as parameters.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/example1/{a1}/{a2}/{a3}/*"</js>)
<jk>public</jk> String doGetExample1(
RestRequest <jv>req</jv>,
RestResponse <jv>res</jv>,
<ja>@Method</ja> String <jv>method</jv>,
<ja>@Path</ja>(<js>"a1"</js>) String <jv>a1</jv>,
<ja>@Path</ja>(<js>"a2"</js>) <jk>int</jk> <jv>a2</jv>,
<ja>@Path</ja>(<js>"a3"</js>) UUID <jv>a3</jv>,
<ja>@Query</ja>(<js>"p1"</js>) <jk>int</jk> <jv>p1</jv>,
<ja>@Query</ja>(<js>"p2"</js>) String <jv>p2</jv>,
<ja>@Query</ja>(<js>"p3"</js>) UUID <jv>p3</jv>,
<ja>@HasQuery</ja>(<js>"p3"</js>) boolean <jv>hasP3</jv>,
<ja>@Path</ja>(<js>"/*"</js>) String <jv>remainder</jv>,
<ja>@Header</ja>(<js>"Accept-Language"</js>) String <jv>lang</jv>,
<ja>@Header</ja>(<js>"Accept"</js>) String <jv>accept</jv>,
<ja>@Header</ja>(<js>"DNT"</js>) <jk>int</jk> <jv>doNotTrack</jv>,
RequestAttributes <jv>attributes</jv>,
ResourceBundle <jv>nls</jv>
) {
<jc>// Do something with all of those</jc>
}
</p>
<p>
Additional parameter types can be defined by overriding <a href="org/apache/juneau/rest/RestContext.Builder.html#createRestOpArgs-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-"><code>RestContext.Builder.createRestOpArgs(BeanStore,Supplier)</code></a> or
by adding them to the bean store using <a href="org/apache/juneau/rest/RestContext.Builder.html#createBeanStore-java.lang.Class-java.util.function.Supplier-"><code>RestContext.Builder.createBeanStore(Class,Supplier)</code></a>.
</p>
</div>
</div><!-- END: 8.3.2 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodParameters -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodReturnTypes' id='juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodReturnTypes'>8.3.3 - Java Method Return Types</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.3.3 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodReturnTypes -->
<div class='topic'>
<p>
The return type of the Java method can be any serializable POJO as defined in <a class='doclink' href='#juneau-marshall.jm.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 <a href="org/apache/juneau/rest/RestResponse.html#setContent-java.lang.Object-"><code>RestResponse.setContent(Object)</code></a> method.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestGet</ja>
<jk>public</jk> String doGet() {
<jk>return</jk> <js>"Hello World!"</js>;
}
</p>
<p>
In addition to POJOs, the following return types are also supported:
</p>
<ul class='spaced-list'>
<li>
<b>Parameters based on class types:</b>
<ul class='spaced-list'>
<li>Direct streams:
<ul class='javatreec'>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a>
</ul>
</li>
<li>Apache HttpComponent beans:
<ul class='javatreec'>
<li class='jic'><code>HttpEntity</code>
<li class='jic'><a href="org/apache/juneau/http/resource/HttpResource.html" title="interface in org.apache.juneau.http.resource"><code>HttpResource</code></a>
<li class='jic'><code>HttpResponse</code>
</ul>
</li>
<li>Standard HTTP response beans:
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/response/Accepted.html" title="class in org.apache.juneau.http.response"><code>Accepted</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/AlreadyReported.html" title="class in org.apache.juneau.http.response"><code>AlreadyReported</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/BadRequest.html" title="class in org.apache.juneau.http.response"><code>BadRequest</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Conflict.html" title="class in org.apache.juneau.http.response"><code>Conflict</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Continue.html" title="class in org.apache.juneau.http.response"><code>Continue</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Created.html" title="class in org.apache.juneau.http.response"><code>Created</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/EarlyHints.html" title="class in org.apache.juneau.http.response"><code>EarlyHints</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/ExpectationFailed.html" title="class in org.apache.juneau.http.response"><code>ExpectationFailed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/FailedDependency.html" title="class in org.apache.juneau.http.response"><code>FailedDependency</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Forbidden.html" title="class in org.apache.juneau.http.response"><code>Forbidden</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Found.html" title="class in org.apache.juneau.http.response"><code>Found</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Gone.html" title="class in org.apache.juneau.http.response"><code>Gone</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/HttpVersionNotSupported.html" title="class in org.apache.juneau.http.response"><code>HttpVersionNotSupported</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/IMUsed.html" title="class in org.apache.juneau.http.response"><code>IMUsed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/InsufficientStorage.html" title="class in org.apache.juneau.http.response"><code>InsufficientStorage</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/InternalServerError.html" title="class in org.apache.juneau.http.response"><code>InternalServerError</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/LengthRequired.html" title="class in org.apache.juneau.http.response"><code>LengthRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Locked.html" title="class in org.apache.juneau.http.response"><code>Locked</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/LoopDetected.html" title="class in org.apache.juneau.http.response"><code>LoopDetected</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MethodNotAllowed.html" title="class in org.apache.juneau.http.response"><code>MethodNotAllowed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MisdirectedRequest.html" title="class in org.apache.juneau.http.response"><code>MisdirectedRequest</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MovedPermanently.html" title="class in org.apache.juneau.http.response"><code>MovedPermanently</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MultipleChoices.html" title="class in org.apache.juneau.http.response"><code>MultipleChoices</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MultiStatus.html" title="class in org.apache.juneau.http.response"><code>MultiStatus</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NetworkAuthenticationRequired.html" title="class in org.apache.juneau.http.response"><code>NetworkAuthenticationRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NoContent.html" title="class in org.apache.juneau.http.response"><code>NoContent</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NonAuthoritiveInformation.html" title="class in org.apache.juneau.http.response"><code>NonAuthoritiveInformation</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotAcceptable.html" title="class in org.apache.juneau.http.response"><code>NotAcceptable</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotExtended.html" title="class in org.apache.juneau.http.response"><code>NotExtended</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotFound.html" title="class in org.apache.juneau.http.response"><code>NotFound</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotImplemented.html" title="class in org.apache.juneau.http.response"><code>NotImplemented</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotModified.html" title="class in org.apache.juneau.http.response"><code>NotModified</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Ok.html" title="class in org.apache.juneau.http.response"><code>Ok</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PartialContent.html" title="class in org.apache.juneau.http.response"><code>PartialContent</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PayloadTooLarge.html" title="class in org.apache.juneau.http.response"><code>PayloadTooLarge</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PermanentRedirect.html" title="class in org.apache.juneau.http.response"><code>PermanentRedirect</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PreconditionFailed.html" title="class in org.apache.juneau.http.response"><code>PreconditionFailed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PreconditionRequired.html" title="class in org.apache.juneau.http.response"><code>PreconditionRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Processing.html" title="class in org.apache.juneau.http.response"><code>Processing</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/RangeNotSatisfiable.html" title="class in org.apache.juneau.http.response"><code>RangeNotSatisfiable</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/RequestHeaderFieldsTooLarge.html" title="class in org.apache.juneau.http.response"><code>RequestHeaderFieldsTooLarge</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/ResetContent.html" title="class in org.apache.juneau.http.response"><code>ResetContent</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/SeeOther.html" title="class in org.apache.juneau.http.response"><code>SeeOther</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/ServiceUnavailable.html" title="class in org.apache.juneau.http.response"><code>ServiceUnavailable</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/SwitchingProtocols.html" title="class in org.apache.juneau.http.response"><code>SwitchingProtocols</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/TemporaryRedirect.html" title="class in org.apache.juneau.http.response"><code>TemporaryRedirect</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/TooManyRequests.html" title="class in org.apache.juneau.http.response"><code>TooManyRequests</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Unauthorized.html" title="class in org.apache.juneau.http.response"><code>Unauthorized</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UnavailableForLegalReasons.html" title="class in org.apache.juneau.http.response"><code>UnavailableForLegalReasons</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UnprocessableEntity.html" title="class in org.apache.juneau.http.response"><code>UnprocessableEntity</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UnsupportedMediaType.html" title="class in org.apache.juneau.http.response"><code>UnsupportedMediaType</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UpgradeRequired.html" title="class in org.apache.juneau.http.response"><code>UpgradeRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UriTooLong.html" title="class in org.apache.juneau.http.response"><code>UriTooLong</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UseProxy.html" title="class in org.apache.juneau.http.response"><code>UseProxy</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/VariantAlsoNegotiates.html" title="class in org.apache.juneau.http.response"><code>VariantAlsoNegotiates</code></a>
</ul>
</li>
<li>Other:
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/rest/beans/ChildResourceDescriptions.html" title="class in org.apache.juneau.rest.beans"><code>ChildResourceDescriptions</code></a>
<li class='jc'><a href="org/apache/juneau/rest/beans/ResourceDescriptions.html" title="class in org.apache.juneau.rest.beans"><code>ResourceDescriptions</code></a>
<li class='jc'><a href="org/apache/juneau/rest/beans/SeeOtherRoot.html" title="class in org.apache.juneau.rest.beans"><code>SeeOtherRoot</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html?is-external=true" title="class or interface in java.lang"><code>Throwable</code></a>
</ul>
</li>
</ul>
<li><b>Annotated parameters (either on the parameter or parameter type):</b>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a>
</ul>
</li>
</ul>
<p>
REST Java methods can also generate a response via the following:
</p>
<ul class='spaced-list'>
<li>
By calling <a href="org/apache/juneau/rest/RestResponse.html#setContent-java.lang.Object-"><code>RestResponse.setContent(Object)</code></a> with any of the types above.
<li>
By accessing the <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Writer.html?is-external=true" title="class or interface in java.io"><code>Writer</code></a> directly by calling
<a href="org/apache/juneau/rest/RestResponse.html#getNegotiatedWriter--"><code>RestResponse.getNegotiatedWriter()</code></a> and writing the output yourself.
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Equivalent method 1</jc>
<ja>@RestGet</ja>(<js>"/example1/{personId}"</js>)
<jk>public</jk> Person doGet1(<ja>@Path</ja>(<js>"personId"</js>) UUID <jv>personId</jv>) {
Person <jv>person</jv> = <jsm>getPersonById</jsm>(<jv>personId</jv>);
<jk>return</jk> <jv>person</jv>;
}
<jc>// Equivalent method 2</jc>
<ja>@RestGet</ja>(<js>"/example2/{personId}"</js>)
<jk>public void</jk> doGet2(RestResponse <jv>res</jv>, <ja>@Path</ja>(<js>"personId"</js>) UUID <jv>personId</jv>) {
Person <jv>person</jv> = <jsm>getPersonById</jsm>(<jv>personId</jv>);
<jv>res</jv>.setContent(<jv>person</jv>);
}
</p>
<p>
Additional parameter types can be defined by overriding <a href="org/apache/juneau/rest/RestContext.Builder.html#createResponseProcessors-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-"><code>RestContext.Builder.createResponseProcessors(BeanStore,Supplier)</code></a>.
</p>
</div>
</div><!-- END: 8.3.3 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodReturnTypes -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodThrowableTypes' id='juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodThrowableTypes'>8.3.4 - Java Method Throwable Types</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.3.4 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodThrowableTypes -->
<div class='topic'>
<p>
Annotated Java methods can throw any of the following:
</p>
<ul class='spaced-list'>
<li>Standard HTTP response beans:
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/http/response/BadRequest.html" title="class in org.apache.juneau.http.response"><code>BadRequest</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Conflict.html" title="class in org.apache.juneau.http.response"><code>Conflict</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/ExpectationFailed.html" title="class in org.apache.juneau.http.response"><code>ExpectationFailed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/FailedDependency.html" title="class in org.apache.juneau.http.response"><code>FailedDependency</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Forbidden.html" title="class in org.apache.juneau.http.response"><code>Forbidden</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Gone.html" title="class in org.apache.juneau.http.response"><code>Gone</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/HttpVersionNotSupported.html" title="class in org.apache.juneau.http.response"><code>HttpVersionNotSupported</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/InsufficientStorage.html" title="class in org.apache.juneau.http.response"><code>InsufficientStorage</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/InternalServerError.html" title="class in org.apache.juneau.http.response"><code>InternalServerError</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/LengthRequired.html" title="class in org.apache.juneau.http.response"><code>LengthRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Locked.html" title="class in org.apache.juneau.http.response"><code>Locked</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/LoopDetected.html" title="class in org.apache.juneau.http.response"><code>LoopDetected</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MethodNotAllowed.html" title="class in org.apache.juneau.http.response"><code>MethodNotAllowed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/MisdirectedRequest.html" title="class in org.apache.juneau.http.response"><code>MisdirectedRequest</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NetworkAuthenticationRequired.html" title="class in org.apache.juneau.http.response"><code>NetworkAuthenticationRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotAcceptable.html" title="class in org.apache.juneau.http.response"><code>NotAcceptable</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotExtended.html" title="class in org.apache.juneau.http.response"><code>NotExtended</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotFound.html" title="class in org.apache.juneau.http.response"><code>NotFound</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/NotImplemented.html" title="class in org.apache.juneau.http.response"><code>NotImplemented</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PayloadTooLarge.html" title="class in org.apache.juneau.http.response"><code>PayloadTooLarge</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PreconditionFailed.html" title="class in org.apache.juneau.http.response"><code>PreconditionFailed</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/PreconditionRequired.html" title="class in org.apache.juneau.http.response"><code>PreconditionRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/RangeNotSatisfiable.html" title="class in org.apache.juneau.http.response"><code>RangeNotSatisfiable</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/RequestHeaderFieldsTooLarge.html" title="class in org.apache.juneau.http.response"><code>RequestHeaderFieldsTooLarge</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/ServiceUnavailable.html" title="class in org.apache.juneau.http.response"><code>ServiceUnavailable</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/TooManyRequests.html" title="class in org.apache.juneau.http.response"><code>TooManyRequests</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/Unauthorized.html" title="class in org.apache.juneau.http.response"><code>Unauthorized</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UnavailableForLegalReasons.html" title="class in org.apache.juneau.http.response"><code>UnavailableForLegalReasons</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UnprocessableEntity.html" title="class in org.apache.juneau.http.response"><code>UnprocessableEntity</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UnsupportedMediaType.html" title="class in org.apache.juneau.http.response"><code>UnsupportedMediaType</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UpgradeRequired.html" title="class in org.apache.juneau.http.response"><code>UpgradeRequired</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/UriTooLong.html" title="class in org.apache.juneau.http.response"><code>UriTooLong</code></a>
<li class='jc'><a href="org/apache/juneau/http/response/VariantAlsoNegotiates.html" title="class in org.apache.juneau.http.response"><code>VariantAlsoNegotiates</code></a>
</ul>
</li>
<li>Annotated throwables:
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a>
</ul>
</li>
</ul>
<p>
All other throwables get processed as follows:
</p>
<ul class='spaced-list'>
<li>Processed as 400/Bad Request:
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/parser/ParseException.html" title="class in org.apache.juneau.parser"><code>ParseException</code></a>
<li class='jc'><a href="org/apache/juneau/InvalidDataConversionException.html" title="class in org.apache.juneau"><code>InvalidDataConversionException</code></a>
</ul>
</li>
<li>Processed as 401/Unauthorized:
<ul>
<li>Any class named <js>"*AccessDenied*"</js> or <js>"*Unauthorized*"</js>
</ul>
</li>
<li>Processed as 404/Not Found:
<ul>
<li>Any class named <js>"*Empty*"</js> or <js>"*NotFound*"</js>
</ul>
</li>
<li>Anything else processed as 500/Internal Server Error.
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/user/login"</js>)
<jk>public</jk> Ok login(
<ja>@FormData</ja>(<js>"username"</js>) String <jv>username</jv>,
<ja>@FormData</ja>(<js>"password"</js>) String <jv>password</jv>
) <jk>throws</jk> Unauthorized
{
<jk>if</jk> (! <jsm>isOK</jsm>(<jv>username</jv>, <jv>password</jv>))
<jk>throw new</jk> Unauthorized(<js>"You're not welcome!"</js>);
<jk>return</jk> Ok.<jsf>OK</jsf>;
}
</p>
</div>
</div><!-- END: 8.3.4 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodThrowableTypes -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.PathPatterns' id='juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.PathPatterns'>8.3.5 - Path Patterns</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.3.5 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.PathPatterns -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/annotation/RestOp.html#path--"><code>@RestOp(path)</code></a> 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='bjava'>
<jc>// Default method</jc>
<ja>@RestGet</ja>(path=<js>"/*"</js>)
<jk>public void</jk> doGetDefault() {
...
}
<jc>// Method with path pattern</jc>
<ja>@RestGet</ja>(path=<js>"/xxx"</js>)
<jk>public void</jk> doGetNoArgs(...) {
...
}
<jc>// Method with path pattern with arguments</jc>
<ja>@RestGet</ja>(path=<js>"/xxx/{foo}/{bar}/{baz}/{bing}"</js>)
<jk>public void</jk> doGetWithArgs(
<ja>@Path</ja>(<js>"foo"</js>) String <jv>foo</jv>,
<ja>@Path</ja>(<js>"bar"</js>) <jk>int</jk> <jv>bar</jv>,
<ja>@Path</ja>(<js>"baz"</js>) MyEnum <jv>baz</jv>,
<ja>@Path</ja>(<js>"bing"</js>) UUID <jv>qux</jv>
) {
...
}
</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='bjava'>
<jc>// Try first </jc>
<ja>@RestGet</ja>(<js>"/foo/bar"</js>)
<jk>public void</jk> method1() {
...
}
<jc>// Try second</jc>
<ja>@RestGet</ja>(<js>"/foo/{bar}"</js>)
<jk>public void</jk> method2(...) {
...
}
<jc>// Try third</jc>
<ja>@RestGet</ja>(<js>"/foo/*"</js>)
<jk>public void</jk> method3(...) {
...
}
<jc>// Try last</jc>
<ja>@RestGet</ja>(<js>"/*"</js>)
<jk>public void</jk> method4(...) {
...
}
</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
<a href="org/apache/juneau/rest/httppart/RequestPathParams.html#getRemainder--"><code>RequestPathParams.getRemainder()</code></a> or parameters with the
<c><ja>@Path</ja>(<js>"/*"</js>)</c> 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='bjava'>
<ja>@RestGet</ja>(<js>"/*"</js>)
<jk>public void</jk> doGet(<ja>@Path</ja>(<js>"/*"</js>) String <jv>remainder</jv>) {
<jc>// URL path pattern can have remainder accessible through req.getRemainder().</jc>
}
<ja>@RestPut</ja>(<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>
</div>
</div><!-- END: 8.3.5 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.PathPatterns -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.Matchers' id='juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.Matchers'>8.3.6 - Matchers</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.3.6 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.Matchers -->
<div class='topic'>
<p>
<code>RestMatchers</code> 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>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// GET method that gets invoked for administrators</jc>
<ja>@RestGet</ja>(path=<js>"/*"</js>, matchers=IsAdminMatcher.<jk>class</jk>)
<jk>public</jk> Object doGetForAdmin() {
...
}
<jc>// GET method that gets invoked for everyone else</jc>
<ja>@RestGet</ja>(<js>"/*"</js>)
<jk>public</jk> Object doGetForEveryoneElse() {
...
}
</p>
<p>
The interface for matchers is simple:
</p>
<p class='bjava'>
<jk>public class</jk> IsAdminMatcher <jk>extends</jk> RestMatcher {
<ja>@Override</ja> <jc>/* RestMatcher */</jc>
<jk>public boolean</jk> matches(RestRequest <jv>req</jv>) {
<jk>return</jk> <jv>req</jv>.isUserInRole(<js>"ADMINS_GROUP"</js>);
}
}
</p>
<ul class='notes'>
<li class='note'>
If no methods are found with a matching matcher, a <l>412 Precondition Failed</l> status is returned.
<li class='note'>
If multiple matchers are specified on the same method, ONLY ONE matcher needs to match for the
method to be invoked.
<li class='note'>
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 class='note'>
Methods with matchers take precedence over methods without.
<br>Otherwise, methods are attempted in the order they appear in the class.
</ul>
<ul class='seealso'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html#matchers--"><code>RestOp(matchers)</code></a>
<li class='jc'><a href="org/apache/juneau/rest/matcher/MultipartFormDataMatcher.html" title="class in org.apache.juneau.rest.matcher"><code>MultipartFormDataMatcher</code></a>
<li class='jc'><a href="org/apache/juneau/rest/matcher/UrlEncodedFormMatcher.html" title="class in org.apache.juneau.rest.matcher"><code>UrlEncodedFormMatcher</code></a>
</ul>
</div>
</div><!-- END: 8.3.6 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.Matchers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.OverloadingHttpMethods' id='juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.OverloadingHttpMethods'>8.3.7 - Overloading HTTP Methods</a></h4>
<div class='topic'><!-- START: 8.3.7 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.OverloadingHttpMethods -->
<div class='topic'>
<p>
Through the use of the built-in <l>"method"</l> GET parameter, you can implement requests beyond the basic
REST http method types.
</p>
<p>
For example, the URL <l>"/sample/foo?method=BAR"</l> will cause the following method to be invoked...
</p>
<p class='bjava'>
<ja>@RestOp</ja>(method=<js>"BAR"</js>)
<jk>public void</jk> doBar(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) {
<jc>// Handle BAR requests</jc>
}
</p>
<p>
To support overloaded methods, the <a href="org/apache/juneau/rest/annotation/Rest.html#allowedMethodParams--"><code>@Rest(allowedMethodParams)</code></a>
setting must be enabled on your servlet.
</p>
<p class='bjava'>
<ja>@Rest</ja>(
<jc>// Allow &amp;method parameter on BAR requests</jc>
allowedMethodParams=<js>"BAR"</js>
)
</p>
</div>
</div><!-- END: 8.3.7 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.OverloadingHttpMethods -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.AdditionalInformation' id='juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.AdditionalInformation'>8.3.8 - Additional Information</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.3.8 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.AdditionalInformation -->
<div class='topic'>
<p>
Refer to the following Javadocs for more information:
</p>
<ul class='javatreec w900'>
<li class='jc'><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>
<li class='jc'><a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestContent.html" title="class in org.apache.juneau.rest.httppart"><code>RequestContent</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestHeaders.html" title="class in org.apache.juneau.rest.httppart"><code>RequestHeaders</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestQueryParams.html" title="class in org.apache.juneau.rest.httppart"><code>RequestQueryParams</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestFormParams.html" title="class in org.apache.juneau.rest.httppart"><code>RequestFormParams</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestPathParams.html" title="class in org.apache.juneau.rest.httppart"><code>RequestPathParams</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestAttributes.html" title="class in org.apache.juneau.rest.httppart"><code>RequestAttributes</code></a>
</ul>
</div>
</div><!-- END: 8.3.8 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.AdditionalInformation -->
</div><!-- END: 8.3 - juneau-rest-server.jrs.RestOpAnnotatedMethods -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpParts' id='juneau-rest-server.jrs.HttpParts'>8.4 - HTTP Parts</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.4 - juneau-rest-server.jrs.HttpParts -->
<div class='topic'>
<p>
In previous examples we showed the ability to pass in annotated parameters on <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>-annotated methods
to parse standard HTTP parts:
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/example1/{a1}/*"</js>)
<jk>public</jk> String doGetExample1(
<ja>@Path</ja>(<js>"a1"</js>) String <jv>a1</jv>,
<ja>@Query</ja>(<js>"p1"</js>) <jk>int</jk> <jv>p1</jv>,
<ja>@HasQuery</ja>(<js>"p2"</js>) <jk>boolean</jk> <jv>hasP3</jv>,
<ja>@Path</ja>(<js>"/*"</js>) String <jv>remainder</jv>,
<ja>@Header</ja>(<js>"Accept-Language"</js>) String <jv>lang</jv>
) {
<jc>// Do something with all of those</jc>
}
</p>
<p>
Annotations are provided for both request and response HTTP parts.
</p>
<p>
The annotations used for defining the schema for request HTTP parts are:
</p>
<ul class='spaced-list'>
<li>HTTP request parts:
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>Request</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/HasFormData.html" title="annotation in org.apache.juneau.http.annotation"><code>HasFormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/HasQuery.html" title="annotation in org.apache.juneau.http.annotation"><code>HasQuery</code></a>
</ul>
</li>
<li>HTTP response parts:
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/StatusCode.html" title="annotation in org.apache.juneau.http.annotation"><code>StatusCode</code></a>
</ul>
</li>
</ul>
<p>
These annotation can be used on method parameters or on the parameter types themselves, or a combination
of both.
</p>
<ul class='notes'>
<li class='note'>When defined on types, annotations are aggregated from parent to child with child values
taking precedence. When defined on both, annotations are aggregated with values on parameters
taking precedence.
</ul>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpParts.jrs.PartMarshallers' id='juneau-rest-server.jrs.HttpParts.jrs.PartMarshallers'>8.4.1 - Part Marshallers</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.4.1 - juneau-rest-server.jrs.HttpParts.jrs.PartMarshallers -->
<div class='topic'>
<p>
Juneau comes with three basic marshaller types for serializing and parsing Header, Query, Form, and Path parts:
</p>
<ul class='javatree'>
<li class='jic'><a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/httppart/SimplePartSerializer.html" title="class in org.apache.juneau.httppart"><code>SimplePartSerializer</code></a> - Serializes directly to strings.
<li class='jc'><a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a> - Serializes to UON notation.
<ul>
<li class='jc'><a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> - Serializes using Open-API schema rules.
</ul>
</li>
</ul>
</li>
<li class='jic'><a href="org/apache/juneau/httppart/HttpPartParser.html" title="interface in org.apache.juneau.httppart"><code>HttpPartParser</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/httppart/SimplePartParser.html" title="class in org.apache.juneau.httppart"><code>SimplePartParser</code></a> - Parses directly from strings.
<li class='jc'><a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a> - Parses from UON notation.
<ul>
<li class='jc'><a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a> - Parses using Open-API schema rules.
</ul>
</li>
</ul>
</li>
</ul>
<p>
By default, the REST API uses the OpenAPI serializer and parser which allows for schema-based
marshalling. You also have the option to use UON marshalling which is schema-less but allows
for JSON-equivalent data structures (object/array/primitives/...) using URL-encoding notation.
This can be done by overriding the part marshallers through the following APIs:
</p>
<ul class='spaced-list'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#partSerializer--"><code>partSerializer</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#partParser--"><code>partParser</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createPartSerializer-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-"><code>createPartSerializer(BeanStore,Supplier)</code></a>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createPartParser-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-"><code>createPartParser(BeanStore,Supplier)</code></a>
</ul>
</li>
</ul>
<p>
The OpenAPI marshallers themselves also have the ability to support UON notation for individual
parts via the schema itself:
</p>
<p class='bjava'>
<ja>@Query</ja>(..., schema=<ja>@Schema</ja>(format=<js>"uon"</js>)) Map&lt;Integer,MyBean&gt; <jv>myMap</jv>
</p>
</div>
</div><!-- END: 8.4.1 - juneau-rest-server.jrs.HttpParts.jrs.PartMarshallers -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpParts.jrs.HttpPartAnnotations' id='juneau-rest-server.jrs.HttpParts.jrs.HttpPartAnnotations'>8.4.2 - HTTP Part Annotations</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.4.2 - juneau-rest-server.jrs.HttpParts.jrs.HttpPartAnnotations -->
<div class='topic'>
<p>
The following annotations allow for defining part schemas based on the OpenAPI standard.
</p>
<ul class='spaced-list'>
<li><b>Request annotations:</b>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>Request</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/Request.html#on--"><code>on</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Request.html#onClass--"><code>onClass</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Request.html#parser--"><code>parser</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/Header.html#name--"><code>name</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Header.html#parser--"><code>parser</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Header.html#schema--"><code>schema</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Header.html#value--"><code>value</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/Query.html#name--"><code>name</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Query.html#parser--"><code>parser</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Query.html#schema--"><code>schema</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Query.html#value--"><code>value</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/FormData.html#name--"><code>name</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/FormData.html#parser--"><code>parser</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/FormData.html#schema--"><code>schema</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/FormData.html#value--"><code>value</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/Path.html#name--"><code>name</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Path.html#parser--"><code>parser</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Path.html#schema--"><code>schema</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Path.html#value--"><code>value</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/Content.html#schema--"><code>schema</code></a>
</ul>
</li>
</ul>
</li>
<li><b>Response annotations:</b>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/Response.html#examples--"><code>examples</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Response.html#headers--"><code>headers</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Response.html#on--"><code>on</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Response.html#onClass--"><code>onClass</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Response.html#schema--"><code>schema</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Response.html#serializer--"><code>serializer</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/Header.html#name--"><code>name</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Header.html#schema--"><code>schema</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Header.html#serializer--"><code>serializer</code></a>
<li class='jma'><a href="org/apache/juneau/http/annotation/Header.html#value--"><code>value</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/Content.html#schema--"><code>schema</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/http/annotation/StatusCode.html" title="annotation in org.apache.juneau.http.annotation"><code>StatusCode</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/StatusCode.html#value--"><code>value</code></a>
</ul>
</li>
</ul>
</li>
<li><b>Common schema annotation:</b>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/annotation/Schema.html" title="annotation in org.apache.juneau.annotation"><code>Schema</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#Z:Z_default--"><code>_default</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#Z:Z_enum--"><code>_enum</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#Z:Z:Dref--"><code>$ref</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#additionalProperties--"><code>additionalProperties</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#aev--"><code>aev</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#allOf--"><code>allOf</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#allowEmptyValue--"><code>allowEmptyValue</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#cf--"><code>cf</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#collectionFormat--"><code>collectionFormat</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#d--"><code>d</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#description--"><code>description</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#df--"><code>df</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#discriminator--"><code>discriminator</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#e--"><code>e</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#emax--"><code>emax</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#emin--"><code>emin</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#exclusiveMaximum--"><code>exclusiveMaximum</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#exclusiveMinimum--"><code>exclusiveMinimum</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#externalDocs--"><code>externalDocs</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#f--"><code>f</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#format--"><code>format</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#ignore--"><code>ignore</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#items--"><code>items</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#max--"><code>max</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#maxi--"><code>maxi</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#maximum--"><code>maximum</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#maxItems--"><code>maxItems</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#maxl--"><code>maxl</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#maxLength--"><code>maxLength</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#maxp--"><code>maxp</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#maxProperties--"><code>maxProperties</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#min--"><code>min</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#mini--"><code>mini</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#minimum--"><code>minimum</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#minItems--"><code>minItems</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#minl--"><code>minl</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#minLength--"><code>minLength</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#minp--"><code>minp</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#minProperties--"><code>minProperties</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#mo--"><code>mo</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#multipleOf--"><code>multipleOf</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#on--"><code>on</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#onClass--"><code>onClass</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#p--"><code>p</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#pattern--"><code>pattern</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#properties--"><code>properties</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#r--"><code>r</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#readOnly--"><code>readOnly</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#required--"><code>required</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#ro--"><code>ro</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#sie--"><code>sie</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#skipIfEmpty--"><code>v</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#t--"><code>t</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#title--"><code>title</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#type--"><code>type</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#ui--"><code>ui</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#uniqueItems--"><code>uniqueItems</code></a>
<li class='jma'><a href="org/apache/juneau/annotation/Schema.html#xml--"><code>xml</code></a>
</ul>
</li>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>@Header</code></a>/<a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>@Query</code></a>/
<a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>@FormData</code></a>/<a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>@Path</code></a> annotations
can be used on parameters of <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestOp</code></a>-annotated methods to
get access to request headers, query parameters, form-data parameters, and path parts.
</p>
<p>
The most typical scenario is to simply use the <c>value</c> field to define parameter names:
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestGet</ja>
<jk>public void</jk> doGet(
<ja>@Query</ja>(<js>"p1"</js>) <jk>int</jk> <jv>p1</jv>,
<ja>@Query</ja>(<js>"p2"</js>) String <jv>p2</jv>,
<ja>@Query</ja>(<js>"p3"</js>) UUID <jv>p3</jv>) {...}
</p>
<p>
This is functionally equivalent to the following code:
</p>
<p class='bjava'>
<ja>@RestGet</ja>
<jk>public void</jk> doGet(RestRequest <jv>req</jv>) {
RequestQueryParams <jv>query</jv> = <jv>req</jv>.getQueryParams();
<jk>int</jk> <jv>p1</jv> = <jv>query</jv>.get(<js>"p1"</js>).asInteger().orElse(0);
String <jv>p2</jv> = <jv>query</jv>.get(<js>"p2"</js>).orElse(<jk>null</jk>);
UUID <jv>p3</jv> = <jv>query</jv>.get(<js>"p3"</js>).as(UUID.<jk>class</jk>).orElse(<jk>null</jk>);
}
</p>
<p>
The special name <js>"*"</js> (or blank) can be used to represent all values.
When used, the data type must be a <c>Map</c> or bean.
</p>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Multiple values passed as a map.</jc>
<ja>@RestGet</ja>
<jk>public void</jk> doGet(<ja>@Query</ja>(<js>"*"</js>) Map&lt;String,Object&gt; <jv>map</jv>) {...}
</p>
<p class='bjava'>
<jc>// Same but name "*" is inferred.</jc>
<ja>@RestGet</ja>
<jk>public void</jk> doGet(<ja>@Query</ja> Map&lt;String,Object&gt; <jv>map</jv>) {...}
</p>
<p class='bjava'>
<jc>// Multiple values passed as a bean.</jc>
<ja>@RestGet</ja>
<jk>public void</jk> doGet(<ja>@Query</ja> MyQueryBean <jv>bean</jv>) {...}
</p>
<p>
The <a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>@Content</code></a> annotation is used to identify POJOs to be used as the body of an HTTP request.
</p>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Defined on parameter</jc>
<ja>@RestPost</ja>
<jk>public void</jk> addPet(<ja>@Content</ja> Pet <jv>pet</jv>) {...}
</p>
<p class='bjava'>
<jc>// Defined on POJO class</jc>
<ja>@RestPost</ja>
<jk>public void</jk> addPet(Pet <jv>pet</jv>) {...}
<ja>@Content</ja>
<jk>public class</jk> Pet {...}
</p>
<p>
This is functionally equivalent to the following code:
</p>
<p class='bjava'>
<ja>@RestPost</ja>
<jk>public void</jk> addPet(RestRequest <jv>req</jv>) {
Pet <jv>pet</jv> = <jv>req</jv>.getContent().as(Pet.<jk>class</jk>);
...
}
</p>
<p>
In addition to <a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>@Content</code></a>-annotated parameters/types, the body of an HTTP request
can be retrieved by passing in parameters of the following types (matched in the specified order):
</p>
<ol class='spaced-list'>
<li>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a>
<br><ja>@Content</ja> annotation is optional.
<br><c>Content-Type</c> is ignored.
<li>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a>
<br><ja>@Content</ja> annotation is optional.
<br><c>Content-Type</c> is ignored.
<li>
Any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Parsable POJO</a> type.
<br><c>Content-Type</c> is required to identify correct parser.
<li>
Objects convertible from <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a> by having one of the following non-deprecated methods:
<ul>
<li><c><jk>public</jk> T(Reader in) {...}</c>
<li><c><jk>public static</jk> T <jsm>create</jsm>(Reader in) {...}</c>
<li><c><jk>public static</jk> T <jsm>fromReader</jsm>(Reader in) {...}</c>
</ul>
<c>Content-Type</c> must not be present or match an existing parser so that it's not parsed as a POJO.
<li>
Objects convertible from <a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a> by having one of the following non-deprecated methods:
<ul>
<li><c><jk>public</jk> T(InputStream in) {...}</c>
<li><c><jk>public static</jk> T <jsm>create</jsm>(InputStream in) {...}</c>
<li><c><jk>public static</jk> T <jsm>fromInputStream</jsm>(InputStream in) {...}</c>
</ul>
<c>Content-Type</c> must not be present or match an existing parser so that it's not parsed as a POJO.
<li>
Objects convertible from <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> by having one of the following non-deprecated methods:
<ul>
<li><c><jk>public</jk> T(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>create</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>fromString</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>parse</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>parseString</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>forName</jsm>(String in) {...}</c>
<li><c><jk>public static</jk> T <jsm>forString</jsm>(String in) {...}</c>
</ul>
Note that this also includes all enums.
<li>
Any <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html?is-external=true" title="class or interface in java.util"><code>Optional</code></a> of anything on this list.
</ol>
<p>
When used in combination with the mutable <a href="org/apache/juneau/Value.html" title="class in org.apache.juneau"><code>Value</code></a> object, the <a href="org/apache/juneau/http/annotation/StatusCode.html" title="annotation in org.apache.juneau.http.annotation"><code>@StatusCode</code></a> and <a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>@Header</code></a> annotations
can be used on parameters <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestOp</code></a>-annotated methods to
to define to response codes and headers.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/user/login"</js>)
<jk>public void</jk> login(
<ja>@FormData</ja>(<js>"username"</js>) String <jv>username</jv>,
<ja>@FormData</ja>(<js>"password"</js>) String <jv>password</jv>,
<ja>@StatusCode</ja> Value&lt;Integer&gt; <jv>status</jv>,
<ja>@Header</ja>(<js>"My-Response-Header"</js>) Value&lt;String&gt; <jv>myResponseHeader</jv>
) {
<jk>if</jk> (<jsm>isValid</jsm>(<jv>username</jv>, <jv>password</jv>)) {
<jv>status</jv>.set(200);
<jv>myResponseHeader</jv>.set(<js>"Welcome "</js> + <jv>username</jv> + <js>"!"</js>);
} <jk>else</jk> {
<jv>status</jv>.set(401);
}
}
</p>
<p>
This is functionally equivalent to the following code:
</p>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/user/login"</js>)
<jk>public void</jk> doGet(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) {
RequestFormParams <jv>form</jv> = <jv>req</jv>.getFormParams();
String <jv>username</jv> = <jv>form</jv>.get(<js>"username"</js>).orElse(<jk>null</jk>);
String <jv>password</jv> = <jv>form</jv>.get(<js>"password"</js>).orElse(<jk>null</jk>);
<jk>if</jk> (<jsm>isValid</jsm>(<jv>username</jv>, <jv>password</jv>) {
<jv>res</jv>.setStatus(200);
<jv>res</jv>.setHeader(<js>"My-Response-Header"</js>, <js>"Welcome "</js> + <jv>username</jv> + <js>"!"</js>);
} else {
<jv>res</jv>.setStatus(401);
}
}
</p>
<p>
The default registered part marshallers, <a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> and <a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a>, are used to
marshall POJOs using schemas defined via the <a href="org/apache/juneau/annotation/Schema.html" title="annotation in org.apache.juneau.annotation"><code>@Schema</code></a> annotation.
</p>
<p>
For example, the following shows how a pipe-delimited list of comma-delimited numbers (e.g. <js>"1,2,3|4,5,6|7,8,9"</js>) can be converted to a 2-dimensional array of <c>Longs</c>:
</p>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/testQuery1"</js>)
<jk>public void</jk> testQuery1(
<ja>@Query</ja>(<js>"queryParamName"</js>)
<ja>@Schema</ja>(
collectionFormat=<js>"pipes"</js>,
items=<ja>@Items</ja>(
collectionFormat=<js>"csv"</js>,
type=<js>"integer"</js>,
format=<js>"int64"</js>,
minimum=<js>"0"</js>,
maximum=<js>"100"</js>
minLength=1,
maxLength=10
),
minLength=1,
maxLength=10
)
Long[][] <jv>queryParameter</jv>
) {...}
<jc>// Same but using condensed notation.</jc>
<ja>@RestGet</ja>(<js>"/testQuery2"</js>)
<jk>public void</jk> testQuery2(
<ja>@Query</ja>(<js>"queryParamName"</js>)
<ja>@Schema</ja>(
cf=<js>"pipes"</js>, minl=1, maxl=10,
i=<ja>@Items</ja>(cf=<js>"csv"</js>, t=<js>"integer"</js>, f=<js>"int64"</js>, min=<js>"0"</js>, max=<js>"100"</js>, minl=1, maxl=10)
)
Long[][] <jv>queryParameter</jv>
) {...}
</p>
<p>
Schema-based marshalling works for both request and response parts.
Input will be converted based on the types and formats defined in the schema definition.
Input validations such as <c>minLength/maxLength</c> that don't match the input will result in automatic <c>400 Bad Request</c> responses.
</p>
<p>
The part and schema annotations are also used for supplying swagger information about the HTTP part.
This information is used to populate the auto-generated Swagger documentation and UI.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Query</ja>(<js>"name"</js>)
<ja>@Schema</ja>(
description=<js>"Pet name"</js>,
required=<jk>true</jk>
)
</p>
<p>
<a class='doclink' href='#juneau-rest-server.jrs.SvlVariables'>SVL Variables</a> (e.g. "$L{my.localized.variable}") are supported on annotation fields as well.
Among other things, this allow for annotation values to be defined externally and the ability to produce localized swagger documents
based on the <c>Accept-Language</c> on a request.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Schema</ja>(
description=<js>"$L{PetNameDescription}"</js>
)
</p>
<p>
The <a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>@Content</code></a> annotation can also be used to parse HTTP request bodies using OpenAPI schemas
when the body content type matches the <a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a> parser via the header <c>Content-Type: text/openapi</c>.
</p>
<p>
The following shows the same for a request body:
</p>
<p class='bjava'>
<ja>@RestPost</ja>(<js>"/testContent"</js>)
<jk>public void</jk> testContent(
<ja>@Content</ja>
<ja>@Schema</ja>(
items=<ja>@Items</ja>(
collectionFormat=<js>"pipes"</js>,
items=<ja>@SubItems</ja>(
collectionFormat=<js>"csv"</js>,
type=<js>"integer"</js>,
format=<js>"int64"</js>,
minimum=<js>"0"</js>,
maximum=<js>"100"</js>
minLength=1,
maxLength=10
)
),
minLength=1,
maxLength=10
)
Long[][] <jv>content</jv>
) {...}
</p>
<p>
The list of valid POJO types for parameters depends on type and format of the value or items/entries of the value.
For example, instead of <c>Longs</c> in the example above, we could also define a 2-dimensional array of POJOs convertible from <c>Longs</c>:
</p>
<p class='bjava'>
<jc>// Content is a 2-dimensional array of POJOs convertible from Longs:</jc>
<ja>@RestPost</ja>(<js>"/example1"</js>)
<jk>public void</jk> testContent(<ja>@Content</ja>(...) MyPojo1[][] <jv>content</jv>) {...}
<jk>public class</jk> MyPojo1 {
<jk>public</jk> MyPojo1(Long <jv>input</jv>) {...}
}
</p>
<p class='bjava'>
<jc>// Content is a POJO that takes in a Long array:</jc>
<ja>@RestPost</ja>(<js>"/example2"</js>)
<jk>public void</jk> testContent(<ja>@Content</ja>(...) MyPojo2[] <jv>content</jv>) {...}
<jk>public class</jk> MyPojo2 {
<jk>public</jk> MyPojo2(Long[] <jv>input</jv>) {...}
}
</p>
<p class='bjava'>
<jc>// Content is a POJO that takes in the whole 2-dimensional array:</jc>
<ja>@RestPost</ja>(<js>"/example3"</js>)
<jk>public void</jk>testContent<ja>@Content</ja>(...) MyPojo3 <jv>content</jv>) {...}
<jk>public class</jk> MyPojo3 {
<jk>public</jk> MyPojo3(Long[][] <jv>input</jv>) {...}
}
</p>
<p>
As you can see, the complexity of possible input types expands significantly.
For more information about valid parameter types, see <a class='doclink' href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiParsers'>OpenAPI Parsers</a>
</p>
</div>
</div><!-- END: 8.4.2 - juneau-rest-server.jrs.HttpParts.jrs.HttpPartAnnotations -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpParts.jrs.DefaultParts' id='juneau-rest-server.jrs.HttpParts.jrs.DefaultParts'>8.4.3 - Default Parts</a><span class='update'>created: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.4.3 - juneau-rest-server.jrs.HttpParts.jrs.DefaultParts -->
<div class='topic'>
<p>
By default, HTTP parts that don't have value (such as missing query parameters) end up with null
values:
</p>
<p class='bjava'>
<ja>@RestPost</ja>(<js>"/example"</js>)
<jk>public</jk> String doGetExample1(
<ja>@Query</ja>(<js>"p1"</js>) <jk>int</jk> <jv>p1</jv>,
<ja>@FormData</ja>(<js>"f1"</js>) MyBean <jv>f1</jv>,
<ja>@Header</ja>(<js>"Accept-Language"</js>) AcceptLanguage <jv>h1</jv>
) {
<jk>if</jk> (<jv>p1</jv> == <jk>null</jk>) <jv>p1</jv> = -1;
<jk>if</jk> (<jv>f1</jv> == <jk>null</jk>) <jv>f1</jv> = <jsf>DEFAULT_BEAN</jsf>;
<jk>if</jk> (<jv>h1</jv> == <jk>null</jk>) <jv>h1</jv> = AcceptLanguage.<jsm>of</jsm>(<js>"en"</js>);
}
</p>
<p>
You have several options to provide default values for HTTP parts. The most common is to simply
use <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html?is-external=true" title="class or interface in java.util"><code>Optional</code></a> parameters and handle default values programmatically:
</p>
<p class='bjava'>
<ja>@RestPost</ja>(<js>"/example"</js>)
<jk>public</jk> String doGetExample1(
<ja>@Query</ja>(<js>"p1"</js>) Optional&lt;Integer&gt; <jv>p1</jv>,
<ja>@FormData</ja>(<js>"f1"</js>) Optional&lt;MyBean&gt; <jv>f1</jv>,
<ja>@Header</ja>(<js>"Accept-Language"</js>) Optional&lt;AcceptLanguage&gt; <jv>h1</jv>
) {
<jk>int</jk> <jv>_p1</jv> = <jv>p1</jv>.orElse(-1);
Bean <jv>_f1</jv> = <jv>f1</jv>.orElse(<jsf>DEFAULT_BEAN</jsf>);
AcceptLanguage <jv>_h1</jv> = <jv>h1</jv>.orElse(AcceptLanguage.<jsm>of</jsm>(<js>"en"</js>));
}
</p>
<p>
You can also specify default values on the annotations:
</p>
<p class='bjava'>
<ja>@RestPost</ja>(<js>"/example"</js>)
<jk>public</jk> String doGetExample1(
<ja>@Query</ja>(name=<js>"p1"</js>, def=<js>"-1"</js>) <jk>int</jk> <jv>p1</jv>,
<ja>@FormData</ja>(name=<js>"f1"</js>, def=<js>"foo=bar,baz=qux"</js>) MyBean <jv>f1</jv>,
<ja>@Header</ja>(name=<js>"Accept-Language"</js>, def=<js>"en"</js>) AcceptLanguage <jv>lang</jv>
) {
...
}
</p>
<p>
A third option is to specify default values via the <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a> and
<a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a> annotations.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultAccept--"><code>defaultAccept</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultCharset--"><code>defaultCharset</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultContentType--"><code>defaultContentType</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultRequestAttributes--"><code>defaultRequestAttributes</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultRequestHeaders--"><code>defaultRequestHeaders</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#defaultResponseHeaders--"><code>defaultResponseHeaders</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultAccept--"><code>defaultAccept</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultCharset--"><code>defaultCharset</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultContentType--"><code>defaultContentType</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultRequestAttributes--"><code>defaultRequestAttributes</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultRequestFormData--"><code>defaultRequestFormData</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultRequestHeaders--"><code>defaultRequestHeaders</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultRequestQueryData--"><code>defaultRequestQueryData</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#defaultResponseHeaders--"><code>defaultResponseHeaders</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Servlet with default headers</jc>
<ja>@Rest</ja>(
<jc>// Assume "text/json" Accept value when Accept not specified</jc>
defaultRequestHeaders={<js>"Accept: text/json"</js>},
<jc>// Add a version header attribute to all responses</jc>
defaultResponseHeaders={<js>"X-Version: 1.0"</js>}
)
<jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
...
}
</p>
<p>
Default parts can also be specified programmatically through any of the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createDefaultRequestAttributes-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-"><code>createDefaultRequestAttributes(BeanStore,Supplier)</code></a>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createDefaultRequestHeaders-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-"><code>createDefaultRequestHeaders(BeanStore,Supplier)</code></a>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createDefaultResponseHeaders-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-"><code>createDefaultResponseHeaders(BeanStore,Supplier)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultAccept-java.lang.String-"><code>defaultAccept(String)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultCharset-java.nio.charset.Charset-"><code>defaultCharset(Charset)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultContentType-java.lang.String-"><code>defaultContentType(String)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestAttributes--"><code>defaultRequestAttributes()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestAttributes-java.util.function.Consumer-"><code>defaultRequestAttributes(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestAttributes-org.apache.juneau.rest.httppart.NamedAttribute...-"><code>defaultRequestAttributes(NamedAttribute...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestHeaders--"><code>defaultRequestHeaders()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestHeaders-java.util.function.Consumer-"><code>defaultRequestHeaders(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestHeaders-org.apache.http.Header...-"><code>defaultRequestHeaders(Header...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultResponseHeaders--"><code>defaultResponseHeaders()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultResponseHeaders-java.util.function.Consumer-"><code>defaultResponseHeaders(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultResponseHeaders-org.apache.http.Header...-"><code>defaultResponseHeaders(Header...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestAttributes--"><code>defaultRequestAttributes()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestAttributes-java.util.function.Consumer-"><code>defaultRequestAttributes(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestAttributes-org.apache.juneau.rest.httppart.NamedAttribute...-"><code>defaultRequestAttributes(NamedAttribute...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestHeaders--"><code>defaultRequestHeaders()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestHeaders-java.util.function.Consumer-"><code>defaultRequestHeaders(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestHeaders-org.apache.http.Header...-"><code>defaultRequestHeaders(Header...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultResponseHeaders--"><code>defaultResponseHeaders()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultResponseHeaders-java.util.function.Consumer-"><code>defaultResponseHeaders(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultResponseHeaders-org.apache.http.Header...-"><code>defaultResponseHeaders(Header...)</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/rest/RestOpContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestOpContext.Builder</code></a>
<ul class='javatreec'>
<li class='jmp'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#createDefaultRequestAttributes-org.apache.juneau.cp.BeanStore-org.apache.juneau.rest.RestContext.Builder-java.util.function.Supplier-"><code>createDefaultRequestAttributes(BeanStore,Builder,Supplier)</code></a>
<li class='jmp'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#createDefaultRequestFormData-org.apache.juneau.cp.BeanStore-org.apache.juneau.rest.RestContext.Builder-java.util.function.Supplier-"><code>createDefaultRequestFormData(BeanStore,Builder,Supplier)</code></a>
<li class='jmp'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#createDefaultRequestHeaders-org.apache.juneau.cp.BeanStore-org.apache.juneau.rest.RestContext.Builder-java.util.function.Supplier-"><code>createDefaultRequestHeaders(BeanStore,Builder,Supplier)</code></a>
<li class='jmp'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#createDefaultRequestQueryData-org.apache.juneau.cp.BeanStore-org.apache.juneau.rest.RestContext.Builder-java.util.function.Supplier-"><code>createDefaultRequestQueryData(BeanStore,Builder,Supplier)</code></a>
<li class='jmp'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#createDefaultResponseHeaders-org.apache.juneau.cp.BeanStore-org.apache.juneau.rest.RestContext.Builder-java.util.function.Supplier-"><code>createDefaultResponseHeaders(BeanStore,Builder,Supplier)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestAttributes--"><code>defaultRequestAttributes()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestAttributes-java.util.function.Consumer-"><code>defaultRequestAttributes(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestFormData--"><code>defaultRequestFormData()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestFormData-java.util.function.Consumer-"><code>defaultRequestFormData(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestHeaders--"><code>defaultRequestHeaders()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestHeaders-java.util.function.Consumer-"><code>defaultRequestHeaders(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestQueryData--"><code>defaultRequestQueryData()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestQueryData-java.util.function.Consumer-"><code>defaultRequestQueryData(Consumer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultResponseHeaders--"><code>defaultResponseHeaders()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultResponseHeaders-java.util.function.Consumer-"><code>defaultResponseHeaders(Consumer)</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 8.4.3 - juneau-rest-server.jrs.HttpParts.jrs.DefaultParts -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpParts.jrs.RequestBeans' id='juneau-rest-server.jrs.HttpParts.jrs.RequestBeans'>8.4.4 - @Request Beans</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.4.4 - juneau-rest-server.jrs.HttpParts.jrs.RequestBeans -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>@Request</code></a> annotation can used to define proxy interfaces against
HTTP requests in combination with the following annotations used on methods:
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/Schema.html" title="annotation in org.apache.juneau.annotation"><code>Schema</code></a>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestPut</ja>(<js>"/pets/{petId}"</js>)
<jk>public void</jk> addPet(UpdatePetBean <jv>updatePet</jv>) {...}
<ja>@Request</ja>
<jk>public interface</jk> UpdatePetBean {
<ja>@Path</ja> <jc>// {petId} inferred.</jc>
<jk>int</jk> getPetId();
<ja>@Query</ja>(<js>"verbose"</js>)
<jk>boolean</jk> isDebug();
<ja>@Header</ja>(<js>"*"</js>)
Map&lt;String,Object&gt; getAllHeaders();
<ja>@Content</ja>
Pet getPet();
}
</p>
<p>
The example above is identical in behavior to specifying individual annotated parameters on the <ja>@RestOp</ja>-annotated method:
</p>
<p class='bjava'>
<ja>@RestPut</ja>(<js>"/pets/{petId}"</js>)
<jk>public void</jk> addPet(
<ja>@Path</ja>(<js>"petId"</js>) <jk>int</jk> <jv>petId</jv>,
<ja>@Query</ja>(<js>"verbose"</js>) <jk>boolean</jk> <jv>debug</jv>,
<ja>@Header</ja>(<js>"*"</js>) Map&lt;String,Object&gt; <jv>allHeaders</jv>,
<ja>@Content</ja> UpdatePetBean <jv>pet</jv>
)
{...}
</p>
<p>
The return types of the getters must be the supported parameter types for the HTTP-part annotation used.
Schema-based serialization and parsing is used just as if used as individual parameter types.
Annotations used are the exact same used on REST parameters and have all the
same feature support including automatic Swagger validation and documentation.
Part names can either be explicitly specified or automatically inferred from the getter names.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Request</ja>
<jk>public interface</jk> MyRequest {
<jc>// Schema-based query parameter "pipedCdlInts":
// Pipe-delimited list of comma-delimited lists of integers.</jc>
<ja>@Query</ja>
<ja>@Schema</ja>(
collectionFormat=<js>"pipes"</js>
items=<ja>@Items</ja>(
items=<ja>@SubItems</ja>(
collectionFormat=<js>"csv"</js>
type=<js>"integer"</js>,
minimum=1,
maximum=100
),
maximumLength=10
)
)
<jk>int</jk>[][] <jv>getPipedCdlInts</jv>();
}
</p>
<p>
For clarity, the <ja>@Request</ja> annotation can be defined on the parameter, class, or both.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestPut</ja>(<js>"/pets/{petId}"</js>)
<jk>public void</jk> addPet(<ja>@Request</ja> UpdatePetBean <jv>updatePet</jv>) {...}
<ja>@Request</ja>
<jk>public interface</jk> UpdatePetBean {...}
</p>
</div>
</div><!-- END: 8.4.4 - juneau-rest-server.jrs.HttpParts.jrs.RequestBeans -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpParts.jrs.ResponseBeans' id='juneau-rest-server.jrs.HttpParts.jrs.ResponseBeans'>8.4.5 - @Response Beans</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.4.5 - juneau-rest-server.jrs.HttpParts.jrs.ResponseBeans -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a> annotation can be used to define beans that return HTTP response
parts via annotations and methods. They are used in combination with the following annotations:
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/StatusCode.html" title="annotation in org.apache.juneau.http.annotation"><code>StatusCode</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/Schema.html" title="annotation in org.apache.juneau.annotation"><code>Schema</code></a>
</ul>
<p>
Response beans can either be returned or thrown from <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestOp</code></a>-annotated methods.
</p>
<ul class='notes'>
<li class='note'>
As a general convention, response beans with return codes <c>&lt;400</c> should be defined as regular classes and
<c>&gt;=400</c> should be defined as exceptions.
</ul>
<p>
The following example shows the <ja>@Response</ja> annotation used to define an exception for an invalid login attempt:
</p>
<p class='bjava'>
<jc>// Our annotated normal response.</jc>
<ja>@Response</ja>
<ja>@StatusCode</ja>(200)
<ja>@Schema</ja>(
description=<js>"User was good."</js> <jc>// Description show in Swagger</jc>
)
<jk>public class</jk> ValidLogin {
<jk>public</jk> ValidLogin() {
...
}
<jc>// Response bean converted to output based on Accept header.</jc>
<ja>@Content</ja>
<jk>public</jk> WelcomeMessageBean getContent() {
<jk>return new</jk> WelcomeMessageBean();
}
}
</p>
<p class='bjava'>
<jc>// Our annotated exception.</jc>
<ja>@Response</ja>
<ja>@StatusCode</ja>(401)
<ja>@Schema</ja>(
description=<js>"Invalid username or password provided"</js> <jc>// Description show in Swagger</jc>
)
<jk>public class</jk> InvalidLogin <jk>extends</jk> Exception {
<jk>public</jk> InvalidLogin() {
<jk>super</jk>(<js>"Invalid username or password."</js>); <jc>// Message sent in response</jc>
}
<ja>@Header</ja>(<js>"My-Message"</js>)
<jk>public</jk> String getMyMessage() {
<jk>return</jk> <js>"Nope!"</js>;
}
}
</p>
<p class='bjava'>
<jc>// Our REST method that throws an annotated exception.</jc>
<ja>@RestGet</ja>(<js>"/user/login"</js>)
<jk>public</jk> ValidLogin login(
<ja>@FormData</ja>(<js>"username"</js>) String <jv>username</jv>,
<ja>@FormData</ja>(<js>"password"</js>) String <jv>password</jv>
) <jk>throws</jk> InvalidLogin
{
<jk>if</jk> (<jsm>isValid</jsm>(<jv>username</jv>, <jv>password</jv>)) {
<jk>return new</jk> ValidLogin();
}
<jk>throw new</jk> InvalidLogin();
}
</p>
<p>
Custom exceptions can also extend from one of the predefined HTTP exceptions such as the <a href="org/apache/juneau/http/response/Unauthorized.html" title="class in org.apache.juneau.http.response"><code>Unauthorized</code></a> exception:
</p>
<p class='bjava'>
<jc>// Our annotated exception.</jc>
<ja>@Response</ja>
<ja>@Schema</ja>(
description=<js>"Invalid username or password provided"</js> <jc>// Overridden from parent class</jc>
)
<jk>public class</jk> InvalidLogin <jk>extends</jk> Unauthorized {
<jk>public</jk> InvalidLogin() {
<jk>super</jk>(<js>"Invalid username or password."</js>);
}
}
<jc>// Parent predefined exception class.</jc>
<ja>@Response</ja>
<ja>@StatusCode</ja>(401)
<ja>@Schema</ja>(
description=<js>"Unauthorized"</js>
)
<jk>public class</jk> Unauthorized <jk>extends</jk> RestException {...}
</p>
</div>
</div><!-- END: 8.4.5 - juneau-rest-server.jrs.HttpParts.jrs.ResponseBeans -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpParts.jrs.HttpPartApis' id='juneau-rest-server.jrs.HttpParts.jrs.HttpPartApis'>8.4.6 - HTTP Part APIs</a><span class='update'>created: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.4.6 - juneau-rest-server.jrs.HttpParts.jrs.HttpPartApis -->
<div class='topic'>
<p>
Request HTTP parts can also be retrieved programmatically through the following classes that
can be passed in as parameters or access through <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> bean:
</p>
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestHeaders.html" title="class in org.apache.juneau.rest.httppart"><code>RequestHeaders</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestQueryParams.html" title="class in org.apache.juneau.rest.httppart"><code>RequestQueryParams</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestFormParams.html" title="class in org.apache.juneau.rest.httppart"><code>RequestFormParams</code></a>
<li class='jc'><a href="org/apache/juneau/rest/httppart/RequestPathParams.html" title="class in org.apache.juneau.rest.httppart"><code>RequestPathParams</code></a>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestPost</ja>(...)
<jk>public</jk> Object myMethod(RequestHeaders <jv>headers</jv>) {
<jc>// Add a default value.</jc>
<jv>headers</jv>.addDefault(<js>"ETag"</js>, <jsf>DEFAULT_UUID</jsf>);
<jc>// Get a header value as a POJO.</jc>
UUID <jv>etag</jv> = <jv>headers</jv>.get(<js>"ETag"</js>).as(UUID.<jk>class</jk>).get();
<jc>// Get a header as a standard HTTP part.</jc>
ContentType <jv>contentType</jv> = <jv>headers</jv>.get(ContentType.<jk>class</jk>).orElse(ContentType.<jsf>TEXT_XML</jsf>);
}
</p>
<p>
Built in to these APIs are various convenience methods such as converting parts to
different types or inline fluent assertions:
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Inline fluent assertion and retrieval.</jc>
String <jv>foo</jv> = <jv>request</jv>
.getHeader(<js>"Foo"</js>)
.assertString().contains(<js>"bar"</js>)
.get();
</p>
</div>
</div><!-- END: 8.4.6 - juneau-rest-server.jrs.HttpParts.jrs.HttpPartApis -->
</div><!-- END: 8.4 - juneau-rest-server.jrs.HttpParts -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Marshalling' id='juneau-rest-server.jrs.Marshalling'>8.5 - Marshalling</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.5 - juneau-rest-server.jrs.Marshalling -->
<div class='topic'>
<p>
Juneau uses <a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parsers</code></a> and <a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializers</code></a> for marshalling
HTTP request and response bodies to POJOs using the <c>Content-Type</c> header to match the best
parser and the <c>Accept</c> header to match the best serializer.
</p>
<p>
Serializers and parsers can be associated with REST servlets using the following annotations:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#serializers--"><code>serializers</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#serializers--"><code>parsers</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#serializers--"><code>serializers</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#serializers--"><code>parsers</code></a>
</ul>
</li>
</ul>
<p>
Request bodies are parsed and passed in via <a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>@Content</code></a>-annotated parameters,
and response bodies are returned or thrown by <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestOp</code></a>-annotated methods
and serialized.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Rest</ja>(
serializers={JsonParser.<jk>class</jk>, HtmlSerializer.<jk>class</jk>},
parsers={JsonParser.<jk>class</jk>, HtmlParser.<jk>class</jk>}
)
<jk>public class</jk> MyResource {
<jc>// Override at the method level.</jc>
<ja>@RestPost</ja>(parsers={XmlParser.<jk>class</jk>})
<jk>public</jk> MyPojo myMethod(<ja>@Content</ja> MyPojo <jv>myPojo</jv>) {
<jc>// Do something with your parsed POJO.</jc>
<jc>// Then return it and serialize the POJO.</jc>
}
}
</p>
<p>
The following classes provide common default serializers and parsers that can be
used as-is or augmented by child classes:
<p>
<ul class='javatree'>
<li>Classes:
<ul class='javatreec'>
<li class='jc'><a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a>
<li class='jc'><a href="org/apache/juneau/rest/servlet/BasicRestServletGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServletGroup</code></a>
<li class='jc'><a href="org/apache/juneau/rest/servlet/BasicRestObject.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObject</code></a>
<li class='jc'><a href="org/apache/juneau/rest/servlet/BasicRestObjectGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObjectGroup</code></a>
</ul>
</li>
<li>Interfaces:
<ul class='javatreec'>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicJsonConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicJsonConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicJsonHtmlConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicJsonHtmlConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicSimpleJsonConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicSimpleJsonConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicOpenApiConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicOpenApiConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicUniversalConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicUniversalConfig</code></a>
<li class='jic'><a href="org/apache/juneau/rest/config/BasicUniversalJenaConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicUniversalJenaConfig</code></a>
</ul>
</li>
</ul>
<p>
Serializers and parsers can also be defined programmatically using an INIT hook method like shown below:
</p>
<p class='bjava'>
<ja>@Rest</ja>
<jk>public class</jk> MyResource {
<ja>@RestHook</ja>(<jsf>INIT</jsf>)
<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) {
<jv>builder</jv>.serializers().add(JsonSerializer.<jk>class</jk>, HtmlSerializer.<jk>class</jk>);
<jv>builder</jv>.parsers().add(JsonParser.<jk>class</jk>, HtmlParser.<jk>class</jk>);
}
}
</p>
<p>
They can also be defined through <a class='doclink' href='#juneau-rest-server.jrs.RestContext'>custom REST context and builders</a>.
</p>
<p>
Config annotations allow you to define serializer and parser properties using specialized annotations
at either the class or operation levels:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
...
)
<ja>@BeanConfig</ja>(sortProperties=<js>"true"</js>)
<ja>@SerializerConfig</ja>(trimNulls=<js>"true"</js>)
<ja>@JsonConfig</ja>(escapeSolidus=<js>"true"</js>)
<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<ja>@RestPost</ja>
<ja>@BeanConfig</ja>(sortProperties=<js>"false"</js>)
<ja>@SerializerConfig</ja>(trimNulls=<js>"false"</js>)
<jk>public</jk> MyPojo myMethod(<ja>@Content</ja> MyPojo <jv>myPojo</jv>) {
...
}
}
</p>
<p>
Swaps are associated serializers and parsers registered on a REST resource via the <a href="org/apache/juneau/annotation/BeanConfig.html" title="annotation in org.apache.juneau.annotation"><code>BeanConfig</code></a> annotation
on either the class or method level:
</p>
<p class='bjava'>
<jc>// Servlet with transforms applied</jc>
<ja>@Rest</ja>(
...
)
<ja>@BeanConfig</ja>(
swaps={
<jc>// Calendars should be serialized/parsed as ISO8601 date-time strings</jc>
TemporalCalendarSwap.IsoInstant.<jk>class</jk>,
<jc>// Byte arrays should be serialized/parsed as BASE64-encoded strings</jc>
ByteArraySwap.Base64.<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> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
Config annotations are defined for all serializers and parsers:
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/annotation/BeanConfig.html" title="annotation in org.apache.juneau.annotation"><code>BeanConfig</code></a>
<li class='ja'><a href="org/apache/juneau/csv/annotation/CsvConfig.html" title="annotation in org.apache.juneau.csv.annotation"><code>CsvConfig</code></a>
<li class='ja'><a href="org/apache/juneau/html/annotation/HtmlConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlConfig</code></a>
<li class='ja'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlDocConfig</code></a>
<li class='ja'><a href="org/apache/juneau/json/annotation/JsonConfig.html" title="annotation in org.apache.juneau.json.annotation"><code>JsonConfig</code></a>
<li class='ja'><a href="org/apache/juneau/jsonschema/annotation/JsonSchemaConfig.html" title="annotation in org.apache.juneau.jsonschema.annotation"><code>JsonSchemaConfig</code></a>
<li class='ja'><a href="org/apache/juneau/msgpack/annotation/MsgPackConfig.html" title="annotation in org.apache.juneau.msgpack.annotation"><code>MsgPackConfig</code></a>
<li class='ja'><a href="org/apache/juneau/oapi/annotation/OpenApiConfig.html" title="annotation in org.apache.juneau.oapi.annotation"><code>OpenApiConfig</code></a>
<li class='ja'><a href="org/apache/juneau/parser/annotation/ParserConfig.html" title="annotation in org.apache.juneau.parser.annotation"><code>ParserConfig</code></a>
<li class='ja'><a href="org/apache/juneau/plaintext/annotation/PlainTextConfig.html" title="annotation in org.apache.juneau.plaintext.annotation"><code>PlainTextConfig</code></a>
<li class='ja'><a href="org/apache/juneau/jena/annotation/RdfConfig.html" title="annotation in org.apache.juneau.jena.annotation"><code>RdfConfig</code></a>
<li class='ja'><a href="org/apache/juneau/serializer/annotation/SerializerConfig.html" title="annotation in org.apache.juneau.serializer.annotation"><code>SerializerConfig</code></a>
<li class='ja'><a href="org/apache/juneau/soap/annotation/SoapXmlConfig.html" title="annotation in org.apache.juneau.soap.annotation"><code>SoapXmlConfig</code></a>
<li class='ja'><a href="org/apache/juneau/uon/annotation/UonConfig.html" title="annotation in org.apache.juneau.uon.annotation"><code>UonConfig</code></a>
<li class='ja'><a href="org/apache/juneau/urlencoding/annotation/UrlEncodingConfig.html" title="annotation in org.apache.juneau.urlencoding.annotation"><code>UrlEncodingConfig</code></a>
<li class='ja'><a href="org/apache/juneau/xml/annotation/XmlConfig.html" title="annotation in org.apache.juneau.xml.annotation"><code>XmlConfig</code></a>
</ul>
<ul class='seealso'>
<li class='jc'><a href="org/apache/juneau/examples/rest/PhotosResource.html" title="class in org.apache.juneau.examples.rest"><code>PhotosResource</code></a> - An example of a REST resource that uses a custom serializer and parser.
</ul>
</div>
</div><!-- END: 8.5 - juneau-rest-server.jrs.Marshalling -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HandlingFormPosts' id='juneau-rest-server.jrs.HandlingFormPosts'>8.6 - Form Posts</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.6 - juneau-rest-server.jrs.HandlingFormPosts -->
<div class='topic'>
<p>
HTTP form posts can be handled two ways:
</p>
<ol class='spaced-list'>
<li>By parsing the entire HTTP body into a POJO using the registered <a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a>
<li>By access the form post entries as HTTP parts.
</ol>
<p>
The following example shows the first approach of handling an <c>application/x-www-form-urlencoded</c>
request of the form <l>"aString=foo&amp;aNumber=123&amp;aDate=2001-07-04T15:30:45Z"</l> and
loading it into a simple bean.
</p>
<p class='bjava'>
<jc>// A simple bean.</jc>
<jk>public static class</jk> FormInputBean {
<jk>public</jk> String <jf>aString</jf>;
<jk>public int</jk> <jf>aNumber</jf>;
<ja>@Swap</ja>(TemporalCalendarSwap.IsoLocalDateTime.<jk>class</jk>)
<jk>public</jk> Calendar <jf>aDate</jf>;
}
</p>
<p class='bjava'>
<ja>@Rest</ja>(...)
<jk>public class</jk> MyRestResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<jc>// Our form input endpoint.</jc>
<ja>@RestPost</ja>(<js>"/"</js>)
<jk>public</jk> Object doPost(<ja>@Content</ja> FormInputBean <jv>input</jv>) {
<jc>// Just mirror back the request</jc>
<jk>return</jk> <jv>input</jv>;
}
}
</p>
<p>
The next example shows handling it as individual parts:
</p>
<p class='bjava'>
<jc>// Our form input endpoint.</jc>
<ja>@RestPost</ja>(<js>"/"</js>)
<jk>public</jk> Object doPost(
<ja>@FormData</ja>(<js>"aString"</js>) String <jv>aString</jv>,
<ja>@FormData</ja>(<js>"aNumber"</js>) <jk>int</jk> <jv>aNumber</jv>,
<ja>@FormData</ja>(<js>"aDate"</js>) Calendar <jv>aDate</jv>) {
...
}
</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 while the latter approach only supports URL-Encoding.
</p>
<div class='warn'>
If you're using form input beans, DO NOT use the <l>@FormData</l> attribute or
<code>ServletRequest.getParameter(String)</code> 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>@Content</l> or <a href="org/apache/juneau/rest/RestRequest.html#getContent--"><code>RestRequest.getContent()</code></a>
</div>
<div class='warn'>
If you want to be able to consume url-encoded form post bodies as POJOs in Spring Boot, you'll need to
add the following Spring Bean to your configuration to prevent Spring Boot from automatically
consuming the body itself:
<p class='bjava' style='max-width:700px'>
<ja>@SpringBootApplication</ja>
<ja>@Controller</ja>
<jk>public class</jk> SpringBootAppConfig {
<ja>@Bean</ja>
<jk>public</jk> FilterRegistrationBean&lt;HiddenHttpMethodFilter> registration(HiddenHttpMethodFilter <jv>filter</jv>) {
FilterRegistrationBean&lt;HiddenHttpMethodFilter> <jv>reg</jv> = <jk>new</jk> FilterRegistrationBean&gt;>(<jv>filter</jv>);
<jv>reg</jv>.setEnabled(<jk>false</jk>);
<jk>return</jk> <jv>reg</jv>;
}
}
</p>
</div>
<h5 class='topic'>Multi-part Form Posts</h5>
<p>
The Juneau framework does not natively support multipart form posts.
However, it can be done in conjunction with the Apache Commons File Upload library or through the Servlet 3.0 API directly.
</p>
<p>
The following is an example that uses the File Upload library to allow files to be uploaded as multipart form posts.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/tempDir"</js>
)
<jk>public class</jk> TempDirResource <jk>extends</jk> DirectoryResource {
<ja>@RestPost</ja>(path=<js>"/upload"</js>, matchers=TempDirResource.MultipartFormDataMatcher.<jk>class</jk>)
<jk>public</jk> Redirect uploadFile(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
ServletFileUpload <jv>upload</jv> = <jk>new</jk> ServletFileUpload();
FileItemIterator <jv>iter</jv> = <jv>upload</jv>.getItemIterator(<jv>req</jv>);
<jk>while</jk> (<jv>iter</jv>.hasNext()) {
FileItemStream <jv>item</jv> = <jv>iter</jv>.next();
<jk>if</jk> (<jv>item</jv>.getFieldName().equals(<js>"contents"</js>)) {
File <jv>file</jv> = <jk>new</jk> File(getRootDir(), <jv>item</jv>.getName());
IOPipe.<jsm>create</jsm>(<jv>item</jv>.openStream(), <jk>new</jk> FileOutputStream(<jv>file</jv>)).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 <jv>req</jv>) {
String <jv>contentType</jv> = <jv>req</jv>.getContentType();
<jk>return</jk> <jv>contentType</jv> != <jk>null</jk> &amp;&amp; <jv>contentType</jv>.startsWith(<js>"multipart/form-data"</js>);
}
}
</p>
<p>
The following shows using the <l>HttpServletRequest.getParts()</l> method to retrieve multi-part form posts when using Jetty.
This example is pulled from the PetStore application.
</p>
<p class='bjava'>
<ja>@RestPost</ja>
<jk>public</jk> SeeOtherRoot uploadFile(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
<jc>// Required for Jetty.</jc>
MultipartConfigElement <jv>mce</jv> = <jk>new</jk> MultipartConfigElement((String)<jk>null</jk>);
<jv>req</jv>.setAttribute(<js>"org.eclipse.jetty.multipartConfig"</js>, <jv>mce</jv>);
String <jv>id</jv> = UUID.<jsm>randomUUID</jsm>().toString();
BufferedImage <jv>img</jv> = <jk>null</jk>;
<jk>for</jk> (Part <jv>part</jv> : <jv>req</jv>.getParts()) {
<jk>switch</jk> (<jv>part</jv>.getName()) {
<jk>case</jk> <js>"id"</js>:
<jv>id</jv> = IOUtils.<jsm>read</jsm>(<jv>part</jv>.getInputStream());
<jk>break</jk>;
<jk>case</jk> <js>"file"</js>:
<jv>img</jv> = ImageIO.<jsm>read</jsm>(<jv>part</jv>.getInputStream());
}
}
<jsm>addPhoto</jsm>(<jv>id</jv>, <jv>img</jv>);
<jk>return new</jk> SeeOtherRoot(); <jc>// Redirect to the servlet root.</jc>
}
</p>
</div>
</div><!-- END: 8.6 - juneau-rest-server.jrs.HandlingFormPosts -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Guards' id='juneau-rest-server.jrs.Guards'>8.7 - Guards</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.7 - juneau-rest-server.jrs.Guards -->
<div class='topic'>
<p>
Guards control access to REST classes and methods.
When guards are associated at the class-level, it's equivalent to associating guards on all Java methods on
the servlet.
If multiple guards are present, ALL guards must pass. (Note that this is different in behavior to <a class='doclink' href='#juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.Matchers'>Matchers</a>
which require only one matcher to pass.)
</p>
<p>
Guards are associated with resource classes and methods via the following:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#guards--"><code>guards</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#guards--"><code>guards</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Define a guard that only lets Billy make a request</jc>
<jk>public</jk> BillyGuard <jk>extends</jk> RestGuard {
<ja>@Override</ja> <jc>/* RestGuard */</jc>
<jk>public boolean</jk> isRequestAllowed(RestRequest <jv>req</jv>) {
<jk>return</jk> <jv>req</jv>.getUserPrincipal().getName().equals(<js>"Billy"</js>);
}
}
<jc>// Servlet with class-level guard applied</jc>
<ja>@Rest</ja>(guards=BillyGuard.<jk>class</jk>)
<jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<jc>// Delete method that only Billy is allowed to call.</jc>
<ja>@RestDelete</ja>
<jk>public</jk> doDelete(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {...}
}
</p>
<p>
A common use for guards is to only allow admin access to certain Java methods...
</p>
<p class='bjava'>
<jc>// DELETE method</jc>
<ja>@RestDelete</ja>(guards={AdminGuard.<jk>class</jk>})
<jk>public void</jk> doDelete(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {...}
</p>
<p class='bjava'>
<jk>public class</jk> AdminGuard <jk>extends</jk> RestGuard {
<ja>@Override</ja> <jc>/* RestGuard */</jc>
<jk>public boolean</jk> isRequestAllowed(RestRequest <jv>req</jv>) {
<jk>return</jk> <jv>req</jv>.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
<a href="org/apache/juneau/rest/guard/RestGuard.html#guard-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>RestGuard.guard(RestRequest,RestResponse)</code></a> and processing the response
yourself.
</p>
<p class='bjava'>
<jk>public class</jk> AdminGuard <jk>extends</jk> RestGuard {
<ja>@Override</ja> <jc>/* RestGuard */</jc>
<jk>public boolean</jk> guard(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> BasicHttpException {
<jk>if</jk> (! <jsm>isOkay</jsm>(<jv>req</jv>))
<jk>throw new</jk> Forbidden(<js>"Access denied!!!"</js>);
<jk>return true</jk>;
}
}
</p>
<p>
A simplified format is available for matching based on the user role on the request using the following:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#roleGuard--"><code>roleGuard</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#roleGuard--"><code>roleGuard</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/foo"</js>,
roleGuard=<js>"ROLE_ADMIN || (ROLE_READ_WRITE &amp;&amp; ROLE_SPECIAL)"</js>
)
<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
...
}
</p>
</div>
</div><!-- END: 8.7 - juneau-rest-server.jrs.Guards -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Converters' id='juneau-rest-server.jrs.Converters'>8.8 - Converters</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.8 - juneau-rest-server.jrs.Converters -->
<div class='topic'>
<p>
Converters can be thought of as "post-processors" for response POJOs before they get passed to the serializer.
</p>
<p>
Converters are associated with resource classes and methods via the following:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#converters--"><code>converters</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#converters--"><code>converters</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<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>@RestGet</ja>(
path=<js>"/people/{id}/*"</js>,
converters={Traversable.<jk>class</jk>,Queryable.<jk>class</jk>}
)
<jk>public</jk> Person getPerson(<ja>@Path</ja>(<js>"id"</js>) <jk>int</jk> <jv>id</jv>) {
<jk>return</jk> findPerson(<jv>id</jv>);
}
</p>
<p>
Juneau defines the following converters out-of-the-box:
</p>
<ul class='javatree'>
<li class='jic'><a href="org/apache/juneau/rest/converter/RestConverter.html" title="interface in org.apache.juneau.rest.converter"><code>RestConverter</code></a>
<ul class='spaced-list'>
<li class='jc'>
<a href="org/apache/juneau/rest/converter/Queryable.html" title="class in org.apache.juneau.rest.converter"><code>Queryable</code></a>
<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'>
<a href="org/apache/juneau/rest/converter/Traversable.html" title="class in org.apache.juneau.rest.converter"><code>Traversable</code></a>
<br>Allows nodes in the POJO response tree to be individually accessed through additional path info on
the request.
<li class='jc'>
<a href="org/apache/juneau/rest/converter/Introspectable.html" title="class in org.apache.juneau.rest.converter"><code>Introspectable</code></a>
<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>
</li>
</ul>
</div>
</div><!-- END: 8.8 - juneau-rest-server.jrs.Converters -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.LocalizedMessages' id='juneau-rest-server.jrs.LocalizedMessages'>8.9 - Localized Messages</a><span class='update'>updated: 8.2.0,<b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.9 - juneau-rest-server.jrs.LocalizedMessages -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/annotation/Rest.html#messages--"><code>@Rest(messages)</code></a> annotation identifies the location of the resource bundle
for a <ja>@Rest</ja>-annotated class if it's different from the class name.
</p>
<p>
By default, the resource bundle name is assumed to match the class name. For example, given the class
<c>MyClass.java</c>, the resource bundle is assumed to be <c>MyClass.properties</c>. This property
allows you to override this setting to specify a different location such as <c>MyMessages.properties</c> by
specifying a value of <js>"MyMessages"</js>.
</p>
<p>
Resource bundles are searched using the following base name patterns:
</p>
<ul>
<li><js>"{package}.{name}"</js>
<li><js>"{package}.i18n.{name}"</js>
<li><js>"{package}.nls.{name}"</js>
<li><js>"{package}.messages.{name}"</js>
</ul>
<p>
This annotation is used to provide request-localized (based on <c>Accept-Language</c>) messages for the following method:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestRequest.html#getMessage-java.lang.String-java.lang.Object...-"><code>getMessage(String,Object)</code></a>
</ul>
</ul>
<p>
Request-localized messages are also available by passing either of the following args into your Java method:
</p>
<ul class='javatree'>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html?is-external=true" title="class or interface in java.util"><code>ResourceBundle</code></a> - Basic Java resource bundle.
<li class='jc'><a href="org/apache/juneau/cp/Messages.html" title="class in org.apache.juneau.cp"><code>Messages</code></a> - Extended resource bundle with several convenience methods.
</ul>
<p>
The value can be a relative path like <js>"nls/Messages"</js>, indicating to look for the resource bundle
<js>"com.foo.sample.nls.Messages"</js> if the resource class is in <js>"com.foo.sample"</js>, or it can be an
absolute path like <js>"com.foo.sample.nls.Messages"</js>
</p>
<h5 class='figure'>Examples:</h5>
<p class='bini'>
<cc>#--------------------------------------------------------------------------------
# Contents of org/apache/foo/nls/MyMessages.properties
#--------------------------------------------------------------------------------</cc>
<ck>HelloMessage</ck> = <cv>Hello {0}!</cv>
</p>
<p class='bjava'>
<jc>// Contents of org/apache/foo/MyResource.java</jc>
<ja>@Rest</ja>(messages=<js>"nls/MyMessages"</js>)
<jk>public class</jk> MyResource {
<ja>@RestGet</ja>(<js>"/hello/{you}"</js>)
<jk>public</jk> Object helloYou(RestRequest <jv>req</jv>, Messages <jv>messages</jv>, <ja>@Path</ja>(<js>"name"</js>) String <jv>you</jv>) {
String <jv>msg</jv>;
<jc>// Get it from the RestRequest object.</jc>
<jv>msg</jv> = <jv>req</jv>.getMessage(<js>"HelloMessage"</js>, <jv>you</jv>);
<jc>// Or get it from the method parameter.</jc>
<jv>msg</jv> = <jv>messages</jv>.getString(<js>"HelloMessage"</js>, <jv>you</jv>);
<jc>// Or get the message in a locale different from the request.</jc>
<jv>msg</jv> = <jv>messages</jv>.forLocale(Locale.<jsf>UK</jsf>).getString(<js>"HelloMessage"</js>, <jv>you</jv>);
<jk>return</jk> <jv>msg</jv>;
}
}
</p>
<p>
When using shared resource bundles, keys can be prefixed by class names like so and still retrieve by simple
key names:
</p>
<p class='bini'>
<cc>#--------------------------------------------------------------------------------
# Contents of shared org/apache/foo/nls/MyMessages.properties
#--------------------------------------------------------------------------------</cc>
<ck>MyResource.HelloMessage</ck> = <cv>Hello {0}!</cv>
</p>
<p>
Messages are automatically inherited from super classes. If a string cannot be found in the bundle of the current
class, it will be searched for up the class hierarchy.
</p>
</div>
</div><!-- END: 8.9 - juneau-rest-server.jrs.LocalizedMessages -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Encoders' id='juneau-rest-server.jrs.Encoders'>8.10 - Encoders</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.10 - juneau-rest-server.jrs.Encoders -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/annotation/Rest.html#encoders--"><code>@Rest(encoders)</code></a> annotation can
be used to associate character encoders with a servlet class.
Encoders can be used to enable various kinds of compression (e.g. <l>"gzip"</l>) on requests and responses
based on the request <l>Accept-Encoding</l> and <l>Content-Encoding</l> headers.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Servlet with automated support for GZIP compression</jc>
<ja>@Rest</ja>(encoders={GzipEncoder.<jk>class</jk>})
<jk>public</jk> MyRestServlet <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
...
}
</p>
<p>
Juneau defines the following encoders out-of-the-box:
</p>
<ul class='javatreec'>
<li class='jc'>
<a href="org/apache/juneau/encoders/GzipEncoder.html" title="class in org.apache.juneau.encoders"><code>GzipEncoder</code></a>
<li class='jc'>
<a href="org/apache/juneau/encoders/IdentityEncoder.html" title="class in org.apache.juneau.encoders"><code>IdentityEncoder</code></a>
</ul>
</div>
</div><!-- END: 8.10 - juneau-rest-server.jrs.Encoders -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ConfigurationFiles' id='juneau-rest-server.jrs.ConfigurationFiles'>8.11 - Configuration Files</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.11 - juneau-rest-server.jrs.ConfigurationFiles -->
<div class='topic'>
<p>
The Server API provides methods for associating configuration files with REST servlets so that
configuration properties can be defined in external files. It uses the following annotation:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#config--"><code>config</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Rest</ja>(
<jc>// Config file is located at ./config_dir/myconfig.cfg</jc>
config=<js>"config_dir/myconfig.cfg"</js>,
...
)
<jk>public class</jk> MyResource {...}
</p>
<p>
In recap, the Configuration API provides support for INI-style configuration files with embedded string variables:
</p>
<h5 class='figure'>Example:</h5>
<p class='bini'>
<cc>#--------------------------</cc>
<cc># Examples </cc>
<cc>#--------------------------</cc>
<cs>[MyProperties]</cs>
<ck>path</ck> = <cv>$E{PATH}</cv>
<ck>javaHome</ck> = <cv>$S{java.home}</cv>
<ck>customMessage</ck> = <cv>Java home is $C{MyProperties/javaHome} and the
environment path is $C{MyProperties/path}.</cv>
</p>
<p>
These properties are then accessible through the <a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a> class.
</p>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/"</js>)
<jk>public</jk> String sample(Config <jv>config</jv>) {
String <jv>path</jv> = <jv>config</jv>.get(<js>"MyProperties/path"</js>).get();
File <jv>javaHome</jv> = <jv>config</jv>.get(<js>"MyProperties/javaHome"</js>).as(File.<jk>class</jk>).orElse(<jv>null</jv>);
String <jv>customMessage</jv> = <jv>config</jv>.get(<js>"MyProperties/customMessage"</js>).orElse(<js>"Hello"</js>);
...
}
</p>
<p>
The annotation itself can contain string variables.
For example, the Microservice API <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> class defines the
location of the config file as a system property <l>"juneau.configFile"</l>:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
<jc>// Config file location is defined as a system property</jc>
config=<js>"$S{juneau.configFile}"</js>,
...
)
<jk>public class</jk> MyResource {...}
</p>
<p>
Spring Boot applications typically define an <c>application.properties</c> file. You can reuse it
as a config file like so:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
config=<js>"application.properties"</js>,
...
)
<jk>public class</jk> MyResource {...}
</p>
<p>
Note that properties files are a subset of functionality of INI files (they're basically just INI files with a single default section).
It's therefore possible to use INI-style syntax such as sections in your <c>application.properties</c> file.
</p>
<p>
Once a config file has been associated with a REST resource, it can be accessed through one of the following:
<a href="org/apache/juneau/rest/RestContext.html#getConfig--"><code>RestContext.getConfig()</code></a> method. It can also be access by passing in a <a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a> bean to any of your
REST OP methods.
</p>
<p>
A common usage is to use this method to initialize fields in your servlet.
</p>
<p class='bjava'>
<ja>@Rest</ja>(
<jc>// Config file is located at ./config_dir/myconfig.cfg</jc>
config=<js>"config_dir/myconfig.cfg"</js>,
...
)
<jk>public class</jk> MyResource {
<jk>private final</jk> String <jf>path</jf>;
<jk>private final</jk> File <jf>javaHome</jf>;
<jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) {
Config <jv>config</jv> = <jv>builder</jv>.getConfig();
<jf>path</jf> = <jv>config</jv>.get(<js>"MyProperties/path"</js>).orElse(<js>"mypath"</js>);
<jf>javaHome</jf> = <jv>config</jv>.get(<js>"MyProperties/javaHome"</js>).as(File.<jk>class</jk>).orElse(<jv>null</jv>);
}
</p>
<p>
Another common usage is to refer to config properties through <ck>$C</ck> variables in your annotations:
</p>
<p class='bjava'>
<ja>@Rest</ja>
<jc>// Get stylesheet from myconfig.cfg but default to devops.css if it's not specified</jc>
<ja>@HtmlDoc</ja>(
stylesheet=<js>"$C{MyServlet/stylesheet,servlet:/styles/devops.css}"</js>,
)
<jk>public class</jk> MyResource {...}
</p>
<p>
It's even possible to reference request-level variables in your config file if you use
<a href="org/apache/juneau/rest/RestRequest.html#getConfig--"><code>RestRequest.getConfig()</code></a> to access the config file:
</p>
<p class='bini'>
<cc>#-------------------------------------</cc>
<cc># Contents of config_dir/myconfig.cfg </cc>
<cc>#-------------------------------------</cc>
<cs>[HelloWorldResource]</cs>
<ck>message</ck> = <cv>Hello $RQ{person}!</cv>
</p>
<p class='bjava'>
<jd>/**
* Sample REST resource that prints out a simple "Hello world!" message.
*/</jd>
<ja>@Rest</ja>(
config=<js>"config_dir/myconfig.cfg"</js>,
...
)
<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<jd>/**
* GET request handler.
* Specify the GET parameter "?person=X" for a specialized message!
*/</jd>
<ja>@RestGet</ja>(<js>"/"</js>)
<jk>public</jk> String sayHello(Config <jv>config</jv>) {
<jk>return</jk> <jv>config</jv>.get(<js>"HelloWorldResource/message"</js>).get();
}
}
</p>
<p>
You can even add resource bundles into the mix:
</p>
<p class='bini'>
<cc>#-------------------------------------</cc>
<cc># Contents of config_dir/myconfig.cfg </cc>
<cc>#-------------------------------------</cc>
<cs>[HelloWorldResource]</cs>
<ck>message</ck> = <cv>$L{localizedMessage,$RQ{person}}</cv>
</p>
<p class='bini'>
<cc>#-------------------------------------------</cc>
<cc># Contents of HelloWorldResource.properties </cc>
<cc>#-------------------------------------------</cc>
<ck>localizedMessage</ck> = <cv>Hello {0}!</cv>
</p>
<p class='bjava'>
<jd>/**
* Sample REST resource that prints out a simple "Hello world!" message.
*/</jd>
<ja>@Rest</ja>(
messages=<js>"HelloWorldResources"</js>,
config=<js>"config_dir/myconfig.cfg"</js>,
...
)
<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<jd>/**
* GET request handler.
* Specify the GET parameter "?person=X" for a specialized message!
*/</jd>
<ja>@RestGet</ja>(<js>"/"</js>)
<jk>public</jk> String sayHello(Config <jv>config</jv>) {
<jk>return</jk> <jv>config</jv>.get(<js>"HelloWorldResource/message"</js>).get();
}
}
</p>
<ul class='seealso'>
<li><a class='doclink' href='#juneau-config'>Overview &gt; juneau-config</a>
</ul>
</div>
</div><!-- END: 8.11 - juneau-rest-server.jrs.ConfigurationFiles -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.SvlVariables' id='juneau-rest-server.jrs.SvlVariables'>8.12 - SVL Variables</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.12 - juneau-rest-server.jrs.SvlVariables -->
<div class='topic'>
<p>
In the previous examples, there were several cases where embedded variables were contained within
annotation values:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
title=<js>"$L{my.label}"</js>
)
</p>
<p>
Variables take the form <l>$X{contents}</l> where <l>X</l> can consist of zero or more ASCII characters and <l>contents</l> can be virtually anything.
This is called Simple Variable Language, or SVL, and is defined here: <a class='doclink' href='#juneau-marshall.jm.SimpleVariableLanguage'>Simple Variable Language</a>.
</p>
<h5 class='topic'>Features</h5>
<ul class='spaced-list'>
<li>
Variables can be nested arbitrarily deep (e.g. <l>"$X{$Y{foo}}"</l>).
<li>
Variables can contain arguments (e.g. <l>"$L{my.label,arg1,arg2}"</l>).
<li>
Variables are recursively resolved.
<br>i.e., if a variable results to a value with another variable in it, that variable will also be
resolved (restricted for security reasons on variables that involve user input).
</ul>
<p>
There are two distinct groups of variables:
</p>
<ul class='spaced-list'>
<li><l>Initialization-time variables</l>
<br>These are variables that can be used in many of the annotations in <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a>.
<br>The <a href="org/apache/juneau/rest/RestContext.html#getVarResolver--"><code>RestContext.getVarResolver()</code></a> method returns initialization-time variables only.
<li><l>Request-time variables</l>
<br>These are variables that are available during HTTP-requests and can be used on annotation such as <dc>@HtmlDoc</dc>.
<br><a href="org/apache/juneau/rest/RestRequest.html#getVarResolverSession--"><code>RestRequest.getVarResolverSession()</code></a> method returns initialization and request-time variables.
</ul>
<p>
The following is the default list of supported variables.
</p>
<h5 class='figure'><a href='#DefaultRestSvlVariables' id='DefaultRestSvlVariables'>Default REST SVL Variables:</a></h5>
<table class='styled w800'>
<tr>
<th>Module</th><th>Class</th><th>Pattern</th><th>Initialization<br>time</th><th>Request<br>time</th><th>Examples</th>
</tr>
<tr class='dark'>
<td rowspan='11' style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-svl</td>
<td><a href="org/apache/juneau/svl/vars/EnvVariablesVar.html" title="class in org.apache.juneau.svl.vars"><code>EnvVariablesVar</code></a></td>
<td class='code'>$E{key[,default]}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$E{PATH}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/SystemPropertiesVar.html" title="class in org.apache.juneau.svl.vars"><code>SystemPropertiesVar</code></a></td>
<td class='code'>$S{key[,default]}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$S{java.home}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/ArgsVar.html" title="class in org.apache.juneau.svl.vars"><code>ArgsVar</code></a></td>
<td class='code'>$A{key[,default]}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$A{foo,null}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/ManifestFileVar.html" title="class in org.apache.juneau.svl.vars"><code>ManifestFileVar</code></a></td>
<td class='code'>$MF{key[,default]}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$MF{Main-Class}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/IfVar.html" title="class in org.apache.juneau.svl.vars"><code>IfVar</code></a></td>
<td class='code'>$IF{arg,then[,else]}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$IF{$S{my.boolean.property},foo,bar}</td>
</tr>
<tr class='dark dd'>
<td><a href="org/apache/juneau/svl/vars/SwitchVar.html" title="class in org.apache.juneau.svl.vars"><code>SwitchVar</code></a></td>
<td class='code'>$SW{arg,p1:then1[,p2:then2...]}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$SW{$S{os.name},*win*:Windows,*:Something else}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/CoalesceVar.html" title="class in org.apache.juneau.svl.vars"><code>CoalesceVar</code></a></td>
<td class='code'>$CO{arg1[,arg2...]}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$CO{$S{my.property},$E{my.property},n/a}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/PatternMatchVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternMatchVar</code></a></td>
<td class='code'>$PM{arg,pattern}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$PM{$S{os.name},*win*}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/NotEmptyVar.html" title="class in org.apache.juneau.svl.vars"><code>NotEmptyVar</code></a></td>
<td class='code'>$NE{arg}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$NE{$S{foo}}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/UpperCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>UpperCaseVar</code></a></td>
<td class='code'>$UC{arg}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$UC{$S{foo}}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/svl/vars/LowerCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>LowerCaseVar</code></a></td>
<td class='code'>$LC{arg}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$LC{$S{foo}}</td>
</tr>
<tr class='light dd'>
<td rowspan='1' style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-config</td>
<td><a href="org/apache/juneau/config/vars/ConfigVar.html" title="class in org.apache.juneau.config.vars"><code>ConfigVar</code></a></td>
<td class='code'>$C{key[,default]}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$C{REST/staticFiles}</td>
</tr>
<tr class='dark'>
<td rowspan='14' style='text-align:center;font-weight:bold;padding:20px;' class='code'>juneau-rest-server</td>
<td><a href="org/apache/juneau/rest/vars/FileVar.html" title="class in org.apache.juneau.rest.vars"><code>FileVar</code></a></td>
<td class='code'>$F{path[,default]}}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$F{resources/MyAsideMessage.html, Oops not found!}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/ServletInitParamVar.html" title="class in org.apache.juneau.rest.vars"><code>ServletInitParamVar</code></a></td>
<td class='code'>$I{name[,default]}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$I{my.param}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/LocalizationVar.html" title="class in org.apache.juneau.rest.vars"><code>LocalizationVar</code></a></td>
<td class='code'>$L{key[,args...]}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$L{MyMessage,foo,bar}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestAttributeVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestAttributeVar</code></a></td>
<td class='code'>$RA{key1[,key2...]}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$RA{attrName}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestFormDataVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestFormDataVar</code></a></td>
<td class='code'>$RF{key1[,key2...]}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$RF{paramName}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestHeaderVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestHeaderVar</code></a></td>
<td class='code'>$RH{key1[,key2...]}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$RH{Header-Name}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestPathVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestPathVar</code></a></td>
<td class='code'>$RP{key1[,key2...]}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$RP{pathVAr}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestQueryVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestQueryVar</code></a></td>
<td class='code'>$RQ{key1[,key2...]}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$RQ{paramName}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestSwaggerVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestSwaggerVar</code></a></td>
<td class='code'>$RS{key}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$RS{title}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/RequestVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestVar</code></a></td>
<td class='code'>$R{key1[,key2...]}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$R{contextPath}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/SerializedRequestAttrVar.html" title="class in org.apache.juneau.rest.vars"><code>SerializedRequestAttrVar</code></a></td>
<td class='code'>$SA{contentType,key[,default]}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$SA{application/json,$RA{foo}}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/UrlVar.html" title="class in org.apache.juneau.rest.vars"><code>UrlVar</code></a></td>
<td class='code'>$U{uri}></td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$U{servlet:/foo}</td>
</tr>
<tr class='dark'>
<td><a href="org/apache/juneau/rest/vars/UrlEncodeVar.html" title="class in org.apache.juneau.rest.vars"><code>UrlEncodeVar</code></a></td>
<td class='code'>$UE{uriPart}</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$U{servlet:/foo?bar=$UE{$RA{bar}}</td>
</tr>
<tr class='dark dd'>
<td><a href="org/apache/juneau/rest/widget/Widget.html" title="class in org.apache.juneau.rest.widget"><code>Widget</code></a></td>
<td class='code'>$W{name}</td>
<td style='text-align:center;font-weight:bold'>no</td>
<td style='text-align:center;font-weight:bold'>yes</td>
<td class='code'>$W{MenuItemWidget}</td>
</tr>
</table>
<p>
Custom variables can be defined on resources via the following API:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createVarResolver-org.apache.juneau.cp.BeanStore-java.lang.Class-"><code>createVarResolver(BeanStore,Class)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#varResolver--"><code>varResolver()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#varResolver-java.util.function.Consumer-"><code>varResolver(Consumer)</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Defined a variable that simply wrapps all strings inside [] brackets.</jc>
<jc>// e.g. "$BRACKET{foobar}" -> "[foobar]"</jc>
<jk>public class</jk> BracketVar <jk>extends</jk> SimpleVar {
<jk>public</jk> BracketVar() {
<jk>super</jk>(<js>"BRACKET"</js>);
}
<ja>@Override</ja> <jc>/* Var */</jc>
<jk>public</jk> String resolve(VarResolverSession <jv>session</jv>, String <jv>arg</jv>) {
<jk>return</jk> <js>'['</js> + <jv>arg</jv> + <js>']'</js>;
}
}
<jc>// Register it with our resource.</jc>
<ja>@Rest</ja>(...)
<jk>public class</jk> MyResource {
<jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) {
<jv>builder</jv>.varResolver().vars(BracketVar.<jk>class</jk>);
}
}
</p>
<p>
The methods involved with variables are:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.html#getVarResolver--"><code>getVarResolver()</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestRequest.html#getVarResolverSession--"><code>getVarResolverSession()</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 8.12 - juneau-rest-server.jrs.SvlVariables -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.StaticFiles' id='juneau-rest-server.jrs.StaticFiles'>8.13 - Static files</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.13 - juneau-rest-server.jrs.StaticFiles -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> and <a href="org/apache/juneau/rest/servlet/BasicRestObject.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObject</code></a> classes come with built-in support
for serving up static files through the following REST operation:
</p>
<p class='bjava'>
<ja>@RestGet</ja>(path=<js>"/htdocs/*"</js>)
<jk>public</jk> HttpResource getHtdoc(<ja>@Path</ja>("/*") String <jv>path</jv>, Locale <jv>locale</jv>) <jk>throws</jk> NotFound {
<jk>return</jk> getContext().getStaticFiles().resolve(<jv>path</jv>, <jv>locale</jv>).orElseThrow(NotFound::<jk>new</jk>);
}
</p>
<p>
The static file finder can be accessed through the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.html#getStaticFiles--"><code>getStaticFiles()</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestRequest.html#getStaticFiles--"><code>getStaticFiles()</code></a>
</ul>
</li>
</ul>
<p>
By default, the <a href="org/apache/juneau/rest/staticfile/StaticFiles.html" title="interface in org.apache.juneau.rest.staticfile"><code>StaticFiles</code></a> bean is configured as follows:
</p>
<p class='bjava'>
StaticFiles
.<jsm>create</jsm>()
.beanStore(<jv>beanStore</jv>) <jc>// Allow injected beans in constructor.</jc>
.type(BasicStaticFiles.<jk>class</jk>) <jc>// Default implementation class.</jc>
.dir(<js>"static"</js>) <jc>// Look in working /static directory.</jc>
.dir(<js>"htdocs"</js>) <jc>// Look in working /htdocs directory.</jc>
.cp(<jv>resourceClass</jv>, <js>"htdocs"</js>, <jk>true</jk>) <jc>// Look in htdocs subpackage.</jc>
.cp(<jv>resourceClass</jv>, <js>"/htdocs"</js>, <jk>true</jk>) <jc>// Look in htdocs package.</jc>
.caching(1_000_000) <jc>// Cache files in memory up to 1MB.</jc>
.exclude(<js>"(?i).*\\.(class|properties)"</js>) <jc>// Ignore class/properties files.</jc>
.headers(<jsm>cacheControl</jsm>(<js>"max-age=86400, public"</js>)); <jc>// Add cache control.</jc>
</p>
<p>
Static files can be configured programmatically through the following APIs:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createStaticFiles-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-"><code>createStaticFiles(BeanStore,Supplier)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#staticFiles--"><code>staticFiles()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#staticFiles-java.util.function.Consumer-"><code>staticFiles(Consumer)</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 8.13 - juneau-rest-server.jrs.StaticFiles -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ClientVersioning' id='juneau-rest-server.jrs.ClientVersioning'>8.14 - Client Versioning</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.14 - juneau-rest-server.jrs.ClientVersioning -->
<div class='topic'>
<p>
Client version headers are used to support backwards compatibility for breaking REST interface changes.
Using them, you're able to return different responses based on which client is making a request.
</p>
<p>
The APIs involved with defining client version headers are:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#clientVersionHeader--"><code>clientVersionHeader</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#clientVersion--"><code>clientVersion</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#clientVersionHeader-java.lang.String-"><code>clientVersionHeader(String)</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Option #1 - Defined via annotation resolving to a config file setting with default value.</jc>
<ja>@Rest</ja>(clientVersionHeader=<js>"Client-Version"</js>)
<jk>public class</jk> MyResource {
<jc>// Call this method if Client-Version is at least 2.0.
// Note that this also matches 2.0.1.</jc>
<ja>@RestGet</ja>(path=<js>"/foobar"</js>, clientVersion=<js>"2.0"</js>)
<jk>public</jk> Object method1() {
...
}
<jc>// Call this method if Client-Version is at least 1.1 but less than 2.0.</jc>
<ja>@RestGet</ja>(path=<js>"/foobar"</js>, clientVersion=<js>"[1.1,2.0)"</js>)
<jk>public</jk> Object method2() {
...
}
<jc>// Call this method if Client-Version is less than 1.1.</jc>
<ja>@RestGet</ja>(path=<js>"/foobar"</js>, clientVersion=<js>"[0,1.1)"</js>)
<jk>public</jk> Object method3() {
...
}
</p>
</div>
</div><!-- END: 8.14 - juneau-rest-server.jrs.ClientVersioning -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger' id='juneau-rest-server.jrs.Swagger'>8.15 - Swagger</a></h3>
<div class='topic'><!-- START: 8.15 - juneau-rest-server.jrs.Swagger -->
<div class='topic'>
<p>
One of the most useful features of Juneau is the ability to generate Swagger-based OPTIONS pages for self-documenting designs
(i.e. REST interfaces that document themselves).
</p>
<p>
As described previously, the <c>PetStore</c> example provides an example of auto-generated Swagger JSON:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.1.png'>
<p>
Using <a href="org/apache/juneau/dto/swagger/ui/SwaggerUI.html" title="class in org.apache.juneau.dto.swagger.ui"><code>SwaggerUI</code></a>, we're able to render that JSON as a Swagger user interface:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.2.png'>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger' id='juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger'>8.15.1 - BasicRestServlet/BasicRestObject</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.15.1 - juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger -->
<div class='topic'>
<p>
Any subclass of <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> and <a href="org/apache/juneau/rest/servlet/BasicRestObject.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObject</code></a> gets an auto-generated Swagger UI when performing an <c>OPTIONS</c>
request with <c>Accept:text/html</c> due to the following method:
</p>
<p class='bjava'>
<ja>@RestGet</ja>(
path=<js>"/api/*"</js>,
summary=<js>"Swagger documentation"</js>,
description=<js>"Swagger documentation for this resource."</js>
)
<ja>@HtmlDocConfig</ja>(
<jc>// Should override config annotations defined on class.</jc>
rank=10,
<jc>// Override the nav links for the swagger page.</jc>
navlinks={
<js>"back: servlet:/"</js>,
<js>"json: servlet:/?Accept=text/json&plainText=true"</js>
},
<jc>// Never show aside contents of page inherited from class.</jc>
aside=<js>"NONE"</js>
)
<ja>@BeanConfig</ja>(
<jc>// POJO swaps to apply to all serializers/parsers on this method.</jc>
swaps={
<jc>// Use the SwaggerUI swap when rendering Swagger beans.
// This is a per-media-type swap that only applies to text/html requests.</jc>
SwaggerUI.class
}
)
<ja>@Override</ja> <jc>/* BasicRestOperations */</jc>
<jk>public</jk> Swagger getSwagger(RestRequest <jv>req</jv>) {
<jk>return</jk> <jv>req</jv>.getSwagger().orElseThrow(NotFound::<jk>new</jk>);
}
</p>
<p>
The underlying mechanics are simple.
The <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html#getSwagger-org.apache.juneau.rest.RestRequest-"><code>BasicRestServlet.getSwagger(RestRequest)</code></a> method returns a <a href="org/apache/juneau/dto/swagger/Swagger.html" title="class in org.apache.juneau.dto.swagger"><code>Swagger</code></a> bean
consisting of information gathered from annotations and other sources.
Then that bean is swapped for a <a href="org/apache/juneau/dto/swagger/ui/SwaggerUI.html" title="class in org.apache.juneau.dto.swagger.ui"><code>SwaggerUI</code></a> bean when rendered as HTML.
</p>
<p>
Note that to have your resource create Swagger UI, you must either extend from one of the basic resource classes or provide
your own <ja>@RestOp</ja>-annotated method that returns a <a href="org/apache/juneau/dto/swagger/Swagger.html" title="class in org.apache.juneau.dto.swagger"><code>Swagger</code></a> object and a <a href="org/apache/juneau/dto/swagger/ui/SwaggerUI.html" title="class in org.apache.juneau.dto.swagger.ui"><code>SwaggerUI</code></a> swap.
</p>
</div>
</div><!-- END: 8.15.1 - juneau-rest-server.jrs.Swagger.jrs.BasicRestServletSwagger -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo' id='juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo'>8.15.2 - Basic Swagger Info</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.15.2 - juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo -->
<div class='topic'>
<p>
Let's look at the various parts of the <c>Petstore</c> application Swagger UI to see how they are defined.
</p>
<p>
The top part of the page shows general information about the REST interface:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.3.png'>
<p>
The information is pulled from the <a href="org/apache/juneau/rest/annotation/Rest.html#swagger--"><code>@Rest(swagger)</code></a> annotation.
</p>
<h5 class='figure'>org.apache.juneau.examples.rest.petstore.PetStoreResource</h5>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/petstore"</js>,
title=<js>"Petstore application"</js>,
...
swagger=<ja>@Swagger</ja>(<js>"$F{PetStoreResource.json}"</js>),
...
)
<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
In this particular case, the Swagger is pulled in from a localized Swagger JSON file located in the
<c>org.apache.juneau.examples.rest.petstore</c> package using the <a href="org/apache/juneau/rest/vars/FileVar.html" title="class in org.apache.juneau.rest.vars"><code>$F</code></a> variable.
</p>
<h5 class='figure'>PetStoreResource.json</h5>
<p class='bjson'>
{
<jok>"swagger"</jok>: <jov>"2.0"</jov>,
<jok>"info"</jok>: {
<jok>"version"</jok>: <jov>"1.0.0"</jov>,
<jok>"title"</jok>: <jov>"Swagger Petstore"</jov>,
<jok>"termsOfService"</jok>: <jov>"You are on your own."</jov>,
<jok>"contact"</jok>: {
<jok>"name"</jok>: <jov>"Juneau Development Team"</jov>,
<jok>"email"</jok>: <jov>"dev@juneau.apache.org"</jov>,
<jok>"url"</jok>: <jov>"http://juneau.apache.org"</jov>
},
<jok>"license"</jok>: {
<jok>"name"</jok>: <jov>"Apache 2.0"</jov>,
<jok>"url"</jok>: <jov>"http://www.apache.org/licenses/LICENSE-2.0.html"</jov>
}
},
<jok>"externalDocs"</jok>: {
<jok>"description"</jok>: <jov>"Find out more about Juneau"</jov>,
<jok>"url"</jok>: <jov>"http://juneau.apache.org"</jov>
},
...
}
</p>
<p>
Note that the <a href="org/apache/juneau/rest/vars/FileVar.html" title="class in org.apache.juneau.rest.vars"><code>$F</code></a> variable allows for request-locale-sensitive name matching so that you can provide
localized Swagger information.
</p>
<p>
The <a href="org/apache/juneau/rest/vars/FileVar.html" title="class in org.apache.juneau.rest.vars"><code>$F</code></a> variable simply expands to a string to fill the <a href="org/apache/juneau/rest/annotation/Swagger.html#value--"><code>@Swagger(value)</code></a>
annotation.
You could equivalently embed JSON directly into your annotation like so:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/petstore"</js>,
title=<js>"Petstore application"</js>,
...
swagger=<ja>@Swagger</ja>(
<jc>// Raw Simplified JSON.</jc>
<jc>// Values are concatenated.</jc>
<js>"{"</js>,
<js>"swagger: '2.0',"</js>,
<js>"version: '1.0.0',"</js>,
...
<js>"}"</js>
),
...
)
<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
However, a more typical (and less error-prone) scenario is to define all of your Swagger as annotations:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/petstore"</js>,
title=<js>"Petstore application"</js>,
...
swagger=<ja>@Swagger</ja>(
version=<js>"1.0.0"</js>,
title=<js>"Swagger Petstore"</js>,
termsOfService=<js>"You are on your own."</js>,
contact=<ja>@Contact</ja>(
name=<js>"Juneau Development Team"</js>,
email=<js>"dev@juneau.apache.org"</js>,
url=<js>"http://juneau.apache.org"</js>
),
license=<ja>@License</ja>(
name=<js>"Apache 2.0"</js>,
url=<js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>
),
externalDocs=<ja>@ExternalDocs</ja>(
description=<js>"Find out more about Juneau"</js>,
url=<js>"http://juneau.apache.org"</js>
)
),
...
)
<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
All annotations support <a class='doclink' href='#juneau-rest-server.jrs.SvlVariables'>SVL variables</a>, so you could for example
pull localized strings from resource bundles using <a href="org/apache/juneau/rest/vars/LocalizationVar.html" title="class in org.apache.juneau.rest.vars"><code>$L</code></a> variables.
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/petstore"</js>,
title=<js>"Petstore application"</js>,
messages=<js>"nls/MyMessages"</js>,
...
swagger=<ja>@Swagger</ja>(
version=<js>"1.0.0"</js>,
title=<js>"$L{myTitle}"</js>,
termsOfService=<js>"$L{myTermsOfService}"</js>,
contact=<ja>@Contact</ja>(
name=<js>"$L{myTeam}"</js>,
email=<js>"dev@juneau.apache.org"</js>,
url=<js>"http://juneau.apache.org"</js>
),
license=<ja>@License</ja>(
name=<js>"Apache 2.0"</js>,
url=<js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>
),
externalDocs=<ja>@ExternalDocs</ja>(
description=<js>"$L{myExternalDocsDescription}"</js>,
url=<js>"http://juneau.apache.org"</js>
)
),
...
)
<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
A third option is to define your Swagger information in your <a href="org/apache/juneau/rest/annotation/Rest.html#messages--"><code>@Rest(messages)</code></a> resource
bundle using predefined Swagger keywords:
</p>
<p class='bini'>
<mk>PetStoreResource.version</mk> = <mv>1.0.0</mv>
<mk>PetStoreResource.title</mk> = <mv>Swagger Petstore</mv>
<mk>PetStoreResource.termsOfService</mk> = <mv>You are on your own.</mv>
<mk>PetStoreResource.contact</mk> = <mv>{name:'Juneau Development Team', email:'dev@juneau.apache.org',...}</mv>
<mk>PetStoreResource.license</mk> = <mv>{name:'Apache 2.0',...}</mv>
<mk>PetStoreResource.externalDocs</mk> = <mv>{description:'Find out more about Juneau',...}</mv>
</p>
<p>
Information defined in multiple locations are merged into a single set of data.
When the same information is provided in multiple locations, the following order-of-precedence is used:
</p>
<ol>
<li>Java annotations
<li>Resource bundle
<li>Swagger JSON file
</ol>
</div>
</div><!-- END: 8.15.2 - juneau-rest-server.jrs.Swagger.jrs.BasicSwaggerInfo -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerTags' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerTags'>8.15.3 - Tags</a></h4>
<div class='topic'><!-- START: 8.15.3 - juneau-rest-server.jrs.Swagger.jrs.SwaggerTags -->
<div class='topic'>
<p>
Tags allow you to group operations into general categories.
In the user interface, these can be expanded/collapsed by clicking on the tag sections.
In the example below, the <c>pet</c> and <c>store</c> tag sections are collapsed
and the <c>user</c> section is not:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.4.png'>
<p>
Tags are also defined in the <ja>@Swagger</ja> annotation
</p>
<h5 class='figure'>PetStoreResource.json</h5>
<p class='bjson'>
<jok>"tags"</jok>: [
{
<jok>"name"</jok>: <jov>"pet"</jov>,
<jok>"description"</jok>: <jov>"Everything about your Pets"</jov>,
<jok>"externalDocs"</jok>: {
<jok>"description"</jok>: <jov>"Find out more"</jov>,
<jok>"url"</jok>: <jov>"http://juneau.apache.org"</jov>
}
},
{
<jok>"name"</jok>: <jov>"store"</jov>,
<jok>"description"</jok>: <jov>"Access to Petstore orders"</jov>
},
{
<jok>"name"</jok>: <jov>"user",
<jok>"description"</jok>: <jov>"Operations about user"</jov>,
<jok>"externalDocs"</jok>: {
<jok>"description"</jok>: <jov>"Find out more about our store"</jov>,
<jok>"url"</jok>: <jov>"http://juneau.apache.org"</jov>
}
}
],
</p>
<p>
The annotation-only approach is shown here:
</p>
<h5 class='figure'>org.apache.juneau.examples.rest.petstore.PetStoreResource</h5>
<p class='bjava'>
swagger=<ja>@Swagger</ja>(
...
tags={
<ja>@Tag</ja>(
name=<js>"pet"</js>,
description=<js>"Everything about your Pets"</js>,
externalDocs=<ja>@ExternalDocs</ja>(
description=<js>"Find out more"</js>,
url=<js>"http://juneau.apache.org"</js>
)
),
<ja>@Tag</ja>(
name=<js>"store"</js>,
description=<js>"Access to Petstore orders"</js>
),
<ja>@Tag</ja>(
name=<js>"user"</js>,
description=<js>"Operations about user"</js>,
externalDocs=<ja>@ExternalDocs</ja>(
description=<js>"Find out more about our store"</js>,
url=<js>"http://juneau.apache.org"</js>
)
)
}
),
</p>
<p>
Tags are associated with operations using the <a href="org/apache/juneau/rest/annotation/OpSwagger.html#tags--"><code>@OpSwagger(tags)</code></a> annotation:
</p>
<h5 class='figure'>GET /user operation</h5>
<p class='bjava'>
<ja>@RestGet</ja>(
path=<js>"/user"</js>,
summary=<js>"Petstore users"</js>,
swagger=<ja>@OpSwagger</ja>(
tags=<js>"user"</js>
)
)
<jk>public</jk> Collection&lt;User&gt; getUsers() <jk>throws</jk> NotAcceptable {...}
</p>
<p>
Operations can be mapped to multiple tags.
</p>
<p>
Tags are optional.
Operations not mapped to tags are listed in the UI before tagged operations.
</p>
<p>
For example, the <c>getTopPage()</c> method in <c>PetStoreResource</c> is not tagged,
as well as the <c>getOptions()</c> method inherited from <c>BaseRestServlet</c>, so these
show up at the top of the page:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.5.png'>
</div>
</div><!-- END: 8.15.3 - juneau-rest-server.jrs.Swagger.jrs.SwaggerTags -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations'>8.15.4 - Operations</a></h4>
<div class='topic'><!-- START: 8.15.4 - juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations -->
<div class='topic'>
<p>
<ja>@RestOp</ja>-annotated methods automatically get rendered as Swagger operations:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.Operations.1.png'>
<p>
The following shows the annotations defined on the <c>GET /pet</c> operation:
</p>
<h5 class='figure'>PetStoreResource.getPets()</h5>
<p class='bjava'>
<ja>@RestGet</ja>(
path=<js>"/pet"</js>,
summary=<js>"All pets in the store"</js>,
swagger=<ja>@OpSwagger</ja>(
tags=<js>"pet"</js>,
...
),
...
)
<jk>public</jk> Collection&lt;Pet&gt; getPets() <jk>throws</jk> NotAcceptable {
<jk>return</jk> <jsf>store</jsf>.getPets();
}
</p>
<p>
Methods marked as deprecated will show up as deprecated in the Swagger UI:
</p>
<h5 class='figure'>PetStoreResource.findPetsByTag()</h5>
<p class='bjava'>
<ja>@RestGet</ja>(
path=<js>"/pet/findByTags"</js>,
summary=<js>"Finds Pets by tags"</js>,
...
)
<ja>@Deprecated</ja>
<jk>public</jk> Collection&lt;Pet&gt; findPetsByTags(...) {
...
}
</p>
</div>
</div><!-- END: 8.15.4 - juneau-rest-server.jrs.Swagger.jrs.SwaggerOperations -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters'>8.15.5 - Parameters</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.15.5 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters -->
<div class='topic'>
<p>
Expanding operations shows you a list of parameters:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.Operations.2.png'>
<p>
Parameter information can be defined in a couple of ways. The typical way is through annotations on parameters
being passed to your <ja>@RestOp</ja>-annotated method, like so:
</p>
<p class='bjava'>
<ja>@RestGet</ja>
<jk>public</jk> Collection&lt;Pet&gt; getPets(
<ja>@Query</ja>(
name=<js>"s"</js>,
schema=<ja>@Schema</ja>(
description={
<js>"Search."</js>,
<js>"Key/value pairs representing column names and search tokens."</js>,
<js>"'*' and '?' can be used as meta-characters in string fields."</js>,
<js>"'&gt;', '&gt;=', '&lt;', and '&lt;=' can be used as limits on numeric and date fields."</js>,
<js>"Date fields can be matched with partial dates (e.g. '2018' to match any date in the year 2018)."</js>
},
type=<js>"array"</js>,
collectionFormat=<js>"csv"</js>
)
)
String[] <jv>s</jv>,
<ja>@Query</ja>(
name=<js>"v"</js>,
schema=<ja>@Schema</ja>(
description={
<js>"View."</js>,
<js>"Column names to display."</js>
},
type=<js>"array"</js>,
collectionFormat=<js>"csv"</js>
)
)
String[] <jv>v</jv>,
...
) <jk>throws</jk> NotAcceptable {
...
}
</p>
<ul class='notes'>
<li class='note'>The <a href="org/apache/juneau/annotation/Schema.html" title="annotation in org.apache.juneau.annotation"><code>@Schema</code></a> annotation can also be attached
directly to the parameter or parameter type as well.
<li class='note'>The <a href="org/apache/juneau/annotation/Schema.html#type--"><code>type</code></a> and <a href="org/apache/juneau/annotation/Schema.html#collectionFormat--"><code>collectionFormat</code></a> values above are optional and auto-detected based on the
parameter class type if omitted. They're included here for clarity.
The examples will be explained in the next section.
</ul>
<p>
Another option is to specify your parameter information in the <c>parameters</c> annotation as free-form Simple JSON.
In the case of the <c>PetStoreResource.getPets()</c> method, we pull this information from a static field
defined in the <a href="org/apache/juneau/rest/converter/Queryable.html" title="class in org.apache.juneau.rest.converter"><code>Queryable</code></a> class:
</p>
<h5 class='figure'>PetStoreResource.getPets()</h5>
<p class='bjava'>
<ja>@RestGet</ja>(
path=<js>"/pet"</js>,
summary=<js>"All pets in the store"</js>,
swagger=<ja>@OpSwagger</ja>(
tags=<js>"pet"</js>,
parameters={
Queryable.<jsf>SWAGGER_PARAMS</jsf>
}
),
...
converters={Queryable.<jk>class</jk>}
)
<jk>public</jk> Collection&lt;Pet&gt; getPets() <jk>throws</jk> NotAcceptable {
<jk>return</jk> <jf>store</jf>.getPets();
}
</p>
<h5 class='figure'>Queryable</h5>
<p class='bjava'>
<jk>public class</jk> Queryable <jk>implements</jk> RestConverter {
<jk>public static final</jk> String <jsf>SWAGGER_PARAMS</jsf>=<js>""</js>
+ <js>"{"</js>
+ <js>"in:'query',"</js>
+ <js>"name:'s',"</js>
+ <js>"description:'"</js>
+ <js>"Search.\n"</js>
+ <js>"Key/value pairs representing column names and search tokens.\n"</js>
+ <js>"\\'*\\' and \\'?\\' can be used as meta-characters in string fields.\n"</js>
+ <js>"\\'&gt;\\', \\'&gt;=\\', \\'&lt;\\', and \\'&lt;=\\' can be used as limits on numeric and date fields.\n"</js>
+ <js>"Date fields can be matched with partial dates (e.g. \\'2018\\' to match any date in the year 2018)."</js>
+ <js>"',"</js>
+ <js>"type:'array',"</js>
+ <js>"collectionFormat:'csv',"</js>
+ <js>"x-examples:{example:'?s=Bill*,birthDate>2000'}"</js>
+ <js>"},"</js>
+ <js>"{"</js>
+ <js>"in:'query',"</js>
+ <js>"name:'v',"</js>
+ <js>"description:'"</js>
+ <js>"View.\n"</js>
+ <js>"Column names to display."</js>
+ <js>"',"</js>
+ <js>"type:'array',"</js>
+ <js>"collectionFormat:'csv',"</js>
+ <js>"x-examples:{example:'?v=name,birthDate'}"</js>
+ <js>"},"</js>
...
;
}
</p>
<p>
This information could have also been defined in the Swagger JSON for the resource as well.
</p>
<p>
The parameter section contains information about the request body as well for PUT and POST methods, as shown here:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.Parameters.2.png'>
<p>
The definition of this method is shown here:
</p>
<p class='bjava'>
<ja>@RestPost</ja>(
summary=<js>"Add a new pet to the store"</js>,
swagger=<ja>@OpSwagger</ja>(
tags=<js>"pet"</js>
)
)
<jk>public</jk> Ok postPet(
<ja>@Content</ja>
<ja>@Schema</ja>(description=<js>"Pet object to add to the store"</js>)
PetCreate <jv>pet</jv>
) <jk>throws</jk> IdConflict, NotAcceptable, UnsupportedMediaType {
<jf>store</jf>.create(<jv>pet</jv>);
<jk>return</jk> <jsf>OK</jsf>;
}
</p>
<p>
Note that the schema information on the body parameter is automatically detected if not provided.
</p>
</div>
</div><!-- END: 8.15.5 - juneau-rest-server.jrs.Swagger.jrs.SwaggerParameters -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses'>8.15.6 - Responses</a></h4>
<div class='topic'><!-- START: 8.15.6 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses -->
<div class='topic'>
<p>
Under the input parameters are listed the possible responses for the resource:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.Operations.3.png'>
<p>
The <c>200</c> response is determined by the return type on the method, in this case a collection of <c>Pet</c> objects:
</p>
<p class='bjava'>
<ja>@RestGet</ja>(
path=<js>"/pet"</js>,
summary=<js>"All pets in the store"</js>,
...
)
<jk>public</jk> Collection&lt;Pet&gt; getPets() <jk>throws</jk> NotAcceptable {
<jk>return</jk> <jf>store</jf>.getPets();
}
</p>
<p>
Note that additional responses can be specified by throwing exceptions annotated with the <a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>@Response</code></a> annotation such
as this one:
</p>
<p class='bjava'>
<ja>@Response</ja>
<ja>@StatusCode</ja>(406)
<ja>@Schema</ja>(description=<js>"Not Acceptable"</js>)
<jk>public class</jk> NotAcceptable <jk>extends</jk> BasicHttpException {...}
</p>
<p>
Like input parameters, the Swagger for responses can be define in multiple locations such as:
</p>
<ul>
<li><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>@Response</code></a> annotated classes, methods, and parameters.
<li><a href="org/apache/juneau/rest/annotation/Rest.html#swagger--"><code>@Rest(swagger)</code></a> / <a href="org/apache/juneau/rest/annotation/RestOp.html#swagger--"><code>@RestOp(swagger)</code></a> annotations.
</ul>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-rest-server.jrs.HttpParts.jrs.ResponseBeans'>Overview &gt; juneau-rest-server &gt; HTTP Parts &gt; @Response Beans</a>
</ul>
</div>
</div><!-- END: 8.15.6 - juneau-rest-server.jrs.Swagger.jrs.SwaggerResponses -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerModels' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerModels'>8.15.7 - Models</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.15.7 - juneau-rest-server.jrs.Swagger.jrs.SwaggerModels -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/jsonschema/JsonSchemaGenerator.Builder.html#useBeanDefs--"><code>JsonSchemaGenerator.Builder.useBeanDefs()</code></a> setting can be used to reduce the size of your
generated Swagger JSON files by creating model definitions for beans and referencing those definitions through <c>$ref</c> attributes.
</p>
<p>
This setting is disabled by default but can be set on the <a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a> object:
</p>
<p class='bjava'>
<ja>@HookEvent</ja>(<jsf>INIT</jsf>)
<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) {
<jv>builder</jv>.jsonSchemaGenerator().useBeanDefs();
}
</p>
<p>
In the Swagger UI, this causes bean definitions to show up in the Models section at the bottom of the page:
</p>
<h5 class='figure'>Models section</h5>
<img class='bordered w900' src='doc-files/jrs.Swagger.Models.1.png'>
<h5 class='figure'>Models section with Order bean expanded</h5>
<img class='bordered w900' src='doc-files/jrs.Swagger.Models.2.png'>
<p>
In the generated Swagger JSON, embedded schema information for beans will be replaced with references such as the one shown below for the <c>Order</c> bean:
</p>
<p class='bjson'>
{
<jok>"swagger"</jok>: <jov>"2.0"</jov>,
<jok>"paths"</jok>: {
<jok>"/store/order"</jok>: {
<jok>"get"</jok>: {
<jok>"operationId"</jok>: <jov>"getOrders"</jov>,
<jok>"summary"</jok>: <jov>"Petstore orders"</jov>,
<jok>"responses"</jok>: {
<jok>"200"</jok>: {
<jok>"description"</jok>: <jov>"OK"</jov>,
<jok>"schema"</jok>: {
<jok>"description"</jok>: <jov>"java.util.Collection&lt;org.apache.juneau.examples.rest.petstore.Order&gt;"</jov>,
<jok>"type"</jok>: <jov>"array"</jov>,
<jok>"items"</jok>: {
<jok>"$ref"</jok>: <jov>"#/definitions/Order"</jov>
}
},
...
...
...
...
...
},
<jok>"definitions"</jok>: {
<jok>"Order"</jok>: {
<jok>"type"</jok>: <jov>"object"</jov>,
<jok>"properties"</jok>: {
<jok>"id"</jok>: {
<jok>"type"</jok>: <jov>"integer"</jov>,
<jok>"format"</jok>: <jov>"int64"</jov>
},
<jok>"petId": {
<jok>"type"</jok>: <jov>"integer"</jov>,
<jok>"format"</jok>: <jov>"int64"</jov>
},
<jok>"shipDate"</jok>: {
<jok>"type"</jok>: <jov>"string"</jov>
},
<jok>"status"</jok>: {
<jok>"type"</jok>: <jov>"string"</jov>,
<jok>"enum"</jok>: [
<jov>"PLACED"</jov>,
<jov>"APPROVED"</jov>,
<jov>"DELIVERED"</jov>
]
}
},
<jok>"description"</jok>: <jov>"org.apache.juneau.examples.rest.petstore.Order"</jov>,
<jok>"example"</jok>: {
<jok>"id"</jok>: <jov>123</jov>,
<jok>"petId"</jok>: <jov>456</jov>,
<jok>"shipDate"</jok>: <jov>"2012-12-21"</jov>,
<jok>"status"</jok>: <jov>"APPROVED"</jov>
}
},
...
}
</p>
<p>
Note that this does not affect how the information is rendered for that bean in the Swagger UI:
</p>
<img class='bordered w900' src='doc-files/jrs.Swagger.Models.3.png'>
</div>
</div><!-- END: 8.15.7 - juneau-rest-server.jrs.Swagger.jrs.SwaggerModels -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet' id='juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet'>8.15.8 - SwaggerUI.css</a></h4>
<div class='topic'><!-- START: 8.15.8 - juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet -->
<div class='topic'>
<p>
The look-and-feel of the Swagger UI is controlled via a single CSS file: <c>SwaggerUI.css</c>.
</p>
<p>
In the microservice template, this file is located in the <c>files/htdocs/styles</c> directory.
It's a simple straightforward file consisting of less than 350 lines.
This file can be modified to change the look-and-feel of your Swagger UI.
</p>
</div>
</div><!-- END: 8.15.8 - juneau-rest-server.jrs.Swagger.jrs.SwaggerStylesheet -->
</div><!-- END: 8.15 - juneau-rest-server.jrs.Swagger -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ExecutionStatistics' id='juneau-rest-server.jrs.ExecutionStatistics'>8.16 - REST method execution statistics</a><span class='update'>created: 8.1.3, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.16 - juneau-rest-server.jrs.ExecutionStatistics -->
<div class='topic'>
<p>
<a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>-annotated classes get automated timing and error statistic information for all <ja>@RestOp</ja>
and <ja>@RestHook</ja> annotated methods on the class.
</p>
<p>
If you extend from <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> or <a href="org/apache/juneau/rest/servlet/BasicRestObject.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestObject</code></a>, then
the statics are made available through the REST interface via the following method:
</p>
<p class='bjava'>
<ja>@RestGet</ja>(
path=<js>"/stats"</js>,
summary=<js>"Timing statistics"</js>,
description=<js>"Timing statistics for method invocations on this resource."</js>
)
<ja>@Override</ja> <jc>/* BasicRestOperations */</jc>
<jk>public</jk> RestContextStats getStats(RestRequest <jv>req</jv>) {
<jk>return</jk> <jv>req</jv>.getContext().getStats();
}
</p>
<p>
Rendered in a browser, it looks like this:
</p>
<img class='bordered w900' src='doc-files/jrs.ExecutionStatistics.1.png'>
<p>
The default REST configuration provides a link to the stats in the navlinks section of the page:
</p>
<img class='bordered w900' src='doc-files/jrs.ExecutionStatistics.2.png'>
<p>
The exception hash shown is the same hash that is shown in the log file and provides a quick way of locating
the exception in the logs.
</p>
<p>
Programmatic access to the statistics are provided via the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.html#getStats--"><code>getStats()</code></a>
</ul>
</li>
</ul>
</div>
</div><!-- END: 8.16 - juneau-rest-server.jrs.ExecutionStatistics -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation' id='juneau-rest-server.jrs.HtmlDocAnnotation'>8.17 - @HtmlDocConfig</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.17 - juneau-rest-server.jrs.HtmlDocAnnotation -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/html/annotation/HtmlDocConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>@HtmlDocConfig</code></a> annotation is used to customize the HTML
view of POJOs serialized by <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a>.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlDocConfig</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#aside--"><code>aside</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#asideFloat--"><code>asideFloat</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#footer--"><code>footer</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#head--"><code>head</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#header--"><code>header</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#nav--"><code>nav</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#navlinks--"><code>navlinks</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#noResultsMessage--"><code>noResultsMessage</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#nowrap--"><code>nowrap</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#rank--"><code>rank</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#script--"><code>script</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#style--"><code>style</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#stylesheet--"><code>stylesheet</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#template--"><code>template</code></a>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#widgets--"><code>widgets</code></a>
</ul>
</li>
</ul>
<p>
It's used in the following locations:
</p>
<ul>
<li><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a>-annotated classes.
<li><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestOp</code></a>-annotated methods.
</ul>
<p>
For example, the following shows setting the title on a page:
</p>
<p class='bjava'>
<ja>@Rest</ja>
<ja>@HtmlDocConfig</ja>(
title=<js>"My Resource Page"</js>
)
</p>
<p>
The purpose of this annotation is to populate the HTML document view which by default consists of the following
structure:
</p>
<p class='bxml'>
<xt>&lt;html&gt;
&lt;head&gt;
&lt;style <xa>type</xa>=<xs>'text/css'</xs>&gt;
<xv>CSS styles and links to stylesheets</xv>
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header&gt;
<xv>Page header</xv>
&lt;/header&gt;
&lt;nav&gt;
<xv>Navigation links</xv>
&lt;/nav&gt;
&lt;aside&gt;
<xv>Side-bar text</xv>
&lt;/aside&gt;
&lt;article&gt;
<xv>Contents of serialized object</xv>
&lt;/article&gt;
&lt;footer&gt;
<xv>Footer message</xv>
&lt;/footer&gt;
&lt;/body&gt;
&lt;/html&gt;</xt>
</p>
<p>
The outline above is controlled by the <a href="org/apache/juneau/html/HtmlDocTemplate.html" title="interface in org.apache.juneau.html"><code>HtmlDocTemplate</code></a> interface
which can be overridden via the <a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#template--"><code>@HtmlDocConfig(template)</code></a> annotation.
</p>
<p>
The <c>HelloWorldResource</c> class was an example of the <c>@HtmlDocConfig</c> annotation in use:
</p>
<p class='bjava'>
<jd>/**
* Sample REST resource that prints out a simple "Hello world!" message.
*/</jd>
<ja>@Rest</ja>(
path=<js>"/helloWorld"</js>
)
<ja>@HtmlDocConfig</ja>(
navlinks={
<js>"up: request:/.."</js>,
<js>"options: servlet:/?method=OPTIONS"</js>
},
aside={
<js>"&lt;div style='max-width:400px' class='text'&gt;"</js>,
<js>" &lt;p&gt;This page shows a resource that simply response with a 'Hello world!' message&lt;/p&gt;"</js>,
<js>" &lt;p&gt;The POJO serialized is a simple String.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
SVL variables can be used in any of these annotations:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/helloWorld"</js>,
<jc>// Register a config file.</jc>
config=<js>"MyConfig.cfg"</js>
)
<ja>@HtmlDocConfig</ja>(
navlinks={
<js>"up: request:/.."</js>,
<js>"options: servlet:/?method=OPTIONS"</js>,
<jc>// Add a nav link to view the source code for this class.</jc>
<js>"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/$R{servletClassSimple}.java"</js>
},
aside={
<jc>// Localize our messages.</jc>
<js>"&lt;div style='max-width:400px' class='text'&gt;"</js>,
<js>" &lt;p&gt;$L{localizedMessage1}&lt;/p&gt;"</js>,
<js>" &lt;p&gt;$L{localizedMessage2}&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI'>8.17.1 - User Interfaces (UI) vs. Developer Interfaces (DI)</a></h4>
<div class='topic'><!-- START: 8.17.1 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI -->
<div class='topic'>
<p>
An important distinction needs to be made about the HTML representations produced by the REST
API. These should not be considered User Interfaces but rather Developer Interfaces.
</p>
<p>
UIs should hide the end-user from the underlying architecture.
The audience generally consists of non-technical people not interested in how the UI works.
</p>
<p>
DIs, on the other hand, should NOT hide the end-user from the underlying architecture.
Instead, it's a thin veneer over the REST interface with the following goals:
</p>
<ul class='spaced-list'>
<li>Make it easy for the developer to explore and understand the REST API.
<li>Make it easy for the developer to debug the REST API using simple tools (hopefully just a browser).
</ul>
<p>
As a result, the following guidelines are recommended:
</p>
<ul class='spaced-list'>
<li>
Use titles/descriptions/asides to describe why the REST interface exists.
A developer knowing little about it should be able to access it with a browser and quickly
understand what it is and how to use it.
<li>
Don't hide the raw data!
The HTML view should simply be considered an easier-to-read representation of the data normally
rendered in JSON or some other format.
<li>
Limit your use of Javascript!
You can use it sparingly if you want to implement something simple like a pull-down menu to
simplify some debug task but remember that your audience cares more about interacting with your
service programmatically using REST.
Remember that the HTML is just icing on the cake.
<li>
Don't use it to implement a Web 2.0 interface!
If you want a Web 2.0 UI, implement it separately ON TOP OF this REST interface.
The architecture is flexible enough that you could in theory pull in and use jQuery, React,
Angular, or any number of sophisticated Javascript UI frameworks. Resist the urge to do so.
</ul>
</div>
</div><!-- END: 8.17.1 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUIvsDI -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets'>8.17.2 - Widgets</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.17.2 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/widget/Widget.html" title="class in org.apache.juneau.rest.widget"><code>Widget</code></a> class allows you to add arbitrary HTML, CSS, and Javascript
to HTML pages.
<br>They are registered in the following location:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlDocConfig</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#widgets--"><code>widgets</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@RestGet</ja>(...)
<ja>@HtmlDocConfig</ja>(
widgets={
MyWidget.<jk>class</jk>
},
navlinks={
<js>"$W{MyWidget}"</js>
},
aside={
<js>"Check out this widget: $W{MyWidget}"</js>
}
)
</p>
<p>
The <l>Widget</l> class is composed of the following methods:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/rest/widget/Widget.html" title="class in org.apache.juneau.rest.widget"><code>Widget</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/widget/Widget.html#getHtml-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>getHtml(RestRequest,RestResponse)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/widget/Widget.html#getStyle-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>getStyle(RestRequest,RestResponse)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/widget/Widget.html#getScript-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>getScript(RestRequest,RestResponse)</code></a>
</ul>
</ul>
<p>
The HTML content returned by the <a href="org/apache/juneau/rest/widget/Widget.html#getHtml-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>getHtml(RestRequest,RestResponse)</code></a>
method is added wherever the <js>"$W{...}"</js> variable is used.
</p>
<p>
The CSS returned by <a href="org/apache/juneau/rest/widget/Widget.html#getScript-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>getScript(RestRequest,RestResponse)</code></a>
is added to the style section in the page header.
</p>
<p>
The Javascript returned by <a href="org/apache/juneau/rest/widget/Widget.html#getScript-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>getScript(RestRequest,RestResponse)</code></a>
is added to the script section in the page header.
</p>
<p>
The following examples shows how to associate a widget with a REST method and then have it rendered in the links
and aside section of the page.
It shows an example of a widget that renders an image located in the <c>htdocs</c> static files
directory in your classpath (see <a href="org/apache/juneau/rest/annotation/Rest.html#staticFiles--"><code>@Rest(staticFiles)</code></a>):
</p>
<p class='bjava'>
<jk>public class</jk> MyWidget <jk>extends</jk> Widget {
<ja>@Override</ja> <jc>/* Widget */</jc>
<jk>public</jk> String getHtml(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
UriResolver <jv>resolver</jv> = <jv>req</jv>.getUriResolver(); <jc>// API used for resolving URIs.</jc>
<jk>return</jk> <js>"&lt;img class='myimage' onclick='myalert(this)' src='"</js>+<jv>resolver</jv>.resolve(<js>"servlet:/htdocs/myimage.png"</js>)+<js>"'&gt;"</js>;
}
<ja>@Override</ja> <jc>/* Widget */</jc>
<jk>public</jk> String getScript(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
<jk>return</jk> <js>""</js>
+ <js>"\n function myalert(imageElement) {"</js>
+ <js>"\n alert('cool!');"</js>
+ <js>"\n }"</js>;
}
<ja>@Override</ja> <jc>/* Widget */</jc>
<jk>public</jk> String getStyle(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
<jk>return</jk> <js>""</js>
+ <js>"\n .myimage {"</js>
+ <js>"\n border: 10px solid red;"</js>
+ <js>"\n }"</js>;
}
}
</p>
</div>
</div><!-- END: 8.17.2 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlWidgets -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets'>8.17.3 - Predefined Widgets</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.17.3 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/widget/package-summary.html"><code>org.apache.juneau.rest.widget</code></a> package contains predefined reusable widgets.
</p>
<ul class='javatree'>
<li class='jp'><a href="org/apache/juneau/rest/widget/package-summary.html"><code>org.apache.juneau.rest.widget</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/rest/widget/Widget.html" title="class in org.apache.juneau.rest.widget"><code>Widget</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/rest/widget/MenuItemWidget.html" title="class in org.apache.juneau.rest.widget"><code>MenuItemWidget</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/rest/widget/ContentTypeMenuItem.html" title="class in org.apache.juneau.rest.widget"><code>ContentTypeMenuItem</code></a>
<li class='jc'><a href="org/apache/juneau/rest/widget/QueryMenuItem.html" title="class in org.apache.juneau.rest.widget"><code>QueryMenuItem</code></a>
<li class='jc'><a href="org/apache/juneau/rest/widget/ThemeMenuItem.html" title="class in org.apache.juneau.rest.widget"><code>ThemeMenuItem</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/rest/widget/PoweredByJuneau.html" title="class in org.apache.juneau.rest.widget"><code>PoweredByJuneau</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/rest/widget/Tooltip.html" title="class in org.apache.juneau.rest.widget"><code>Tooltip</code></a>
</ul>
</li>
</ul>
<h5 class='topic'>MenuItemWidget</h5>
<p>
<a href="org/apache/juneau/rest/widget/MenuItemWidget.html" title="class in org.apache.juneau.rest.widget"><code>MenuItemWidget</code></a> is an abstract class for rendering menu items with drop-downs.
It defines some simple CSS and Javascript for enabling drop-down menus in the nav section of the page (although
nothing keeps you from using it in an arbitrary location in the page).
</p>
<p>
The script specifies a <c>menuClick(element)</c> function that toggles the visibility of the next sibling of the element.
</p>
<p>
Subclasses implement the following two methods:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/rest/widget/MenuItemWidget.html" title="class in org.apache.juneau.rest.widget"><code>MenuItemWidget</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/widget/MenuItemWidget.html#getLabel-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>getLabel(RestRequest,RestResponse)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/widget/MenuItemWidget.html#getContent-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>getContent(RestRequest,RestResponse)</code></a>
</ul>
</li>
</ul>
<p>
For example, to render a link that brings up a simple dialog in a div tag:
</p>
<p class='bjava'>
<ja>@Override</ja>
<jk>public</jk> String getLabel() {
<jk>return</jk> <js>"my-menu-item"</js>;
};
<ja>@Override</ja>
<jk>public</jk> Div getContent() {
<jk>return</jk> Html5Builder.<jsm>div</jsm>(<js>"Surprise!"</js>).style(<js>"color:red"</js>);
};
</p>
<p>
The HTML content returned by the <a href="org/apache/juneau/rest/widget/MenuItemWidget.html#getHtml-org.apache.juneau.rest.RestRequest-org.apache.juneau.rest.RestResponse-"><code>getHtml(RestRequest,RestResponse)</code></a> method is added where the <js>"$W{...}"</js> is referenced in the page.
</p>
<h5 class='topic'>ContentTypeMenuItem</h5>
<p>
<a href="org/apache/juneau/rest/widget/ContentTypeMenuItem.html" title="class in org.apache.juneau.rest.widget"><code>ContentTypeMenuItem</code></a> is a predefined Widget that returns back a list of hyperlinks for rendering the contents of a page in a variety of content types.
</p>
<p>
The variable it resolves is <js>"$W{ContentTypeMenuItem}"</js>.
</p>
<p>
An example of this widget can be found in the <c>PetStoreResource</c> in the examples that provides a drop-down menu item for rendering all other supported content types in plain text:
</p>
<p class='bjava'>
<ja>@RestGet</ja>(path=<js>"/"</js>)
<ja>@HtmlDocConfig</ja>(
widgets={
ContentTypeMenuItem.<jk>class</jk>,
},
navlinks={
<js>"up: ..."</js>,
<js>"options: ..."</js>,
<js>"$W{QueryMenuItem}"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"$W{ThemeMenuItem}"</js>,
<js>"source: ..."</js>
}
)
<jk>public</jk> Collection&lt;Pet&gt; getPets() {
</p>
<p>
It renders the following popup-box:
</p>
<img class='bordered w800' src='doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.1.png'>
<h5 class='topic'>QueryMenuItem</h5>
<p>
<a href="org/apache/juneau/rest/widget/QueryMenuItem.html" title="class in org.apache.juneau.rest.widget"><code>QueryMenuItem</code></a> is a predefined Widget that returns a menu-item drop-down form for entering search/view/sort arguments.
</p>
<p>
The variable it resolves is <js>"$W{QueryMenuItem}"</js>.
</p>
<p>
This widget is designed to be used in conjunction with the <a href="org/apache/juneau/rest/converter/Queryable.html" title="class in org.apache.juneau.rest.converter"><code>Queryable</code></a> converter, although implementations
can process the query parameters themselves if they wish to do so by using the <a href="org/apache/juneau/rest/httppart/RequestQueryParams.html#getSearchArgs--"><code>RequestQueryParams.getSearchArgs()</code></a>
method to retrieve the arguments and process the data themselves.
</p>
<p>
An example of this widget can be found in the <c>PetStoreResource</c> in the examples that provides
search/view/sort capabilities against the collection of POJOs:
<p class='bjava'>
<ja>@RestGet</ja>(
path=<js>"/"</js>,
converters=Queryable.<jk>class</jk>
)
<ja>@HtmlDocConfig</ja>(
widgets={
QueryMenuItem.<jk>class</jk>,
},
navlinks={
<js>"up: ..."</js>,
<js>"options: ..."</js>,
<js>"$W{QueryMenuItem}"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"$W{ThemeMenuItem}"</js>,
<js>"source: ..."</js>
}
)
<jk>public</jk> Collection&lt;Pet&gt; getPets() {
</p>
<p>
It renders the following popup-box:
</p>
<img class='bordered w800' src='doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.2.png'>
<p>
Tooltips are provided by hovering over the field names.
</p>
<img class='bordered w800' src='doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.3.png'>
<p>
When submitted, the form submits a GET request against the current URI with special GET search API query parameters.
(e.g. <js>"?s=column1=Foo*&amp;v=column1,column2&amp;o=column1,column2-&amp;p=100&amp;l=100"</js>).
The <a href="org/apache/juneau/rest/converter/Queryable.html" title="class in org.apache.juneau.rest.converter"><code>Queryable</code></a> class knows how to perform these filters against collections of POJOs.
</p>
<h5 class='topic'>ThemeMenuItem</h5>
<p>
<a href="org/apache/juneau/rest/widget/ThemeMenuItem.html" title="class in org.apache.juneau.rest.widget"><code>ThemeMenuItem</code></a> is a predefined Widget that returns back a list of hyperlinks for rendering the contents of a page in the various default styles.
</p>
<p>
The variable it resolves is <js>"$W{ThemeMenuItem}"</js>.
</p>
<p>
An example of this widget can be found in the <c>PetStoreResource</c> in the examples that provides
a drop-down menu item for rendering all other supported content types in plain text:
</p>
<p class='bjava'>
<ja>@RestGet</ja>(path=<js>"/"</js>)
<ja>@HtmlDocConfig</ja>(
widgets={
ThemeMenuItem.<jk>class</jk>,
},
navlinks={
<js>"up: ..."</js>,
<js>"options: ..."</js>,
<js>"$W{QueryMenuItem}"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"$W{ThemeMenuItem}"</js>,
<js>"source: ..."</js>
}
)
<jk>public</jk> Collection&lt;Pet&gt; getPets() {
</p>
<h5 class='topic'>PoweredByJuneau</h5>
<p>
<a href="org/apache/juneau/rest/widget/PoweredByJuneau.html" title="class in org.apache.juneau.rest.widget"><code>PoweredByJuneau</code></a> is a predefined Widget that places a powered-by-Juneau message on a page.
</p>
<p>
The variable it resolves is <js>"$W{PoweredByJuneau}"</js>.
</p>
<p>
It produces a simple Apache Juneau icon floating on the right.
Typically it's used in the footer of the page, as shown below in the <c>AddressBookResource</c> from the examples:
</p>
<p class='bjava'>
<ja>@Rest</ja>(path=<js>"/addressBook"</js>)
<ja>@HtmlDocConfig</ja>(
widgets={
PoweredByJuneau.<jk>class</jk>
},
footer=<js>"$W{PoweredByJuneau}"</js>
)
</p>
<p>
It renders the following image:
</p>
<img class='bordered' src='doc-files/jrs.HtmlDocAnnotation.PredefinedWidgets.4.png'>
<h5 class='topic'>Tooltip</h5>
<p>
<a href="org/apache/juneau/rest/widget/Tooltip.html" title="class in org.apache.juneau.rest.widget"><code>Tooltip</code></a> is a predefined template for adding tooltips to HTML5 bean constructs, typically in menu item widgets.
</p>
<p>
The following examples shows how tooltips can be added to a menu item widget.
</p>
<p class='bjava'>
<jk>public class</jk> MyFormMenuItem <jk>extends</jk> MenuItemWidget {
<ja>@Override</ja>
<jk>public</jk> String getLabel(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
<jk>return</jk> <js>"myform"</js>;
}
<ja>@Override</ja>
<jk>public</jk> Object getContent(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
<jk>return</jk> div(
<jsm>form</jsm>().id(<js>"form"</js>).action(<js>"servlet:/form"</js>).method(<jsf>POST</jsf>).children(
<jsm>table</jsm>(
<jsm>tr</jsm>(
<jsm>th</jsm>(<js>"Field 1:"</js>),
<jsm>td</jsm>(<jsm>input</jsm>().name(<js>"field1"</js>).type(<js>"text"</js>)),
<jsm>td</jsm>(<jk>new</jk> Tooltip(<js>"(?)"</js>, <js>"This is field #1!"</js>, br(), <js>"(e.g. '"</js>, code(<js>"Foo"</js>), <js>"')"</js>))
),
<jsm>tr</jsm>(
<jsm>th</jsm>(<js>"Field 2:"</js>),
<jsm>td</jsm>(<jsm>input</jsm>().name(<js>"field2"</js>).type(<js>"text"</js>)),
<jsm>td</jsm>(<jk>new</jk> Tooltip(<js>"(?)"</js>, <js>"This is field #2!"</js>, br(), <js>"(e.g. '"</js>, code(<js>"Bar"</js>), <js>"')"</js>))
)
)
)
);
}
}
</p>
</div>
</div><!-- END: 8.17.3 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlPredefinedWidgets -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization'>8.17.4 - UI Customization</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.17.4 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization -->
<div class='topic'>
<p>
The HTML views of POJOs can somewhat be considered a rudimentary User Interface.
In reality, a better term for them would be a Developer Interface as they're meant to be used
primarily by developers and not end users.
Despite that distinction, it is possible to 'brand' the HTML page to whatever you desire.
</p>
<p>
The sample root page below includes some default branding for Juneau and Apache:
</p>
<p class='bcode'>
http://localhost:10000/helloWorld
</p>
<img class='bordered w800' src='doc-files/jrs.UiCustomization.1.png'>
<p>
The Juneau REST framework does not provide specific branding support (i.e. there is no concept of a brand icon).
Instead, it just uses the existing open-ended API for defining branding via annotations on your REST classes.
</p>
<p class='bjava'>
<ja>@Rest</ja>(
<jc>// Optional external configuration file.</jc>
config=<js>"$S{juneau.configFile}"</js>,
)
<ja>@HtmlDocConfig</ja>(
<jc>// Default stylesheet to use for the page.
// Can be overridden from external config file.
// Default is DevOps look-and-feel (aka Depression look-and-feel).</jc>
stylesheet=<js>"$C{REST/theme,servlet:/htdocs/themes/devops.css}"</js>,
<jc>// Default page header contents.</jc>
header={
<js>"&lt;h1&gt;$RS{title}&lt;/h1&gt;"</js>, <jc>// Use @Rest(title)</jc>
<js>"&lt;h2&gt;$RS{operationSummary,description}&lt;/h2&gt;"</js>, <jc>// Use either @RestOp(summary) or @Rest(description)</jc>
<js>"$C{REST/header}"</js> <jc>// Extra header HTML defined in external config file.</jc>
},
<jc>// Default contents to add to the &lt;head&gt; section of the HTML page.
// Use it to add a favicon link to the page.</jc>
head={
<js>"&lt;link rel='icon' href='$U{$C{REST/favicon}}'/&gt;"</js>
},
<jc>// Basic page navigation links.</jc>
navlinks={
<js>"up: request:/.."</js>
},
<jc>// No default page footer contents.
// Can be overridden from external config file.</jc>
footer=<js>"$C{REST/footer}"</js>
)
<jk>public interface</jk> BasicUniversalConfig {}
</p>
<p class='bjava'>
<ja>@Rest</ja>(...)
<ja>@HtmlDocConfig</ja>(
widgets={
ContentTypeMenuItem.<jk>class</jk>,
ThemeMenuItem.<jk>class</jk>
},
navlinks={
<js>"options: ?method=OPTIONS"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"$W{ThemeMenuItem}"</js>,
<js>"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/$R{servletClassSimple}.java"</js>
},
aside={
<js>"&lt;div style='max-width:400px' class='text'&gt;"</js>,
<js>" &lt;p&gt;This is an example of a 'router' page that serves as a jumping-off point to child resources.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Resources can be nested arbitrarily deep through router pages.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Note the &lt;span class='link'&gt;options&lt;/span&gt; link provided that lets you see the generated swagger doc for this page.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Also note the &lt;span class='link'&gt;sources&lt;/span&gt; link on these pages to view the source code for the page.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;All content on pages in the UI are serialized POJOs. In this case, it's a serialized array of beans with 2 properties, 'name' and 'description'.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Other features (such as this aside) are added through annotations.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
},
asideFloat=<js>"RIGHT"</js>
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicRestServletGroup <jk>implements</jk> BasicUniversalJenaConfig {...}
</p>
<p>
The default annotation values use <a href="org/apache/juneau/config/vars/ConfigVar.html" title="class in org.apache.juneau.config.vars"><code>$C</code></a> variables to pull in values from an optional
external configuration file such as the one shown below:
</p>
<p class='bini'>
<cc>#=======================================================================================================================
# REST settings
#=======================================================================================================================</cc>
<cs>[REST]</cs>
<ck>staticFiles</ck> = <cv>htdocs:files/htdocs</cv>
<cc># Stylesheet to use for HTML views.</cc>
<ck>theme</ck> = <cv>servlet:/htdocs/themes/devops.css</cv>
<ck>headerIcon</ck> = <cv>servlet:/htdocs/images/juneau.png</cv>
<ck>headerLink</ck> = <cv>http://juneau.apache.org</cv>
<ck>footerIcon</ck> = <cv>servlet:/htdocs/images/asf.png</cv>
<ck>footerLink</ck> = <cv>http://www.apache.org</cv>
<ck>favicon</ck> = <cv>$C{REST/headerIcon}</cv>
<ck>header</ck> =
<cv>&lt;a href='$U{$C{REST/headerLink}}'&gt;</cv>
<cv>&lt;img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/&gt;</cv>
<cv>&lt;/a&gt;</cv>
<ck>footer</ck> =
<cv>&lt;a href='$U{$C{REST/footerLink}}'&gt;</cv>
<cv>&lt;img src='$U{$C{REST/footerIcon}}' style='float:right;padding-right:20px;height:32px'/&gt;</cv>
<cv>&lt;/a&gt;</cv>
</p>
<p>
The take-away here is that the "User Interface" is open-ended, lets you define pretty much anything you want through arbitrary HTML,
and allows you either hardcode your interface inside annotations or pull them in via string variables from other places such as
external config files.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-microservice-jetty.jmj.UiCustomization'>Overview &gt; juneau-microservice-jetty &gt; UI Customization</a>
</ul>
</div>
</div><!-- END: 8.17.4 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlUiCustomization -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets' id='juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets'>8.17.5 - Stylesheets</a><span class='update'>updated: 8.1.0,<b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 8.17.5 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets -->
<div class='topic'>
<p>
The sample root page renders in the default "devops" look-and-feel:
</p>
<p class='bcode'>
http://localhost:10000
</p>
<img class='bordered w800' src='doc-files/jrs.Stylesheets.0.png'>
<p>
The sample root page provides a dropdown widget to try out the other default look-and-feels:
</p>
<img class='bordered' src='doc-files/jrs.Stylesheets.1.png'/>
<p>
For example, the "light" look-and-feel:
</p>
<p class='bcode'>
http://localhost:10000/?stylesheet=styles%2Flight.css
</p>
<img class='bordered w800' src='doc-files/jrs.Stylesheets.2.png'>
<p>
And the "dark" look-and-feel:
</p>
<p class='bcode'>
http://localhost:10000/?stylesheet=styles%2Fdark.css
</p>
<img class='bordered w800' src='doc-files/jrs.Stylesheets.3.png'>
<p>
The stylesheet URL is controlled by the <a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#stylesheet--"><code>@HtmlDocConfig(stylesheet)</code></a> annotation.
The <a href="org/apache/juneau/rest/config/BasicUniversalConfig.html" title="interface in org.apache.juneau.rest.config"><code>BasicUniversalConfig</code></a> interface defines the stylesheet served up as a static file:
<p class='bjava'>
<ja>@HtmlDocConfig</ja>(
stylesheet=<js>"$C{REST/theme,servlet:/htdocs/themes/devops.css}"</js>
)
<jk>public interface</jk> BasicUniversalConfig {...}
</p>
<p>
The <js>"$C{REST/theme,servlet:/htdocs/themes/devops.css}"</js> variable says to use the URI defined
in your servlet's config file, if there is one, and to default to serving up the file
<c>htdocs/themes/devops.css</c> which is in the resource folder of the <c>juneau-rest-server</c> module.
</p>
<p>
To provide your own stylesheet, simply override the stylesheet attribute and point to a different
file:
</p>
<p class='bjava'>
<ja>@HtmlDocConfig</ja>(
stylesheet=<js>"servlet:/htdocs/themes/my-style.css"</js>
)
<jk>public class</jk> MyResourceBaseClass <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
You can try out different stylesheets by passing in a <c>stylesheet</c> attribute in the request
URL.
The example above show this in use.
</p>
<p>
In case you're curious about how the menu item works, it's defined via a widget:
</p>
<p class='bjava'>
<ja>@Rest</ja>(...)
<ja>@HtmlDocConfig</ja>(
widgets={
PoweredByApache.<jk>class</jk>,
ContentTypeMenuItem.<jk>class</jk>,
StyleMenuItem.<jk>class</jk>
},
navlinks={
<js>"options: ?method=OPTIONS"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"$W{StyleMenuItem}"</js>,
<js>"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/$R{servletClassSimple}.java"</js>
}
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicRestServletGroup <jk>implements</jk> BasicUniversalConfig {...}
</p>
<p>
The <c>StyleMenuItem</c> is a widget that extends from <a href="org/apache/juneau/rest/widget/MenuItemWidget.html" title="class in org.apache.juneau.rest.widget"><code>MenuItemWidget</code></a>, a
specialized widget for creating pop-up menus.
In the case of <l>StyleMenuItem</l>, it's simply returning a list of links wrapped in a div tag:
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
<jk>public class</jk> StyleMenuItem <jk>extends</jk> MenuItemWidget {
<jk>private static final</jk> String[] <jsf>BUILT_IN_STYLES</jsf> = {<js>"devops"</js>, <js>"light"</js>, <js>"original"</js>, <js>"dark"</js>};
<ja>@Override</ja> <jc>/* Widget */</jc>
<jk>public</jk> String getLabel(RestRequest <jv>req</jv>) {
<jk>return</jk> <js>"styles"</js>;
}
<ja>@Override</ja> <jc>/* MenuItemWidget */</jc>
<jk>public</jk> Div getContent(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
Div <jv>div</jv> = <jsm>div</jsm>();
<jk>for</jk> (String <jv>style</jv> : <jsf>BUILT_IN_STYLES</jsf>) {
java.net.URI <jk>uri</jk> = <jv>req</jv>.getUri(<jk>true</jk>, <jk>new</jk> AMap&lt;String,String&gt;().append(<js>"stylesheet"</js>, <js>"styles/"</js>+s+<js>".css"</js>));
<jv>div</jv>.children(<jsm>a</jsm>(<jv>uri</jv>, <jv>style</jv>), <jsm>br</jsm>());
}
<jk>return</jk> <jv>div</jv>;
}
}
</p>
</div>
</div><!-- END: 8.17.5 - juneau-rest-server.jrs.HtmlDocAnnotation.jrs.HtmlStylesheets -->
</div><!-- END: 8.17 - juneau-rest-server.jrs.HtmlDocAnnotation -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.LoggingAndDebugging' id='juneau-rest-server.jrs.LoggingAndDebugging'>8.18 - Logging / Debugging</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.18 - juneau-rest-server.jrs.LoggingAndDebugging -->
<div class='topic'>
<p>
The REST APIs provides supports enabling logging of HTTP requests and responses through
the following annotations:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#debug--"><code>debug</code></a>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#debugOn--"><code>debugOn</code></a>
</ul>
</li>
<li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/RestOp.html#debug--"><code>debug</code></a>
</ul>
</li>
</ul>
<p>
Debug mode enables the following:
</p>
<ul class='spaced-list'>
<li>
HTTP request/response bodies are cached in memory for logging purposes.
<li>
HTTP requests/responses are logged to the registered <code>org.apache.juneau.rest.logging.RestLogger</code>.
</ul>
<p>
The possible annotation values are:
</p>
<ul>
<li><js>"true"</js> - Debug is enabled for all requests.
<li><js>"false"</js> - Debug is disabled for all requests.
<li><js>"conditional"</js> - Debug is enabled only for requests that have a <c class='snippet'>Debug: true</c> header.
</ul>
<h5 class='figure'>Example</h5>
<p class='bjava'>
<jc>// Enable debugging on all op calls on this resource</jc>
<ja>@Rest</ja>(debug=<js>"true"</js>)
<jk>public class</jk> MyResource {...}
</p>
<p>
These annotations support SVL variables, so it's possible to define them as a system property for example.
</p>
<p class='bjava'>
<jc>// Enable via system property 'MyResource.debug'</jc>
<ja>@Rest</ja>(debug=<js>"$S{MyResource.debug}"</js>)
<jk>public class</jk> MyResource {...}
</p>
<p>
The <a href="org/apache/juneau/rest/annotation/Rest.html#debugOn--"><code>@Rest(debugOn)</code></a> annotation can also be used
to enable debugging. It takes a comma-delimited list of key-value pairs, the keys
being class or method names, and the values being one of <c>true|false|conditional</c>.
</p>
<p class='bjava'>
<jc>// Turn on debug per-request on the class and always on the doX() method</jc>
<ja>@Rest</ja>(debugOn=<js>"MyResource=conditional,MyResource.doX=true"</js>)
<jk>public class</jk> MyResource {...}
</p>
<p>
The primary advantage of <a href="org/apache/juneau/rest/annotation/Rest.html#debugOn--"><code>@Rest(debugOn)</code></a> is that
you can control debugging externally such as through a system property or environment variable:
</p>
<p class='bjava'>
<jc>// Turn on debug per-request on the class and always on the doX() method</jc>
<ja>@Rest</ja>(debugOn=<js>"$E{DEBUG}"</js>)
<jk>public class</jk> MyResource {...}
</p>
<p>
Debugging can also be enabled programmatically with the use of the following APIs:
</p>
<ul class='javatree'>
<li class='jic'><a href="org/apache/juneau/rest/debug/DebugEnablement.html" title="interface in org.apache.juneau.rest.debug"><code>DebugEnablement</code></a>
<li class='jc'><a href="org/apache/juneau/rest/debug/BasicDebugEnablement.html" title="class in org.apache.juneau.rest.debug"><code>BasicDebugEnablement</code></a>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createDebugEnablement-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-"><code>createDebugEnablement(BeanStore,Supplier)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#debugEnablement--"><code>debugEnablement()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#debugEnablement-java.util.function.Consumer-"><code>debugEnablement(Consumer)</code></a>
</ul>
</li>
</ul>
<p>
HTTP calls can be logged with the following levels of granularity:
</p>
<ul class='javatree'>
<li class='je'><code>org.apache.juneau.rest.logging.RestLoggingDetail</code>
<ul class='javatreec'>
<li class='jf'><code>STATUS_LINE</code>
<li class='jf'><code>HEADER</code>
<li class='jf'><code>ENTITY</code>
</ul>
</li>
</ul>
<p>
The following examples show the output format for each detail type:
</p>
<h5 class='figure'>STATUS_LINE</h5>
<p class='bcode'>
WARNING: [500] HTTP POST /foo?foo=bar
</p>
<h5 class='figure'>HEADER</h5>
<p class='bcode'>
WARNING:
=== HTTP Call (incoming) ===================================================
[500] HTTP POST /foo?foo=bar
Request length: 3 bytes
Response code: 500
Response length: 3 bytes
Exec time: 20ms
---Request Headers---
Foo: bar
---Response Headers---
Foo: bar
Content-Type: text/plain
=== END ===================================================================
</p>
<h5 class='figure'>ENTITY</h5>
<p class='bcode'>
WARNING:
=== HTTP Call (incoming) ===================================================
[500] HTTP POST /foo?foo=bar
Request length: 3 bytes
Response code: 500
Response length: 3 bytes
Exec time: 20ms
---Request Headers---
Foo: bar
---Response Headers---
Foo: bar
Content-Type: text/plain
---Request Content UTF-8---
Foo
---Request Content Hex---
46 6F 6F
---Response Content UTF-8---
Foo
---Response Content Hex---
46 6F 6F
=== END ===================================================================
</p>
<p>
The interface responsible for generating the log entries is <code>org.apache.juneau.rest.logging.RestLogger</code>
and the default is <code>org.apache.juneau.rest.logging.BasicRestLogger</code> which produces the output above. It
can be changed through any of the following:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/rest/annotation/Rest.html#callLogger--"><code>callLogger()</code></a>
</ul>
</li>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createCallLogger--"><code>createCallLogger()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#callLogger--"><code>callLogger()</code></a>
</ul>
</li>
</ul>
<p>
The call logger uses logging rules to map requests to logging detail levels.
By default, these are the logging rules:
</p>
<p class='bjava'>
RestLogger
.<jsm>create</jsm>()
.beanStore(<jv>beanStore</jv>) <jc>// Allow injected beans in constructor</jc>
.normalRules( <jc>// Rules when debugging is not enabled</jc>
RestLoggerRule.<jsm>create</jsm>() <jc>// Log 500+ errors with status-line and header information</jc>
.statusFilter(<jv>x</jv> -> <jv>x</jv> >= 500)
.level(<jsf>SEVERE</jsf>)
.requestDetail(<jsf>HEADER</jsf>)
.responseDetail(<jsf>HEADER</jsf>)
.build(),
RestLoggerRule.<jsm>create</jsm>() <jc>// Log 400-500 errors with just status-line information</jc>
.statusFilter(<jv>x</jv> -> <jv>x</jv> >= 400)
.level(<jsf>WARNING</jsf>)
.requestDetail(<jsf>STATUS_LINE</jsf>)
.responseDetail(<jsf>STATUS_LINE</jsf>)
.build()
)
.debugRules( <jc>// Rules when debugging is enabled</jc>
RestLoggerRule.<jsm>create</jsm>() <jc>// Log everything with full details</jc>
.level(<jsf>SEVERE</jsf>)
.requestDetail(<jsf>ENTITY</jsf>)
.responseDetail(<jsf>ENTITY</jsf>)
.build()
);
</p>
<p>
Thrown exceptions get logged with a stack trace hash and a counter like below:
</p>
<p class='bcode'>
WARNING: [500,9b85cc96.13] HTTP POST /foo?foo=bar
</p>
<p>
Stack trace hashes are controlled by the <a href="org/apache/juneau/rest/stats/ThrownStore.html" title="class in org.apache.juneau.rest.stats"><code>ThrownStore</code></a> bean which is configured
via the following:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jmp'><a href="org/apache/juneau/rest/RestContext.Builder.html#createThrownStore-org.apache.juneau.cp.BeanStore-java.util.function.Supplier-org.apache.juneau.rest.RestContext-"><code>createThrownStore(BeanStore,Supplier)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#thrownStore--"><code>thrownStore()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#thrownStore-java.util.function.Consumer-"><code>thrownStore(Consumer)</code></a>
</ul>
</li>
</ul>
<ul class='notes'>
<li class='note'>The <code>org.apache.juneau.rest.logging.BasicTestRestLogger</code> class is useful for testing and
allows you to suppress logging when testing error conditions by passing in a <c>noTrace=true</c> query parameter
or <c>No-Trace: true</c> header on requests.
<li class='note'><a href="org/apache/juneau/rest/debug/DebugEnablement.html" title="interface in org.apache.juneau.rest.debug"><code>DebugEnablement</code></a>, <code>org.apache.juneau.rest.logging.RestLogger</code>, and
<a href="org/apache/juneau/rest/stats/ThrownStore.html" title="class in org.apache.juneau.rest.stats"><code>ThrownStore</code></a> can all be defined globally as Spring beans in a Spring Boot environment.
</ul>
</div>
</div><!-- END: 8.18 - juneau-rest-server.jrs.LoggingAndDebugging -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HttpStatusCodes' id='juneau-rest-server.jrs.HttpStatusCodes'>8.19 - HTTP Status Codes</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.19 - juneau-rest-server.jrs.HttpStatusCodes -->
<div class='topic'>
<p>
By default, a 200 (OK) status is automatically set as the HTTP status when a Java method executes
successfully.
</p>
<p>
Other status codes can be generated by throwing a <a href="org/apache/juneau/http/response/BasicHttpException.html" title="class in org.apache.juneau.http.response"><code>BasicHttpException</code></a> with a
specific HTTP status code, or calling <code>HttpServletResponse.setStatus(int)</code>.
</p>
<p>
Non-OK (200) status codes are automatically triggered by the following conditions:
</p>
<table class='styled w800'>
<tr>
<th><l>Code</l></th>
<th><l>Description</l></th>
<th><l>When triggered</l></th>
</tr>
<tr>
<td><l>401</l></td>
<td>Unauthorized</td>
<td>A <a href="org/apache/juneau/rest/guard/RestGuard.html" title="class in org.apache.juneau.rest.guard"><code>guard</code></a> prevented the method from being executed</td>
</tr>
<tr>
<td><l>404</l></td>
<td>Not Found</td>
<td>No matching path patterns were found on any method</td>
</tr>
<tr>
<td><l>405</l></td>
<td>Method Not Implemented</td>
<td>A path pattern matched but no Java methods were found for the HTTP method</td>
</tr>
<tr>
<td><l>406</l></td>
<td>Not Acceptable</td>
<td>
A path pattern matched but no Java methods were found with a matching serializer for the
<l>Accept</l> on the request
</td>
</tr>
<tr>
<td><l>412</l></td>
<td>Precondition Failed</td>
<td>
A path pattern matched but no Java methods were found that were not rejected by
<code>matchers</code>
</td>
</tr>
<tr>
<td><l>415</l></td>
<td>Unsupported Media Type</td>
<td>
A path pattern matched but no Java methods were found with a matching parser for the
<l>Content-Type</l> on the request
</td>
</tr>
<tr>
<td><l>500</l></td>
<td>Internal Server Error</td>
<td>The Java method threw an exception other than <a href="org/apache/juneau/http/response/BasicHttpException.html" title="class in org.apache.juneau.http.response"><code>BasicHttpException</code></a></td>
</tr>
</table>
</div>
</div><!-- END: 8.19 - juneau-rest-server.jrs.HttpStatusCodes -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.BuiltInParameters' id='juneau-rest-server.jrs.BuiltInParameters'>8.20 - Built-in Parameters</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.20 - juneau-rest-server.jrs.BuiltInParameters -->
<div class='topic'>
<p>
The following URL parameters have special meaning and can be passed in through the URL of the request:
</p>
<table class='styled w800'>
<tr>
<th><l>GET Parameter</l></th>
<th><l>Description</l></th>
</tr>
<tr>
<td class='code'>&amp;plainText=true</td>
<td>
Response will always be <l>Content-Type: text/plain</l> and the returned text will be human-readable
(<a href="org/apache/juneau/serializer/WriterSerializer.Builder.html#useWhitespace--"><code>WriterSerializer.Builder.useWhitespace()</code></a> enabled).
<br>Useful for debugging.
</td>
</tr>
<tr>
<td class='code'>&amp;debug=true</td>
<td>
Enable debug mode for request.
</td>
</tr>
<tr>
<td class='code'>&amp;noTrace=true</td>
<td>
If an error occurs, don't log the stack trace to the log file.
<br>Useful for automated JUnit testcases testing error states to prevent the log file from filling
up with useless stack traces.
</td>
</tr>
<tr>
<td class='code'>&amp;method=X</td>
<td>
Overload the HTTP method as a GET parameter (e.g <l>"POST"</l>).
<br>Must be enabled via <a href="org/apache/juneau/rest/annotation/Rest.html#allowedMethodParams--"><code>@Rest(allowedMethodParams)</code></a> setting.
</td>
</tr>
<tr>
<td class='code'>&amp;Header-Name=headerValue</td>
<td>
Specify a header value as a GET parameter.
<br>Must be enabled via <a href="org/apache/juneau/rest/annotation/Rest.html#allowedHeaderParams--"><code>@Rest(allowedHeaderParams)</code></a> setting.
</td>
</tr>
<tr>
<td class='code'>&amp;body=X</td>
<td>
Pass in the HTTP body content on PUT and POST methods as a UON-encoded GET parameter.
<br>Can be disabled via <a href="org/apache/juneau/rest/annotation/Rest.html#disableContentParam--"><code>@Rest(disableContentParam)</code></a> setting.
</td>
</tr>
<tr>
<td class='code'>&amp;x-response-headers=X</td>
<td>
Pass-through headers to the response.
<br>Must be a UON-encoded map of key-value pairs.
</td>
</tr>
</table>
</div>
</div><!-- END: 8.20 - juneau-rest-server.jrs.BuiltInParameters -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.UsingWithOsgi' id='juneau-rest-server.jrs.UsingWithOsgi'>8.21 - Using with OSGi</a></h3>
<div class='topic'><!-- START: 8.21 - juneau-rest-server.jrs.UsingWithOsgi -->
<div class='topic'>
<p>
Since REST servlets are basically just <l>HttpServlets</l>, incorporating them into an OSGi environment
is pretty straightforward.
</p>
<p>
The following code shows how to register your REST servlets in an OSGi <l>Activator</l>:
</p>
<p class='bjava'>
<jk>package</jk> org.apache.juneau.examples.rest;
<jk>import</jk> org.osgi.framework.*;
<jk>import</jk> org.osgi.service.http.*;
<jk>import</jk> org.osgi.util.tracker.*;
<jk>import</jk> org.apache.juneau.rest.samples.*;
<jd>/**
* Activator class used when running samples as a bundle in an OSGi environment.
*/</jd>
<jk>public class</jk> Activator <jk>implements</jk> BundleActivator, ServiceTrackerCustomizer {
<jk>private</jk> ServiceTracker <jf>httpServiceTracker</jf>;
<jk>private</jk> BundleContext <jf>context</jf>;
<ja>@Override</ja> <jc>/* BundleActivator */</jc>
<jk>public void</jk> start(BundleContext <jv>context</jv>) <jk>throws</jk> Exception {
<jk>this</jk>.<jf>context</jf> = <jv>context</jv>;
<jf>httpServiceTracker</jf> = <jk>new</jk> ServiceTracker(<jv>context</jv>, HttpService.<jk>class</jk>.getName(), <jk>this</jk>);
<jf>httpServiceTracker</jf>.open();
}
<ja>@Override</ja> <jc>/* BundleActivator */</jc>
<jk>public void</jk> stop(BundleContext <jv>context</jv>) <jk>throws</jk> Exception {
<jf>httpServiceTracker</jf>.close();
}
<ja>@Override</ja> <jc>/* ServiceTrackerCustomizer */</jc>
<jk>public</jk> Object addingService(ServiceReference <jv>reference</jv>) {
Object <jv>service</jv> = <jf>context</jf>.getService(<jv>reference</jv>);
<jk>if</jk> (service <jk>instanceof</jk> HttpService) {
HttpService <jv>service</jv> = (HttpService)<jv>service</jv>;
<jk>try</jk> {
<jv>service</jv>.registerServlet(<js>"/sample"</js>, <jk>new</jk> MyRestServlet(), <jk>null</jk>, <jk>null</jk>);
} <jk>catch</jk> (Exception <jv>e</jv>) {
<jk>throw new</jk> RuntimeException(<jv>e</jv>);
}
}
<jk>return</jk> <jv>service</jv>;
}
<ja>@Override</ja> <jc>/* ServiceTrackerCustomizer */</jc>
<jk>public void</jk> modifiedService(ServiceReference <jv>reference</jv>, Object <jv>service</jv>) {
}
<ja>@Override</ja> <jc>/* ServiceTrackerCustomizer */</jc>
<jk>public void</jk> removedService(ServiceReference <jv>reference</jv>, Object <jv>service</jv>) {
}
}
</p>
</div>
</div><!-- END: 8.21 - juneau-rest-server.jrs.UsingWithOsgi -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestContext' id='juneau-rest-server.jrs.RestContext'>8.22 - RestContext</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.22 - juneau-rest-server.jrs.RestContext -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a> object is the workhorse class for all of the configuration
of a single REST resource class. It's by-far the most important class in the REST API.
</p>
<p>
Every class annotated with <l>@Rest</l> ends up with an instance of this object. The object itself is read-only and unchangeable and is
initialized with all of the various annotations pulled from the class and methods. All functionality available through annotations
have programmatic equivalents through the builder of this class.
</p>
<p>
The <a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a> class extends <a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
allowing you to programmatically set any properties defined on that builder class.
It also implements <code>ServletConfig</code>
</p>
<p>
To access this object, simply pass it in as a constructor argument or in an INIT hook:
</p>
<p class='bjava'>
<jc>// Option #1 - Pass in through constructor.</jc>
<jk>public</jk> MyResource(RestContext.Builder <jv>builder</jv>) {
<jv>builder</jv>
.beanContext(<jv>x</jv> -&gt; <jv>x</jv>.swaps(TemporalCalendarSwap.Rfc1123DateTime.<jk>class</jk>))
.debugEnablement(<jsf>CONDITIONAL</jsf>);
}
<jc>// Option #2 - Use an INIT hook.</jc>
<ja>@RestHook</ja>(<jsf>INIT</jsf>)
<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
<jv>builder</jv>
.beanContext(<jv>x</jv> -&gt; <jv>x</jv>.swaps(TemporalCalendarSwap.Rfc1123DateTime.<jk>class</jk>))
.debugEnablement(<jsf>CONDITIONAL</jsf>);
}
</p>
<p>
This class is vast. Combined with <a href="org/apache/juneau/rest/RestOpContext.html" title="class in org.apache.juneau.rest"><code>RestOpContext</code></a> (which is the equivalent per-method context), these classes
define the entire configuration and workflow of the REST API.
</p>
<p>
There are multiple ways to programmatically alter how RestContext behaves. The most straightforward are the following
builder methods which are direct equivalents to values defined on the <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a> annotation:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#allowedHeaderParams-java.lang.String-"><code>allowedHeaderParams</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#allowedMethodHeaders-java.lang.String-"><code>allowedMethodHeaders</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#allowedMethodParams-java.lang.String-"><code>allowedMethodParams</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#clientVersionHeader-java.lang.String-"><code>clientVersionHeader</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#child-java.lang.String-java.lang.Object-"><code>child</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#children-java.lang.Object...-"><code>children</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#config-org.apache.juneau.config.Config-"><code>config</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#consumes-org.apache.juneau.MediaType...-"><code>consumes</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#debug-org.apache.juneau.Enablement-"><code>debug</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#debugDefault-org.apache.juneau.Enablement-"><code>debugDefault</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#debugOn-java.lang.String-"><code>debugOn</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultAccept-java.lang.String-"><code>defaultAccept</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultCharset-java.nio.charset.Charset-"><code>defaultCharset</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultClasses-java.lang.Class...-"><code>defaultClasses</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultContentType-java.lang.String-"><code>defaultContentType</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestAttributes-org.apache.juneau.rest.httppart.NamedAttribute...-"><code>defaultRequestAttributes</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestHeaders-org.apache.http.Header...-"><code>defaultRequestHeaders</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultResponseHeaders-org.apache.http.Header...-"><code>defaultResponseHeaders</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultSetting-java.lang.String-java.lang.Object-"><code>defaultSetting</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#disableContentParam-boolean-"><code>disableContentParam</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#logger-java.util.logging.Logger-"><code>logger</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#maxInput-java.lang.String-"><code>maxInput</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#path-java.lang.String-"><code>path</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#parserListener-java.lang.Class-"><code>parserListener</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#produces-org.apache.juneau.MediaType...-"><code>produces</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#renderResponseStackTraces-boolean-"><code>renderResponseStackTraces</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#restOpArgs-java.lang.Class...-"><code>restOpArgs</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#serializerListener-java.lang.Class-"><code>serializerListener</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#swaggerProvider-java.lang.Class-"><code>swaggerProvider</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#uriAuthority-java.lang.String-"><code>uriAuthority</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#uriContext-java.lang.String-"><code>uriContext</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#uriRelativity-org.apache.juneau.UriRelativity-"><code>uriRelativity</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#uriResolution-org.apache.juneau.UriResolution-"><code>uriResolution</code></a>
</ul>
</ul>
<p>
For more complex configurations, access to sub-builders is provided via the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#callLogger--"><code>callLogger</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#config--"><code>config</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#consumes--"><code>consumes</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#debugEnablement--"><code>debugEnablement</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultClasses--"><code>defaultClasses</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestAttributes--"><code>defaultRequestAttributes</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultRequestHeaders--"><code>defaultRequestHeaders</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultResponseHeaders--"><code>defaultResponseHeaders</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#defaultSettings--"><code>defaultSettings</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#encoders--"><code>encoders</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#fileFinder--"><code>fileFinder</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#jsonSchemaGenerator--"><code>jsonSchemaGenerator</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#logger--"><code>logger</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#messages--"><code>messages</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#methodExecStore--"><code>methodExecStore</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#parsers--"><code>parsers</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#partParser--"><code>partParser</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#partSerializer--"><code>partSerializer</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#produces--"><code>produces</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#responseProcessors--"><code>responseProcessors</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#restOpArgs--"><code>restOpArgs</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#rootBeanStore--"><code>rootBeanStore</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#serializers--"><code>serializers</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#staticFiles--"><code>staticFiles</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#swaggerProvider--"><code>swaggerProvider</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#thrownStore--"><code>thrownStore</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#varResolver--"><code>varResolver</code></a>
</ul>
</ul>
<ul>
<li class='note'>
The builders or built objects above can also be defined as injected beans defined in a Spring Configuration if
you wish to do all your app configuration Spring-style. This is described in detail in the <a class='doclink' href='#juneau-rest-server-springboot'>Overview &gt; juneau-rest-server-springboot</a>
documentation.
</ul>
<p>
The programmatic equivalent to the annotated lifecycle methods are below:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#postInitMethods--"><code>postInitMethods</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#postInitChildFirstMethods--"><code>postInitChildFirstMethods</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#startCallMethods--"><code>startCallMethods</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#preCallMethods--"><code>preCallMethods</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#postCallMethods--"><code>postCallMethods</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#endCallMethods--"><code>endCallMethods</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#destroyMethods--"><code>destroyMethods</code></a>
</ul>
</ul>
<ul>
<li class='note'>
It is also possible to override methods on the <a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a> class itself by providing your own specialized subclass via the
<a href="org/apache/juneau/rest/RestContext.Builder.html#type-java.lang.Class-"><code>RestContext.Builder.type(Class)</code></a> method.
</ul>
</div>
</div><!-- END: 8.22 - juneau-rest-server.jrs.RestContext -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestOpContext' id='juneau-rest-server.jrs.RestOpContext'>8.23 - RestOpContext</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.23 - juneau-rest-server.jrs.RestOpContext -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/RestOpContext.html" title="class in org.apache.juneau.rest"><code>RestOpContext</code></a> object is the workhorse class for an individual <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>-annotated method.
</p>
<p>
Every class annotated with <l>@RestOp</l> ends up with an instance of this object. Similar to <a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>, the object is read-only and unchangeable and is
initialized with all of the various annotations pulled from the method. All functionality available through annotations
have programmatic equivalents through the builder of this class.
</p>
<p>
To access the builder for these objects, simply implement the following init method that will be called for each <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a>-annotated method.
</p>
<p class='bjava'>
<jc>// Use an INIT hook with RestOpContext.Builder as a parameter.</jc>
<ja>@RestHook</ja>(<jsf>INIT</jsf>)
<jk>public void</jk> init(RestOpContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
<jv>builder</jv>
.beanContext(<jv>x</jv> -&gt; <jv>x</jv>.swaps(TemporalCalendarSwap.Rfc1123DateTime.<jk>class</jk>))
.debugEnablement(<jsf>CONDITIONAL</jsf>);
}
</p>
<p>
There are multiple ways to programmatically alter how RestOpContext behaves. The most straightforward are the following
builder methods which are direct equivalents to values defined on the <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a> annotation:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestOpContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestOpContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#clientVersion-java.lang.String-"><code>clientVersion</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#consumes-org.apache.juneau.MediaType...-"><code>consumes</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#debug-org.apache.juneau.Enablement-"><code>debug</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultCharset-java.nio.charset.Charset-"><code>defaultCharset</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#dotAll--"><code>dotAll</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#httpMethod-java.lang.String-"><code>httpMethod</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#maxInput-java.lang.String-"><code>maxInput</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#path-java.lang.String...-"><code>path</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#produces-org.apache.juneau.MediaType...-"><code>produces</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#roleGuard-java.lang.String-"><code>roleGuard</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#rolesDeclared-java.lang.String...-"><code>rolesDeclared</code></a>
</ul>
</ul>
<p>
For more complex configurations, access to sub-builders is provided via the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestOpContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestOpContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#converters--"><code>converters</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultClasses--"><code>defaultClasses</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestAttributes--"><code>defaultRequestAttributes</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestFormData--"><code>defaultRequestFormData</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestHeaders--"><code>defaultRequestHeaders</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultRequestQueryData--"><code>defaultRequestQueryData</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#defaultResponseHeaders--"><code>defaultResponseHeaders</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#encoders--"><code>encoders</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#guards--"><code>guards</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#jsonSchemaGenerator--"><code>jsonSchemaGenerator</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#matchers--"><code>matchers</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#parsers--"><code>parsers</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#partParser--"><code>partParser</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#partSerializer--"><code>partSerializer</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestOpContext.Builder.html#serializers--"><code>serializers</code></a>
</ul>
</ul>
<ul>
<li class='note'>
It is also possible to override methods on the <a href="org/apache/juneau/rest/RestOpContext.html" title="class in org.apache.juneau.rest"><code>RestOpContext</code></a> class itself by providing your own specialized subclass via the
<a href="org/apache/juneau/rest/RestOpContext.Builder.html#type-java.lang.Class-"><code>RestOpContext.Builder.type(Class)</code></a> method.
</ul>
</div>
</div><!-- END: 8.23 - juneau-rest-server.jrs.RestOpContext -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.ResponseProcessors' id='juneau-rest-server.jrs.ResponseProcessors'>8.24 - Response Processors</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.24 - juneau-rest-server.jrs.ResponseProcessors -->
<div class='topic'>
<p>
The REST Server API uses the concept of registered response processors for converting objects returned by REST
methods or set through <a href="org/apache/juneau/rest/RestResponse.html#setContent-java.lang.Object-"><code>RestResponse.setContent(Object)</code></a> into appropriate HTTP responses.
</p>
<p>
By default, REST resource classes are registered with the following response processors:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/processor/HttpEntityProcessor.html" title="class in org.apache.juneau.rest.processor"><code>HttpEntityProcessor</code></a>
<li class='jc'><a href="org/apache/juneau/rest/processor/HttpResourceProcessor.html" title="class in org.apache.juneau.rest.processor"><code>HttpResourceProcessor</code></a>
<li class='jc'><a href="org/apache/juneau/rest/processor/HttpResponseProcessor.html" title="class in org.apache.juneau.rest.processor"><code>HttpResponseProcessor</code></a>
<li class='jc'><a href="org/apache/juneau/rest/processor/InputStreamProcessor.html" title="class in org.apache.juneau.rest.processor"><code>InputStreamProcessor</code></a>
<li class='jc'><a href="org/apache/juneau/rest/processor/PlainTextPojoProcessor.html" title="class in org.apache.juneau.rest.processor"><code>PlainTextPojoProcessor</code></a>
<li class='jc'><a href="org/apache/juneau/rest/processor/ReaderProcessor.html" title="class in org.apache.juneau.rest.processor"><code>ReaderProcessor</code></a>
<li class='jc'><a href="org/apache/juneau/rest/processor/ResponseBeanProcessor.html" title="class in org.apache.juneau.rest.processor"><code>ResponseBeanProcessor</code></a>
<li class='jc'><a href="org/apache/juneau/rest/processor/SerializedPojoProcessor.html" title="class in org.apache.juneau.rest.processor"><code>SerializedPojoProcessor</code></a>
<li class='jc'><a href="org/apache/juneau/rest/processor/ThrowableProcessor.html" title="class in org.apache.juneau.rest.processor"><code>ThrowableProcessor</code></a>
</ul>
<p>
Custom response processors can be associated with REST resources via the following:
</p>
<ul>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html#responseProcessors--"><code>Rest.responseProcessors()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#responseProcessors--"><code>RestContext.Builder.responseProcessors()</code></a>
</ul>
<p>
Response processors can be used to process POJOs that cannot normally be handled through Juneau serializers, or
because it's simply easier to define response processors for special cases.
</p>
<p>
The following example shows how to create a response processor to handle special <c>Foo</c> objects outside the
normal Juneau architecture.
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/example"</js>,
responseProcessors=FooProcessor.<jk>class</jk>
)
<jk>public class</jk> Example <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<ja>@RestGet</ja>(<js>"/"</js>)
<jk>public</jk> Foo test1() {
<jk>return new</jk> Foo(<js>"123"</js>);
}
<jk>public static class</jk> FooProcessor <jk>implements</jk> ResponseProcessor {
<ja>@Override</ja>
<jk>public int</jk> process(RestOpSession <jv>opSession</jv>) {
RestResponse <jv>res</jv> = <jv>opSession</jv>.getRestResponse();
Foo <jv>foo</jv> = <jv>res</jv>.getOutput(Foo.<jk>class</jk>);
<jk>if</jk> (<jv>foo</jv> == <jk>null</jk>)
<jk>return</jk> <jsf>NEXT</jsf>; <jc>// Let the next processor handle it.</jc>
<jc>// Set some headers and body content.</jc>
<jv>res</jv>.setHeader(<js>"Foo-ID"</js>, <jv>foo</jv>.getId());
<jv>res</jv>.getWriter().write(<js>"foo.id="</js> + <jv>foo</jv>.getId());
<jk>return</jk> <jsf>FINISHED</jsf>; <jc>// We handled it.</jc>
}
}
}
</p>
</div>
</div><!-- END: 8.24 - juneau-rest-server.jrs.ResponseProcessors -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.RestRpc' id='juneau-rest-server.jrs.RestRpc'>8.25 - REST/RPC</a><span class='update'>updated: 8.0.0,<b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.25 - juneau-rest-server.jrs.RestRpc -->
<div class='topic'>
<p>
The REST/RPC (RPC over REST) API allows the creation of client-side remote proxy interfaces for calling methods on server-side POJOs using entirely REST.
</p>
<ul>
<li class='note'>
This is not to be confused with <a class='doclink' href='#juneau-rest-server-springboot'>REST Proxies</a> which are entirely client-side driven Java interfaces
against arbitrary backend REST interfaces.
</ul>
<h5 class='topic'>Remote Interfaces</h5>
<p>
The following example shows a remote interface:
</p>
<p class='bjava'>
<ja>@RemoteInterface</ja> <jc>// Annotation is optional</jc>
<jk>public interface</jk> IAddressBook {
<jk>void</jk> init() <jk>throws</jk> Exception;
List&lt;Person&gt; getPeople();
List&lt;Address&gt; getAddresses();
<jk>int</jk> createPerson(CreatePerson cp) <jk>throws</jk> Exception;
Person findPerson(<jk>int</jk> id);
Address findAddress(<jk>int</jk> id);
Person findPersonWithAddress(<jk>int</jk> id);
Person removePerson(<jk>int</jk> id);
}
</p>
<p>
The requirements for a remote interface method are:
</p>
<ul class='spaced-list'>
<li>
Must be public.
<li>
Can be called anything.
<li>
Can have any number of <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>serializable and parsable</a> parameters.
<li>
Can return a <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>serializable and parsable</a> value.
<li>
Can throw any <c>Throwables</c>.
</ul>
<p>
Throwables with public no-arg or single-arg-string constructors are automatically recreated on the client side
when thrown on the server side.
</p>
<h5 class='topic'>Client side</h5>
<p>
Remote Interface proxies are instantiated on the client side using one of the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#getRrpcInterface-java.lang.Class-"><code>getRrpcInterface(Class)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#getRrpcInterface-java.lang.Class-java.lang.Object-"><code>getRrpcInterface(Class,Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#getRrpcInterface-java.lang.Class-java.lang.Object-org.apache.juneau.serializer.Serializer-org.apache.juneau.parser.Parser-"><code>getRrpcInterface(Class,Object,Serializer,Parser)</code></a>
</ul>
</li>
</ul>
<p>
Since we build upon the existing <c>RestClient</c> API, we inherit all of it's features.
For example, convenience methods for setting POJO filters and properties to customize the behavior of the
serializers and parsers, and the ability to provide your own customized Apache <c>HttpClient</c> for
handling various scenarios involving authentication and Internet proxies.
</p>
<p>
Here's an example of the above interface being used:
</p>
<p class='bjava'>
<jc>// Create a RestClient using JSON for serialization, and point to the server-side remote interface servlet.</jc>
RestClient client = RestClient.<jsm>create</jsm>()
.json()
.rootUrl(<js>"http://localhost:10000/remote"</js>)
.build();
<jc>// Create a proxy interface.</jc>
IAddressBook ab = client.getRrpcInterface(IAddressBook.<jk>class</jk>);
<jc>// Invoke a method on the server side and get the returned result.</jc>
Person p = ab.createPerson(
<jk>new</jk> Person(
<js>"John Smith"</js>,
<js>"Aug 1, 1999"</js>,
<jk>new</jk> Address(<js>"My street"</js>, <js>"My city"</js>, <js>"My state"</js>, 12345, <jk>true</jk>)
)
);
</p>
<p>
Under the covers, this method call gets converted to a REST POST.
</p>
<p class='bcode'>
HTTP POST http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook/createPerson(org.apache.juneau.examples.addressbook.Person)
Accept: application/json
Content-Type: application/json
[
{
"name":"John Smith",
"birthDate":"Aug 1, 1999",
"addresses":[
{
"street":"My street",
"city":"My city",
"state":"My state",
"zip":12345,
"isCurrent":true
}
]
}
]
</p>
<p>
Note that the body of the request is an array.
This array contains the serialized arguments of the method.
The object returned by the method is then serialized as the body of the response.
</p>
<h5 class='topic'>Server side</h5>
<p>
There are two ways to expose remote interfaces on the server side:
</p>
<ol class='spaced-list'>
<li>
Extending from <a href="org/apache/juneau/rest/remote/RrpcServlet.html" title="class in org.apache.juneau.rest.remote"><code>RrpcServlet</code></a>.
<li>
Using a <c><ja>@RestOp</ja>(method=<jsf>RRPC</jsf>)</c> annotation on a Java method.
</ol>
<p>
In either case, the proxy communications layer is pure REST.
Therefore, in cases where the interface classes are not available on the client side, the same method calls can
be made through pure REST calls.
This can also aid significantly in debugging, since calls to the remote interface service can be made directly from
a browser with no coding involved.
</p>
<h5 class='topic'>RrpcServlet</h5>
<p>
The <a href="org/apache/juneau/rest/remote/RrpcServlet.html" title="class in org.apache.juneau.rest.remote"><code>RrpcServlet</code></a> class is a simple specialized servlet with an abstract
<c>getServiceMap()</c> method to define the server-side POJOs:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/remote"</js>
)
<jk>public class</jk> SampleRrpcServlet <jk>extends</jk> RrpcServlet {
<jc>// Our server-side POJO.</jc>
<jk>private</jk> AddressBook <jf>addressBook</jf> = <jk>new</jk> AddressBook();
<ja>@Override</ja> <jc>/* RrpcServlet */</jc>
<jk>protected</jk> Map&lt;Class&lt;?&gt;,Object&gt; getServiceMap() <jk>throws</jk> Exception {
Map&lt;Class&lt;?&gt;,Object&gt; <jv>map</jv> = <jk>new</jk> LinkedHashMap&lt;Class&lt;?&gt;,Object&gt;();
<jc>// In this simplified example, we expose the same POJO service under two different interfaces.
// One is IAddressBook which only exposes methods defined on that interface, and
// the other is AddressBook itself which exposes all methods defined on the class itself (dangerous!).</jc>
<jv>map</jv>.put(IAddressBook.<jk>class</jk>, <jf>addressBook</jf>);
<jv>map</jv>.put(AddressBook.<jk>class</jk>, <jf>addressBook</jf>);
<jk>return</jk> <jv>map</jv>;
}
}
</p>
<h5 class='topic'>@RestOp(method=RRPC)</h5>
<p>
The <c><ja>@RestOp</ja>(method=<jsf>RRPC</jsf>)</c> approach is easier if you only have a single
interface you want to expose.
You simply define a Java method whose return type is an interface, and return the implementation of that
interface:
</p>
<p class='bjava'>
<jc>// Our exposed interface.</jc>
<ja>@RestOp</ja>(method=<jsf>RRPC</jsf>, path=<js>"/addressbookproxy/*"</js>)
<jk>public</jk> IAddressBook getProxy() {
<jk>return</jk> <jf>addressBook</jf>;
}
</p>
<h5 class='topic'>RrpcServlet in a browser</h5>
<p>
If you point your browser to the servlet above, you get a list of available interfaces:
</p>
<p class='bcode'>
http://localhost:10000/remote
</p>
<img class='bordered w800' src='doc-files/jrs.restRPC.1.png'>
<p>
Clicking the hyperlinks on each shows you the list of methods that can be invoked on that service.
Note that the <c>IAddressBook</c> link shows that you can only invoke methods defined on that
interface, whereas the <c>AddressBook</c> link shows ALL public methods defined on that class.
</p>
<h5 class='figure'>IAddressBook</h5>
<p class='bcode'>
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook
</p>
<img class='bordered w800' src='doc-files/jrs.restRPC.2.png'>
<p>
Since <c>AddressBook</c> extends from <c>LinkedList</c>, you may notice familiar collections
framework methods listed.
</p>
<h5 class='figure'>AddressBook</h5>
<p class='bcode'>
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.AddressBook
</p>
<img class='bordered w800' src='doc-files/jrs.restRPC.3.png'>
<p>
Let's see how we can interact with this interface through nothing more than REST calls to get a better idea on
how this works.
We'll use the same method call as in the introduction.
First, we need to create the serialized form of the arguments:
</p>
<p class='bjava'>
Object[] <jv>args</jv> = <jk>new</jk> Object[] {
<jk>new</jk> CreatePerson(<js>"Test Person"</js>,
AddressBook.<jsm>toCalendar</jsm>(<js>"Aug 1, 1999"</js>),
<jk>new</jk> CreateAddress(<js>"Test street"</js>, <js>"Test city"</js>, <js>"Test state"</js>, 12345, <jk>true</jk>))
};
String <jv>asJson</jv> = SimpleJsonSerializer.<jsf>DEFAULT_READABLE</jsf>.toString(<jv>args</jv>);
System.<jsf>err</jsf>.println(<jv>asJson</jv>);
</p>
<p>
That produces the following JSON output:
</p>
<p class='bjson'>
[
{
name: <js>'Test Person'</js>,
birthDate: <js>'Aug 1, 1999'</js>,
addresses: [
{
street: <js>'Test street'</js>,
city: <js>'Test city'</js>,
state: <js>'Test state'</js>,
zip: 12345,
isCurrent: <jk>true</jk>
}
]
}
]
</p>
<p>
Note that in this example we're using JSON.
However, various other content types can also be used such as XML, URL-Encoding, UON, or HTML.
In practice however, JSON will preferred since it is often the most efficient.
</p>
<p>
Next, we can use a tool such as Poster to make the REST call.
Methods are invoked by POSTing the serialized object array to the URI of the interface method.
In this case, we want to POST our JSON to the following URL:
</p>
<p class='bcode'>
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook/createPerson(org.apache.juneau.examples.addressbook.CreatePerson)
</p>
<p>
Make sure that we specify the <c>Content-Type</c> of the body as <c>text/json</c>.
We also want the results to be returned as JSON, so we set the <c>Accept</c> header to
<c>text/json</c> as well.
</p>
<img class='bordered w400' src='doc-files/jrs.restRPC.4.png'>
<p>
When we execute the POST, we should see the following successful response whose body contains the returned
<c>Person</c> bean serialized to JSON:
</p>
<img class='bordered w400' src='doc-files/jrs.restRPC.5.png'>
<p>
From there, we could use the following code snippet to reconstruct the response object from JSON:
</p>
<p class='bjava'>
String response = <js>"<i>output from above</i>"</js>;
Person p = JsonParser.<jsf>DEFAULT</jsf>.parse(response, Person.<jk>class</jk>);
</p>
<p>
If we alter our servlet to allow overloaded GET requests, we can invoke methods using nothing more than a
browser...
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/remote"</js>,
<jc>// Allow us to use method=POST from a browser.</jc>
allowedMethodParams=<js>"*"</js>
)
<jk>public class</jk> SampleRrpcServlet <jk>extends</jk> RrpcServlet {
</p>
<p>
For example, to invoke the <c>getPeople()</c> method on our bean:
</p>
<p class='bcode'>
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook/getPeople?method=POST
</p>
<img class='bordered w800' src='doc-files/jrs.restRPC.6.png'>
<p>
Here we call the <c>findPerson(<jk>int</jk>)</c> method to retrieve a person and get the
returned POJO (in this case as HTML since that's what's in the <c>Accept</c> header when calling from a
browser):
</p>
<p class='bcode'>
http://localhost:10000/remote/org.apache.juneau.examples.addressbook.IAddressBook/findPerson(int)?method=POST&amp;body=@(3)
</p>
<img class='bordered w800' src='doc-files/jrs.restRPC.7.png'>
<p>
When specifying the POST body as a <c>&amp;body</c> parameter, the method arguments should be in UON
notation.
See <a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a> for more information about this encoding.
Usually you can also pass in JSON if you specify <c>&amp;Content-Type=text/json</c> in the URL parameters
but passing in unencoded JSON in a URL may not work in all browsers.
Therefore, UON is preferred.
</p>
<p>
The hyperlinks on the method names above lead you to a simple form-entry page where you can test
passing parameters in UON notation as URL-encoded form posts.
</p>
<h5 class='figure'>Sample form entry page</h5>
<img class='bordered w800' src='doc-files/jrs.restRPC.8.png'>
<h5 class='figure'>Sample form entry page results</h5>
<img class='bordered w800' src='doc-files/jrs.restRPC.9.png'>
</div>
</div><!-- END: 8.25 - juneau-rest-server.jrs.RestRpc -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.SerializingUris' id='juneau-rest-server.jrs.SerializingUris'>8.26 - Serializing URIs</a><span class='update'>updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.26 - juneau-rest-server.jrs.SerializingUris -->
<div class='topic'>
<p>
As mention earlier <a class='doclink' href='#juneau-marshall.jm.MarshallingUris'>here</a>, Juneau serializers have sophisticated support for transforming relative URIs to absolute form.
</p>
<p>
The following example shows a REST method that returns a list of URIs of various forms:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
uriAuthority=<js>"http://foo.com:123"</js>,
uriContext=<js>"/myContext"</js>
)
<jk>public class</jk> MyResource {
<ja>@RestGet</ja>
<jk>public</jk> URI[] getURIs() {
<jk>return new</jk> URI[] {
URI.<jsm>create</jsm>(<js>"http://www.apache.org/f1a"</js>),
URI.<jsm>create</jsm>(<js>"/f1b"</js>),
URI.<jsm>create</jsm>(<js>"/f1c/x/y"</js>),
URI.<jsm>create</jsm>(<js>"f1d"</js>),
URI.<jsm>create</jsm>(<js>"f1e/x/y"</js>),
URI.<jsm>create</jsm>(<js>""</js>),
URI.<jsm>create</jsm>(<js>"context:/f2a/x"</js>),
URI.<jsm>create</jsm>(<js>"context:/f2b"</js>),
URI.<jsm>create</jsm>(<js>"context:/"</js>),
URI.<jsm>create</jsm>(<js>"context:/.."</js>),
URI.<jsm>create</jsm>(<js>"servlet:/f3a/x"</js>),
URI.<jsm>create</jsm>(<js>"servlet:/f3b"</js>),
URI.<jsm>create</jsm>(<js>"servlet:/"</js>),
URI.<jsm>create</jsm>(<js>"servlet:/.."</js>),
URI.<jsm>create</jsm>(<js>"request:/f4a/x"</js>),
URI.<jsm>create</jsm>(<js>"request:/f4b"</js>),
URI.<jsm>create</jsm>(<js>"request:/"</js>),
URI.<jsm>create</jsm>(<js>"request:/.."</js>)
};
}
}
</p>
<p>
When requested as JSON, it produces the following result:
</p>
<p class='bjson'>
{
<jok>f1a</jok>:<jov>'http://www.apache.org/f1a'</jov>,
<jok>f1b</jok>:<jov>'http://foo.com:123/f1b'</jov>,
<jok>f1c</jok>:<jov>'http://foo.com:123/f1c/x/y'</jov>,
<jok>f1d</jok>:<jov>'http://foo.com:123/myContext/myServlet/f1d'</jov>,
<jok>f1e</jok>:<jov>'http://foo.com:123/myContext/myServlet/f1e/x/y'</jov>,
<jok>f1f</jok>:<jov>'http://foo.com:123/myContext/myServlet'</jov>,
<jok>f2a</jok>:<jov>'http://foo.com:123/myContext/f2a/x'</jov>,
<jok>f2b</jok>:<jov>'http://foo.com:123/myContext/f2b'</jov>,
<jok>f2c</jok>:<jov>'http://foo.com:123/myContext'</jov>,
<jok>f2d</jok>:<jov>'http://foo.com:123'</jov>,
<jok>f3a</jok>:<jov>'http://foo.com:123/myContext/myServlet/f3a/x'</jov>,
<jok>f3b</jok>:<jov>'http://foo.com:123/myContext/myServlet/f3b'</jov>,
<jok>f3c</jok>:<jov>'http://foo.com:123/myContext/myServlet'</jov>,
<jok>f3d</jok>:<jov>'http://foo.com:123/myContext'</jov>,
<jok>f4a</jok>:<jov>'http://foo.com:123/myContext/myServlet/myPath/f4a/x'</jov>,
<jok>f4b</jok>:<jov>'http://foo.com:123/myContext/myServlet/myPath/f4b'</jov>,
<jok>f4c</jok>:<jov>'http://foo.com:123/myContext/myServlet/myPath'</jov>,
<jok>f4d</jok>:<jov>'http://foo.com:123/myContext/myServlet'</jov>
}
</p>
<p>
URI resolution is controlled by the following settings:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#uriAuthority-java.lang.String-"><code>uriAuthority(String)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#uriContext-java.lang.String-"><code>uriContext(String)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#uriRelativity-org.apache.juneau.UriRelativity-"><code>uriRelativity(UriRelativity)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.Builder.html#uriResolution-org.apache.juneau.UriResolution-"><code>uriResolution(UriResolution)</code></a>
</ul>
</li>
</ul>
<p>
URIs are resolved by both regular and part serializers.
</p>
</div>
</div><!-- END: 8.26 - juneau-rest-server.jrs.SerializingUris -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.UtilityBeans' id='juneau-rest-server.jrs.UtilityBeans'>8.27 - Utility Beans</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.27 - juneau-rest-server.jrs.UtilityBeans -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/beans/package-summary.html"><code>org.apache.juneau.rest.beans</code></a> package contains a set of reusable utility beans meant to help with putting together
explorable REST interfaces.
</p>
<p>
The <a href="org/apache/juneau/examples/rest/UtilityBeansResource.html" title="class in org.apache.juneau.examples.rest"><code>UtilityBeansResource</code></a> class shows how these beans are used.
The resource class is hosted in the example REST applications rendered below:
</p>
<img class='bordered w800' src='doc-files/jrs.UtilityBeans.png'>
<h5 class='topic'>ResourceDescriptions</h5>
<p>
The <a href="org/apache/juneau/examples/rest/UtilityBeansResource.html#getChildDescriptions--"><code>getChildDescriptions()</code></a> method shows an example
of rendering a list of descriptive links for child endpoints.
</p>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/"</js>)
<jk>public</jk> ResourceDescriptions getChildDescriptions() {
<jk>return</jk> ResourceDescriptions
.<jsm>create</jsm>()
.append(<js>"BeanDescription"</js>, <js>"Example of BeanDescription bean"</js>)
.append(<js>"Hyperlink"</js>, <js>"Example of Hyperlink bean"</js>)
.append(<js>"SeeOtherRoot"</js>, <js>"Example of SeeOtherRoot bean"</js>);
}
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrs.UtilityBeans.png'>
<h5 class='figure'>JSON representation</h5>
<img class='bordered w800' src='doc-files/jrs.UtilityBeans.json.png'>
<h5 class='topic'>BeanDescription</h5>
<p>
The <a href="org/apache/juneau/examples/rest/UtilityBeansResource.html#aBeanDescription--"><code>aBeanDescription()</code></a> method shows an example
of rendering simple schema information about an arbitrary bean class.
</p>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/BeanDescription"</js>)
<ja>@HtmlDocConfig</ja>(
aside={
<js>"&lt;div class='text'&gt;"</js>,
<js>" &lt;p&gt;Example of serialized org.apache.juneau.rest.utilitybeans.ResourceDescriptions bean.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public</jk> BeanDescription aBeanDescription() {
<jk>return</jk> BeanDescription.<jsm>of</jsm>(Address.<jk>class</jk>);
}
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrs.UtilityBeans.BeanDescription.png'>
<h5 class='figure'>JSON representation</h5>
<img class='bordered w800' src='doc-files/jrs.UtilityBeans.BeanDescription.json.png'>
<h5 class='topic'>Hyperlink</h5>
<p>
The <a href="org/apache/juneau/examples/rest/UtilityBeansResource.html#aHyperlink--"><code>aHyperlink()</code></a> method shows an example
of rendering a simple hyperlink.
</p>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/Hyperlink"</js>)
<ja>@HtmlDocConfig</ja>(
aside={
<js>"&lt;div class='text'&gt;"</js>,
<js>" &lt;p&gt;Example of serialized org.apache.juneau.rest.utilitybeans.Hyperlink bean.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public</jk> Hyperlink aHyperlink() {
<jk>return</jk> Hyperlink.<jsm>create</jsm>(<js>"/utilitybeans"</js>, <js>"Back to /utilitybeans"</js>);
}
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrs.UtilityBeans.Hyperlink.png'>
<h5 class='figure'>JSON representation</h5>
<img class='bordered w800' src='doc-files/jrs.UtilityBeans.Hyperlink.json.png'>
<h5 class='topic'>SeeOtherRoot</h5>
<p>
The <a href="org/apache/juneau/examples/rest/UtilityBeansResource.html#aSeeOtherRoot--"><code>aSeeOtherRoot()</code></a> method shows an example
of sending a <c>303 See Other</c> with a <c>Location</c> header pointing to the servlet root.
</p>
<p class='bjava'>
<ja>@RestGet</ja>(<js>"/SeeOtherRoot"</js>)
<ja>@HtmlDocConfig</ja>(
aside={
<js>"&lt;div class='text'&gt;"</js>,
<js>" &lt;p&gt;Example of serialized org.apache.juneau.rest.utilitybeans.SeeOtherRoot bean.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public</jk> SeeOtherRoot aSeeOtherRoot() {
<jk>return</jk> SeeOtherRoot.<jsf>INSTANCE</jsf>;
}
</p>
<p>
Clicking on the link will just redirect to this same page.
</p>
<img class='bordered w800' src='doc-files/jrs.UtilityBeans.png'>
<p>
Typically this is useful for endpoints where you want to redirect back to the servlet root, such as a DELETE.
</p>
</div>
</div><!-- END: 8.27 - juneau-rest-server.jrs.UtilityBeans -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.HtmlBeans' id='juneau-rest-server.jrs.HtmlBeans'>8.28 - Using with HTML Beans</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 8.28 - juneau-rest-server.jrs.HtmlBeans -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/examples/rest/HtmlBeansResource.html" title="class in org.apache.juneau.examples.rest"><code>HtmlBeansResource</code></a> class shows how <a href="org/apache/juneau/dto/html5/package-summary.html"><code>HTML5 beans</code></a> can be
used to generate arbitrary HTML on REST endpoints.
</p>
<img class='bordered w800' src='doc-files/jrs.HtmlBeans.png'>
<h5 class='topic'>table</h5>
<p>
The <a href="org/apache/juneau/examples/rest/HtmlBeansResource.html#aTable--"><code>aTable()</code></a> method shows an example
of rendering an HTML table.
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
<ja>@RestGet</ja>(<js>"/table"</js>)
<ja>@HtmlDocConfig</ja>(
aside={
<js>"&lt;div class='text'&gt;"</js>,
<js>" &lt;p&gt;Example of serialized table.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public</jk> Table aTable() {
<jk>return</jk> <jsm>table</jsm>(
<jsm>tr</jsm>(
<jsm>th</jsm>(<js>"c1"</js>),
<jsm>th</jsm>(<js>"c2"</js>)
),
<jsm>tr</jsm>(
<jsm>td</jsm>(<js>"v1"</js>),
<jsm>td</jsm>(<js>"v2"</js>)
)
);
}
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrs.HtmlBeans.table.png'>
<h5 class='figure'>JSON representation</h5>
<img class='bordered w800' src='doc-files/jrs.HtmlBeans.table.json.png'>
<h5 class='topic'>div</h5>
<p>
The <a href="org/apache/juneau/examples/rest/HtmlBeansResource.html#aDiv--"><code>aDiv()</code></a> method shows an example
of rendering a div tag with mixed content.
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
<ja>@RestGet</ja>(<js>"/div"</js>)
<ja>@HtmlDocConfig</ja>(
aside={
<js>"&lt;div class='text'&gt;"</js>,
<js>" &lt;p&gt;Example of serialized div tag.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public</jk> HtmlElement aDiv() {
<jk>return</jk> <jsm>div</jsm>()
.children(
<jsm>p</jsm>(<js>"Juneau supports "</js>, <jsm>b</jsm>(<jsm>i</jsm>(<js>"mixed"</js>)), <js>" content!"</js>)
)
.onmouseover(<js>"alert(\"boo!\");"</js>);
}
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrs.HtmlBeans.div.png'>
<h5 class='figure'>JSON representation</h5>
<img class='bordered w800' src='doc-files/jrs.HtmlBeans.div.json.png'>
<h5 class='topic'>form</h5>
<p>
The <a href="org/apache/juneau/examples/rest/HtmlBeansResource.html#aForm--"><code>aForm()</code></a> method shows an example
of rendering an HTML form.
</p>
<p class='bjava'>
<jk>import static</jk> org.apache.juneau.dto.html5.HtmlBuilder.*;
<ja>@RestGet</ja>(<js>"/form"</js>)
<ja>@HtmlDocConfig</ja>(
aside={
<js>"&lt;div class='text'&gt;"</js>,
<js>" &lt;p&gt;Example of serialized HTML form.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public Form</jk> aForm() {
<jk>return</jk> <jsm>form</jsm>().action(<js>"/submit"</js>).method(<js>"POST"</js>)
.children(
<js>"Position (1-10000): "</js>, <jsm>input</jsm>(<js>"number"</js>).name(<js>"pos"</js>).value(1), <jsm>br</jsm>(),
<js>"Limit (1-10000): "</js>, <jsm>input</jsm>(<js>"number"</js>).name(<js>"limit"</js>).value(100), <jsm>br</jsm>(),
<jsm>button</jsm>(<js>"submit"</js>, <js>"Submit"</js>),
<jsm>button</jsm>(<js>"reset"</js>, <js>"Reset"</js>)
);
}
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrs.HtmlBeans.form.png'>
<h5 class='figure'>JSON representation</h5>
<img class='bordered w800' src='doc-files/jrs.HtmlBeans.form.json.png'>
</div>
</div><!-- END: 8.28 - juneau-rest-server.jrs.HtmlBeans -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server.jrs.OtherNotes' id='juneau-rest-server.jrs.OtherNotes'>8.29 - Other Notes</a></h3>
<div class='topic'><!-- START: 8.29 - juneau-rest-server.jrs.OtherNotes -->
<div class='topic'>
<ul class='notes'>
<li class='note'>
Subclasses can use either <code>GenericServlet.init(ServletConfig)</code>
or <code>GenericServlet.init()</code> for initialization just like any other servlet.
<li class='note'>
The <l>X-Response-Headers</l> header can be used to pass through header values into the response.
The value should be a URL-encoded map of key-value pairs.
For example, to add a <l>"Refresh: 1"</l> header to the response to auto-refresh a page, the following
parameter can be specified: <l>"/sample?X-Response-Headers={Refresh=1}"</l>
</ul>
</div>
</div><!-- END: 8.29 - juneau-rest-server.jrs.OtherNotes -->
</div><!-- END: 8 - juneau-rest-server -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server-rdf' id='juneau-rest-server-rdf'>9 - juneau-rest-server-rdf</a></h2>
<div class='topic'><!-- START: 9 - juneau-rest-server-rdf -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-rest-server-jaxrs<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-rest-server-jaxrs-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.rest.server_9.0.0.jar
</p>
<p>
The <c>juneau-rest-server-jaxrs</c> library provides an implementation of a <c>MessageBodyReader</c>
and <c>MessageBodyWriter</c> to allow any of the Juneau serializers and parsers to be used in a
JAX/RS environment.
</p>
</div>
</div><!-- END: 9 - juneau-rest-server-rdf -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server-jaxrs' id='juneau-rest-server-jaxrs'>10 - juneau-rest-server-jaxrs</a></h2>
<div class='topic'><!-- START: 10 - juneau-rest-server-jaxrs -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-rest-server-jaxrs<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-rest-server-jaxrs-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.rest.server_9.0.0.jar
</p>
<p>
The <c>juneau-rest-server-jaxrs</c> library provides an implementation of a <c>MessageBodyReader</c>
and <c>MessageBodyWriter</c> to allow any of the Juneau serializers and parsers to be used in a
JAX/RS environment.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server-jaxrs.jrsj.BaseProvider' id='juneau-rest-server-jaxrs.jrsj.BaseProvider'>10.1 - Juneau JAX-RS Provider</a></h3>
<div class='topic'><!-- START: 10.1 - juneau-rest-server-jaxrs.jrsj.BaseProvider -->
<div class='topic'>
<p>
The Juneau framework contains the <l>juneau-rest-server-jaxrs</l> bundle for performing simple
integration of Juneau serializers and parsers in JAX-RS compliant environments.
</p>
<p>
It should be noted that although some of the functionality of the Juneau Server API is provided through the JAX-RS
integration components, it is not nearly as flexible as using the <a href="org/apache/juneau/rest/servlet/RestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>RestServlet</code></a> class directly.
</p>
<p>
What you can do with the Juneau JAX-RS provider classes:
</p>
<ul class='spaced-list'>
<li>
Use existing Juneau serializers and parsers for converting streams to POJOs and vis-versa.
<li>
Use annotations to specify filters and properties using the <a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestOp</code></a>
and <a href="org/apache/juneau/rest/jaxrs/JuneauProvider.html" title="annotation in org.apache.juneau.rest.jaxrs"><code>JuneauProvider</code></a> annotations.
</ul>
<p>
What you can't do with the Juneau JAX-RS provider classes:
</p>
<ul class='spaced-list'>
<li>
Specify or override serializers/parsers at the Java class and method levels.
<br>JAX-RS does not provide the capability to use different providers for the same media types
at the class or method levels.
<li>
Specify or override filters and properties at the Java class level.
<li>
Default stylesheets for the <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a> class.
<br>It will produce HTML but it won't contain any styles applied.
<li>
The ability to specify HTTP method, headers, and content using GET parameters.
<br>These make debugging REST interfaces using only a browser possible.
<li>
Class or method level encoding.
<li>
Class or method level guards.
<li>
Class or method level converters.
</ul>
<p>
The Juneau JAX-RS provider API consists of the following classes:
</p>
<ul class='javatree'>
<li class='jc'>
<a href="org/apache/juneau/rest/jaxrs/BaseProvider.html" title="class in org.apache.juneau.rest.jaxrs"><code>BaseProvider</code></a> - The base provider class that implements the JAX-RS
<c>MessageBodyReader</c> and <c>MessageBodyWriter</c> interfaces.
<li class='jc'>
<a href="org/apache/juneau/rest/jaxrs/JuneauProvider.html" title="annotation in org.apache.juneau.rest.jaxrs"><code>JuneauProvider</code></a> - Annotation that is applied to subclasses of <c>BaseProvider</c>
to specify the serializers/parsers associated with a provider, and optionally filters and properties to
apply to those serializers and parsers.
<li class='jc'>
<a href="org/apache/juneau/rest/jaxrs/BasicProvider.html" title="class in org.apache.juneau.rest.jaxrs"><code>BasicProvider</code></a> - A default provider that provides the same level
of media type support as the <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> class.
</ul>
<p>
For the most part, when using these components, you'll either use the existing <l>BasicProvider</l>,
or define your own by subclassing <l>BaseProvider</l>.
</p>
</div>
</div><!-- END: 10.1 - juneau-rest-server-jaxrs.jrsj.BaseProvider -->
</div><!-- END: 10 - juneau-rest-server-jaxrs -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server-springboot' id='juneau-rest-server-springboot'>11 - juneau-rest-server-springboot</a><span class='update'>created: 8.0.0, updated: <b>9.0.0</b></span></h2>
<div class='topic'><!-- START: 11 - juneau-rest-server-springboot -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-rest-server-springboot<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-rest-server-springboot-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.rest.server.springboot_9.0.0.jar
</p>
<p>
The <c>juneau-rest-server-springboot</c> library provides classes to make it easy to integrate
Juneau REST resources with Spring and Spring Boot.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-server-springboot.jrss.Overview' id='juneau-rest-server-springboot.jrss.Overview'>11.1 - Overview</a><span class='update'>created: 8.0.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 11.1 - juneau-rest-server-springboot.jrss.Overview -->
<div class='topic'>
<p>
The Juneau REST servlet APIs are designed to work seemlessly with the Spring Boot framework.
The only restriction is that your top-level REST resource must extend from one of the following classes:
</p>
<ul class='javatree'>
<li class='jp'><a href="org/apache/juneau/rest/springboot/package-summary.html"><code>org.apache.juneau.rest.springboot</code></a>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/springboot/BasicSpringRestServlet.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServlet</code></a> - Basic servlet
<li class='jc'><a href="org/apache/juneau/rest/springboot/BasicSpringRestServletGroup.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServletGroup</code></a> - Basic servlet group
</ul>
</ul>
<p>
These classes are the equivalent to the <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> and <a href="org/apache/juneau/rest/servlet/BasicRestServletGroup.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServletGroup</code></a>
except they hook into the injection framework of Spring Boot to provide resolution of beans (e.g. child resources, various
configuration classes).
</p>
<p>
The <a href="org/apache/juneau/examples/rest/springboot/package-summary.html"><code>org.apache.juneau.examples.rest.springboot</code></a> package and <a href="org/apache/juneau/examples/rest/springboot/App.html" title="class in org.apache.juneau.examples.rest.springboot"><code>App</code></a>
application are a basic Spring Boot application that shows off simple Juneau examples including injection beans.
</p>
<p class='bjava'>
<ja>@SpringBootApplication</ja>
<ja>@Controller</ja>
<jk>public class</jk> App {
<jc>//Entry point method.</jc>
<jk>public static void</jk> main(String[] <jv>args</jv>) {
<jk>new</jk> SpringApplicationBuilder(App.<jk>class</jk>).run(<jv>args</jv>);
}
<jc>// Our root REST bean.
// Note that this must extend from <code>SpringRestServlet</code> to allow use of injection.
// All REST objects are attached to this bean using the <code>Rest#children()</code> annotation.</jc>
<ja>@Bean</ja>
<jk>public</jk> RootResources getRootResources() {
<jk>return new</jk> RootResources();
}
<jc>// Registers our REST bean at the URI root.</jc>
<ja>@Bean</ja>
<jk>public</jk> ServletRegistrationBean&lt;Servlet&gt; getRootServlet(RootResources <jv>rootResources</jv>) {
<jk>return new</jk> ServletRegistrationBean&lt;&gt;(<jv>rootResources</jv>, <js>"/*"</js>);
}
<jc>// Injected child resource.</jc>
<ja>@Bean</ja>
<jk>public</jk> HelloWorldResource getHelloWorldResource() {
<jk>return new</jk> HelloWorldResource();
}
<jc>// Injected child bean used in injected child resource.</jc>
<ja>@Bean</ja>
<jk>public</jk> HelloWorldMessageProvider getHelloWorldMessageProvider() {
<jk>return new</jk> HelloWorldMessageProvider(<js>"Hello Spring injection user!"</js>);
}
}
</p>
<p>
Our root resource servlet serves as a router page. It is defined as follows:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
title=<js>"Root resources"</js>,
description=<js>"Example of a router resource page."</js>,
children={
HelloWorldResource.<jk>class</jk>,
DtoExamples.<jk>class</jk>,
UtilityBeansResource.<jk>class</jk>,
HtmlBeansResource.<jk>class</jk>,
ConfigResource.<jk>class</jk>,
ShutdownResource.<jk>class</jk>
}
)
<ja>@HtmlDocConfig</ja>(
widgets={
ContentTypeMenuItem.<jk>class</jk>
},
navlinks={
<js>"api: servlet:/api"</js>,
<js>"stats: servlet:/stats"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/$R{servletClassSimple}.java"</js>
},
aside={
<js>"&lt;div class='text'&gt;"</js>,
<js>" &lt;p&gt;This is an example of a 'router' page that serves as a jumping-off point to child resources.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Resources can be nested arbitrarily deep through router pages.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Note the &lt;span class='link'&gt;API&lt;/span&gt; link provided that lets you see the generated swagger doc for this page.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Also note the &lt;span class='link'&gt;STATS&lt;/span&gt; link that provides basic usage statistics.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Also note the &lt;span class='link'&gt;SOURCE&lt;/span&gt; link on these pages to view the source code for the page.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;All content on pages in the UI are serialized POJOs. In this case, it's a serialized array of beans with 2 properties, 'name' and 'description'.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Other features (such as this aside) are added through annotations.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
},
asideFloat=<js>"RIGHT"</js>
)
<ja>@SerializerConfig</ja>(
quoteChar=<js>"'"</js>
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicSpringRestServletGroup <jk>implements</jk> BasicUniversalConfig {
<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L;
}
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrss.Overview.RootResources.png'>
<h5 class='figure'>JSON representation</h5>
<img class='bordered w800' src='doc-files/jrss.Overview.RootResources.json.png'>
<p>
The <a href="org/apache/juneau/examples/rest/springboot/HelloWorldResource.html" title="class in org.apache.juneau.examples.rest.springboot"><code>HelloWorldResource</code></a> class shows an example of a child resource
defined as an injected bean.
</p>
<p class='bjava'>
<ja>@Rest</ja>(
title=<js>"Hello World"</js>,
description=<js>"An example of the simplest-possible resource"</js>,
path=<js>"/helloWorld"</js>
)
<ja>@HtmlDocConfig</ja>(
aside={
<js>"&lt;div style='max-width:400px' class='text'&gt;"</js>,
<js>" &lt;p&gt;This page shows a resource that simply response with a 'Hello world!' message&lt;/p&gt;"</js>,
<js>" &lt;p&gt;The POJO serialized is a simple String.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig {
<ja>@Inject</ja>
<jk>private</jk> HelloWorldMessageProvider <jf>messageProvider</jf>;
<ja>@RestGet</ja>(path=<js>"/*"</js>, summary=<js>"Responds with injected message"</js>)
<jk>public</jk> String sayHello() {
<jk>return</jk> <jf>messageProvider</jf>.get();
}
}
</p>
<p>
Note that the message rendered is coming from our injected message provider:
</p>
<h5 class='figure'>HTML representation</h5>
<img class='bordered w800' src='doc-files/jrss.Overview.HelloWorldResource.png'>
</div>
</div><!-- END: 11.1 - juneau-rest-server-springboot.jrss.Overview -->
</div><!-- END: 11 - juneau-rest-server-springboot -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client' id='juneau-rest-client'>12 - juneau-rest-client</a><span class='update'>updated: <b>9.0.0</b></span></h2>
<div class='topic'><!-- START: 12 - juneau-rest-client -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-rest-client<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-rest-client-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.rest.client_9.0.0.jar
</p>
<p>
Built upon the feature-rich Apache HttpClient library, the Juneau RestClient API adds support for fluent-style
REST calls and the ability to perform marshalling of POJOs to and from HTTP parts.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a basic REST client with JSON support and download a bean.</jc>
MyBean <jv>bean</jv> = RestClient.<jsm>create</jsm>()
.simpleJson()
.build()
.get(<jsf>URI</jsf>)
.run()
.assertStatus().asCode().is(200)
.assertHeader(<js>"Content-Type"</js>).matchesSimple(<js>"application/json*"</js>)
.getContent().as(MyBean.<jk>class</jk>);
</p>
<p>
Breaking apart the fluent call, we can see the classes being used:
</p>
<p class='bjava'>
RestClient.Builder <jv>builder</jv> = RestClient.<jsm>create</jsm>().simpleJson();
RestClient <jv>client</jv> = <jv>builder</jv>.build();
RestRequest <jv>req</jv> = <jv>client</jv>.get(<jsf>URI</jsf>);
RestResponse <jv>res</jv> = <jv>req</jv>.run();
RestResponseStatusLineAssertion <jv>statusLineAssertion</jv> = <jv>res</jv>.assertStatus();
FluentIntegerAssertion&lt;RestResponse&gt; <jv>codeAssertion</jv> = <jv>statusLineAssertion</jv>.asCode();
<jv>res</jv> = <jv>codeAssertion</jv>.is(200);
FluentStringAssertion&lt;RestResponse&gt; <jv>headerAssertion</jv> = <jv>res</jv>.assertHeader(<js>"Content-Type"</js>);
<jv>res</jv> = <jv>headerAssertion</jv>.matchesSimple(<js>"application/json*"</js>);
ResponseContent <jv>content</jv> = <jv>res</jv>.getContent();
MyBean <jv>bean</jv> = <jv>content</jv>.as(MyBean.<jk>class</jk>);
</p>
<p>
It additionally provides support for creating remote proxy interfaces using REST as the transport medium.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Define a Remote proxy for interacting with a REST interface.</jc>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStore {
<ja>@RemotePost</ja>(<js>"/pets"</js>)
Pet addPet(
<ja>@Content</ja> CreatePet <jv>pet</jv>,
<ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
<ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
);
}
PetStore <jv>store</jv> = RestClient
.<jsm>create</jsm>()
.simpleJson()
.build()
.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
CreatePet <jv>createPet</jv> = <jk>new</jk> CreatePet(<js>"Fluffy"</js>, 9.99);
Pet <jv>pet</jv> = <jv>store</jv>.addPet(<jv>createPet</jv>, UUID.<jsm>randomUUID</jsm>(), <jk>true</jk>);
</p>
<p>
The classes are closely tied to Apache HttpClient, yet provide lots of additional functionality:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> <jk>implements</jk> <code>HttpClient</code>, creates <a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a> objects.
<li class='jc'><a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a> <jk>implements</jk> <code>HttpUriRequest</code>, creates <a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a> objects.
<li class='jc'><a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a> <jk>implements</jk> <code>HttpResponse</code>, creates <a href="org/apache/juneau/rest/client/ResponseContent.html" title="class in org.apache.juneau.rest.client"><code>ResponseContent</code></a> and <a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a> objects.
<li class='jc'><a href="org/apache/juneau/rest/client/ResponseContent.html" title="class in org.apache.juneau.rest.client"><code>ResponseContent</code></a> <jk>implements</jk> <code>HttpEntity</code>
</ul>
<p>
Instances of this class are built using the <a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a> class which can be constructed using
the <a href="org/apache/juneau/rest/client/RestClient.html#create--"><code>RestClient.create()</code></a> method as shown above.
</p>
<p>
Clients are typically created with a root URI so that relative URIs can be used when making requests.
This is done using the <a href="org/apache/juneau/rest/client/RestClient.Builder.html#rootUri-java.lang.Object-"><code>RestClient.Builder.rootUri(Object)</code></a> method.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a client where all URIs are relative to localhost.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().rootUri(<js>"http://localhost:10000"</js>).build();
<jc>// Use relative paths.</jc>
String <jv>content</jv> = <jv>client</jv>.get(<js>"/subpath"</js>).run().getContent().asString();
</p>
<p>
The <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> class creates <a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a> objects using the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#get-java.lang.Object-"><code>get(uri)</code></a> / <a href="org/apache/juneau/rest/client/RestClient.html#get--"><code>get()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#put-java.lang.Object-java.lang.Object-"><code>put(uri,body)</code></a> / <a href="org/apache/juneau/rest/client/RestClient.html#put-java.lang.Object-"><code>put(uri)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#post-java.lang.Object-"><code>post(uri,body)</code></a> / <a href="org/apache/juneau/rest/client/RestClient.html#post-java.lang.Object-"><code>post(uri)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#patch-java.lang.Object-java.lang.Object-"><code>patch(uri,body)</code></a> / <a href="org/apache/juneau/rest/client/RestClient.html#patch-java.lang.Object-"><code>patch(uri)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#delete-java.lang.Object-"><code>delete(uri)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#head-java.lang.Object-"><code>head(uri)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#options-java.lang.Object-"><code>options(uri)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#formPost-java.lang.Object-java.lang.Object-"><code>formPost(uri,body)</code></a> / <a href="org/apache/juneau/rest/client/RestClient.html#formPost-java.lang.Object-"><code>formPost(uri)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#formPostPairs-java.lang.Object-java.lang.Object...-"><code>formPostPairs(uri,parameters...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.html#request-java.lang.String-java.lang.Object-java.lang.Object-"><code>request(method,uri,body)</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a> class creates <a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a> objects using the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#run--"><code>run()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#complete--"><code>complete()</code></a>
</ul>
</li>
</ul>
<p>
The distinction between the two methods is that <a href="org/apache/juneau/rest/client/RestRequest.html#complete--"><code>complete()</code></a> automatically consumes the response body and
<a href="org/apache/juneau/rest/client/RestRequest.html#run--"><code>run()</code></a> does not. Note that you must consume response bodies in order for HTTP connections to be freed up
for reuse! The <a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStreams</code></a> returned by the <a href="org/apache/juneau/rest/client/ResponseContent.html" title="class in org.apache.juneau.rest.client"><code>ResponseContent</code></a> object are auto-closing once
they are exhausted, so it is often not necessary to explicitly close them.
</p>
<p>
The following examples show the distinction between the two calls:
</p>
<p class='bjava'>
<jc>// Consuming the response, so use run().</jc>
String <jv>content</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).run().getContent().asString();
<jc>// Only interested in response status code, so use complete().</jc>
<jk>int</jk> <jv>status</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode();
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.PojoMarshalling' id='juneau-rest-client.jrc.PojoMarshalling'>12.1 - POJO Marshalling</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.1 - juneau-rest-client.jrc.PojoMarshalling -->
<div class='topic'>
<p>
By default, JSON support is provided for HTTP request and response bodies.
Other languages can be specified using any of the following builder methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#json--"><code>json()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#simpleJson--"><code>simpleJson()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#xml--"><code>xml()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#html--"><code>html()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#plainText--"><code>plainText()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#msgPack--"><code>msgPack()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#uon--"><code>uon()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#urlEnc--"><code>urlEnc()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#openApi--"><code>openApi()</code></a>
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a basic REST client with Simplified-JSON support.</jc>
<jc>// Typically easier to use when performing unit tests.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().simpleJson().build();
</p>
<p>
Clients can also support multiple languages:
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a REST client with support for multiple languages.</jc>
RestClient <jv>client1</jv> = RestClient.<jsm>create</jsm>().json().xml().openApi().build();
<jc>// Create a REST client with support for all supported languages.</jc>
RestClient <jv>client2</jv> = RestClient.<jsm>create</jsm>().universal().build();
</p>
<p>
When using clients with multiple language support, the request language is selected by setting the <c>Content-Type</c>
request header.
</p>
<p class='bjava'>
<jc>// Create a REST client with support for multiple languages.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().universal().build();
<jv>client</jv>.post(<jsf>URI</jsf>, myBean)
.contentType(<js>"application/json"</js>)
.complete()
.assertStatus().asCode().is(200);
</p>
<p>
Languages can also be specified per-request.
</p>
<p class='bjava'>
<jc>// Create a REST client with no default languages supported.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().build();
<jc>// Use JSON for this request.</jc>
<jv>client</jv>.post(<jsf>URI</jsf>, myBean)
.json()
.complete()
.assertStatus().asCode().is(200);
</p>
<p>
The <a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a> class provides convenience methods for setting common serializer and parser
settings.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a basic REST client with JSON support.</jc>
<jc>// Use single-quotes and whitespace.</jc>
RestClient <jv>client1</jv> = RestClient.<jsm>create</jsm>().json().sq().ws().build();
</p>
<p>
Other methods are also provided for specifying the serializers and parsers used for lower-level marshalling support:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#serializer-org.apache.juneau.serializer.Serializer-"><code>serializer(Serializer)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#parser-org.apache.juneau.parser.Parser-"><code>parser(Parser)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#marshaller-org.apache.juneau.marshaller.Marshaller-"><code>marshaller(Marshaller)</code></a>
</ul>
</ul>
<p>
HTTP parts (headers, query parameters, form data...) are serialized and parsed using the <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a>
and <a href="org/apache/juneau/httppart/HttpPartParser.html" title="interface in org.apache.juneau.httppart"><code>HttpPartParser</code></a> APIs. By default, clients are configured to use <a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> and
<a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a>. These can be overridden using the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#partSerializer-java.lang.Class-"><code>partSerializer(Class&lt;? extends HttpPartSerializer>)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#partParser-java.lang.Class-"><code>partParser(Class&lt;? extends HttpPartParser>)</code></a>
</ul>
</ul>
</div>
</div><!-- END: 12.1 - juneau-rest-client.jrc.PojoMarshalling -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.RequestParts' id='juneau-rest-client.jrc.RequestParts'>12.2 - Request Parts</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.2 - juneau-rest-client.jrc.RequestParts -->
<div class='topic'>
<p>
Per-client or per-request HTTP parts (headers, query/form data, path parameters) can be manipulated via the following methods
that return back builders for those parts:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#headers--"><code>headers()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#formData--"><code>formData()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#queryData--"><code>queryData()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#pathData--"><code>pathData()</code></a>
</ul>
<li class='jc'><a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#headers--"><code>headers()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#formData--"><code>formData()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#queryData--"><code>queryData()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#pathData--"><code>pathData()</code></a>
</ul>
</ul>
<p>
Convenience methods are also provided for quickly adding parts:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#header-java.lang.String-java.lang.String-"><code>header(String,String)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#header-java.lang.String-java.util.function.Supplier-"><code>header(String,Supplier&lt;String&gt;)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#headers-org.apache.http.Header...-"><code>headers(Header...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#headersDefault-org.apache.http.Header...-"><code>headersDefault(Header...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#formData-org.apache.http.NameValuePair...-"><code>formData(NameValuePair...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#formData-java.lang.String-java.lang.String-"><code>formData(String,String)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#formData-java.lang.String-java.util.function.Supplier-"><code>formData(String,Supplier&lt;String&gt;)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#formDataDefault-org.apache.http.NameValuePair...-"><code>formDataDefault(NameValuePair...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#queryData-org.apache.http.NameValuePair...-"><code>queryData(NameValuePair...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#queryData-java.lang.String-java.lang.String-"><code>queryData(String,String)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#queryData-java.lang.String-java.util.function.Supplier-"><code>queryData(String,Supplier&lt;String&gt;)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#queryDataDefault-org.apache.http.NameValuePair...-"><code>queryDataDefault(NameValuePair...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#pathData-org.apache.http.NameValuePair...-"><code>pathData(NameValuePair...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#pathData-java.lang.String-java.lang.String-"><code>pathData(String,String)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#pathData-java.lang.String-java.util.function.Supplier-"><code>pathData(String,Supplier&lt;String&gt;)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#pathDataDefault-org.apache.http.NameValuePair...-"><code>pathDataDefault(NameValuePair...)</code></a>
</ul>
<li class='jc'><a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#header-org.apache.http.Header-"><code>header(Header)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#header-java.lang.String-java.lang.Object-"><code>header(String,Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#headerPairs-java.lang.String...-"><code>headerPairs(String...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#headers-org.apache.http.Header...-"><code>headers(Header...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#headersBean-java.lang.Object-"><code>headersBean(Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#formData-org.apache.http.NameValuePair...-"><code>formData(NameValuePair...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#formData-java.lang.String-java.lang.Object-"><code>formData(String,Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#formDataBean-java.lang.Object-"><code>formDataBean(Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#formDataCustom-java.lang.Object-"><code>formDataCustom(Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#formDataPairs-java.lang.String...-"><code>formDataPairs(String...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#queryData-org.apache.http.NameValuePair...-"><code>queryData(NameValuePair...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#queryData-java.lang.String-java.lang.Object-"><code>queryData(String,Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#queryDataBean-java.lang.Object-"><code>queryDataBean(Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#queryDataPairs-java.lang.String...-"><code>queryDataPairs(String...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#pathData-org.apache.http.NameValuePair...-"><code>pathData(NameValuePair...)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#pathData-java.lang.String-java.lang.Object-"><code>pathData(String,Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#pathDataBean-java.lang.Object-"><code>pathDataBean(Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#pathDataPairs-java.lang.String...-"><code>pathDataPairs(String...)</code></a>
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a client that adds a "Foo: bar" header to every request.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().header(<js>"Foo"</js>,<js>"bar"</js>).build();
<jc>// Or do it on every request.</jc>
String <jv>response</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).header(<js>"Foo"</js>,<js>"bar"</js>).run().getContent().asString();
</p>
<p>
The supplier methods are particularly useful for header values whose values may change over time (such as <c>Authorization</c> headers
which may need to change every few minutes).
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a client that adds a dynamic Authorization header to every request.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().header(<js>"Authorization"</js>, ()->getMyAuthToken()).build();
</p>
<ul class='seealso'>
<li class='jp'><a href="org/apache/juneau/http/header/package-summary.html"><code>org.apache.juneau.http.header</code></a> - Predefined <code>Header</code> beans.
</ul>
</div>
</div><!-- END: 12.2 - juneau-rest-client.jrc.RequestParts -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.RequestContent' id='juneau-rest-client.jrc.RequestContent'>12.3 - Request Content</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.3 - juneau-rest-client.jrc.RequestContent -->
<div class='topic'>
<p>
The request body can either be passed in with the client creator method (e.g. <a href="org/apache/juneau/rest/client/RestClient.html#post-java.lang.Object-java.lang.Object-"><code>post(uri,body)</code></a>),
or can be specified via the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#content-java.lang.Object-"><code>content(Object)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#content-java.lang.Object-org.apache.juneau.httppart.HttpPartSchema-"><code>content(Object,HttpPartSchema)</code></a>
</ul>
</ul>
<p>
The request body can be any of the following types:
</p>
<ul class='javatree'>
<li class='jc'>
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><code>Object</code></a> - POJO to be converted to text using the <a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a> defined on the client or request.
<li class='jc'>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a> - Raw contents of <code>Reader</code> will be serialized to remote resource.
<li class='jc'>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a> - Raw contents of <code>InputStream</code> will be serialized to remote resource.
<li class='jc'>
<code>HttpEntity</code> - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
<li class='jc'>
<a href="org/apache/juneau/http/part/PartList.html" title="class in org.apache.juneau.http.part"><code>PartList</code></a> - Converted to a URL-encoded FORM post.
<li class='jc'>
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html?is-external=true" title="class or interface in java.util.function"><code>Supplier</code></a> - A supplier of anything on this list.
</ul>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Create a client with Simple-JSON support.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().simpleJson().build();
<jc>// Post a JSON-serialized bean.</jc>
<jv>client</jv>
.post(<jsf>URI</jsf>)
.content(<jv>bean</jv>)
.complete()
.assertStatus().asCode().is(200);
<jc>// Post contents from a reader.</jc>
<jv>client</jv>
.post(<jsf>URI</jsf>)
.content(<jk>new</jk> FileReader(<js>"/tmp/foo.json"</js>))
.complete()
.assertStatus().asCode().is(200);
<jc>// Post contents from an Apache HttpEntity object.</jc>
<jv>client</jv>
.post(<jsf>URI</jsf>)
.content(<jk>new</jk> StringEntity(<jv>jsonString</jv>, ContentType.<jsf>APPLICATION_JSON</jsf>))
.complete()
.assertStatus().asCode().is(200);
</p>
<ul class='notes'>
<li class='note'>If the serializer on the client or request is explicitly set to <jk>null</jk>, POJOs will be converted to strings
using the registered part serializer as content type <js>"text/plain</js>. If the part serializer is also <jk>null</jk>,
POJOs will be converted to strings using <a href="org/apache/juneau/ClassMeta.html#toString-java.lang.Object-"><code>ClassMeta.toString(Object)</code></a> which typically just calls <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang"><code>Object.toString()</code></a>.
</ul>
</div>
</div><!-- END: 12.3 - juneau-rest-client.jrc.RequestContent -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.ResponseStatus' id='juneau-rest-client.jrc.ResponseStatus'>12.4 - Response Status</a><span class='update'>created: 8.1.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.4 - juneau-rest-client.jrc.ResponseStatus -->
<div class='topic'>
<p>
After execution using <a href="org/apache/juneau/rest/client/RestRequest.html#run--"><code>RestRequest.run()</code></a> or <a href="org/apache/juneau/rest/client/RestRequest.html#complete--"><code>RestRequest.complete()</code></a>, the following methods can be used
to get the response status:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a>
<ul>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getStatusLine--"><code>getStatusLine()</code></a> <jk>returns</jk> <code>StatusLine</code></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getStatusCode--"><code>getStatusCode()</code></a> <jk>returns</jk> <jk>int</jk></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getReasonPhrase--"><code>getReasonPhrase()</code></a> <jk>returns</jk> String</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#assertStatus--"><code>assertStatus()</code></a> <jk>returns</jk> <code>org.apache.juneau.rest.client.RestResponseStatusLineAssertion</code></c>
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Only interested in status code.</jc>
<jk>int</jk> <jv>statusCode</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode();
</p>
<p>
Equivalent methods with mutable parameters are provided to allow access to status values without breaking fluent call chains.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Interested in multiple values.</jc>
Value&lt;Integer&gt; <jv>statusCode</jv> = Value.<jsm>empty</jsm>();
Value&lt;String&gt; <jv>reasonPhrase</jv> = Value.<jsm>empty</jsm>();
<jv>client</jv>.get(<jsf>URI</jsf>).complete().getStatusCode(<jv>statusCode</jv>).getReasonPhrase(<jv>reasonPhrase</jv>);
System.<jsf>err</jsf>.println(<js>"statusCode="</js>+<jv>statusCode</jv>.get()+<js>", reasonPhrase="</js>+<jv>reasonPhrase</jv>.get());
</p>
<ul class='notes'>
<li class='note'>If you are only interested in the response status and not the response body, be sure to use <a href="org/apache/juneau/rest/client/RestRequest.html#complete--"><code>RestRequest.complete()</code></a> instead
of <a href="org/apache/juneau/rest/client/RestRequest.html#run--"><code>RestRequest.run()</code></a> to make sure the response body gets automatically cleaned up. Otherwise you must
consume the response yourself.
</ul>
<p>
The assertion method is provided for quickly asserting status codes in fluent calls.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Status assertion using a static value.</jc>
String <jv>content1</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
.run()
.assertStatus().asCode().isBetween(200,399)
.getContent().asString();
<jc>// Status assertion using a predicate.</jc>
String <jv>content2</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
.run()
.assertStatus().asCode().is(<jv>x</jv> -> <jv>x</jv>&lt;400)
.getContent().asString();
</p>
</div>
</div><!-- END: 12.4 - juneau-rest-client.jrc.ResponseStatus -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.ResponseHeaders' id='juneau-rest-client.jrc.ResponseHeaders'>12.5 - Response Headers</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.5 - juneau-rest-client.jrc.ResponseHeaders -->
<div class='topic'>
<p>
Response headers are accessed through the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a>
<ul>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getHeader-java.lang.String-"><code>getHeader(String)</code></a> <jk>returns</jk> <a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getHeaders-java.lang.String-"><code>getHeaders(String)</code></a> <jk>returns</jk> <a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a>[]</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getFirstHeader-java.lang.String-"><code>getFirstHeader(String)</code></a> <jk>returns</jk> <a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getLastHeader-java.lang.String-"><code>getLastHeader(String)</code></a> <jk>returns</jk> <a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getAllHeaders--"><code>getAllHeaders()</code></a> <jk>returns</jk> <a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a>[]</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getStringHeader-java.lang.String-"><code>getStringHeader(String)</code></a> <jk>returns</jk> String</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#containsHeader-java.lang.String-"><code>containsHeader(String)</code></a> <jk>returns</jk> <jk>boolean</jk></c>
</ul>
</ul>
<p>
Unlike <a href="org/apache/juneau/rest/client/RestResponse.html#getFirstHeader-java.lang.String-"><code>RestResponse.getFirstHeader(String)</code></a> and <a href="org/apache/juneau/rest/client/RestResponse.html#getLastHeader-java.lang.String-"><code>RestResponse.getLastHeader(String)</code></a>, the <a href="org/apache/juneau/rest/client/RestResponse.html#getHeader-java.lang.String-"><code>RestResponse.getHeader(String)</code></a>
method returns an empty <a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a> object instead of returning <jk>null</jk>.
This allows it to be used more easily in fluent calls.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
RestResponse <jv>res</jv> = <jv>client</jv>.get(<jsf>URI</jsf>).complete();
ResponseHeader <jv>header</jv> = <jv>res</jv>.getHeader(<js>"Location"</js>);
<jc>// See if response contains Location header.</jc>
<jk>boolean</jk> <jv>hasLocationHeader</jv> = <jv>header</jv>.isPresent();
<jc>// Get actual value if it exists.</jc>
<jk>String</jk> <jv>locationHeader1</jv> = <jv>header</jv>.orElse(<js>"http://localhost"</js>);
<jc>// Converted to object.</jc>
<jk>URI</jk> <jv>locationHeader2</jv> = <jv>header</jv>.as(URI.<jk>class</jk>).orElse(<jk>null</jk>);
</p>
<p>
The <a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a> class extends from the HttpClient <code>Header</code> class and provides several convenience
methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a>
<ul>
<li class='jm'><c><a href="org/apache/juneau/http/header/BasicHeader.html#isPresent--"><code>isPresent()</code></a> <jk>returns</jk> <jk>boolean</jk></c>
<li class='jm'><c><a href="org/apache/juneau/http/header/BasicHeader.html#asString--"><code>asString()</code></a> <jk>returns</jk> String</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#as-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>as(Type,Type...)</code></a> <jk>returns</jk> T</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#as-java.lang.Class-"><code>as(Class&lt;T&gt;)</code></a> <jk>returns</jk> T</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asMatcher-java.util.regex.Pattern-"><code>asMatcher(Pattern)</code></a> <jk>returns</jk> <a href="https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html?is-external=true" title="class or interface in java.util.regex"><code>Matcher</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asMatcher-java.lang.String-"><code>asMatcher(String)</code></a> <jk>returns</jk> <a href="https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html?is-external=true" title="class or interface in java.util.regex"><code>Matcher</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asHeader-java.lang.Class-"><code>asHeader(Class&lt;T <jk>extends</jk> BasicHeader&gt; c)</code></a> <jk>returns</jk> <code>org.apache.juneau.http.BasicHeader</code></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asStringHeader--"><code>asStringHeader()</code></a> <jk>returns</jk> <a href="org/apache/juneau/http/header/BasicIntegerHeader.html" title="class in org.apache.juneau.http.header"><code>BasicIntegerHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asIntegerHeader--"><code>asIntegerHeader()</code></a> <jk>returns</jk> <a href="org/apache/juneau/http/header/BasicStringHeader.html" title="class in org.apache.juneau.http.header"><code>BasicStringHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asLongHeader--"><code>asLongHeader()</code></a> <jk>returns</jk> <a href="org/apache/juneau/http/header/BasicLongHeader.html" title="class in org.apache.juneau.http.header"><code>BasicLongHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asDateHeader--"><code>asDateHeader()</code></a> <jk>returns</jk> <a href="org/apache/juneau/http/header/BasicDateHeader.html" title="class in org.apache.juneau.http.header"><code>BasicDateHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asCsvHeader--"><code>asCsvHeader()</code></a> <jk>returns</jk> <a href="org/apache/juneau/http/header/BasicCsvHeader.html" title="class in org.apache.juneau.http.header"><code>BasicCsvHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asEntityTagsHeader--"><code>asEntityTagsHeader()</code></a> <jk>returns</jk> <a href="org/apache/juneau/http/header/BasicEntityTagsHeader.html" title="class in org.apache.juneau.http.header"><code>BasicEntityTagsHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asStringRangesHeader--"><code>asStringRangesHeader()</code></a> <jk>returns</jk> <a href="org/apache/juneau/http/header/BasicStringRangesHeader.html" title="class in org.apache.juneau.http.header"><code>BasicStringRangesHeader</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#asUriHeader--"><code>asUriHeader()</code></a> <jk>returns</jk> <a href="org/apache/juneau/http/header/BasicUriHeader.html" title="class in org.apache.juneau.http.header"><code>BasicUriHeader</code></a></c>
</ul>
</ul>
<p>
The <a href="org/apache/juneau/rest/client/ResponseHeader.html#schema-org.apache.juneau.httppart.HttpPartSchema-"><code>ResponseHeader.schema(HttpPartSchema)</code></a> method allows you to perform parsing of OpenAPI formats for
header parts.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Parse the header "Foo: bar|baz".</jc>
List&lt;String&gt; <jv>fooHeader</jv> = <jv>client</jv>
.get(<jsf>URI</jsf>)
.complete()
.getHeader(<js>"Foo"</js>).schema(<jsf>T_ARRAY_PIPES</jsf>).as(List.<jk>class</jk>, String.<jk>class</jk>);
</p>
<p>
Assertion methods are also provided for fluent-style calls:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/ResponseHeader.html" title="class in org.apache.juneau.rest.client"><code>ResponseHeader</code></a>
<ul>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#assertString--"><code>assertString()</code></a> <jk>returns</jk> <a href="org/apache/juneau/assertions/FluentStringAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentStringAssertion</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#assertInteger--"><code>assertInteger()</code></a> <jk>returns</jk> <a href="org/apache/juneau/assertions/FluentIntegerAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentIntegerAssertion</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#assertLong--"><code>assertLong()</code></a> <jk>returns</jk> <a href="org/apache/juneau/assertions/FluentLongAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentLongAssertion</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseHeader.html#assertZonedDateTime--"><code>assertZonedDateTime()</code></a> <jk>returns</jk> <a href="org/apache/juneau/assertions/FluentZonedDateTimeAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentZonedDateTimeAssertion</code></a></c>
</ul>
</ul>
<p>
Note how in the following example, the fluent assertion returns control to the <a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a> object after
the assertion has been completed:
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Assert the response content type is any sort of JSON.</jc>
String <jv>content</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
.run()
.getHeader(<js>"Content-Type"</js>).assertString().matchesSimple(<js>"application/json*"</js>)
.getContent().asString();
</p>
</div>
</div><!-- END: 12.5 - juneau-rest-client.jrc.ResponseHeaders -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.ResponseContent' id='juneau-rest-client.jrc.ResponseContent'>12.6 - Response Content</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.6 - juneau-rest-client.jrc.ResponseContent -->
<div class='topic'>
<p>
The response body is accessed through the following method:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a>
<ul>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestResponse.html#getContent--"><code>getContent()</code></a> <jk>returns</jk> <a href="org/apache/juneau/rest/client/ResponseContent.html" title="class in org.apache.juneau.rest.client"><code>ResponseContent</code></a></c>
</ul>
</ul>
<p>
The <a href="org/apache/juneau/rest/client/ResponseContent.html" title="class in org.apache.juneau.rest.client"><code>ResponseContent</code></a> class extends from the HttpClient <code>HttpEntity</code> class and provides several convenience
methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/ResponseContent.html" title="class in org.apache.juneau.rest.client"><code>ResponseContent</code></a>
<ul>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asInputStream--"><code>asInputStream()</code></a> <jk>returns</jk> InputStream</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asReader--"><code>asReader()</code></a> <jk>returns</jk> Reader</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asReader-java.nio.charset.Charset-"><code>asReader(Charset)</code></a> <jk>returns</jk> Reader</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#pipeTo-java.io.OutputStream-"><code>pipeTo(OutputStream)</code></a> <jk>returns</jk> <a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#pipeTo-java.io.Writer-"><code>pipeTo(Writer)</code></a> <jk>returns</jk> <a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#as-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>as(Type,Type...)</code></a> <jk>returns</jk> T</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#as-java.lang.Class-"><code>as(Class&lt;T&gt;)</code></a> <jk>returns</jk> T</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asFuture-java.lang.Class-"><code>asFuture(Class&lt;T&gt;)</code></a> <jk>returns</jk> Future&lt;T&gt;</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asFuture-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>asFuture(Type,Type...)</code></a> <jk>returns</jk> Future&lt;T&gt;</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asString--"><code>asString()</code></a> <jk>returns</jk> String</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asStringFuture--"><code>asStringFuture()</code></a> <jk>returns</jk> Future&lt;String&gt;</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asAbbreviatedString-int-"><code>asAbbreviatedString(int)</code></a> <jk>returns</jk> String</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asMatcher-java.util.regex.Pattern-"><code>asMatcher(Pattern)</code></a> <jk>returns</jk> <a href="https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html?is-external=true" title="class or interface in java.util.regex"><code>Matcher</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#asMatcher-java.lang.String-"><code>asMatcher(String)</code></a> <jk>returns</jk> <a href="https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html?is-external=true" title="class or interface in java.util.regex"><code>Matcher</code></a></c>
</ul>
</ul>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Parse into a bean.</jc>
MyBean <jv>bean</jv> = <jv>client</jv>
.get(<jsf>URI</jsf>)
.run()
.getContent().as(MyBean.<jk>class</jk>);
<jc>// Parse into a linked-list of strings.</jc>
List&lt;String&gt; <jv>list1</jv> = <jv>client</jv>
.get(<jsf>URI</jsf>)
.run()
.getContent().as(LinkedList.<jk>class</jk>, String.<jk>class</jk>);
<jc>// Parse into a linked-list of beans.</jc>
List&lt;MyBean&gt; <jv>list2</jv> = <jv>client</jv>
.get(<jsf>URI</jsf>)
.run()
.getContent().as(LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
<jc>// Parse into a linked-list of linked-lists of strings.</jc>
List&lt;List&lt;String&gt;&gt; <jv>list3</jv> = <jv>client</jv>
.get(<jsf>URI</jsf>)
.run()
.getContent().as(LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>);
<jc>// Parse into a map of string keys/values.</jc>
Map&lt;String,String&gt; <jv>map1</jv> = <jv>client</jv>
.get(<jsf>URI</jsf>)
.run()
.getContent().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
<jc>// Parse into a map containing string keys and values of lists containing beans.</jc>
Map&lt;String,List&lt;MyBean&gt;&gt; <jv>map2</jv> = <jv>client</jv>
.get(<jsf>URI</jsf>)
.run()
.getContent().as(TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>);
</p>
<p>
The response body can only be consumed once unless it has been cached into memory. In many cases, the body is
automatically cached when using the assertions methods or methods such as <a href="org/apache/juneau/rest/client/ResponseContent.html#asString--"><code>ResponseContent.asString()</code></a>.
However, methods that involve reading directly from the input stream cannot be called twice.
In these cases, the <a href="org/apache/juneau/rest/client/RestResponse.html#cacheContent--"><code>RestResponse.cacheContent()</code></a> and <a href="org/apache/juneau/rest/client/ResponseContent.html#cache--"><code>ResponseContent.cache()</code></a> methods are provided
to cache the response body in memory so that you can perform several operations against it.
</p>
<p class='bjava'>
<jc>// Cache the response body so we can access it twice.</jc>
InputStream <jv>inputStream</jv> = <jv>client</jv>
.get(<jsf>URI</jsf>)
.run()
.cacheContent()
.getContent().pipeTo(<jv>someOtherStream</jv>)
.getContent().asInputStream();
</p>
<p>
Assertion methods are also provided for fluent-style calls:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/ResponseContent.html" title="class in org.apache.juneau.rest.client"><code>ResponseContent</code></a>
<ul>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#assertString--"><code>assertString()</code></a> <jk>returns</jk> <a href="org/apache/juneau/assertions/FluentStringAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentStringAssertion</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#assertBytes--"><code>assertBytes()</code></a> <jk>returns</jk> <a href="org/apache/juneau/assertions/FluentByteArrayAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentByteArrayAssertion</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#assertObject-java.lang.Class-"><code>assertObject(Class)</code></a> <jk>returns</jk> <a href="org/apache/juneau/assertions/FluentObjectAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentObjectAssertion</code></a></c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/ResponseContent.html#assertObject-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>assertObject(Type,Type...)</code></a> <jk>returns</jk> <a href="org/apache/juneau/assertions/FluentObjectAssertion.html" title="class in org.apache.juneau.assertions"><code>FluentObjectAssertion</code></a></c>
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Assert that the body contains the string "Success".</jc>
String <jv>content</jv> = <jv>client</jv>
.get(<jsf>URI</jsf>)
.run()
.getContent().assertString().contains(<js>"Success"</js>)
.getContent().asString();
</p>
<p>
Object assertions allow you to parse the response body into a POJO and then perform various tests on that resulting
POJO.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Parse bean into POJO and then validate that it was parsed correctly.</jc>
MyBean <jv>bean</jv> = <jv>client</jv>.get(<jsf>URI</jsf>)
.run()
.getContent().assertObject(MyBean.<jk>class</jk>).asJson().is(<js>"{foo:'bar'}"</js>)
.getContent().as(MyBean.<jk>class</jk>);
</p>
</div>
</div><!-- END: 12.6 - juneau-rest-client.jrc.ResponseContent -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.CustomCallHandlers' id='juneau-rest-client.jrc.CustomCallHandlers'>12.7 - Custom Call Handlers</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.7 - juneau-rest-client.jrc.CustomCallHandlers -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/client/RestCallHandler.html" title="interface in org.apache.juneau.rest.client"><code>RestCallHandler</code></a> interface provides the ability to provide custom handling of requests.
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#callHandler-java.lang.Class-"><code>callHandler(Class&lt;? extends RestCallHandler&gt;)</code></a>
</ul>
<li class='jic'><a href="org/apache/juneau/rest/client/RestCallHandler.html" title="interface in org.apache.juneau.rest.client"><code>RestCallHandler</code></a>
<ul>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestCallHandler.html#run-org.apache.http.HttpHost-org.apache.http.HttpRequest-org.apache.http.protocol.HttpContext-"><code>run(HttpHost,HttpRequest,HttpContext)</code></a> <jk>returns</jk> HttpResponse</c>
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Our custom call handler.</jc>
<jk>public class</jk> MyRestCallHandler <jk>implements</jk> RestCallHandler {
<jk>private final</jk> RestClient <jf>client</jf>;
<jk>public</jk> MyRestCallHandler(RestClient <jv>client</jv>) {
<jk>this</jk>.<jf>client</jf> = <jv>client</jv>;
}
<ja>@Override</ja>
<jk>public</jk> HttpResponse run(HttpHost <jv>target</jv>, HttpRequest <jv>request</jv>, HttpContext <jv>context</jv>) <jk>throws</jk> IOException {
<jc>// Insert any special handling here.</jc>
<jc>// The following is the default behavior:</jc>
<jk>if</jk> (<jv>target</jv> == <jk>null</jk>)
<jk>return</jk> <jf>client</jf>.execute((HttpUriRequest)<jv>request</jv>, <jv>context</jv>);
<jk>return</jk> <jf>client</jf>.execute(<jv>target</jv>, <jv>request</jv>, <jv>context</jv>);
}
}
<jc>// Create a client that uses our custom handler.</jc>
RestClient <jv>client</jv> = RestClient()
.create()
.json()
.callHandler(MyCallHandler.<jk>class</jk>)
.build();
</p>
<p>
Note that there are other ways of accomplishing this such as extending the <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> class and overriding
the <a href="org/apache/juneau/rest/client/RestClient.html#run-org.apache.http.HttpHost-org.apache.http.HttpRequest-org.apache.http.protocol.HttpContext-"><code>RestClient.run(HttpHost,HttpRequest,HttpContext)</code></a> method
or by defining your own <code>HttpRequestExecutor</code>. Using this interface is often simpler though.
</p>
</div>
</div><!-- END: 12.7 - juneau-rest-client.jrc.CustomCallHandlers -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Interceptors' id='juneau-rest-client.jrc.Interceptors'>12.8 - Interceptors</a><span class='update'>created: 8.2.0</span></h3>
<div class='topic'><!-- START: 12.8 - juneau-rest-client.jrc.Interceptors -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/client/RestCallInterceptor.html" title="interface in org.apache.juneau.rest.client"><code>RestCallInterceptor</code></a> API provides a quick way of intercepting and manipulating requests and responses beyond
the existing <code>org.apache.http.protocol.HttpRequestInterceptor</code> and <code>org.apache.http.protocol.HttpResponseInterceptor</code> APIs.
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#interceptors-java.lang.Object...-"><code>interceptors(Object...)</code></a>
</ul>
<li class='jc'><a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestRequest.html#interceptors-org.apache.juneau.rest.client.RestCallInterceptor...-"><code>interceptors(RestCallInterceptor...)</code></a>
</ul>
<li class='jic'><a href="org/apache/juneau/rest/client/RestCallInterceptor.html" title="interface in org.apache.juneau.rest.client"><code>RestCallInterceptor</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestCallInterceptor.html#onInit-org.apache.juneau.rest.client.RestRequest-"><code>onInit(RestRequest)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestCallInterceptor.html#onConnect-org.apache.juneau.rest.client.RestRequest-org.apache.juneau.rest.client.RestResponse-"><code>onConnect(RestRequest,RestResponse)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestCallInterceptor.html#onClose-org.apache.juneau.rest.client.RestRequest-org.apache.juneau.rest.client.RestResponse-"><code>onClose(RestRequest,RestResponse)</code></a>
</ul>
</ul>
<h5 class='section'>Example:</h5>
<p class='bjava'>
<jc>// Create a client with a customized interceptor.</jc>
RestClient <jv>client</jv> = RestClient
.<jsm>create</jsm>()
.interceptors(
<jk>new</jk> RestCallInterceptor() {
<ja>@Override</ja>
<jk>public void</jk> onInit(RestRequest <jv>req</jv>) <jk>throws</jk> Exception {
<jc>// Intercept immediately after RestRequest object is created and all headers/query/form-data has been
// set on the request from the client.</jc>
}
<ja>@Override</ja>
<jk>public void</jk> onConnect(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
<jc>// Intercept immediately after an HTTP response has been received.</jc>
}
<ja>@Override</ja>
<jk>public void</jk> onClose(RestRequest <jv>req</jv>, RestResponse <jv>res</jv>) <jk>throws</jk> Exception {
<jc>// Intercept when the response body is consumed.</jc>
}
}
)
.build();
</p>
</div>
</div><!-- END: 12.8 - juneau-rest-client.jrc.Interceptors -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies' id='juneau-rest-client.jrc.Proxies'>12.9 - REST Proxies</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.9 - juneau-rest-client.jrc.Proxies -->
<div class='topic'>
<p>
One of the more powerful features of the REST client class is the ability to produce Java interface proxies against
arbitrary 3rd party REST resources.
</p>
<p>
The methods to retrieve remote interfaces are:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a>
<ul>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestClient.html#getRemote-java.lang.Class-"><code>getRemote(Class&lt;T&gt;)</code></a> <jk>returns</jk> T</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestClient.html#getRemote-java.lang.Class-java.lang.Object-"><code>getRemote(Class&lt;T&gt;,Object)</code></a> <jk>returns</jk> T</c>
<li class='jm'><c><a href="org/apache/juneau/rest/client/RestClient.html#getRemote-java.lang.Class-java.lang.Object-org.apache.juneau.serializer.Serializer-org.apache.juneau.parser.Parser-"><code>getRemote(Class&lt;T&gt;,Object,Serializer,Parser)</code></a> <jk>returns</jk> T</c>
</ul>
</ul>
<p>
Annotations are used on the interface and interface methods to specify how to convert input and output to HTTP headers, query parameters, form
post parameters, or request/response bodies.
</p>
<ul class='javatree'>
<li class='jp'><a href="org/apache/juneau/http/remote/package-summary.html"><code>org.apache.juneau.http.remote</code></a>
<ul>
<li class='ja'><a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>Remote</code></a> - Applied to interface class.
<li class='ja'><a href="org/apache/juneau/http/remote/RemoteOp.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteOp</code></a> - Applied to interface methods.
</ul>
<li class='jp'><a href="org/apache/juneau/http/annotation/package-summary.html"><code>org.apache.juneau.http.annotation</code></a>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>Request</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a>
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStore {
<ja>@RemotePost</ja>(<js>"/pets"</js>)
Pet addPet(
<ja>@Content</ja> CreatePet <jv>createPet</jv>,
<ja>@Header</ja>(<js>"E-Tag"</js>) UUID <jv>etag</jv>,
<ja>@Query</ja>(<js>"debug"</js>) <jk>boolean</jk> <jv>debug</jv>
);
}
</p>
<p class='bjava'>
<jc>// Use a RestClient with default Simple JSON support.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().simpleJson().build();
<jc>// Instantiate our proxy interface.</jc>
PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
<jc>// Use it to create a pet.</jc>
CreatePet <jv>createPet</jv> = <jk>new</jk> CreatePet(<js>"Fluffy"</js>, 9.99);
Pet <jv>pet</jv> = <jv>store</jv>.addPet(<jv>createPet</jv>, UUID.<jsm>randomUUID</jsm>(), <jk>true</jk>);
</p>
<p>
The call above translates to the following REST call:
</p>
<p class='bcode'>
POST http://localhost:10000/petstore/pets?debug=true HTTP/1.1
Accept: application/json
Content-Type: application/json
E-Tag: 475588d4-0b27-4f56-9296-cc683251d314
{
name: 'Fluffy',
price: 9.99
}
</p>
<p>
The <ja>@RemoteOp</ja> annotations can be eliminated if you use specific naming conventions on your
method names to identify the HTTP method and path.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStore {
<jc>// @RemoteOp optional since method and path is inferred from method name.</jc>
String postPets(<ja>@Content</ja> CreatePet pet);
}
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.Remote' id='juneau-rest-client.jrc.Proxies.jrc.Remote'>12.9.1 - @Remote</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 12.9.1 - juneau-rest-client.jrc.Proxies.jrc.Remote -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>@Remote</code></a> annotation is used on your interface class
to identify it as a REST proxy interface.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>Remote</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/remote/Remote.html#path--"><code>path</code></a>
<li class='jma'><a href="org/apache/juneau/http/remote/Remote.html#headers--"><code>headers</code></a>
<li class='jma'><a href="org/apache/juneau/http/remote/Remote.html#version--"><code>version</code></a>
<li class='jma'><a href="org/apache/juneau/http/remote/Remote.html#versionHeader--"><code>versionHeader</code></a>
</ul>
</li>
</ul>
<p>
The <ja>@Remote</ja> annotation is optional but often included for code readability.
</p>
<h5 class='topic'>@Remote(path)</h5>
<p>
The <a href="org/apache/juneau/http/remote/Remote.html#path--"><code>@Remote(path)</code></a> annotation is used to define the
HTTP path of the REST service.
</p>
<p>
The path can be an absolute path to your REST service.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"http://localhost:10000/petstore"</js>)
<jk>public interface</jk> PetStore {...}
</p>
<p class='bjava'>
PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>);
</p>
<p>
<a class='doclink' href='#juneau-marshall.jm.SimpleVariableLanguage.jm.DefaultVarResolver'>Overview &gt; juneau-marshall &gt; Simple Variable Language &gt; VarResolver.DEFAULT</a> can also be used in the path.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// URL is specified via a system property.</jc>
<ja>@Remote</ja>(path=<js>"$S{PetStoreUrl}"</js>)
<jk>public interface</jk> PetStore {...}
</p>
<p>
When a relative path is specified, it's relative to the root-url defined on the <c>RestClient</c> used to instantiate the interface.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStore {...}
</p>
<p class='bjava'>
RestClient <jv>client</jv> = RestClient
.<jsm>create</jsm>()
.json()
.rootUrl(<js>"http://localhost:10000"</js>)
.build();
PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>);
</p>
<p>
When no path is specified, the root-url defined on the <c>RestClient</c> is used.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>
<jk>public interface</jk> PetStore {...}
</p>
<p class='bjava'>
RestClient <jv>client</jv> = RestClient
.<jsm>create</jsm>()
.json()
.rootUrl(<js>"http://localhost:10000/petstore"</js>)
.build();
PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>);
</p>
<h5 class='topic'>@Remote(headers/headerList)</h5>
<p>
The <a href="org/apache/juneau/http/remote/Remote.html#headers--"><code>@Remote(headers)</code></a> and <a href="org/apache/juneau/http/remote/Remote.html#headerList--"><code>@Remote(headerList)</code></a>
annotations are used to add headers on all requests.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(
path=<js>"/petstore"</js>,
headers={
<js>"Foo: bar"</js>,
<js>"Baz: $S{bazProperty}"</js>
},
headerList=MyHeaderList.<jk>class</jk>
)
<jk>public interface</jk> PetStore {...}
</p>
<p class='bjava'>
<jc>// Our dynamic supplier.</jc>
<jk>public class</jk> MyHeaderList <jk>extends</jk> HeaderList {
...
}
</p>
<h5 class='topic'>@Remote(version/versionHeader)</h5>
<p>
The <a href="org/apache/juneau/http/remote/Remote.html#version--"><code>@Remote(version)</code></a> and <a href="org/apache/juneau/http/remote/Remote.html#versionHeader--"><code>@Remote(versionHeader)</code></a>
annotations are used to specify the client-side version of this interface that can be used on the server side
to perform version-specific handling.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(
path=<js>"/petstore"</js>,
version=<js>"1.2.3"</js> <jc>// Adds "Client-Version: 1.2.3" header to all requests.</jc>
)
<jk>public interface</jk> PetStore {...}
</p>
<p>
This can be used in conjunction with the server-side client-versioning support.
</p>
<p class='bjava'>
<jc>// Call this method if Client-Version is at least 2.0.
// Note that this also matches 2.0.1.</jc>
<ja>@RestGet</ja>(clientVersion=<js>"2.0"</js>)
<jk>public</jk> Object foo() {...}
<jc>// Call this method if Client-Version is at least 1.1 but less than 2.0.</jc>
<ja>@RestGet</ja>(clientVersion=<js>"[1.1,2.0)"</js>)
<jk>public</jk> Object foo() {...}
<jc>// Call this method if Client-Version is less than 1.1.</jc>
<ja>@RestGet</ja>(clientVersion=<js>"[0,1.1)"</js>)
<jk>public</jk> Object foo() {...}
</p>
<ul class='seealso'>
<li class='doclink'><a class='doclink' href='#juneau-rest-server.jrs.ClientVersioning'>Overview &gt; juneau-rest-server &gt; Client Versioning</a>
</ul>
</div>
</div><!-- END: 12.9.1 - juneau-rest-client.jrc.Proxies.jrc.Remote -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.RemoteMethod' id='juneau-rest-client.jrc.Proxies.jrc.RemoteMethod'>12.9.2 - @RemoteOp</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 12.9.2 - juneau-rest-client.jrc.Proxies.jrc.RemoteMethod -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/remote/RemoteOp.html" title="annotation in org.apache.juneau.http.remote"><code>@RemoteOp</code></a> annotation is applied to methods
of <ja>@Remote</ja>-annotated interfaces to identify REST endpoints.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/remote/RemoteOp.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteOp</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/remote/RemoteOp.html#method--"><code>method</code></a>
<li class='jma'><a href="org/apache/juneau/http/remote/RemoteOp.html#path--"><code>path</code></a>
<li class='jma'><a href="org/apache/juneau/http/remote/RemoteOp.html#returns--"><code>returns</code></a>
</ul>
</li>
</ul>
<h5 class='topic'>@RemoteOp(method/path)</h5>
<p>
The HTTP method and path are mapped to a Java method using the <c>method</c> and <c>path</c> annotations.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>
<jk>public interface</jk> PetStore {
<jc>// GET /pets/{petId}</jc>
<ja>@RemoteGet</ja>(<js>"/pets/{petId}"</js>)
Pet getPet(<ja>@Path</ja>(<js>"petId"</js>) <jk>int</jk> <jv>id</jv>);
}
</p>
<p>
The Java method name can be anything.
</p>
<h5 class='topic'>Inferred method/path</h5>
<p>
In such cases, <c>method</c> and <c>path</c> annotations are optional if you follow certain naming
conventions on your method that identify the method and path.
</p>
<p>
For example, the <c>getPet</c> method below defaults to <c>GET /pet</c>:
</p>
<p class='bjava'>
<ja>@Remote</ja>
<jk>public interface</jk> PetStore {
<jc>// GET /pet</jc>
<ja>@RemoteOp</ja>
Pet getPet(...);
}
</p>
<p>
In such cases, the <ja>@RemoteOp</ja> annotation is optional.
</p>
<p>
Method names matching the following pattern are assumed to be implying the HTTP method name:
</p>
<p class='bcode'>
(get|put|post|delete|options|head|connect|trace|patch).*
</p>
<p class='bcode'>
do(?i)(get|put|post|delete|options|head|connect|trace|patch)
</p>
<h5 class='figure'>Examples:</h5>
<table class='styled w500'>
<tr>
<th>Java method name</th>
<th>Inferred HTTP method</th>
<th>Inferred HTTP path</th>
</tr>
<tr>
<td class='code'>getPet()</td>
<td class='code'>GET</td>
<td class='code'>/pet</td>
</tr>
<tr>
<td class='code'>get()</td>
<td class='code'>GET</td>
<td class='code'>/</td>
</tr>
<tr>
<td class='code'>postPet()</td>
<td class='code'>POST</td>
<td class='code'>/pet</td>
</tr>
<tr>
<td class='code'>fooPet()</td>
<td class='code'>[default]</td>
<td class='code'>/fooPet</td>
</tr>
<tr>
<td class='code'>doGet()</td>
<td class='code'>GET</td>
<td class='code'>/</td>
</tr>
<tr>
<td class='code'>doGET()</td>
<td class='code'>GET</td>
<td class='code'>/</td>
</tr>
<tr>
<td class='code'>doFoo()</td>
<td class='code'>[default]</td>
<td class='code'>/doFoo</td>
</tr>
</table>
<h5 class='topic'>@RemoteOp(returns)</h5>
<p>
The return type of the Java methods of can be any of the following:
</p>
<ul class='spaced-list'>
<li>
<jk>void</jk>/<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Void.html?is-external=true" title="class or interface in java.lang"><code>Void</code></a>
- Don't parse any response.
<br>Note that the method will still throw a runtime exception if an error HTTP status is returned.
<li>
Any <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>parsable</a> POJO
- The body of the response will be converted to the POJO using the parser defined on the
<c>RestClient</c> based on the <c>Content-Type</c> of the response.
<li>
Any <a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>@Response</code></a>-annotated type. (described later)
<li>
<c>HttpResponse</c>
- Returns the raw <c>HttpResponse</c> returned by the inner <c>HttpClient</c>.
<li>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a>
- Returns access to the raw reader of the response.
<li>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a>
- Returns access to the raw input stream of the response.
<li>
A <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html?is-external=true" title="class or interface in java.util.concurrent"><code>Future</code></a> or <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html?is-external=true" title="class or interface in java.util.concurrent"><code>CompletableFuture</code></a> of anything on this list.
</ul>
<p>
If you're only interested in the HTTP status code of the response, you can use the <a href="org/apache/juneau/http/remote/RemoteOp.html#returns--"><code>returns</code></a>
annotation with a value of <a href="org/apache/juneau/http/remote/RemoteReturn.html#STATUS"><code>STATUS</code></a>:
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>
<jk>public interface</jk> PetStore {
<jc>// POST /pets</jc>
<jc>// Returns HTTP status code.</jc>
<ja>@RemotePost</ja>(returns=<jsf>STATUS</jsf>)
<jk>int</jk> pets(...);
}
</p>
<p>
If your <c>RestClient</c> does not have a parser associated with it, then the value is converted directly from a String using
the rules defined in <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Overview &gt; juneau-marshall &gt; POJO Categories</a>.
</p>
</div>
</div><!-- END: 12.9.2 - juneau-rest-client.jrc.Proxies.jrc.RemoteMethod -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.Content' id='juneau-rest-client.jrc.Proxies.jrc.Content'>12.9.3 - @Content</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 12.9.3 - juneau-rest-client.jrc.Proxies.jrc.Content -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>@Content</code></a> annotation can be applied to arguments of <ja>@RemoteOp</ja>-annotated methods
to denote that they are the HTTP body of the request.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<ul class='javatreec'>
<li class='jma'><a href="org/apache/juneau/http/annotation/Content.html#schema--"><code>schema</code></a>
</ul>
</li>
</ul>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// Used on parameter</jc>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStore {
<ja>@RemotePost</ja>(<js>"/pets"</js>)
String addPet(<ja>@Content</ja> Pet <jv>pet</jv>);
}
</p>
<p class='bjava'>
<jc>// Used on class</jc>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStore {
<ja>@RemotePost</ja>(<js>"/pets"</js>)
String addPet(Pet <jv>pet</jv>);
}
<ja>@Content</ja>
<jk>public class</jk> Pet {...}
</p>
<p>
The argument can be any of the following types:
</p>
<ul class='spaced-list'>
<li>
Any serializable POJO - Converted to output using the <a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a> registered with the <c>RestClient</c>.
<br><c>Content-Type</c> is set to that of the <c>Serializer</c>.
<li>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a> - Raw contents of <code>Reader</code> will be serialized to remote resource.
<br><c>Content-Type</c> is set to <js>"text/plain"</js>.
<li>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a> - Raw contents of <code>InputStream</code> will be serialized to remote resource.
<br><c>Content-Type</c> is set to <js>"application/octet-stream"</js>.
<li>
<a href="org/apache/juneau/http/part/PartList.html" title="class in org.apache.juneau.http.part"><code>PartList</code></a> - Converted to a URL-encoded FORM post.
<br><c>Content-Type</c> is set to <js>"aplication/x-www-form-urlencoded"</js>.
<li>
<c>HttpEntity</c> - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
</ul>
<p>
OpenAPI schema based serialization can be used by using the <a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> class.
</p>
<p class='bjava'>
<ja>@RemotePost</ja>(<js>"/comma-delimited-pipe-delimited-ints"</js>)
String addCommaDelimitedPipeDelimitedInts(
<ja>@Content</ja>(
serializer=OpenApiSerializer.<jk>class</jk>,
schema=<ja>@Schema</ja>(
type=<js>"array"</js>,
collectionFormat=<js>"pipes"</js>,
items=<ja>@Items</ja>(
type=<js>"array"</js>
items=<ja>@SubItems</ja>(
type=<js>"int32"</js>,
<jc>// Auto-validates on client side!</jc>
minimum=<js>"0"</js>,
maximum=<js>"64"</js>
)
)
)
)
<jk>int</jk>[][] <jv>input</jv>
);
</p>
<p class='bjava'>
<jc>// Same as above but using free-form schema.</jc>
<jc>// Format is simplified-JSON (outer {} brackets are optional).</jc>
<ja>@RemotePost</ja>(<js>"/comma-delimited-pipe-delimited-ints"</js>)
String addCommaDelimitedPipeDelimitedInts(
<ja>@Content</ja>(
serializer=OpenApiSerializer.<jk>class</jk>,
schema=<ja>@Schema</ja>(
<js>"type:'array',collectionFormat:'pipes',items:[type:'array',items:[type:'int32',minimum:0,maximum:64]]"</js>
)
)
<jk>int</jk>[][] <jv>input</jv>
);
</p>
<p>
See <a class='doclink' href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers'>Overview &gt; juneau-marshall &gt; OpenAPI Details &gt; OpenAPI Serializers</a> for information about supported data types in OpenAPI serialization.
</p>
<p>
If your <c>RestClient</c> class does not have a serializer associated with it, the body will automatically be serialized to a
string using the rules defined in <a class='doclink' href='#juneau-marshall.jm.PojoCategories'>Overview &gt; juneau-marshall &gt; POJO Categories</a>.
</p>
</div>
</div><!-- END: 12.9.3 - juneau-rest-client.jrc.Proxies.jrc.Content -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.FormData' id='juneau-rest-client.jrc.Proxies.jrc.FormData'>12.9.4 - @FormData</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 12.9.4 - juneau-rest-client.jrc.Proxies.jrc.FormData -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>@FormData</code></a> annotation can be applied to arguments of <ja>@RemoteOp</ja>-annotated methods
to denote that they are form-data parameters on the request.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/http/annotation/FormData.html#name--"><code>name</code></a> - Form data entry name.
<li class='jf'><a href="org/apache/juneau/http/annotation/FormData.html#serializer--"><code>serializer</code></a> - Override the part serializer.
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/myproxy"</js>)
<jk>public interface</jk> MyProxy {
<jc>// Explicit names specified for form data parameters.</jc>
<ja>@RemotePost</ja>
String postParameters(
<ja>@FormData</ja>(<js>"foo"</js>)</ja> String <jv>foo</jv>,
<ja>@FormData</ja>(<js>"bar"</js>)</ja> MyPojo <jv>pojo</jv>
);
<jc>// Multiple values pulled from a PartList object.</jc>
<jc>// Name "*" is inferred.</jc>
<ja>@RemotePost</ja>
String postPartList(<ja>@FormData</ja> PartList <jv>partList</jv>);
<jc>// Multiple values pulled from a Map.</jc>
<ja>@RemotePost</ja>
String postMap(<ja>@FormData</ja> Map&lt;String,Object&gt; <jv>map</jv>);
<jc>// Multiple values pulled from a bean.</jc>
<ja>@RemotePost</ja>
String postBean(<ja>@FormData</ja> MyBean <jv>bean</jv>);
<jc>// An entire form-data HTTP body as a String.</jc>
<ja>@RemotePost</ja>
String postString(<ja>@FormData</ja> String <jv>string</jv>);
<jc>// An entire form-data HTTP body as a Reader.</jc>
<ja>@RemotePost</ja>
String postReader(<ja>@FormData</ja> Reader <jv>reader</jv>);
}
</p>
<p>
Single-part arguments (i.e. those with name != <js>"*"</js>) can be any of the following types:
</p>
<ul class='spaced-list'>
<li>
Any serializable POJO - Converted to a string using the <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> registered with the
<c>RestClient</c> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default) or associated via the <a href="org/apache/juneau/http/annotation/FormData.html#serializer--"><code>@FormData(serializer)</code></a> annotation.
</ul>
<p>
Multi-part arguments (i.e. those with name == <js>"*"</js> or empty) can be any of the following types:
</p>
<ul class='spaced-list'>
<li>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a> - Raw contents of <code>Reader</code> will be serialized to remote resource.
<li>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a> - Raw contents of <code>InputStream</code> will be serialized to remote resource.
<li>
<a href="org/apache/juneau/http/part/PartList.html" title="class in org.apache.juneau.http.part"><code>PartList</code></a> - Converted to a URL-encoded FORM post.
<li>
<c>Map</c> - Converted to key-value pairs.
<br>Values serialized using the registered <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default).
<li>
Bean - Converted to key-value pairs.
<br>Values serialized using the registered <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default).
<li>
<c>CharSequence</c> - Used directly as am <js>"application/x-www-form-urlencoded"</js> entity.
</ul>
<p>
See the link below for information about supported data types in OpenAPI serialization.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers'>Overview &gt; juneau-marshall &gt; OpenAPI Details &gt; OpenAPI Serializers</a>
</ul>
</div>
</div><!-- END: 12.9.4 - juneau-rest-client.jrc.Proxies.jrc.FormData -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.Query' id='juneau-rest-client.jrc.Proxies.jrc.Query'>12.9.5 - @Query</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 12.9.5 - juneau-rest-client.jrc.Proxies.jrc.Query -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>@Query</code></a> annotation can be applied to arguments of <ja>@RemoteOp</ja>-annotated methods
to denote that they are query parameters on the request.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/http/annotation/Query.html#name--"><code>name</code></a> - Query parameter name.
<li class='jf'><a href="org/apache/juneau/http/annotation/Query.html#serializer--"><code>serializer</code></a> - Override the part serializer.
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/myproxy"</js>)
<jk>public interface</jk> MyProxy {
<jc>// Explicit names specified for query parameters.</jc>
<ja>@RemoteGet</ja>
String parameters(
<ja>@Query</ja>(<js>"foo"</js>)</ja> String <jv>foo</jv>,
<ja>@Query</ja>(<js>"bar"</js>)</ja> MyPojo <jv>pojo</jv>);
<jc>// Multiple values pulled from a PartList object.</jc>
<jc>// Same as @Query("*").</jc>
<ja>@RemoteGet</ja>
String partList(<ja>@Query</ja> PartList <jv>partList</jv>);
<jc>// Multiple values pulled from a Map.</jc>
<jc>// Same as @Query("*").</jc>
<ja>@RemoteGet</ja>
String map(<ja>@Query</ja> Map&lt;String,Object&gt; <jv>map</jv>);
<jc>// Multiple values pulled from a bean.</jc>
<jc>// Same as @Query("*").</jc>
<ja>@RemoteGet</ja>
String bean(<ja>@Query</ja> MyBean <jv>myBean</jv>);
<jc>// An entire query string as a String.</jc>
<jc>// Same as @Query("*").</jc>
<ja>@RemoteGet</ja>
String string(<ja>@Query</ja> String <jv>string</jv>);
<jc>// An entire query string as a Reader.</jc>
<jc>// Same as @Query("*").</jc>
<ja>@RemoteGet</ja>
String reader(<ja>@Query</ja> Reader <jv>reader</jv>);
}
</p>
<p>
Single-part arguments (i.e. those with name != <js>"*"</js>) can be any of the following types:
</p>
<ul class='spaced-list'>
<li>
Any serializable POJO - Converted to a string using the <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> registered with the
<c>RestClient</c> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default) or associated via the <a href="org/apache/juneau/http/annotation/Query.html#serializer--"><code>@Query(serializer)</code></a> annotation.
</ul>
<p>
Multi-part arguments (i.e. those with name == <js>"*"</js> or empty) can be any of the following types:
</p>
<ul class='spaced-list'>
<li>
<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a> - Raw contents of <code>Reader</code> will be serialized directly a query string.
<li>
<a href="org/apache/juneau/http/part/PartList.html" title="class in org.apache.juneau.http.part"><code>PartList</code></a> - Serialized as individual query parameters.
<li>
<c>Map</c> - Converted to key-value pairs.
<br>Values serialized using the registered <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default).
<li>
Bean - Converted to key-value pairs.
<br>Values serialized using the registered <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default).
<li>
<c>CharSequence</c> - Serialized directly a query string.
</ul>
<p>
See the link below for information about supported data types in OpenAPI serialization.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers'>Overview &gt; juneau-marshall &gt; OpenAPI Details &gt; OpenAPI Serializers</a>
</ul>
</div>
</div><!-- END: 12.9.5 - juneau-rest-client.jrc.Proxies.jrc.Query -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.Header' id='juneau-rest-client.jrc.Proxies.jrc.Header'>12.9.6 - @Header</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 12.9.6 - juneau-rest-client.jrc.Proxies.jrc.Header -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>@Header</code></a> annotation can be applied to arguments of <ja>@RemoteOp</ja>-annotated methods
to denote that they are header parameters on the request.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/http/annotation/Header.html#name--"><code>name</code></a> - Header name.
<li class='jf'><a href="org/apache/juneau/http/annotation/Header.html#serializer--"><code>serializer</code></a> - Override the part serializer.
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/myproxy"</js>)
<jk>public interface</jk> MyProxy {
<jc>// Explicit names specified for HTTP headers.</jc>
<jc>// pojo will be converted to UON notation (unless plain-text parts enabled).</jc>
<ja>@RemoteGet</ja>(<js>"/mymethod1"</js>)
String myProxyMethod1(<ja>@Header</ja>(<js>"Foo"</js>)</ja> String <jv>foo</jv>,
<ja>@Header</ja>(<js>"Bar"</js>)</ja> MyPojo <jv>pojo</jv>);
<jc>// Multiple values pulled from a HeaderList object.</jc>
<jc>// Same as @Header("*").</jc>
<ja>@RemoteGet</ja>(<js>"/mymethod2"</js>)
String myProxyMethod2(<ja>@Header</ja> HeaderList <jv>headerList</jv>);
<jc>// Multiple values pulled from a Map.</jc>
<jc>// Same as @Header("*").</jc>
<ja>@RemoteGet</ja>(<js>"/mymethod3"</js>)
String myProxyMethod3(<ja>@Header</ja> Map&lt;String,Object&gt; <jv>map</jv>);
<jc>// Multiple values pulled from a bean.</jc>
<jc>// Same as @Header("*").</jc>
<ja>@RemoteGet</ja>(<js>"/mymethod4"</js>)
String myProxyMethod4(<ja>@Header</ja> MyBean <jv>myBean</jv>);
}
</p>
<p>
Single-part arguments (i.e. those with name != <js>"*"</js>) can be any of the following types:
</p>
<ul class='spaced-list'>
<li>
Any serializable POJO - Converted to a string using the <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> registered with the
<c>RestClient</c> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default) or associated via the <a href="org/apache/juneau/http/annotation/Header.html#serializer--"><code>@Header(serializer)</code></a> annotation.
</ul>
<p>
Multi-part arguments (i.e. those with name == <js>"*"</js> or empty) can be any of the following types:
</p>
<ul class='spaced-list'>
<li>
<a href="org/apache/juneau/http/header/HeaderList.html" title="class in org.apache.juneau.http.header"><code>HeaderList</code></a> - Serialized as individual headers.
<li>
<c>Map</c> - Converted to key-value pairs.
<br>Values serialized using the registered <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default).
<li>
Bean - Converted to key-value pairs.
<br>Values serialized using the registered <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default).
</ul>
<p>
See the link below for information about supported data types in OpenAPI serialization.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers'>Overview &gt; juneau-marshall &gt; OpenAPI Details &gt; OpenAPI Serializers</a>
</ul>
</div>
</div><!-- END: 12.9.6 - juneau-rest-client.jrc.Proxies.jrc.Header -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.Path' id='juneau-rest-client.jrc.Proxies.jrc.Path'>12.9.7 - @Path</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 12.9.7 - juneau-rest-client.jrc.Proxies.jrc.Path -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>@Path</code></a> annotation can be applied to arguments of <ja>@RemoteOp</ja>-annotated methods
to denote that they are path parameters on the request.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/http/annotation/Path.html#name--"><code>name</code></a> - Path variable name.
<li class='jf'><a href="org/apache/juneau/http/annotation/Path.html#serializer--"><code>serializer</code></a> - Override the part serializer.
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/myproxy"</js>)
<jk>public interface</jk> MyProxy {
<jc>// Explicit names specified for path parameters.</jc>
<jc>// pojo will be converted to UON notation (unless plain-text parts enabled).</jc>
<ja>@RemoteGet</ja>(<js>"/mymethod1/{foo}/{bar}"</js>)
String myProxyMethod1(<ja>@Path</ja>(<js>"foo"</js>)</ja> String <jv>foo</jv>, <ja>@Path</ja>(<js>"bar"</js>)</ja> MyPojo <jv>pojo</jv>);
<jc>// Multiple values pulled from a PartList object.</jc>
<jc>// Same as @Path("*").</jc>
<ja>@RemoteGet</ja>(<js>"/mymethod2/{foo}/{bar}/{baz}"</js>)
String myProxyMethod2(<ja>@Path</ja> PartList <jv>partList</jv>);
<jc>// Multiple values pulled from a Map.</jc>
<jc>// Same as @Path("*").</jc>
<ja>@RemoteGet</ja>(<js>"/mymethod3/{foo}/{bar}/{baz}"</js>)
String myProxyMethod3(<ja>@Path</ja> Map&lt;String,Object&gt; <jv>map</jv>);
<jc>// Multiple values pulled from a bean.</jc>
<jc>// Same as @Path("*").</jc>
<ja>@RemoteGet</ja>(<js>"/mymethod4/{foo}/{bar}/{baz}"</js>)
String myProxyMethod4(<ja>@Path</ja> MyBean <jv>myBean</jv>);
}
</p>
<p>
Single-part arguments (i.e. those with name != <js>"*"</js>) can be any of the following types:
</p>
<ul class='spaced-list'>
<li>
Any serializable POJO - Converted to a string using the <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> registered with the
<c>RestClient</c> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default) or associated via the <a href="org/apache/juneau/http/annotation/Path.html#serializer--"><code>@Path(serializer)</code></a> annotation.
</ul>
<p>
Multi-part arguments (i.e. those with name == <js>"*"</js> or empty) can be any of the following types:
</p>
<ul class='spaced-list'>
<li>
<a href="org/apache/juneau/http/part/PartList.html" title="class in org.apache.juneau.http.part"><code>PartList</code></a> - Serialized as individual path parameters.
<li>
<c>Map</c> - Converted to key-value pairs.
<br>Values serialized using the registered <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default).
<li>
Bean - Converted to key-value pairs.
<br>Values serialized using the registered <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a> (<a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a> by default).
</ul>
<p>
See the link below for information about supported data types in OpenAPI serialization.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails.jm.OpenApiSerializers'>Overview &gt; juneau-marshall &gt; OpenAPI Details &gt; OpenAPI Serializers</a>
</ul>
</div>
</div><!-- END: 12.9.7 - juneau-rest-client.jrc.Proxies.jrc.Path -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.Request' id='juneau-rest-client.jrc.Proxies.jrc.Request'>12.9.8 - @Request</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 12.9.8 - juneau-rest-client.jrc.Proxies.jrc.Request -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>@Request</code></a> annotation can be applied to a type of a <ja>@RemoteOp</ja>-annotated method
to identify it as a bean for setting HTTP parts through a bean-like interface.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>Request</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/http/annotation/Request.html#serializer--"><code>serializer</code></a> - Override the part serializer.
</ul>
</ul>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStore {
<ja>@RemotePost</ja>
String postPet(CreatePetRequest <jv>bean</jv>);
}
</p>
<p class='bjava'>
<ja>@Request</ja>
<jk>public class</jk> CreatePetRequest {
<jk>private</jk> CreatePet <jf>pet</jf>;
<jk>public</jk> CreatePetRequest(String <jv>name</jv>, <jk>float</jk> <jv>price</jv>) {
<jk>this</jk>.<jf>pet</jf> = <jk>new</jk> CreatePet(<jv>name</jv>, <jv>price</jv>);
}
<ja>@Content</ja>
<jk>public</jk> CreatePet getContent() {
<jk>return</jk> <jk>this</jk>.<jf>pet</jf>;
}
<ja>@Query</ja>
<jk>public</jk> Map&lt;String,Object&gt; getQueryParams() {
<jk>return</jk> AMap.<jsm>of</jsm>(<js>"debug"</js>, <jk>true</jk>);
}
<ja>@Header</ja>(<js>"E-Tag"</js>)
<jk>public static</jk> UUID <jsm>getUUID</jsm>() {
<jk>return</jk> UUID.<jsm>generatedUUID</jsm>();
}
}
</p>
<p class='bjava'>
PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
CreatePetRequest <jv>requestBean</jv> = <jk>new</jk> CreatePetRequest(<js>"Fluffy"</js>, 9.99);
String <jv>response</jv> = <jv>store</jv>.postPet(requestBean);
</p>
<p>
The <ja>@Request</ja> annotation can be applied to either the class or argument.
</p>
<p>
The annotated methods must be no-arg and public.
They can be named anything.
</p>
<p>
Any of the following annotations can be used on the methods:
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
</ul>
<p>
The behavior and functionality of all of the annotations are the same as if they were used on method arguments directly.
This means full support for OpenAPI serialization and validation.
</p>
<p>
Annotations on methods are inherited from parent classes and interfaces.
For example, the request bean above could have defined annotations in an interface to keep them clear from the implementation:
</p>
<p class='bjava'>
<ja>@Request</ja>
<jk>public interface</jk> CreatePetRequest {
<ja>@Content</ja>
CreatePet getContent();
<ja>@Query</ja>
Map&lt;String,Object&gt; getQueryParams();
<ja>@Header</ja>(<js>"E-Tag"</js>)
UUID getUUID();
}
</p>
<p class='bjava'>
<jk>public class</jk> CreatePetRequestImpl <jk>implements</jk> CreatePetRequest {
<jk>public</jk> CreatePetRequestImpl(String <jv>name</jv>, <jk>float</jk> <jv>price</jv>) {...}
<ja>@Override</ja>
<jk>public</jk> CreatePet getContent() {
<jk>return</jk> <jk>this</jk>.<jf>pet</jf>;
}
<ja>@Override</ja>
<jk>public</jk> Map&lt;String,Object&gt; getQueryParams() {
<jk>return</jk> JsonMap.<jsm>of</jsm>(<js>"debug"</js>, <jk>true</jk>);
}
<ja>@Override</ja>
<jk>public</jk> UUID getUUID() {
<jk>return</jk> UUID.<jsm>generateUUID</jsm>();
}
}
</p>
</div>
</div><!-- END: 12.9.8 - juneau-rest-client.jrc.Proxies.jrc.Request -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.Response' id='juneau-rest-client.jrc.Proxies.jrc.Response'>12.9.9 - @Response</a><span class='update'>updated: <b>9.0.0</b></span></h4>
<div class='topic'><!-- START: 12.9.9 - juneau-rest-client.jrc.Proxies.jrc.Response -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>@Response</code></a> annotation can be applied to types returned by <ja>@RemoteOp</ja>-annotated methods.
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/http/annotation/Response.html#parser--"><code>parser</code></a> - Override the part parser.
</ul>
</ul>
<p>
The <ja>@Response</ja> annotation can be used to define interfaces for retrieving response parts using a bean-like proxy.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Remote</ja>
<jk>public interface</jk> PetStore {
<ja>@RemotePost</ja>
CreatePetResponse postPet(...);
}
</p>
<p class='bjava'>
<ja>@Response</ja>
<jk>public interface</jk> CreatePetResponse {
<ja>@Content</ja>
Pet getContent();
<ja>@Header</ja>(<js>"E-Tag"</js>)
UUID getUUID();
<ja>@StatusCode</ja>
<jk>int</jk> getStatus();
}
</p>
<p class='bjava'>
PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:10000"</js>);
CreatePetResponse <jv>response</jv> = <jv>store</jv>.postPet(...);
Pet <jv>pet</jv> = <jv>response</jv>.getContent();
UUID <jv>uuid</jv> = <jv>response</jv>.getUUID();
<jk>int</jk> <jv>status</jv> = <jv>response</jv>.getStatus();
</p>
<p>
The annotated methods must be no-arg.
They can be named anything.
</p>
<p>
Any of the following annotations can be used on the methods:
</p>
<ul class='javatreec'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/StatusCode.html" title="annotation in org.apache.juneau.http.annotation"><code>StatusCode</code></a>
</ul>
<p>
The behavior and functionality of all of the annotations are the same as if they were used on method arguments directly. This means full support for OpenAPI serialization and validation.
</p>
</div>
</div><!-- END: 12.9.9 - juneau-rest-client.jrc.Proxies.jrc.Response -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Proxies.jrc.DualPurposeInterfaces' id='juneau-rest-client.jrc.Proxies.jrc.DualPurposeInterfaces'>12.9.10 - Dual-purpose (end-to-end) interfaces</a><span class='update'>created: 8.0.0</span></h4>
<div class='topic'><!-- START: 12.9.10 - juneau-rest-client.jrc.Proxies.jrc.DualPurposeInterfaces -->
<div class='topic'>
<p>
A common coding practice is to use the same Java interface to define both your server and client side REST interfaces.
The advantage to this approach is that changes that you make to your REST interface can be reflected in both places
at the same time, reducing the chances for compatibility mistakes.
</p>
<p>
What makes this possible is that method-level annotations such as <ja>@RestOp</ja> and parameter-level annotations
such as <ja>@Query</ja> are inherited from parent classes.
This normally isn't possible but the framework will spider up the parent hierarchy of classes to find method and parameter level
annotations defined on overridden methods.
</p>
<p>
The general approach is to define your <a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>@Remote</code></a>-annotated interface first.
The following example is pulled from the PetStore app:
</p>
<p class='bjava'>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStore {
<ja>@RemoteGet</ja>(<js>"/pet"</js>)
<jk>public</jk> Collection&lt;Pet&gt; getPets() <jk>throws</jk> NotAcceptable;
<ja>@RemotDelete</ja>(<js>"/pet/{petId}"</js>)
<jk>public</jk> Ok deletePet(
<ja>@Header</ja>(
name=<js>"api_key"</js>,
description=<js>"Security API key"</js>,
required=<jk>true</jk>,
example=<js>"foobar"</js>
)
String <jv>apiKey</jv>,
<ja>@Path</ja>(
name=<js>"petId"</js>,
description=<js>"Pet id to delete"</js>,
example=<js>"123"</js>
)
<jk>long</jk> <jv>petId</jv>
) <jk>throws</jk> IdNotFound, NotAcceptable;
...
</p>
<p>
Next you define the implementation of your interface as a normal Juneau REST resource:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/petstore"</js>,
title=<js>"Petstore application"</js>,
...
)
<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalJenaConfig, PetStore {
...
<ja>@Override</ja> <jc>/* PetStore */</jc>
<ja>@RestOp</ja>(
method=<jsm>GET</jsm>,
path=<js>"/pet"</js>,
summary=<js>"All pets in the store"</js>,
...
)
<jk>public</jk> Collection&lt;Pet&gt; getPets() <jk>throws</jk> NotAcceptable {
<jk>return</jk> <jsf>store</jsf>.getPets();
}
<ja>@Override</ja> <jc>/* PetStore */</jc>
<ja>@RestOp</ja>(
method=<jsf>DELETE</jsf>,
path=<js>"/pet/{petId}"</js>,
summary=<js>"Deletes a pet"</js>,
...
)
<jk>public</jk> Ok deletePet(String <jv>apiKey</jv>, <jk>long</jk> <jv>petId</jv>) <jk>throws</jk> IdNotFound, NotAcceptable {
<jsf>store</jsf>.removePet(<jv>petId</jv>);
<jk>return</jk> <jsf>OK</jsf>;
}
</p>
<p>
Then use the interface as a remote resource like so:
</p>
<p class='bjava'>
RestClient client = RestClient.<jsm>create</jsm>().json().rootUrl(<js>"http://localhost:10000"</js>).build();
PetStore <jv>store</jv> = <jv>client</jv>.getRemote(PetStore.<jk>class</jk>);
<jk>for</jk> (Pet <jv>pet</jv> : <jv>store</jv>.getPets()) {
<jv>store</jv>.deletePet(<js>"my-special-key"</js>, <jv>pet</jv>.getId());
System.<jsf>err</jsf>.println(<js>"Deleted pet: id="</js> + <jv>pet</jv>.getId());
}
</p>
<p>
In the example above, we chose to add the <ja>@RestOp</ja> annotation to the implementation class.
However, they could have been added to the interface instead. It's personal preference where you want to place
the annotations.
</p>
<p>
Note how we didn't need to use the <ja>@Header</ja> and <ja>@Path</ja> annotations in our implementation since
the annotations were inherited from the interface.
</p>
</div>
</div><!-- END: 12.9.10 - juneau-rest-client.jrc.Proxies.jrc.DualPurposeInterfaces -->
</div><!-- END: 12.9 - juneau-rest-client.jrc.Proxies -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.LoggingAndDebugging' id='juneau-rest-client.jrc.LoggingAndDebugging'>12.10 - Logging and Debugging</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.10 - juneau-rest-client.jrc.LoggingAndDebugging -->
<div class='topic'>
<p>
The following methods provide logging of requests and responses:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#logger-java.util.logging.Logger-"><code>logger(Logger)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#logToConsole--"><code>logToConsole()</code></a>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#logRequests-org.apache.juneau.DetailLevel-java.util.logging.Level-java.util.function.BiPredicate-"><code>logRequests(DetailLevel,Level,BiPredicate)</code></a>
</ul>
</ul>
<p>
The following example shows the results of logging all requests that end with <c>/bean</c>.
</p>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// A simple bean we're going to round-trip.</jc>
MyBean <jv>bean</jv> = <jk>new</jk> MyBean();
<jv>bean</jv> = RestClient
.<jsm>create</jsm>()
.simpleJson()
.logRequests(DetailLevel.<jsf>FULL</jsf>, Level.<jsf>SEVERE</jsf>, (<jv>req</jv>,<jv>res</jv>)-><jv>req</jv>.getUri().endsWith(<js>"/bean"</js>))
.logToConsole()
.build()
.post(<js>"http://localhost/bean"</js>, <jv>bean</jv>)
.run()
.getContent().as(MyBean.<jk>class</jk>);
</p>
<p>
This produces the following console output:
</p>
<p class='bconsole'>
=== HTTP Call (outgoing) ======================================================
=== REQUEST ===
POST http://localhost/bean
---request headers---
Accept: application/json+simple
---request entity---
Content-Type: application/json+simple
---request content---
{f:1}
=== RESPONSE ===
HTTP/1.1 200
---response headers---
Content-Type: application/json
---response content---
{f:1}
=== END =======================================================================",
</p>
<p class='notes w900'>
It should be noted that if you enable request logging detail level <a href="org/apache/juneau/DetailLevel.html#FULL"><code>DetailLevel.FULL</code></a>, response bodies will be cached by default which may introduce
a performance penalty.
</p>
<p>
Additionally, the following method is also provided for enabling debug mode:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#debug--"><code>debug()</code></a>
</ul>
</ul>
<p>
Enabling debug mode has the following effects:
</p>
<ul>
<li><a href="org/apache/juneau/rest/client/RestClient.Builder.html#logToConsole--"><code>RestClient.Builder.logToConsole()</code></a> is called.
</ul>
</div>
</div><!-- END: 12.10 - juneau-rest-client.jrc.LoggingAndDebugging -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.CustomizingHttpClient' id='juneau-rest-client.jrc.CustomizingHttpClient'>12.11 - Customizing HttpClient</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 12.11 - juneau-rest-client.jrc.CustomizingHttpClient -->
<div class='topic'>
<p>
Several methods are provided for customizing the underlying HTTP client and client builder classes:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#httpClientBuilder-org.apache.http.impl.client.HttpClientBuilder-"><code>httpClientBuilder(HttpClientBuilder)</code></a> - Set the client builder yourself.
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#createHttpClientBuilder--"><code>createHttpClientBuilder()</code></a> - Override to create the client builder.
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#createHttpClient--"><code>createHttpClient()</code></a> - Override to create the client.
<li class='jm'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#createConnectionManager--"><code>createConnectionManager()</code></a> - Override to create the connection management.
</ul>
</ul>
<p>
Additionally, all methods on the <c>HttpClientBuilder</c> class have been extended with fluent setters.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a client with customized HttpClient settings.</jc>
MyBean <jv>bean</jv> = RestClient
.<jsm>create</jsm>()
.disableRedirectHandling()
.connectionManager(<jv>myConnectionManager</jv>)
.addInterceptorFirst(<jv>myHttpRequestInterceptor</jv>)
.build();
</p>
<p>
Refer to the <code>org.apache.http.client.impl.HttpClientBuilder</code> docs for more information.
</p>
</div>
</div><!-- END: 12.11 - juneau-rest-client.jrc.CustomizingHttpClient -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.ExtendingRestClient' id='juneau-rest-client.jrc.ExtendingRestClient'>12.12 - Extending RestClient</a><span class='update'>created: 8.2.0</span></h3>
<div class='topic'><!-- START: 12.12 - juneau-rest-client.jrc.ExtendingRestClient -->
<div class='topic'>
<p>
The <c>RestClient</c> API has been designed to allow for the ability to be easily extended.
The following example that overrides the primary run method shows how this can be done.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>public class</jk> MyRestClient <jk>extends</jk> RestClient {
<jc>// Must provide this constructor!</jc>
<jk>public</jk> MyRestClient(ContextProperties <jv>ps</jv>) {
<jk>super</jk>(<jv>ps</jv>);
}
<ja>@Override</ja>
<jk>public</jk> HttpResponse run(HttpHost <jv>target</jv>, HttpRequest <jv>request</jv>, HttpContext <jv>context</jv>) <jk>throws</jk> IOException {
<jc>// Perform special handling of requests.</jc>
}
}
<jc>// Instantiate your client.</jc>
MyRestClient <jv>client</jv> = RestClient.<jsm>create</jsm>().json().build(MyRestClient.<jk>class</jk>);
</p>
<p>
The <a href="org/apache/juneau/rest/client/RestRequest.html" title="class in org.apache.juneau.rest.client"><code>RestRequest</code></a> and <a href="org/apache/juneau/rest/client/RestResponse.html" title="class in org.apache.juneau.rest.client"><code>RestResponse</code></a> objects can also be extended and integrated by overriding the
<a href="org/apache/juneau/rest/client/RestClient.html#createRequest-java.net.URI-java.lang.String-boolean-"><code>RestClient.createRequest(URI, String, boolean)</code></a> and <a href="org/apache/juneau/rest/client/RestClient.html#createResponse-org.apache.juneau.rest.client.RestRequest-org.apache.http.HttpResponse-org.apache.juneau.parser.Parser-"><code>RestClient.createResponse(RestRequest, HttpResponse, Parser)</code></a> methods.
</p>
</div>
</div><!-- END: 12.12 - juneau-rest-client.jrc.ExtendingRestClient -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Authentication' id='juneau-rest-client.jrc.Authentication'>12.13 - Authentication</a><span class='update'>updated: 8.2.0</span></h3>
<div class='topic'><!-- START: 12.13 - juneau-rest-client.jrc.Authentication -->
<div class='topic'>
<p>
The Juneau REST client itself does not implement any support for authentication.
Instead, it delegates it to the underlying Apache HTTP Client interface.
</p>
<p>
The following sections show how some common authentication mechanisms can be set up using HTTP Client APIs.
</p>
</div>
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Authentication.jrc.AuthenticationBASIC' id='juneau-rest-client.jrc.Authentication.jrc.AuthenticationBASIC'>12.13.1 - BASIC Authentication</a></h4>
<div class='topic'><!-- START: 12.13.1 - juneau-rest-client.jrc.Authentication.jrc.AuthenticationBASIC -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/client/RestClient.Builder.html#basicAuth-java.lang.String-int-java.lang.String-java.lang.String-"><code>RestClient.Builder.basicAuth(String,int,String,String)</code></a> method
can be used to quickly enable BASIC authentication support.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Create a client that performs BASIC authentication using the specified user/pw.</jc>
RestClient <jv>client</jv> = RestClient.<jsm>create</jsm>()
.basicAuth(<jsf>HOST</jsf>, <jsf>PORT</jsf>, <jsf>USER</jsf>, <jsf>PW</jsf>)
.build();
</p>
<p>
This is functionally equivalent to the following:
</p>
<p class='bjava'>
RestClient.Builder <jv>builder</jv> = RestClient.<jsm>create</jsm>();
AuthScope <jv>scope</jv> = <jk>new</jk> AuthScope(<jsf>HOST</jsf>, <jsf>PORT</jsf>);
Credentials <jv>up</jv> = <jk>new</jk> UsernamePasswordCredentials(<jsf>USER</jsf>, <jsf>PW</jsf>);
CredentialsProvider <jv>provider</jv> = <jk>new</jk> BasicCredentialsProvider();
<jv>provider</jv>.setCredentials(<jv>scope</jv>, <jv>up</jv>);
<jv>builder</jv>.setDefaultCredentialsProvider(<jv>provider</jv>);
</p>
</div>
</div><!-- END: 12.13.1 - juneau-rest-client.jrc.Authentication.jrc.AuthenticationBASIC -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Authentication.jrc.AuthenticationForm' id='juneau-rest-client.jrc.Authentication.jrc.AuthenticationForm'>12.13.2 - FORM-based Authentication</a></h4>
<div class='topic'><!-- START: 12.13.2 - juneau-rest-client.jrc.Authentication.jrc.AuthenticationForm -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a> class does not itself provide FORM-based
authentication since there is no standard way of providing such support.
Typically, to perform FORM-based or other types of authentication, you'll want to create your own
subclass of <a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a> and override the
<a href="org/apache/juneau/rest/client/RestClient.Builder.html#createHttpClient--"><code>RestClient.Builder.createHttpClient()</code></a> method to provide an
authenticated client.
</p>
<p>
The following example shows an implementation of a client that performs FORM-based authentication against
the IBM Jazz platform.
</p>
<p class='bjava'>
<jd>/**
* Constructor.
*/</jd>
<jk>public</jk> JazzRestClient.Builder(URI <jv>jazzUri</jv>, String <jv>user</jv>, String <jv>pw</jv>) <jk>throws</jk> IOException {
...
}
<jd>/**
* Override the createHttpClient() method to return an authenticated client.
*/</jd>
<ja>@Override</ja> <jc>/* RestClient.Builder */</jc>
<jk>protected</jk> CloseableHttpClient createHttpClient() <jk>throws</jk> Exception {
CloseableHttpClient <jv>client</jv> = <jk>super</jk>.createHttpClient();
formBasedAuthenticate(<jv>client</jv>);
visitAuthenticatedURL(<jv>client</jv>);
<jk>return</jk> <jv>client</jv>;
}
<jc>/*
* Performs form-based authentication against the Jazz server.
*/</jc>
<jk>private void</jk> formBasedAuthenticate(HttpClient <jv>client</jv>) <jk>throws</jk> IOException {
URI <jv>uri2</jv> = <jf>jazzUri</jf>.resolve(<js>"j_security_check"</js>);
HttpPost <jv>request</jv> = <jk>new</jk> HttpPost(uri2);
<jv>request</jv>.setConfig(RequestConfig.<jsm>custom</jsm>().setRedirectsEnabled(<jk>false</jk>).build());
<jc>// Charset must explicitly be set to UTF-8 to handle user/pw with non-ascii characters.</jc>
<jv>request</jv>.addHeader(<js>"Content-Type"</js>, <js>"application/x-www-form-urlencoded; charset=utf-8"</js>);
List&lt;NameValuePair&gt; <jv>params</jv> = AList.<jsm>of</jsm>(
BasicNameValuePair.<jsm>of</jsm>(<js>"j_username""</js>, <jf>user</jf>),
BasicNameValuePair.<jsm>of</jsm>(<js>"j_password"</js>, <jf>pw</jf>)
);
<jv>request</jv>.setEntity(<jk>new</jk> UrlEncodedFormEntity(<jv>params</jv>));
HttpResponse <jv>response</jv> = <jv>client</jv>.execute(<jv>request</jv>);
<jk>try</jk> {
<jk>int</jk> <jv>rc</jv> = <jv>response</jv>.getStatusLine().getStatusCode();
Header <jv>authMsg</jv> = <jv>response</jv>.getFirstHeader(<js>"X-com-ibm-team-repository-web-auth-msg"</js>);
<jk>if</jk> (<jv>authMsg</jv> != <jk>null</jk>)
<jk>throw new</jk> IOException(<jv>authMsg</jv>.getValue());
<jc>// The form auth request should always respond with a 200 ok or 302 redirect code</jc>
<jk>if</jk> (<jv>rc</jv> == <jsf>SC_MOVED_TEMPORARILY</jsf>) {
<jk>if</jk> (<jv>response</jv>.getFirstHeader(<js>"Location"</js>).getValue().isPattern(<js>"^.*/auth/authfailed.*$"</js>))
<jk>throw new</jk> IOException(<js>"Invalid credentials."</js>);
} <jk>else if</jk> (<jv>rc</jv> != <jsf>SC_OK</jsf>) {
<jk>throw new</jk> IOException(<js>"Unexpected HTTP status: "</js> + <jv>rc</jv>);
}
} <jk>finally</jk> {
EntityUtils.<jsm>consume</jsm>(<jv>response</jv>.getEntity());
}
}
<jc>/*
* This is needed for Tomcat because it responds with SC_BAD_REQUEST when the j_security_check URL is visited before an
* authenticated URL has been visited. This same URL must also be visited after authenticating with j_security_check
* otherwise tomcat will not consider the session authenticated
*/</jc>
<jk>private int</jk> visitAuthenticatedURL(HttpClient <jv>httpClient</jv>) <jk>throws</jk> IOException {
HttpGet <jv>authenticatedURL</jv> = <jk>new</jk> HttpGet(<jf>jazzUri</jf>.resolve(<js>"authenticated/identity"</js>));
HttpResponse <jv>response</jv> = <jv>httpClient</jv>.execute(<jv>authenticatedURL</jv>);
<jk>try</jk> {
<jk>return</jk> <jv>response</jv>.getStatusLine().getStatusCode();
} <jk>finally</jk> {
EntityUtils.<jsm>consume</jsm>(<jv>response</jv>.getEntity());
}
}
</p>
</div>
</div><!-- END: 12.13.2 - juneau-rest-client.jrc.Authentication.jrc.AuthenticationForm -->
<!-- ==================================================================================================== -->
<h5 class='topic' onclick='toggle(this)'><a href='#juneau-rest-client.jrc.Authentication.jrc.AuthenticationOIDC' id='juneau-rest-client.jrc.Authentication.jrc.AuthenticationOIDC'>12.13.3 - OIDC Authentication</a></h4>
<div class='topic'><!-- START: 12.13.3 - juneau-rest-client.jrc.Authentication.jrc.AuthenticationOIDC -->
<div class='topic'>
<p>
The following example shows an implementation of a client that performs OIDC authentication against
the IBM Jazz platform.
</p>
<p class='bjava'>
<jd>/**
* Constructor.
*/</jd>
<jk>public</jk> JazzRestClient.Builder(URI <jv>jazzUri</jv>, String <jv>user</jv>, String <jv>pw</jv>) <jk>throws</jk> IOException {
...
}
<jd>/**
* Override the createHttpClient() method to return an authenticated client.
*/</jd>
<ja>@Override</ja> <jc>/* RestClient.Builder */</jc>
<jk>protected</jk> CloseableHttpClient createHttpClient() <jk>throws</jk> Exception {
CloseableHttpClient <jv>client</jv> = <jk>super</jk>.createHttpClient();
oidcAuthenticate(<jv>client</jv>);
<jk>return</jk> <jv>client</jv>;
}
<jk>private void</jk> oidcAuthenticate(HttpClient <jv>client</jv>) <jk>throws</jk> IOException {
HttpGet <jv>request</jv> = <jk>new</jk> HttpGet(<jf>jazzUri</jf>);
<jv>request</jv>.setConfig(RequestConfig.<jsm>custom</jsm>().setRedirectsEnabled(<jk>false</jk>).build());
<jc>// Charset must explicitly be set to UTF-8 to handle user/pw with non-ascii characters.</jc>
<jv>request</jv>.addHeader(<js>"Content-Type"</js>, <js>"application/x-www-form-urlencoded; charset=utf-8"</js>);
HttpResponse <jv>response</jv> = <jv>client</jv>.execute(<jv>request</jv>);
<jk>try</jk> {
<jk>int</jk> <jv>code</jv> = <jv>response</jv>.getStatusLine().getStatusCode();
<jc>// Already authenticated</jc>
<jk>if</jk> (<jv>code</jv> == <jsf>SC_OK</jsf>)
<jk>return</jk>;
<jk>if</jk> (<jv>code</jv> != <jsf>SC_UNAUTHORIZED</jsf>)
<jk>throw new</jk> RestCallException(<js>"Unexpected response during OIDC authentication: "</js>
+ <jv>response</jv>.getStatusLine());
<jc>// x-jsa-authorization-redirect</jc>
String <jv>redirectUri</jv> = getHeader(<jv>response</jv>, <js>"X-JSA-AUTHORIZATION-REDIRECT"</js>);
<jk>if</jk> (<jv>redirectUri</jv> == <jk>null</jk>)
<jk>throw new</jk> RestCallException(<js>"Expected a redirect URI during OIDC authentication: "</js>
+ <jv>response</jv>.getStatusLine());
<jc>// Handle Bearer Challenge</jc>
HttpGet <jv>method</jv> = <jk>new</jk> HttpGet(<jv>redirectUri</jv> + <js>"&amp;prompt=none"</js>);
addDefaultOidcHeaders(<jv>method</jv>);
<jv>response</jv> = <jv>client</jv>.execute(<jv>method</jv>);
<jv>code</jv> = <jv>response</jv>.getStatusLine().getStatusCode();
<jk>if</jk> (<jv>code</jv> != <jsf>SC_OK</jsf>)
<jk>throw new</jk> RestCallException(<js>"Unexpected response during OIDC authentication phase 2: "</js>
+ <jv>response</jv>.getStatusLine());
String <jv>loginRequired</jv> = getHeader(<jv>response</jv>, <js>"X-JSA-LOGIN-REQUIRED"</js>);
<jk>if</jk> (! <js>"true"</js>.equals(<jv>loginRequired</jv>))
<jk>throw new</jk> RestCallException(<js>"X-JSA-LOGIN-REQUIRED header not found on response during OIDC authentication phase 2: "</js>
+ <jv>response</jv>.getStatusLine());
<jv>method</jv> = <jk>new</jk> HttpGet(<jv>redirectUri</jv> + <js>"&amp;prompt=none"</js>);
addDefaultOidcHeaders(<jv>method</jv>);
<jv>response</jv> = <jv>client</jv>.execute(<jv>method</jv>);
<jv>code</jv> = <jv>response</jv>.getStatusLine().getStatusCode();
<jk>if</jk> (<jv>code</jv> != <jsf>SC_OK</jsf>)
<jk>throw new</jk> RestCallException(<js>"Unexpected response during OIDC authentication phase 3: "</js>
+ <jv>response</jv>.getStatusLine());
<jc>// Handle JAS Challenge</jc>
<jv>method</jv> = <jk>new</jk> HttpGet(<jv>redirectUri</jv>);
addDefaultOidcHeaders(<jv>method</jv>);
<jv>response</jv> = <jv>client</jv>.execute(<jv>method</jv>);
<jv>code</jv> = <jv>response</jv>.getStatusLine().getStatusCode();
<jk>if</jk> (<jv>code</jv> != <jsf>SC_OK</jsf>)
<jk>throw new</jk> RestCallException(<js>"Unexpected response during OIDC authentication phase 4: "</js>
+ <jv>response</jv>.getStatusLine());
<jf>cookie</jf> = getHeader(<jv>response</jv>, <js>"Set-Cookie"</js>);
Header[] <jv>defaultHeaders</jv> = <jk>new</jk> Header[] {
BasicStringHeader.<jsm>of</jsm>(<js>"User-Agent"</js>, <js>"Jazz Native Client"</js>),
BasicStringHeader.<jsm>of</jsm>(<js>"X-com-ibm-team-configuration-versions"</js>,
<js>"com.ibm.team.rtc=6.0.0,com.ibm.team.jazz.foundation=6.0"</js>),
BasicStringHeader.<jsm>of</jsm>(<js>"Accept"</js>, <js>"text/json"</js>),
BasicStringHeader.<jsm>of</jsm>(<js>"Authorization"</js>, <js>"Basic "</js>
+ StringUtils.<jsm>base64EncodeToString</jsm>(<jf>user</jf> + <js>":"</js> + <jf>pw</jf>)),
BasicStringHeader.<jsm>of</jsm>(<js>"Cookie"</js>, <jf>cookie</jf>)
};
setDefaultHeaders(AList.<jsm>of</jsm>(<jv>defaultHeaders</jv>));
} <jk>finally</jk> {
EntityUtils.<jsm>consume</jsm>(<jv>response</jv>.getEntity());
}
}
<jk>private void</jk> addDefaultOidcHeaders(HttpRequestBase <jv>method</jv>) {
<jv>method</jv>.addHeader(<js>"User-Agent"</js>, <js>"Jazz Native Client"</js>);
<jv>method</jv>.addHeader(<js>"X-com-ibm-team-configuration-versions"</js>,
<js>"com.ibm.team.rtc=6.0.0,com.ibm.team.jazz.foundation=6.0"</js>);
<jv>method</jv>.addHeader(<js>"Accept"</js>, <js>"text/json"</js>);
<jk>if</jk> (<jf>cookie</jf> != <jk>null</jk>) {
<jv>method</jv>.addHeader(<js>"Authorization"</js>, <js>"Basic "</js>
+ StringUtils.<jsm>base64EncodeToString</jsm>(<jf>user</jf> + <js>":"</js> + <jf>pw</jf>));
<jv>method</jv>.addHeader(<js>"Cookie"</js>, <jf>cookie</jf>);
}
}
</p>
</div>
</div><!-- END: 12.13.3 - juneau-rest-client.jrc.Authentication.jrc.AuthenticationOIDC -->
</div><!-- END: 12.13 - juneau-rest-client.jrc.Authentication -->
</div><!-- END: 12 - juneau-rest-client -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-rest-mock' id='juneau-rest-mock'>13 - juneau-rest-mock</a><span class='update'>created: 8.1.0, updated: 8.2.0</span></h2>
<div class='topic'><!-- START: 13 - juneau-rest-mock -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-rest-mock<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-rest-mock-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.rest.mock_9.0.0.jar
</p>
<p>
The <c>juneau-rest-mock</c> module contains convenience APIs for performing serverless unit
testing of your REST APIs.
Each of the APIs provide the ability to fully test your server and client REST interfaces without the
need for a running servlet container.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-rest-mock.jrm.MockRestClient' id='juneau-rest-mock.jrm.MockRestClient'>13.1 - MockRestClient</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 13.1 - juneau-rest-mock.jrm.MockRestClient -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/rest/mock/MockRestClient.html" title="class in org.apache.juneau.rest.mock"><code>MockRestClient</code></a> class is used for performing serverless unit testing of <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a>-annotated
and <a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>@Remote</code></a>-annotated classes.
</p>
<p>
The <a href="org/apache/juneau/rest/mock/MockRestClient.html" title="class in org.apache.juneau.rest.mock"><code>MockRestClient</code></a> itself extends from <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> providing it with the rich
feature set of that API.
The following shows a simple example of invoking a PUT method on a simple REST interface and asserting
the correct status code and response body:
</p>
<p class='bjava'>
<jk>public class</jk> MockTest {
<jc>// A simple bean with one field.</jc>
<jk>public static class</jk> MyBean {
<jk>public int</jk> <jf>foo</jf> = 1;
}
<jc>// Our REST resource to test.</jc>
<jc>// Simply echos the response.</jc>
<ja>@Rest</ja>
<jk>public static class</jk> EchoRest <jk>implements</jk> BasicRestServlet {
<ja>@RestPut</ja>
<jk>public</jk> MyBean echo(<ja>@Content</ja> MyBean <jv>bean</jv>) {
<jk>return</jk> <jv>bean</jv>;
}
}
<jc>// Our JUnit test.</jc>
<ja>@Test</ja>
<jk>public void</jk> testEcho() <jk>throws</jk> Exception {
MyBean <jv>myBean</jv> = <jk>new</jk> MyBean();
<jc>// Do a round-trip on the bean through the REST interface</jc>
<jv>myBean</jv> = MockRestClient
.<jsm>create</jsm>(EchoRest.<jk>class</jk>)
.simpleJson()
.build()
.put(<js>"/echo"</js>, <jv>myBean</jv>)
.run()
.assertStatus().is(200)
.assertContent().is(<js>"{foo:1}"</js>)
.getContent().as(MyBean.<jk>class</jk>);
<jsm>assertEquals</jsm>(1, <jv>myBean</jv>.<jf>foo</jf>);
}
}
</p>
<p>
Breaking apart the fluent method call above will help you understand how this works.
</p>
<p class='bjava'>
<ja>@Test</ja>
<jk>public void</jk> testEcho() <jk>throws</jk> Exception {
<jc>// Instantiate our mock client.</jc>
MockRestClient <jv>client</jv> = MockRestClient
.<jsm>create</jsm>(EchoRest.<jk>class</jk>)
.simpleJson()
.build();
<jc>// Create a request.</jc>
RestRequest <jv>req</jv> = <jv>client</jv>.put(<js>"/echo"</js>, <jv>myBean</jv>);
<jc>// Execute it (by calling RestCallHandler.service(...) and then returning the response object).</jc>
RestResponse <jv>res</jv> = <jv>req</jv>.run();
<jc>// Run assertion tests on the results.</jc>
<jv>res</jv>.assertStatus().is(200);
<jv>res</jv>.assertContent().is(<js>"'foo'"</js>);
<jv>myBean</jv> = <jv>res</jv>.getContent().as(MyBean.<jk>class</jk>);
}
</p>
<p>
The concept of the design is simple. The <a href="org/apache/juneau/rest/mock/MockRestClient.html" title="class in org.apache.juneau.rest.mock"><code>MockRestClient</code></a> class is used to create instances of <a href="org/apache/juneau/rest/mock/MockServletRequest.html" title="class in org.apache.juneau.rest.mock"><code>MockServletRequest</code></a>
and <a href="org/apache/juneau/rest/mock/MockServletResponse.html" title="class in org.apache.juneau.rest.mock"><code>MockServletResponse</code></a> which are passed directly to the call handler on the resource class <a href="org/apache/juneau/rest/RestOpInvoker.html#invoke-org.apache.juneau.rest.RestOpSession-"><code>RestOpInvoker.invoke(RestOpSession)</code></a>.
In effect, you're fully testing your REST API as if it were running in a live servlet container, yet not
actually having to run in a servlet container.
All aspects of the client and server side code are tested, yet no servlet container is required. The actual
over-the-wire transmission is the only aspect being bypassed.
</p>
<p>
The <c>create(Object)</c> method can take in either <c>Class</c> objects or pre-instantiated beans.
The latter is particularly useful for testing REST APIs written as Spring beans.
</p>
<p class='bjava'>
<ja>@RunWith</ja>(SpringRunner.<jk>class</jk>)
<ja>@ContextConfiguration</ja>(classes = {MyApp.<jk>class</jk>})
<ja>@SpringBootTest</ja>
<jk>public class</jk> MockTest {
<ja>@Autowired</ja>
EchoRest <jf>echoRest</jf>;
MockRestClient <jf>client</jf>;
<ja>@Before</ja>
<jk>public void</jk> setup() {
<jc>// Instantiate our mock client.</jc>
<jf>client</jf> = MockRestClient
.<jsm>create</jsm>(<jf>echoRest</jf>)
.simpleJson()
.build();
}
<jc>// Our JUnit test.</jc>
<ja>@Test</ja>
<jk>public void</jk> testEcho() <jk>throws</jk> Exception {
MyBean <jv>myBean</jv> = <jk>new</jk> MyBean();
<jc>// Do a round-trip on the bean through the REST interface</jc>
<jv>myBean</jv> = <jf>client</jf>
.put(<js>"/echo"</js>, <jv>myBean</jv>)
.run()
.assertStatus().is(200)
.assertContent().is(<js>"{foo:1}"</js>)
.getContent().as(MyBean.<jk>class</jk>);
<jsm>assertEquals</jsm>(1, <jv>myBean</jv>.<jf>foo</jf>);
}
}
</p>
<hr>
<p>
The <a href="org/apache/juneau/rest/mock/MockRestRequest.html" title="class in org.apache.juneau.rest.mock"><code>MockRestRequest</code></a> object has convenience methods provided to allow you to set properties
directly on the underlying <code>javax.servlet.HttpServletRequest</code> object. The following example shows how
this can be used to directly set roles on the request object to perform security testing.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<ja>@Rest</ja>(roleGuard=<js>"ADMIN"</js>)
<jk>public</jk> class A {
<ja>@RestGet</ja>
<jk>public</jk> String get() {
<jk>return</jk> <js>"OK"</js>;
}
}
<ja>@Test</ja>
<jk>public void</jk> mytest() <jk>throws</jk> Exception {
MockRestClient <jv>client</jv> = MockRestClient.<jsm>build</jsm>(A.<jk>class</jk>);
<jc>// Admin user should get 200 but anyone else should get 403-Unauthorized.</jc>
<jv>client</jv>.get().roles(<js>"ADMIN"</js>).run().assertStatus().is(200);
<jv>client</jv>.get().roles(<js>"USER"</js>).run().assertStatus().is(403);
}
</p>
<hr>
<p>
The <a href="org/apache/juneau/rest/mock/MockRestClient.html" title="class in org.apache.juneau.rest.mock"><code>MockRestClient</code></a> class has a debug mode that will cause your HTTP requests and responses to
be sent to the console:
</p>
<p class='bjava'>
MockRestClient <jv>client</jv> = MockRestClient
.<jsm>create</jsm>(MyRest.<jk>class</jk>)
.debug()
.simpleJson()
.build();
</p>
<hr>
<p>
The <a href="org/apache/juneau/rest/mock/MockRestClient.html" title="class in org.apache.juneau.rest.mock"><code>MockRestClient</code></a> class can also be used for testing of <a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>Remote</code></a>-annotated
interfaces against <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a>-annotated resources.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// Our remote resource to test.</jc>
<ja>@Remote</ja>
<jk>public interface</jk> MyRemoteInterface {
<ja>@RemoteGet</ja>(<js>"/echoQuery"</js>)
<jk>public int</jk> echoQuery(<ja>@Query</ja>(name=<js>"id"</js>) <jk>int</jk> <jv>id</jv>);
}
<jc>// Our mocked-up REST interface to test against.</jc>
<ja>@Rest</ja>
<jk>public class</jk> MyRest {
<ja>@RestGet</ja>
<jk>public int</jk> echoQuery(<ja>@Query</ja>(<js>"id"</js>) String <jv>id</jv>) {
<jk>return</jk> <jv>id</jv>;
}
}
<ja>@Test</ja>
<jk>public void</jk> testProxy() {
MyRemoteInterface <jv>mri</jv> = MockRestClient
.create(MyRest.<jk>class</jk>)
.json()
.build()
.getRemote(MyRemoteInterface.<jk>class</jk>);
<jsm>assertEquals</jsm>(123, <jv>mri</jv>.echoQuery(123));
}
</p>
</div>
</div><!-- END: 13.1 - juneau-rest-mock.jrm.MockRestClient -->
</div><!-- END: 13 - juneau-rest-mock -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core' id='juneau-microservice-core'>14 - juneau-microservice-core</a><span class='update'>created: 8.1.0</span></h2>
<div class='topic'><!-- START: 14 - juneau-microservice-core -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-microservice-core<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-microservice-core-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.microservice.core_9.0.0.jar
</p>
<p>
Juneau Microservice is an API for creating stand-alone executable jars with automatic support for
Juneau configurations and console commands.
</p>
<p>
Features include:
</p>
<ul class='spaced-list'>
<li>
A builder-based API for defining and starting microservices.
<li>
An extensible API that allows you to hook into various lifecycle events.
<li>
Simple-to-use APIs for accessing manifest file entries, command-line arguments, and external configuration
file properties.
</ul>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core.jmc.Overview' id='juneau-microservice-core.jmc.Overview'>14.1 - Microservice Overview</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 14.1 - juneau-microservice-core.jmc.Overview -->
<div class='topic'>
<p>
The Microservice API consists of a base class for defining executable microservices.
</p>
<p>
Features include:
</p>
<ul class='spaced-list'>
<li>
A builder-based API for defining and starting microservices.
<li>
An extensible API that allows you to hook into various lifecycle events.
<li>
Simple-to-use APIs for accessing manifest file entries, command-line arguments, and external configuration
file properties.
</ul>
<p>
The Microservice API consists of the following packages and classes:
</p>
<ul class='javatree'>
<li class='jp'><a href="org/apache/juneau/microservice/package-summary.html"><code>org.apache.juneau.microservice</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> - The base microservice class.
<li class='jc'><a href="org/apache/juneau/microservice/Microservice.Builder.html" title="class in org.apache.juneau.microservice"><code>Microservice.Builder</code></a> - Builder for the microservice class.
<li class='jic'><a href="org/apache/juneau/microservice/MicroserviceListener.html" title="interface in org.apache.juneau.microservice"><code>MicroserviceListener</code></a> - Interface for hooking into lifecyle events of the microservice.
<ul>
<li class='jc'><a href="org/apache/juneau/microservice/BasicMicroserviceListener.html" title="class in org.apache.juneau.microservice"><code>BasicMicroserviceListener</code></a> - Adapter for MicroserviceListener class.
</ul>
</ul>
</li>
<li class='jp'><a href="org/apache/juneau/microservice/console/package-summary.html"><code>org.apache.juneau.microservice.console</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/microservice/console/ConsoleCommand.html" title="class in org.apache.juneau.microservice.console"><code>ConsoleCommand</code></a> - Abstract class for defining console commands.
</ul>
</li>
</ul>
<p>
By itself the Microservice API doesn't provided much functionality but it does provide the basis for the <a class='doclink' href='#juneau-microservice-jetty'>Jetty Microservice</a> described later.
</p>
<p>
The most-basic creation of a microservice from an entry-point method is shown below:
</p>
<p class='bjava'>
<jk>public class</jk> App {
<jk>public static void</jk> main(String[] <jv>args</jv>) {
Microservice
.<jsm>create</jsm>() <jc>// Create builder.</jc>
.args(<jv>args</jv>) <jc>// Pass in args.</jc>
.build() <jc>// Create microservice.</jc>
.start() <jc>// Start microservice.</jc>
;
}
}
</p>
</div>
</div><!-- END: 14.1 - juneau-microservice-core.jmc.Overview -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core.jmc.LifecycleMethods' id='juneau-microservice-core.jmc.LifecycleMethods'>14.2 - Lifecycle Methods</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 14.2 - juneau-microservice-core.jmc.LifecycleMethods -->
<div class='topic'>
<p>
The lifecycle methods of the <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> class consists of the following:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#start--"><code>start()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#startConsole--"><code>startConsole()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#join--"><code>join()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#stop--"><code>stop()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#stopConsole--"><code>stopConsole()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#exit--"><code>exit()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#kill--"><code>kill()</code></a>
</ul>
</li>
</ul>
<p>
A typical implementation of an app with lifecycle methods might look like the following:
</p>
<p class='bjava'>
<jk>public class</jk> App {
<jk>private static final</jk> Microservice <jsf>MICROSERVICE</jsf>;
<jk>public static void</jk> main(String[] <jv>args</jv>) {
<jsf>MICROSERVICE</jsf> = Microservice
.<jsm>create</jsm>() <jc>// Create builder.</jc>
.args(<jv>args</jv>) <jc>// Pass in args.</jc>
.build() <jc>// Create microservice.</jc>
.start() <jc>// Start microservice.</jc>
.startConsole() <jc>// Start console.</jc>
.join() <jc>// Join thread.</jc>
;
}
<jk>public static void</jk> restart() {
<jsf>MICROSERVICE</jsf>.stop().start();
}
<jk>public static void</jk> exit() {
<jsf>MICROSERVICE</jsf>.exit();
}
}
</p>
<p>
If your application consists of a single microservice, you can use the <a href="org/apache/juneau/microservice/Microservice.html#getInstance--"><code>Microservice.getInstance()</code></a> method
from anywhere in your code:
</p>
<p class='bjava'>
<jk>public class</jk> App {
<jk>public static void</jk> main(String[] <jv>args</jv>) {
Microservice
.<jsm>create</jsm>() <jc>// Create builder.</jc>
.args(<jv>args</jv>) <jc>// Pass in args.</jc>
.build() <jc>// Create microservice.</jc>
.start() <jc>// Start microservice.</jc>
.startConsole() <jc>// Start console.</jc>
.join() <jc>// Join thread.</jc>
;
}
<jk>public static void</jk> restart() {
Microservice.<jsm>getInstance</jsm>().stop().start();
}
<jk>public static void</jk> exit() {
Microservice.<jsm>getInstance</jsm>().exit();
}
}
</p>
<p>
The <a href="org/apache/juneau/microservice/Microservice.html#startConsole--"><code>Microservice.startConsole()</code></a> and <a href="org/apache/juneau/microservice/Microservice.html#stopConsole--"><code>Microservice.stopConsole()</code></a> control
the lifecycle of the console commands.
Typically you'll want to control these separately from the app so that you can easily restart your application
from the console without affecting the console itself.
</p>
<p>
The lifecycle methods on the <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> class are purposely left non-final so that
subclasses can override them to provide customized behavior.
</p>
</div>
</div><!-- END: 14.2 - juneau-microservice-core.jmc.LifecycleMethods -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core.jmc.Args' id='juneau-microservice-core.jmc.Args'>14.3 - Args</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 14.3 - juneau-microservice-core.jmc.Args -->
<div class='topic'>
<p>
Command-line arguments can be associated with a microservice using the <a href="org/apache/juneau/microservice/Microservice.Builder.html#args-java.lang.String...-"><code>Microservice.Builder.args(String...)</code></a> method.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jk>public static void</jk> main(String[] <jv>args</jv>) {
Microservice
.<jsm>create</jsm>() <jc>// Create builder.</jc>
.args(<jv>args</jv>) <jc>// Pass in args.</jc>
.build() <jc>// Create microservice.</jc>
.start() <jc>// Start microservice.</jc>
.join() <jc>// Join thread.</jc>
;
}
</p>
<p>
When specified, the arguments can be retrieved using the <a href="org/apache/juneau/microservice/Microservice.html#getArgs--"><code>Microservice.getArgs()</code></a> method which provides
an API for easily accessing command-line arguments using common notation:
</p>
<p class='bjava'>
Args <jv>args</jv> = Microservice.<jsm>getInstance</jsm>().getArgs();
<jc>// One main argument</jc>
<jc>// a1</jc>
String <jv>a1</jv> = <jv>args</jv>.getArg(0); <jc>// "a1"</jc>
String <jv>a2</jv> = <jv>args</jv>.getArg(1); <jc>// null</jc>
<jc>// Two main arguments</jc>
<jc>// a1 a2</jc>
String <jv>a1</jv> = <jv>args</jv>.getArg(0); <jc>// "a1"</jc>
String <jv>a2</jv> = <jv>args</jv>.getArg(1); <jc>// "a2"</jc>
<jc>// One main argument and one optional argument with no value</jc>
<jc>// a1 -a2</jc>
String <jv>args</jv>a1 = <jv>args</jv>.getArg(0);
<jk>boolean</jk> <jv>hasA2</jv> = <jv>args</jv>.hasArg(<js>"a2"</js>); <jc>// true</jc>
<jk>boolean</jk> <jv>hasA3</jv> = <jv>args</jv>.hasArg(<js>"a3"</js>); <jc>// false</jc>
<jc>// One main argument and one optional argument with one value</jc>
<jc>// a1 -a2 v2</jc>
String <jv>a1</jv> = <jv>args</jv>.getArg(0);
String <jv>a2</jv> = <jv>args</jv>.getArg(<js>"a2"</js>); <jc>// "v2"</jc>
String <jv>a3</jv> = <jv>args</jv>.getArg(<js>"a3"</js>); <jc>// null</jc>
<jc>// One main argument and one optional argument with two values</jc>
<jc>// a1 -a2 v2a v2b</jc>
String <jv>a1</jv> = <jv>args</jv>.getArg(0);
List&lt;String&gt; <jv>a2</jv> = <jv>args</jv>.getArgs(<js>"a2"</js>); <jc>// Contains ["v2a","v2b"]</jc>
List&lt;String&gt; <jv>a3</jv> = <jv>args</jv>.getArgs(<js>"a3"</js>); <jc>// Empty list</jc>
<jc>// Same as previous, except specify optional argument name multiple times</jc>
<jc>// a1 -a2 v2a -a2 v2b</jc>
String <jv>a1</jv> = <jv>args</jv>.getArg(0);
List&lt;String&gt; <jv>a2</jv> = <jv>args</jv>.getArgs(<js>"a2"</js>); <jc>// Contains ["v2a","v2b"]</jc>
</p>
<p>
Specifying the command-line arguments also makes them available through <a href="org/apache/juneau/svl/vars/ArgsVar.html" title="class in org.apache.juneau.svl.vars"><code>$A</code></a> SVL variables.
These can be used in the configuration file and throughout various Juneau annotations.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
<jc>// $A used in variable resolver.</jc>
VarResolver <jv>varResolver</jv> = Microservice.<jsm>getInstance</jsm>().getVarResolver();
System.<jsf>out</jsf>.println(<jv>varResolver</jv>.resolve(<js>"Arg #1 is set to $A{1}"</js>));
</p>
<p class='bjava'>
<jc>// $A used in annotation.</jc>
<ja>@Rest</ja>(
title=<js>"$A{title}"</js>,
...
)
</p>
</div>
</div><!-- END: 14.3 - juneau-microservice-core.jmc.Args -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core.jmc.Manifest' id='juneau-microservice-core.jmc.Manifest'>14.4 - Manifest</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 14.4 - juneau-microservice-core.jmc.Manifest -->
<div class='topic'>
<p>
The <a href="org/apache/juneau/microservice/Microservice.Builder.html#manifest-java.lang.Object-"><code>Microservice.Builder.manifest(Object)</code></a> method can be used to specify the contents or location of of the main
manifest file of the executable jar.
</p>
<p>
If you do not specify the location/contents of the manifest file, the microservice will attempt to resolve it through the following methods:
</p>
<ol class='spaced-list'>
<li>
Looking on the file system for a file at <js>"META-INF/MANIFEST.MF"</js>.
This is primarily to allow for running microservices from within eclipse workspaces where the manifest file
is located in the project root.
<li>
Using the class loader for this class to find the file at the URL <js>"META-INF/MANIFEST.MF"</js>.
</ol>
<p>
If you do manually specify the manifest file, you can pass in any of the following types:
</p>
<ul>
<li><a href="org/apache/juneau/utils/ManifestFile.html" title="class in org.apache.juneau.utils"><code>ManifestFile</code></a> - A pre-parsed manifest file.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/jar/Manifest.html?is-external=true" title="class or interface in java.util.jar"><code>Manifest</code></a> - A pre-parsed manifest file.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a> - Containing the raw contents of the manifest.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a> - Containing the raw contents of the manifest.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/File.html?is-external=true" title="class or interface in java.io"><code>File</code></a> - File containing the raw contents of the manifest.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>String</code></a> - Path to file containing the raw contents of the manifest.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html?is-external=true" title="class or interface in java.lang"><code>Class</code></a> - Finds and loads the manifest file of the jar file that the specified class is contained within.
</ul>
<p>
The manifest file can be retrieved using the the <a href="org/apache/juneau/microservice/Microservice.html#getManifest--"><code>Microservice.getManifest()</code></a> method which
provides an API for accessing manifest file entries.
This method returns an instance of <a href="org/apache/juneau/utils/ManifestFile.html" title="class in org.apache.juneau.utils"><code>ManifestFile</code></a> which extends from <a href="org/apache/juneau/collections/JsonMap.html" title="class in org.apache.juneau.collections"><code>JsonMap</code></a> allowing
you to retrieve entries as any data types supported by that class.
</p>
<h5 class='figure'>Example:</h5>
<p class='bjava'>
ManifestFile <jv>manifestFile</jv> = Microservice.<jsm>getInstance</jsm>().getManifest();
String <jv>mainClass</jv> = <jv>manifestFile</jv>.getString(<js>"Main-Class"</js>);
<jk>int</jk> <jv>myInt</jv> = <jv>manifestFile</jv>.getInt(<js>"My-Int"</js>, 123);
<jk>boolean</jk> <jv>myBoolean</jv> = <jv>manifestFile</jv>.getBoolean(<js>"My-Boolean"</js>);
</p>
<p>
The manifest is also used for the <a href="org/apache/juneau/svl/vars/ManifestFileVar.html" title="class in org.apache.juneau.svl.vars"><code>$MF</code></a> SVL variable.
</p>
<h5 class='figure'>Examples:</h5>
<p class='bjava'>
<jc>// $MF used in variable resolver.</jc>
VarResolver <jv>var</jv> = Microservice.<jsm>getInstance</jsm>().getVarResolver();
System.<jsf>out</jsf>.println(<jv>vr</jv>.resolve(<js>"The main class is $MF{Main-Class}"</js>));
</p>
<p class='bjava'>
<jc>// $MF used in annotation.</jc>
<ja>@Rest</ja>(
title=<js>"$MF{Application-Title}"</js>,
...
)
</p>
</div>
</div><!-- END: 14.4 - juneau-microservice-core.jmc.Manifest -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core.jmc.Config' id='juneau-microservice-core.jmc.Config'>14.5 - Config</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 14.5 - juneau-microservice-core.jmc.Config -->
<div class='topic'>
<p>
The following methods can be used to define the configuration for your microservice using the powerful Config API:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/microservice/Microservice.Builder.html" title="class in org.apache.juneau.microservice"><code>Microservice.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#config-org.apache.juneau.config.Config-"><code>config(Config)</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#configName-java.lang.String-"><code>configName(String)</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#configStore-org.apache.juneau.config.store.ConfigStore-"><code>configStore(ConfigStore)</code></a>
</ul>
</li>
</ul>
<p>
If you do not specify any of this information, we attempt to resolve it through the following methods:
</p>
<ol class='spaced-list'>
<li>
Resolve file first in working directory, then in classpath, using the following names:
<ol>
<li>
The <js>"configFile"</js> argument in the command line arguments passed in through the constructor.
<li>
The value of the <c>Main-Config</c> entry in the manifest file.
<li>
A config file in the same location and with the same name as the executable jar file.
(e.g. <js>"java -jar myjar.jar"</js> will look for <js>"myjar.cfg"</js>).
</ol>
<li>
Resolve any <js>"*.cfg"</js> file that can be found in the working directory.
<li>
Resolve any of the following files in the classpath:
<ol>
<li><c>juneau.cfg</c>
<li><c>default.cfg</c>
<li><c>application.cfg</c>
<li><c>app.cfg</c>
<li><c>settings.cfg</c>
</ol>
</ol>
<p>
If no configuration file is found, and empty in-memory configuration is used.
</p>
<p>
The <a href="org/apache/juneau/microservice/Microservice.Builder.html#configName-java.lang.String-"><code>configName(String)</code></a> method allows you to explicitly specify the name
of the external configuration file location for your microservice.
</p>
<p class='bjava'>
Microservice
.<jsm>create</jsm>()
.config(<js>"my-files/MyMicroservice.cfg"</js>)
.build()
.start()
;
</p>
<p>
By default, we try to find the file on the file system and then the classpath.
If located on the file system, then the configuration is writeable and the microservice can automatically
listen for and react to changes in the configuration file on the file system.
If located on the classpath, then the configuration can still react to modifications made to it through
the Config API but the changes cannot be persisted since the location prevents the file from being modified.
</p>
<p>
The <a href="org/apache/juneau/microservice/Microservice.Builder.html#configStore-org.apache.juneau.config.store.ConfigStore-"><code>configStore(ConfigStore)</code></a> method can be used to explicitly
specify a configuration store.
This can include your own custom configuration store, such as one that's implemented in a relational database.
</p>
<p class='bjava'>
Microservice
.<jsm>create</jsm>()
.configStore(<jk>new</jk> MyConfigSqlStore())
.configName(<js>"MyConfig"</js>)
.build()
.start()
;
</p>
<p>
The <a href="org/apache/juneau/microservice/Microservice.Builder.html#config-org.apache.juneau.config.Config-"><code>config(Config)</code></a> method can be used to explicitly specify a <a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>
file as the microservice configuration. When this method is used, the above two methods are bypassed entirely.
</p>
<p class='bjava'>
Config <jv>config</jv> = <jsm>getMyOwnConfig</jsm>();
Microservice
.<jsm>create</jsm>()
.config(<jv>config</jv>)
.build()
.start()
;
</p>
<p>
Once the configuration is resolved, it is made as the system default configuration available through the <a href="org/apache/juneau/config/Config.html#getSystemDefault--"><code>Config.getSystemDefault()</code></a>.
This in turn allows it to be used by REST resources that reference the system default configuration via the <js>"SYSTEM_DEFAULT"</js> such as those
implementing the <dc>org.apache.juneau.rest.BasicRestConfig</dc> interface.
<p>
<h5 class='figure'>BasicRestConfig.java</h5>
<p class='bjava'>
<ja>@Rest</ja>(
config=<js>"$S{juneau.configFile,SYSTEM_DEFAULT}"</js>
...
)
</p>
<p>
The <a href="org/apache/juneau/microservice/Microservice.html#getConfig--"><code>Microservice.getConfig()</code></a> method can be used to get access to the configuration.
</p>
<p class='bjava'>
Config <jv>config</jv> = Microservice.<jsm>getInstance</jsm>().getConfig();
File <jv>logDir</jv> = <jv>config</jv>.get(<js>"Logging/logDir"</js>).as(File.<jk>class</jk>).orElse(<jk>null</jk>);
<jk>boolean</jk> <jv>append</jv> = <jv>config</jv>.get(<js>"Logging/append"</js>).asBoolean().orElse(<jk>null</jk>);
String <jv>format</jv> = <jv>config</jv>.get(<js>"Logging/format"</js>, <js>"[{date} {level}] {msg}%n"</js>).orElse(<jk>null</jk>);
<jk>long</jk> <jv>limit</jv> = <jv>config</jv>.get(<js>"Logging/limit"</js>).asLong().orElse(<jk>null</jk>);
Map&lt;String,Level&gt; <jv>levels</jv> = <jv>config</jv>.get(<js>"Logging/levels"</js>).as(Map.<jk>class</jk>, String.<jk>class</jk>, Level.<jk>class</jk>).orElse(<jk>null</jk>);
</p>
<p>
Changes to the configuration file can trigger notifications that can be used to restart your microservice or make various other
on-the-fly changes.
This can be accomplished by either overriding the <a href="org/apache/juneau/microservice/Microservice.html#onConfigChange-org.apache.juneau.config.event.ConfigEvents-"><code>Microservice.onConfigChange(ConfigEvents)</code></a> or implementing
a listener and using the <a href="org/apache/juneau/microservice/MicroserviceListener.html#onConfigChange-org.apache.juneau.microservice.Microservice-org.apache.juneau.config.event.ConfigEvents-"><code>MicroserviceListener.onConfigChange(Microservice,ConfigEvents)</code></a> methods.
These will be described in detail later.
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-config'>Overview &gt; juneau-config</a>
</ul>
</div>
</div><!-- END: 14.5 - juneau-microservice-core.jmc.Config -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core.jmc.SystemProperties' id='juneau-microservice-core.jmc.SystemProperties'>14.6 - System properties</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 14.6 - juneau-microservice-core.jmc.SystemProperties -->
<div class='topic'>
<p>
As a convenience, the <c>SystemProperties</c> section of your configuration file can be used to define system
properties to set during initialization of your microservice:
</p>
<p class='bini'>
<cc>#=======================================================================================================================
# System properties
#-----------------------------------------------------------------------------------------------------------------------
# These are arbitrary system properties that are set during startup.
#=======================================================================================================================</cc>
<cs>[SystemProperties]</cs>
<cc># Configure Jetty for StdErrLog Logging
# org.eclipse.jetty.util.log.class = org.eclipse.jetty.util.log.StrErrLog</cc>
<cc># Configure Jetty to log using java-util logging</cc>
<ck>org.eclipse.jetty.util.log.class</ck> = <cv>org.apache.juneau.microservice.jetty.JettyLogger</cv>
<cc># Jetty logging level
# Possible values: ALL, DEBUG, INFO, WARN, OFF</cc>
<ck>org.eclipse.jetty.LEVEL</ck> = <cv>WARN</cv>
<ck>derby.stream.error.file</ck> = <cv>$C{Logging/logDir}/derby-errors.log</cv>
</p>
</div>
</div><!-- END: 14.6 - juneau-microservice-core.jmc.SystemProperties -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core.jmc.VarResolver' id='juneau-microservice-core.jmc.VarResolver'>14.7 - VarResolver</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 14.7 - juneau-microservice-core.jmc.VarResolver -->
<div class='topic'>
<p>
The Microservice API incorporates the <a class='doclink' href='#juneau-marshall.jm.SimpleVariableLanguage'>Simple Variable Language</a> API.
</p>
<p>
The variable resolver can be augmented through the following methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/microservice/Microservice.Builder.html" title="class in org.apache.juneau.microservice"><code>Microservice.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#vars-java.lang.Class...-"><code>vars(Class...)</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#varBean-java.lang.Class-T-"><code>varBean(Class,Object)</code></a>
</ul>
</li>
</ul>
<p>
A typical usage pattern is shown below:
</p>
<p class='bjava'>
<jc>// $A used in variable resolver.</jc>
VarResolver <jv>varResolver</jv> = Microservice.<jsm>getInstance</jsm>().getVarResolver();
System.<jsf>out</jsf>.println(<jv>varResolver</jv>.resolve(<js>"Main class is set to $MF{Main-Class, unknown}"</js>));
</p>
<p>
The variable resolver becomes much more powerful when used in REST resource annotations which will be
described latter in <a class='doclink' href='#juneau-microservice-jetty'>Overview &gt; juneau-microservice-jetty</a>
</p>
<p>
By default, support for the following variables are provided:
</p>
<ul>
<li><c>$S{key[,default]}</c> - <a href="org/apache/juneau/svl/vars/SystemPropertiesVar.html" title="class in org.apache.juneau.svl.vars"><code>SystemPropertiesVar</code></a>
<li><c>$E{key[,default]}</c> - <a href="org/apache/juneau/svl/vars/EnvVariablesVar.html" title="class in org.apache.juneau.svl.vars"><code>EnvVariablesVar</code></a>
<li><c>$A{key[,default]}</c> - <a href="org/apache/juneau/svl/vars/ArgsVar.html" title="class in org.apache.juneau.svl.vars"><code>ArgsVar</code></a>
<li><c>$C{key[,default]}</c> - <a href="org/apache/juneau/config/vars/ConfigVar.html" title="class in org.apache.juneau.config.vars"><code>ConfigVar</code></a>
<li><c>$MF{key[,default]}</c> - <a href="org/apache/juneau/svl/vars/ManifestFileVar.html" title="class in org.apache.juneau.svl.vars"><code>ManifestFileVar</code></a>
<li><c>$IF{arg,then[,else]}</c> - <a href="org/apache/juneau/svl/vars/IfVar.html" title="class in org.apache.juneau.svl.vars"><code>IfVar</code></a>
<li><c>$SW{arg,pattern1:then1[,pattern2:then2...]}</c> - <a href="org/apache/juneau/svl/vars/SwitchVar.html" title="class in org.apache.juneau.svl.vars"><code>SwitchVar</code></a>
<li><c>$CO{arg[,arg2...]}</c> - <a href="org/apache/juneau/svl/vars/CoalesceVar.html" title="class in org.apache.juneau.svl.vars"><code>CoalesceVar</code></a>
<li><c>$PM{arg,pattern}</c> - <a href="org/apache/juneau/svl/vars/PatternMatchVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternMatchVar</code></a>
<li><c>$UC{arg}</c> - <a href="org/apache/juneau/svl/vars/UpperCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>UpperCaseVar</code></a>
<li><c>$LC{arg}</c> - <a href="org/apache/juneau/svl/vars/LowerCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>LowerCaseVar</code></a>
<li><c>$NE{arg}</c> - <a href="org/apache/juneau/svl/vars/NotEmptyVar.html" title="class in org.apache.juneau.svl.vars"><code>NotEmptyVar</code></a>
</ul>
</div>
</div><!-- END: 14.7 - juneau-microservice-core.jmc.VarResolver -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core.jmc.ConsoleCommands' id='juneau-microservice-core.jmc.ConsoleCommands'>14.8 - Console Commands</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 14.8 - juneau-microservice-core.jmc.ConsoleCommands -->
<div class='topic'>
<p>
The Microservice API provides support for simple console commands.
</p>
<p class='bjava'>
<jk>public static void</jk> main(String[] <jv>args</jv>) {
Microservice
.<jsm>create</jsm>()
.args(<jv>args</jv>)
.build()
.start()
.startConsole() <jc>// Start console.</jc>
.join()
;
}
</p>
<p>
When started, the console renders the following output:
</p>
<p class='bconsole'>
Running class 'Microservice' using config file 'my-microservice.cfg'.
List of available commands:
exit -- Shut down service
restart -- Restarts service
help -- Commands help
>
</p>
<p>
The builder methods for controlling the console are as follows:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/microservice/Microservice.Builder.html" title="class in org.apache.juneau.microservice"><code>Microservice.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#consoleEnabled-boolean-"><code>consoleEnabled(boolean)</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#consoleCommands-org.apache.juneau.microservice.console.ConsoleCommand...-"><code>consoleCommands(ConsoleCommand...)</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#consoleCommands-java.lang.Class...-"><code>consoleCommands(Class...)</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#console-java.util.Scanner-java.io.PrintWriter-"><code>console(Scanner,PrintWriter)</code></a>
</ul>
</li>
</ul>
<p>
By default, the supported commands are pulled from the configuration file:
</p>
<p class='bini'>
<cc>#=======================================================================================================================
# Console settings
#=======================================================================================================================</cc>
<cs>[Console]</cs>
<ck>enabled = <cv>true</cv>
<cc># List of available console commands.
# These are classes that implements ConsoleCommand that allow you to submit commands to the microservice via
# the console.
# When listed here, the implementations must provide a no-arg constructor.
# They can also be provided dynamically by overriding the Microservice.createConsoleCommands() method.</cc>
<ck>commands</ck> =
<cv>org.apache.juneau.microservice.console.ExitCommand,
org.apache.juneau.microservice.console.RestartCommand,
org.apache.juneau.microservice.console.HelpCommand</cv>
</p>
<p>
New commands can be added by adding them to the configuration file, or programmatically using the <a href="org/apache/juneau/microservice/Microservice.Builder.html#consoleCommands-org.apache.juneau.microservice.console.ConsoleCommand...-"><code>consoleCommands(ConsoleCommand...)</code></a>
builder method.
</p>
<p>
The API for defining console commands is shown below:
</p>
<ul class='javatree'>
<li class='jac'><a href="org/apache/juneau/microservice/console/ConsoleCommand.html" title="class in org.apache.juneau.microservice.console"><code>ConsoleCommand</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/microservice/console/ConsoleCommand.html#execute-java.util.Scanner-java.io.PrintWriter-org.apache.juneau.collections.Args-"><code>execute(Scanner,PrintWriter,Args)</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/console/ConsoleCommand.html#getDescription--"><code>getDescription()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/console/ConsoleCommand.html#getExamples--"><code>getExamples()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/console/ConsoleCommand.html#getInfo--"><code>getInfo()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/console/ConsoleCommand.html#getName--"><code>getName()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/console/ConsoleCommand.html#getSynopsis--"><code>getSynopsis()</code></a>
</ul>
</li>
</ul>
<p>
By default, the console input and output are taken from <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/System.in.html?is-external=true" title="class or interface in java.lang"><code>System.in</code></a> and <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/System.out.html?is-external=true" title="class or interface in java.lang"><code>System.out</code></a>.
These can be overridden using the <a href="org/apache/juneau/microservice/Microservice.Builder.html#console-java.util.Scanner-java.io.PrintWriter-"><code>console(Scanner,PrintWriter)</code></a> method.
</p>
</div>
</div><!-- END: 14.8 - juneau-microservice-core.jmc.ConsoleCommands -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-core.jmc.Listeners' id='juneau-microservice-core.jmc.Listeners'>14.9 - Listeners</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 14.9 - juneau-microservice-core.jmc.Listeners -->
<div class='topic'>
<p>
As mentioned previously, the lifecycle methods for the <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> class are explicitly
defined as non-final so that they can be overridden by subclasses.
</p>
<p>
In addition to this support, an interface for defining event listeners for your microservice:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/microservice/Microservice.Builder.html" title="class in org.apache.juneau.microservice"><code>Microservice.Builder</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.Builder.html#listener-org.apache.juneau.microservice.MicroserviceListener-"><code>listener(MicroserviceListener)</code></a>
</ul>
</li>
<li class='jic'><a href="org/apache/juneau/microservice/MicroserviceListener.html" title="interface in org.apache.juneau.microservice"><code>MicroserviceListener</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/microservice/MicroserviceListener.html#onStart-org.apache.juneau.microservice.Microservice-"><code>onStart(Microservice)</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/MicroserviceListener.html#onStop-org.apache.juneau.microservice.Microservice-"><code>onStop(Microservice)</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/MicroserviceListener.html#onConfigChange-org.apache.juneau.microservice.Microservice-org.apache.juneau.config.event.ConfigEvents-"><code>onConfigChange(Microservice,ConfigEvents)</code></a>
</ul>
</li>
<li class='jac'><a href="org/apache/juneau/microservice/BasicMicroserviceListener.html" title="class in org.apache.juneau.microservice"><code>BasicMicroserviceListener</code></a>
</ul>
<p>
This listener API can be used for listening for and reacting to configuration changes on the file system.
</p>
<p class='bjava'>
<jk>public class</jk> MyMicroserviceListener <jk>extends</jk> BasicMicroserviceListener {
<ja>@Override</ja> <jc>/* MicroserviceListener */</jc>
<jk>public void</jk> onConfigChange(Microservice <jv>microservice</jv>, ConfigEvents <jv>events</jv>) {
<jc>// Restart the microservice if anything was modified in one of our sections</jc>
<jk>if</jk> (<jv>events</jv>.isSectionChanged(<js>"MySection"</js>))
<jv>microservice</jv>.stop().start();
}
}
</p>
<p>
Note that the <a href="org/apache/juneau/microservice/Microservice.html#onConfigChange-org.apache.juneau.config.event.ConfigEvents-"><code>Microservice.onConfigChange(ConfigEvents)</code></a> method can also be overridden
to react to configuration changes as well:
</p>
<p class='bjava'>
<jk>public class</jk> MyMicroservice <jk>extends</jk> Microservice {
<ja>@Override</ja> <jc>/* MicroserviceListener */</jc>
<jk>public void</jk> onConfigChange(ConfigEvents <jv>events</jv>) {
<jc>// Restart the microservice if anything was modified in one of our sections</jc>
<jk>if</jk> (<jv>events</jv>.isSectionChanged(<js>"MySection"</js>))
<jk>this</jk>.stop().start();
}
}
</p>
</div>
</div><!-- END: 14.9 - juneau-microservice-core.jmc.Listeners -->
</div><!-- END: 14 - juneau-microservice-core -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-jetty' id='juneau-microservice-jetty'>15 - juneau-microservice-jetty</a><span class='update'>created: 8.1.0</span></h2>
<div class='topic'><!-- START: 15 - juneau-microservice-jetty -->
<div class='topic'>
<h5 class='figure'>Maven Dependency</h5>
<p class='bxml w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-microservice-jetty<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.0.0<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-microservice-jetty-9.0.0.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.microservice.jetty_9.0.0.jar
</p>
<p>
Juneau Microservice Jetty is an API for creating stand-alone executable jars that can be used to
start lightweight configurable REST interfaces with all the power of the Juneau REST server and client APIs.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-jetty.jmj.Overview' id='juneau-microservice-jetty.jmj.Overview'>15.1 - Overview</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 15.1 - juneau-microservice-jetty.jmj.Overview -->
<div class='topic'>
<p>
The Jetty Microservice API consists of a combination of the Juneau Core, Server, and Client APIs and an embedded
Eclipse Jetty Servlet Container.
</p>
<p>
The API builds upon the <a class='doclink' href='#juneau-microservice-core'>Core Microservice</a> classes to produce easy-to-create and
easy-to-use microservices in a standard Java 1.8+ environment.
</p>
<p>
The <c>juneau-microservice-jetty</c> library consists of the following classes:
</p>
<ul class='javatree'>
<li class='jp'><a href="org/apache/juneau/microservice/jetty/package-summary.html"><code>org.apache.juneau.microservice.jetty</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html" title="class in org.apache.juneau.microservice.jetty"><code>JettyMicroservice</code></a> - The Jetty microservice class.
<li class='jc'><a href="org/apache/juneau/microservice/jetty/JettyMicroservice.Builder.html" title="class in org.apache.juneau.microservice.jetty"><code>JettyMicroservice.Builder</code></a> - Builder for the microservice class.
<li class='jic'><a href="org/apache/juneau/microservice/jetty/JettyMicroserviceListener.html" title="interface in org.apache.juneau.microservice.jetty"><code>JettyMicroserviceListener</code></a> - Interface for hooking into lifecyle events of the microservice.
<ul>
<li class='jc'><a href="org/apache/juneau/microservice/jetty/BasicJettyMicroserviceListener.html" title="class in org.apache.juneau.microservice.jetty"><code>BasicJettyMicroserviceListener</code></a> - Adapter for JettyMicroserviceListener class.
</ul>
</li>
<li class='jic'><a href="org/apache/juneau/microservice/jetty/JettyServerFactory.html" title="interface in org.apache.juneau.microservice.jetty"><code>JettyServerFactory</code></a> - Interface for defining custom Jetty servers.
<ul>
<li class='jc'><a href="org/apache/juneau/microservice/jetty/BasicJettyServerFactory.html" title="class in org.apache.juneau.microservice.jetty"><code>BasicJettyServerFactory</code></a> - Adapter for JettyServerFactory class.
</ul>
</li>
</ul>
</li>
</ul>
<p>
The most-basic creation of a Jetty microservice from an entry-point method is shown below:
</p>
<p class='bjava'>
<jk>public class</jk> App {
<jk>public static void</jk> main(String[] <jv>args</jv>) {
JettyMicroservice
.<jsm>create</jsm>() <jc>// Create builder.</jc>
.args(<jv>args</jv>) <jc>// Pass in args.</jc>
.servlets(RootResource.<jk>class</jk>) <jc>// A Juneau RestServlet class.</jc>
.build() <jc>// Create microservice.</jc>
.start() <jc>// Start microservice.</jc>
;
}
}
</p>
</div>
</div><!-- END: 15.1 - juneau-microservice-jetty.jmj.Overview -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-jetty.jmj.LifecycleMethods' id='juneau-microservice-jetty.jmj.LifecycleMethods'>15.2 - Lifecycle Methods</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 15.2 - juneau-microservice-jetty.jmj.LifecycleMethods -->
<div class='topic'>
<p>
To review, the <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> class contains the following lifecycle methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#start--"><code>start()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#startConsole--"><code>startConsole()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#join--"><code>join()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#stop--"><code>stop()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#stopConsole--"><code>stopConsole()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#exit--"><code>exit()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#kill--"><code>kill()</code></a>
</ul>
</li>
</ul>
<p>
The <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html" title="class in org.apache.juneau.microservice.jetty"><code>JettyMicroservice</code></a> class which extends from <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a>
provides the following additional lifecycle methods:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html" title="class in org.apache.juneau.microservice.jetty"><code>JettyMicroservice</code></a>
<ul class='javatreec'>
<li class='jm'><a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html#createServer--"><code>createServer()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html#startServer--"><code>startServer()</code></a>
<li class='jm'><a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html#destroyServer--"><code>destroyServer()</code></a>
</ul>
</li>
</ul>
<p>
The additional lifecycle methods are typically not called directly but are exposed to allow subclasses to
provide customized behavior for these events.
For this reason, these methods are left as non-final so that they can be overridden.
</p>
<p>
A typical implementation of an app with lifecycle methods might look like the following:
</p>
<p class='bjava'>
<jk>public class</jk> App {
<jk>private static final</jk> JettyMicroservice <jsf>MICROSERVICE</jsf>;
<jk>public static void</jk> main(String[] <jv>args</jv>) {
<jsf>MICROSERVICE</jsf> = JettyMicroservice
.<jsm>create</jsm>() <jc>// Create builder.</jc>
.args(<jv>args</jv>) <jc>// Pass in args.</jc>
.servlets(RootResource.<jk>class</jk>) <jc>// A Juneau RestServlet class.</jc>
.build() <jc>// Create microservice.</jc>
.start() <jc>// Start microservice.</jc>
.startConsole() <jc>// Start console.</jc>
.join() <jc>// Join thread.</jc>
;
}
<jk>public static void</jk> restart() {
<jsf>MICROSERVICE</jsf>.stop().start();
}
<jk>public static void</jk> exit() {
<jsf>MICROSERVICE</jsf>.exit();
}
}
</p>
<p>
Similar to <a href="org/apache/juneau/microservice/Microservice.html#getInstance--"><code>Microservice.getInstance()</code></a>, the <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html#getInstance--"><code>JettyMicroservice.getInstance()</code></a>
also allows easy access to the microservice:
</p>
<p class='bjava'>
<jk>public class</jk> App {
<jk>public static void</jk> main(String[] <jv>args</jv>) {
JettyMicroservice
.<jsm>create</jsm>() <jc>// Create builder.</jc>
.args(<jv>args</jv>) <jc>// Pass in args.</jc>
.servlets(RootResource.<jk>class</jk>) <jc>// A Juneau RestServlet class.</jc>
.build() <jc>// Create microservice.</jc>
.start() <jc>// Start microservice.</jc>
.startConsole() <jc>// Start console.</jc>
.join() <jc>// Join thread.</jc>
;
}
<jk>public static void</jk> restart() {
JettyMicroservice.<jsm>getInstance</jsm>().stop().start();
}
<jk>public static void</jk> exit() {
JettyMicroservice.<jsm>getInstance</jsm>().exit();
}
}
</p>
</div>
</div><!-- END: 15.2 - juneau-microservice-jetty.jmj.LifecycleMethods -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-jetty.jmj.ResourceClasses' id='juneau-microservice-jetty.jmj.ResourceClasses'>15.3 - Resource Classes</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 15.3 - juneau-microservice-jetty.jmj.ResourceClasses -->
<div class='topic'>
<p>
This section describes how to define a top-level REST resource page and deploy it in our microservice.
The example is a router page that serves as a jumping off page to child resources.
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/*"</js>,
title=<js>"My Microservice"</js>,
description=<js>"Top-level resources page"</js>,
htmldoc=<ja>@HtmlDoc</ja>(
navlinks={
<js>"options: servlet:/?method=OPTIONS"</js>
}
),
children={
HelloWorldResource.<jk>class</jk>,
ConfigResource.<jk>class</jk>,
LogsResource.<jk>class</jk>
}
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicRestServletGroup <jk>implements</jk> BasicUniversalConfig {
<jc>// No code! </jc>
}
</p>
<p>
When deployed, it looks like this in a browser:
</p>
<p class='bcode'>
http://localhost:10000
</p>
<img class='bordered w800' src='doc-files/jmj.Running.1.png'>
<ul class='spaced-list'>
<li>
The </l>title</l> and <l>description</l> annotations define the titles on the page.
<br>These can be globalized using <l>$L{...}</l> variables, or by defining specially-named properties in the
properties file for the resource.
<li>
In this case, the <l>path</l> annotation defines the context root of your application since it was
not specified in the manifest or config file.
<br>Therefore, this resource is mapped to <l>http://localhost:10000</l>.
<li>
The <l>children</l> annotation make up the list of child resources.
<br>These child resources can be anything that extends from <l>Servlet</l>, although usually
they will be subclasses of <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> or other resource groups.
</ul>
<p>
If you click the <l>helloWorld</l> link in your application, you'll get a simple hello world message:
</p>
<p class='bcode'>
http://localhost:10000/helloWorld
</p>
<img class='bordered w800' src='doc-files/jmj.ResourceClasses.1.png'>
<p>
...which is generated by this class...
</p>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/helloWorld"</js>,
title=<js>"Hello World example"</js>,
description=<js>"Simplest possible REST resource"</js>
)
<jk>public class</jk> HelloWorldResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<ja>@RestGet</ja>(<js>"/*"</js>)
<jk>public</jk> String sayHello() {
<jk>return</jk> <js>"Hello world!"</js>;
}
}
</p>
<p>
The most-common case for deploying the top-level resource is to use the <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.Builder.html#servlet-java.lang.Class-"><code>JettyMicroservice.Builder.servlet(Class)</code></a> method:
</p>
<p class='bjava'>
<jk>public class</jk> App {
<jk>public static void</jk> main(String[] <jv>args</jv>) {
JettyMicroservice
.<jsm>create</jsm>()
.args(<jv>args</jv>)
.servlet(RootResources.<jk>class</jk>) <jc>// Our root resource.</jc>
.build()
.start()
;
}
}
</p>
<p>
However, there are multiple ways of deploying top-level resources:
</p>
<ul class='spaced-list'>
<li>
<a href="org/apache/juneau/microservice/jetty/JettyMicroservice.Builder.html#servlet-java.lang.Class-"><code>JettyMicroservice.Builder.servlet(Class)</code></a> - Using the builder. Several methods provided.
<li>
<a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html#addServlet-javax.servlet.Servlet-java.lang.String-"><code>JettyMicroservice.addServlet(Servlet,String)</code></a> - After the Jetty container has been started.
<li>
As a configuration variable <js>"Jetty/servlets"</js>.
<p class='bini'>
<cc>#=======================================================================================================================
# Jetty settings
#=======================================================================================================================</cc>
<cs>[Jetty]</cs>
<cc># Subclasses of RestServlet</cc>
<ck>servlets</ck> = <cv>org.apache.juneau.examples.rest.RootResources</cv>
</p>
<li>
As a configuration variable <js>"Jetty/servletMap"</js>.
<p class='bini'>
<cc>#=======================================================================================================================
# Jetty settings
#=======================================================================================================================</cc>
<cs>[Jetty]</cs>
<cc># Any servlets and their path specs</cc>
<ck>servletMap</ck> =
<cv>{
'/*': 'org.apache.juneau.examples.rest.RootResources'
}</cv>
</cv>
</p>
<li>
Directly in the <c>jetty.xml</c> file.
<p class='bxml'>
<xt>&lt;Configure</xt> <xa>id</xa>=<xs>"ExampleServer"</xs> <xa>class</xa>=<xs>"org.eclipse.jetty.server.Server"</xs><xt>&gt;</xt>
...
<xt>&lt;New</xt> <xa>id</xa>=<xs>"context"</xs> <xa>class</xa>=<xs>"org.eclipse.jetty.servlet.ServletContextHandler"</xs><xt>&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"contextPath"</xs><xt>&gt;/&lt;/Set&gt;</xt>
<xt>&lt;Call</xt> <xa>name</xa>=<xs>"addServlet"</xs><xt>&gt;</xt>
<xt>&lt;Arg&gt;</xt>org.apache.juneau.rest.test.Root<xt>&lt;/Arg&gt;</xt>
<xt>&lt;Arg&gt;</xt>/*<xt>&lt;/Arg&gt;</xt>
<xt>&lt;/Call&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"sessionHandler"</xs><xt>&gt;</xt>
<xt>&lt;New</xt> <xa>class</xa>=<xs>"org.eclipse.jetty.server.session.SessionHandler"</xs> <xt>/&gt;</xt>
<xt>&lt;/Set&gt;</xt>
<xt>&lt;/New&gt;</xt>
...
</p>
</ul>
</div>
</div><!-- END: 15.3 - juneau-microservice-jetty.jmj.ResourceClasses -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-jetty.jmj.PredefinedResourceClasses' id='juneau-microservice-jetty.jmj.PredefinedResourceClasses'>15.4 - Predefined Resource Classes</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 15.4 - juneau-microservice-jetty.jmj.PredefinedResourceClasses -->
<div class='topic'>
<p>
The following predefined resource classes are also provided for easy inclusion into your microservice:
</p>
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/microservice/resources/ConfigResource.html" title="class in org.apache.juneau.microservice.resources"><code>ConfigResource</code></a>
- View and modify the external INI config file.
<li class='jc'><a href="org/apache/juneau/microservice/resources/DirectoryResource.html" title="class in org.apache.juneau.microservice.resources"><code>DirectoryResource</code></a>
- View and modify file system directories.
<li class='jc'><a href="org/apache/juneau/microservice/resources/SampleRootResource.html" title="class in org.apache.juneau.microservice.resources"><code>SampleRootResource</code></a>
- A sample root resource class to get started from.
<li class='jc'><a href="org/apache/juneau/microservice/resources/ShutdownResource.html" title="class in org.apache.juneau.microservice.resources"><code>ShutdownResource</code></a>
- Shutdown and/or restart the JVM.
</ul>
</div>
</div><!-- END: 15.4 - juneau-microservice-jetty.jmj.PredefinedResourceClasses -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-jetty.jmj.Config' id='juneau-microservice-jetty.jmj.Config'>15.5 - Config</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 15.5 - juneau-microservice-jetty.jmj.Config -->
<div class='topic'>
<p>
In <a class='doclink' href='#juneau-microservice-core.jmc.Config'>Overview &gt; juneau-microservice-core &gt; Config</a>, we described how to associate a configuration file with your
microservice.
In this section we describe how that configuration can be used to customize the behavior or your REST resource
classes.
</p>
<p>
The most common usage for the configuration file is to reference values using the <a href="org/apache/juneau/config/vars/ConfigVar.html" title="class in org.apache.juneau.config.vars"><code>$C</code></a> variable in annotations.
For example, the <code>org.apache.juneau.rest.config.BasicRestConfig</code> interface that defines the annotations that control the look-and-feel of
classes that extend from <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a> use several <c>$C</c> variables to externalize values:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
...
<jc>// These are static files that are served up by the servlet under the specified sub-paths.
// For example, "/servletPath/htdocs/javadoc.css" resolves to the file "[servlet-package]/htdocs/javadoc.css"
// By default, we define static files through the external configuration file.</jc>
staticFiles=<js>"$C{REST/staticFiles}"</js>
)
<jc>// HTML-page specific settings</jc>
<ja>@HtmlDocConfig</ja>(
<jc>// Default page header contents.</jc>
header={
<js>"&lt;h1&gt;$RS{title}&lt;/h1&gt;"</js>, <jc>// Use @Rest(title)</jc>
<js>"&lt;h2&gt;$RS{operationSummary,description}&lt;/h2&gt;"</js>, <jc>// Use either @RestOp(summary) or @Rest(description)</jc>
<js>"$C{REST/header}"</js> <jc>// Extra header HTML defined in external config file.</jc>
},
<jc>// Default stylesheet to use for the page.
// Can be overridden from external config file.
// Default is DevOps look-and-feel (aka Depression look-and-feel).</jc>
stylesheet=<js>"$C{REST/theme,servlet:/htdocs/themes/devops.css}"</js>,
<jc>// Default contents to add to the &lt;head&gt; section of the HTML page.
// Use it to add a favicon link to the page.</jc>
head={
<js>"&lt;link rel='icon' href='$U{$C{REST/favicon}}'/&gt;"</js>
},
<jc>// No default page footer contents.
// Can be overridden from external config file.</jc>
footer=<js>"$C{REST/footer}"</js>,
...
)
<jk>public interface</jk> BasicRestConfig {}
</p>
<p>
These values in turn are pulled from the external configuration file shown below.
Note that the configuration file can also contain <c>$C</c> variables.
</p>
<p class='bini'>
<cc>#=======================================================================================================================
# REST settings
#=======================================================================================================================</cc>
<cs>[REST]</cs>
<cc># Mappings to folders containing static files.</cc>
<cc># Can be in the working directory or in the classpath.</cc>
<ck>staticFiles</ck> = <cv>htdocs:files/htdocs</cv>
<cc># Stylesheet to use for HTML views.</cc>
<ck>theme</ck> = <cv>servlet:/htdocs/themes/devops.css</cv>
<ck>headerIcon</ck> = <cv>servlet:/htdocs/images/juneau.png</cv>
<ck>headerLink</ck> = <cv>http://juneau.apache.org</cv>
<ck>footerIcon</ck> = <cv>servlet:/htdocs/images/asf.png</cv>
<ck>footerLink</ck> = <cv>http://www.apache.org</cv>
<ck>favicon</ck> = <cv>$C{REST/headerIcon}</cv>
<ck>header</ck> =
<cv>&lt;a href='$U{$C{REST/headerLink}}'&gt;</cv>
<cv>&lt;img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/&gt;</cv>
<cv>&lt;/a&gt;</cv>
<ck>footer</ck> =
<cv>&lt;a href='$U{$C{REST/footerLink}}'&gt;</cv>
<cv>&lt;img src='$U{$C{REST/footerIcon}}' style='float:right;padding-right:20px;height:32px'/&gt;</cv>
<cv>&lt;/a&gt;</cv>
</p>
<p>
Configuration files can also be accessed programmatically.
There are 3 primary ways of getting access to the config file:
</p>
<ul class='javatree'>
<li class='jm'><a href="org/apache/juneau/microservice/Microservice.html#getConfig--"><code>Microservice.getConfig()</code></a>
<p>Any <a class='doclink' href='#juneau-rest-server.jrs.SvlVariables'>initialization-time variables</a> can be used.</p>
</li>
<li class='jm'><a href="org/apache/juneau/rest/RestContext.html#getConfig--"><code>RestContext.getConfig()</code></a>
<p>Any <a class='doclink' href='#juneau-rest-server.jrs.SvlVariables'>initialization-time variables</a> can be used.</p>
<h5 class='figure'>Example usage:</h5>
<p class='bini'>
<cc>#----------------------------------</cc>
<cc># Configuration for MyHelloResource </cc>
<cc>#----------------------------------</cc>
<cs>[MyHelloResource]</cs>
<ck>greeting</ck> = <cv>Hello world!</cv>
</p>
<p class='bjava'>
<cc>#---------------------------------</cc>
<cc># Contents of MyHelloResource.java </cc>
<cc>#---------------------------------</cc>
<ja>@Rest</ja>(...)
<jk>public class</jk> MyHelloResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<jk>private</jk> String <jf>greeting</jf>;
<jc>// Or access config file in servlet init method.</jc>
<ja>@Override</ja> <jc>/* Servlet */</jc>
<jk>public void</jk> init() {
Config <jv>config</jv> = getContext().getConfig();
<jk>this</jk>.<jf>greeting</jf> = <jv>config</jv>.getString(<js>"MyHelloResource/greeting"</js>);
}
}
</p>
<p>
Additional user-defined variables at the servlet level can be defined by adding a
<a href="org/apache/juneau/rest/annotation/HookEvent.html#INIT"><code>HookEvent.INIT</code></a> hook method
and using the <dc>)</dc> method.
</p>
</li>
<li class='jm'>
<a href="org/apache/juneau/rest/RestRequest.html#getConfig--"><code>RestRequest.getConfig()</code></a>
- An instance method to access it from inside a REST method.
<p>Any <a class='doclink' href='#juneau-rest-server.jrs.SvlVariables'>initialization-time or request-time variables</a> can be used.</p>
<h5 class='figure'>Example usage:</h5>
<p class='bini'>
<cc>#----------------------------------</cc>
<cc># Configuration for MyHelloResource</cc>
<cc>#----------------------------------</cc>
<cs>[MyHelloResource]</cs>
<ck>greeting</ck> = <cv>Hello $RP{person}!</cv> <cc>// $RP is RequestPathVar</cc>
<ck>localizedGreeting</ck> = <cv>$L{HelloMessage,$RP{person}}</cv> <cc>// $L is LocalizationVar with args</cc>
</p>
<p class='bjava'>
<cc>#---------------------------------</cc>
<cc># Contents of MyHelloResource.java </cc>
<cc>#---------------------------------</cc>
<ja>@Rest</ja>(
path=<js>"/hello"</js>,
messages=<js>"nls/Messages"</js>,
...
)
<jk>public class</jk> MyHelloResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
<jd>/** Standard hello message. */</jd>
<ja>@RestGet</ja>(<js>"/{person}"</js>)
<jk>public</jk> String sayHello(RestRequest <jv>req</jv>) {
<jk>return</jk> <jv>req</jv>.getConfig().getString(<js>"MyHelloResource/greeting"</js>);
}
<jd>/** Hello message in users language. */</jd>
<ja>@RestGet</ja>(<js>"/localized/{person}"</js>)
<jk>public</jk> String sayLocalizedHello(RestRequest <jv>req</jv>) {
<jk>return</jk> <jv>req</jv>.getConfig().getString(<js>"MyHelloResource/localizedGreeting"</js>);
}
}
</p>
<p class='bini'>
<cc>#---------------------------------------</cc>
<cc># Contents of nls/Messages_en.properties </cc>
<cc>#---------------------------------------</cc>
<ck>MyHelloResource.HelloMessage</ck> = <cv>Hello {0}!</cv>
</p>
<p>
Additional user-defined variables can be defined at this level by overriding the
<dc>)</dc> method.
</p>
</li>
</ul>
<p>
That <l>sayLocalizedHello()</l> example might need some explanation since there's a lot going on there.
Here's what happens when an HTTP call is made to <l>GET /hello/localized/Bob</l>:
</p>
<ol class='spaced-list'>
<li>
The HTTP call matches the <l>/hello</l> path on the <l>MyHelloResource</l> class.
<li>
The HTTP call matches the <l>/localized/{person}</l> path on the <l>sayLocalizedHello()</l> method.
<li>
The request attribute <l>person</l> gets assigned the value <l>"Bob"</l>.
<li>
The call to <l>req.getConfig().getString("MyHelloResource/localizedGreeting")</l>
finds the value <l>"$L{HelloMessage,$RP{person}}"</l>.
<li>
The arguments in the <l>$L{}</l> variable get resolved, resulting in <l>"$L{HelloMessage,Bob}"</l>.
<li>
The <l>$L{}</l> variable gets resolved to the message <l>"Hello {0}!"</l> in the localized properties
file of the servlet based on the <l>Accept-Language</l> header on the request.
<li>
The arguments get replaced in the message resulting in <l>"Hello Bob!"</l>.
<li>
The resulting message <l>"Hello Bob!"</l> is returned as a POJO to be serialized to whatever content
type was specified on the <l>Accept</l> header on the request.
</ol>
<p>
This particular example is needlessly complex but it gives an idea of how variables can be used
recursively to produce sophisticated results
</p>
<ul class='seealso'>
<li class='link'><a class='doclink' href='#juneau-config'>Overview &gt; juneau-config</a>
</ul>
</div>
</div><!-- END: 15.5 - juneau-microservice-jetty.jmj.Config -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-jetty.jmj.JettyXml' id='juneau-microservice-jetty.jmj.JettyXml'>15.6 - Jetty.xml file</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 15.6 - juneau-microservice-jetty.jmj.JettyXml -->
<div class='topic'>
<p>
The Jetty microservice comes with a bare-bones <c>jetty.xml</c> file which can be modified to suite any needs.
</p>
<p>
The <c>jetty.xml</c> can be located in either the <js>"."</js> or <js>"files"</js> working directory or classpath.
It can also be specified in any of the following ways:
</p>
<ul class='spaced-list'>
<li>
Using the <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.Builder.html#jettyXml-java.lang.Object-boolean-"><code>JettyMicroservice.Builder.jettyXml(Object,boolean)</code></a> method to specify the location or contents
of the file.
<li>
Specifying the location using a <c>Jetty-Config</c> value in the <c>MANIFEST.MF</c> file.
<p class='bini'>
<mk>Jetty-Config:</mk> <mv>files/jetty.xml</mv>
</p>
<li>
Specifying the location using the <js>"Jetty/jettyXml"</js> configuration value.
<p class='bini'>
<cc>#=======================================================================================================================
# Jetty settings
#=======================================================================================================================</cc>
<cs>[Jetty]</cs>
<cc># Path of the jetty.xml file used to configure the Jetty server.</cc>
<ck>config</ck> = <cv>files/jetty.xml</cv>
</p>
</ul>
<p>
SVL variables in the <c>jetty.xml</c> file are automatically resolved by the microservice.
This allows you to reference values in your configuration file from the <c>jetty.xml</c> file.
</p>
<p>
The HTTP port used is controlled via the following:
</p>
<ul class='spaced-list'>
<li>
The <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.Builder.html#ports-int...-"><code>JettyMicroservice.Builder.ports(int...)</code></a> method.
<p class='bjava'>
JettyMicroservice
.<jsm>create</jsm>()
.args(<jv>args</jv>)
.servlets(RootResource.<jk>class</jk>)
.port(1000,2000,0,0,0) <jc>// Try port 1000, then 2000, then 3 random ports.</jc>
.build()
.start()
</p>
<li>
The <js>"Jetty/ports"</js> configuration property.
<p class='bini'>
<cc>#=======================================================================================================================
# Jetty settings
#=======================================================================================================================</cc>
<cs>[Jetty]</cs>
<cc># Port to use for the jetty server.
# You can specify multiple ports. The first available will be used. '0' indicates to try a random port.
<ck>port</ck> = <cv>1000,2000,0,0,0</cv>
</p>
</ul>
<p>
The first available port is then made available through the system property <js>"availablePort"</js> so that it
can be referenced in our <c>jetty.xml</c> file.
</p>
<p class='bxml'>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"connectors"</xs><xt>&gt;</xt>
<xt>&lt;Array</xt> <xa>type</xa>=<xs>"org.eclipse.jetty.server.Connector"</xs><xt>&gt;</xt>
<xt>&lt;Item&gt;</xt>
<xt>&lt;New</xt> <xa>class</xa>=<xs>"org.eclipse.jetty.server.ServerConnector"</xs><xt>&gt;</xt>
<xt>&lt;Arg&gt;</xt>
<xt>&lt;Ref</xt> <xa>refid</xa>=<xs>"ExampleServer"</xs> <xt>/&gt;</xt>
<xt>&lt;/Arg&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"port"</xs><xt>&gt;</xt>$S{availablePort,8080}<xt>&lt;/Set&gt;</xt>
<xt>&lt;/New&gt;</xt>
<xt>&lt;/Item&gt;</xt>
<xt>&lt;/Array&gt;</xt>
<xt>&lt;/Set&gt;</xt>
</p>
<p>
The <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.Builder.html#jettyServerFactory-org.apache.juneau.microservice.jetty.JettyServerFactory-"><code>JettyMicroservice.Builder.jettyServerFactory(JettyServerFactory)</code></a> method is also provided
to use your own customized Jetty server.
</p>
</div>
</div><!-- END: 15.6 - juneau-microservice-jetty.jmj.JettyXml -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-jetty.jmj.UiCustomization' id='juneau-microservice-jetty.jmj.UiCustomization'>15.7 - UI Customization</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 15.7 - juneau-microservice-jetty.jmj.UiCustomization -->
<div class='topic'>
<p>
The Microservice project contains a <c>files/htdocs</c> folder with predefined stylesheets and
images.
</p>
<img style='width:200px' src='doc-files/jmj.UiCustomization.1.png'>
<p>
These files can be used to tailor the look-and-feel of your microservice.
</p>
<p class='bcode'>
http://localhost:10000/helloWorld
</p>
<img class='bordered w800' src='doc-files/jrs.UiCustomization.1.png'>
<p>
The REST configuration section of your microservice configuration file can be used to tailor the header and footer on the pages:
</p>
<p class='bini'>
<cc>#=======================================================================================================================
# REST settings
#=======================================================================================================================</cc>
<cs>[REST]</cs>
<ck>staticFiles</ck> = <cv>htdocs:files/htdocs</cv>
<cc># Stylesheet to use for HTML views.</cc>
<ck>theme</ck> = <cv>servlet:/htdocs/themes/devops.css</cv>
<ck>headerIcon</ck> = <cv>servlet:/htdocs/images/juneau.png</cv>
<ck>headerLink</ck> = <cv>http://juneau.apache.org</cv>
<ck>footerIcon</ck> = <cv>servlet:/htdocs/images/asf.png</cv>
<ck>footerLink</ck> = <cv>http://www.apache.org</cv>
<ck>favicon</ck> = <cv>$C{REST/headerIcon}</cv>
<ck>header</ck> =
<cv>&lt;a href='$U{$C{REST/headerLink}}'&gt;</cv>
<cv>&lt;img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/&gt;</cv>
<cv>&lt;/a&gt;</cv>
<ck>footer</ck> =
<cv>&lt;a href='$U{$C{REST/footerLink}}'&gt;</cv>
<cv>&lt;img src='$U{$C{REST/footerIcon}}' style='float:right;padding-right:20px;height:32px'/&gt;</cv>
<cv>&lt;/a&gt;</cv>
</p>
<p>
The <code>org.apache.juneau.rest.config.BasicRestConfig</code> interface (which defines the default settings for <a href="org/apache/juneau/rest/servlet/BasicRestServlet.html" title="class in org.apache.juneau.rest.servlet"><code>BasicRestServlet</code></a>
pulls in this information using <a href="org/apache/juneau/config/vars/ConfigVar.html" title="class in org.apache.juneau.config.vars"><code>$C</code></a> and <a href="org/apache/juneau/rest/vars/UrlVar.html" title="class in org.apache.juneau.rest.vars"><code>$U</code></a> variables:
</p>
<p class='bjava'>
<ja>@Rest</ja>(
...
<jc>// Optional external configuration file.</jc>
config=<js>"$S{juneau.configFile}"</js>,
<jc>// These are static files that are served up by the servlet under the specified sub-paths.
// For example, "/servletPath/htdocs/javadoc.css" resolves to the file "[servlet-package]/htdocs/javadoc.css"
// By default, we define static files through the external configuration file.</jc>
staticFiles=<js>"$C{REST/staticFiles}"</js>
)
<jc>// HTML-page specific settings</jc>
<ja>@HtmlDocConfig</ja>(
<jc>// Default page header contents.</jc>
header={
<js>"&lt;h1&gt;$RS{title}&lt;/h1&gt;"</js>, <jc>// Use @Rest(title)</jc>
<js>"&lt;h2&gt;$RS{operationSummary,description}&lt;/h2&gt;"</js>, <jc>// Use either @RestOp(summary) or @Rest(description)</jc>
<js>"$C{REST/header}"</js> <jc>// Extra header HTML defined in external config file.</jc>
},
<jc>// Default stylesheet to use for the page.
// Can be overridden from external config file.
// Default is DevOps look-and-feel (aka Depression look-and-feel).</jc>
stylesheet=<js>"$C{REST/theme,servlet:/htdocs/themes/devops.css}"</js>,
<jc>// Default contents to add to the &lt;head&gt; section of the HTML page.
// Use it to add a favicon link to the page.</jc>
head={
<js>"&lt;link rel='icon' href='$U{$C{REST/favicon}}'/&gt;"</js>
},
<jc>// No default page footer contents.
// Can be overridden from external config file.</jc>
footer=<js>"$C{REST/footer}"</js>
)
<jk>public interface</jk> BasicRestConfig {}
</p>
<p>
Note that the <c>files/htdocs</c> directory is mapped to <js>"servlet:/htdocs"</js> using the <c>staticFiles</c>
setting. This allows those files to be served up through the servlet through the URL <js>"/[servlet-path]/htdocs"</js>
</p>
<p>
The theme files are externally accessible and can be modified to produce any look-and-feel you desire.
The microservice still works without the files directory. An embedded <c>devops.css</c> is included in the jar as a default spreadsheet.
</p>
<p>
If you're testing out changes in the theme stylesheets, you may want to set the following system property that prevents caching of those files so
that you don't need to restart the microservice each time a change is made:
</p>
<p class='bini'>
<cc>#=======================================================================================================================
# System properties
#-----------------------------------------------------------------------------------------------------------------------
# These are arbitrary system properties that are set during startup.
#=======================================================================================================================</cc>
<cs>[SystemProperties]</cs>
<cc># Disable classpath resource caching.
# Useful if you're attached using a debugger and you're modifying classpath resources while running.</cc>
<ck>RestContext.disableClasspathResourceCaching.b</ck> = <cv>true</cv>
</p>
</div>
</div><!-- END: 15.7 - juneau-microservice-jetty.jmj.UiCustomization -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-microservice-jetty.jmj.Extending' id='juneau-microservice-jetty.jmj.Extending'>15.8 - Extending JettyMicroservice</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 15.8 - juneau-microservice-jetty.jmj.Extending -->
<div class='topic'>
<p>
This example shows how the <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html" title="class in org.apache.juneau.microservice.jetty"><code>JettyMicroservice</code></a> class
can be extended to implement lifecycle listener methods or override existing methods.
We'll create a new class <l>com.foo.MyJettyMicroservice</l>.
</p>
<p class='bjava'>
<jd>/**
* Sample subclass of a JettyMicroservice that provides customized behavior.
*/</jd>
<jk>public class</jk> MyJettyMicroservice <jk>extends</jk> JettyMicroservice {
<jk>public static void</jk> main(String[] <jv>args</jv>) <jk>throws</jk> Exception {
JettyMicroservice.Builder builder = JettyMicroservice.<jsm>create</jsm>();
<jk>new</jk> MyJettyMicroservice(builder).start().join();
}
<jk>public</jk> MyJettyMicroservice(JettyMicroservice.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
<jk>super</jk>(<jv>builder</jv>);
}
<jc>// Customized code here.</jc>
</p>
<p>
Optionally, you can extend the <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.Builder.html" title="class in org.apache.juneau.microservice.jetty"><code>JettyMicroservice.Builder</code></a> class as well:
</p>
<p class='bjava'>
<jk>public class</jk> MyJettyMicroservice.Builder <jk>extends</jk> JettyMicroservice.Builder {
<jk>int</jk> <jf>extraField</jf>;
<jd>/**
* Constructor (required).
*/</jd>
<jk>protected</jk> MyJettyMicroservice.Builder() {}
<jd>/**
* Copy constructor (required).
*
* <ja>@param</ja> copyFrom The builder to copy settings from.
*/</jd>
<jk>protected</jk> MyJettyMicroservice.Builder(MyJettyMicroservice.Builder <jv>copyFrom</jv>) {
<jk>super</jk>(<jv>copyFrom</jv>);
}
<jc>// Additional setters</jc>
<jk>public</jk> MyJettyMicroservice.Builder extraField(<jk>int</jk> <jv>extraField</jv>) {
<jk>this</jk>.<jf>extraField</jf> = <jv>extraField</jv>;
<jk>return this</jk>;
}
<jc>// Overridden methods</jc>
<ja>@Override</ja> <jc>/* JettyMicroservice.Builder */</jc>
<jk>public</jk> MyJettyMicroservice.Builder copy() {
<jk>return new</jk> MyJettyMicroservice.Builder(<jk>this</jk>);
}
<ja>@Override</ja> <jc>/* JettyMicroservice.Builder */</jc>
<jk>public</jk> MyJettyMicroservice.Builder ports(<jk>int</jk>...<jv>ports</jv>) {
<jk>super</jk>.ports(<jv>ports</jv>);
<jk>return this</jk>;
}
<ja>@Override</ja> <jc>/* JettyMicroservice.Builder */</jc>
<jk>public</jk> MyJettyMicroservice.Builder servlet(Class&lt;? <jk>extends</jk> RestServlet&gt; <jv>cls</jv>) <jk>throws</jk> InstantiationException, IllegalAccessException {
<jk>super</jk>.servlet(<jv>cls</jv>);
<jk>return this</jk>;
}
...
}
</p>
</div>
</div><!-- END: 15.8 - juneau-microservice-jetty.jmj.Extending -->
</div><!-- END: 15 - juneau-microservice-jetty -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#my-jetty-microservice' id='my-jetty-microservice'>16 - my-jetty-microservice</a><span class='update'>created: 8.1.0</span></h2>
<div class='topic'><!-- START: 16 - my-jetty-microservice -->
<div class='topic'>
<h5 class='figure'>Starter Project Zip</h5>
<p class='bcode w500'>
my-jetty-microservice-9.0.0.zip
</p>
<p>
The <l>my-jetty-microservice.zip</l> file is a predefined starter Eclipse project for developing
REST microservices using the <a class='doclink' href='#juneau-microservice-jetty'>juneau-microservice-jetty</a> package.
</p>
<p>
It includes a combination of the Juneau Core, Server, and Client APIs and all libraries needed to execute in a Java 1.8+ environment.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#my-jetty-microservice.mjm.Installing' id='my-jetty-microservice.mjm.Installing'>16.1 - Installing in Eclipse</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 16.1 - my-jetty-microservice.mjm.Installing -->
<div class='topic'>
<p>
Follow these instructions to create a new template project in Eclipse.
</p>
<ol class='spaced-list'>
<li>
Download the <c>my-jetty-microservice-9.0.0.zip</c> file from the downloads page
(located in the binaries) and import it into your workspace as an existing project:
<br><br>
<img class='bordered' src='doc-files/mjm.Installing.1.png' style='width:524px'>
<li>
Select the archive file and import the project:
<br><br>
<img class='bordered' src='doc-files/mjm.Installing.2.png' style='width:549px'>
<li>
In your workspace, you should now see the following project:
<br><br>
<img class='bordered' src='doc-files/mjm.Installing.3.png' style='width:400px'>
</ol>
<p>
The important elements in this project are:
</p>
<ul class='spaced-list'>
<li>
<l>App.java</l> - The entry point.
<br>This class creates and starts our microservice:
<br><br>
<p class='bjava'>
<jk>public class</jk> App {
<jk>public static void</jk> main(String[] <jv>args</jv>) <jk>throws</jk> Exception {
JettyMicroservice
.<jsm>create</jsm>()
.args(<jv>args</jv>)
.servlet(RootResources.<jk>class</jk>)
.build()
.start()
.startConsole()
.join();
}
}
</p>
<li>
<l>RootResources.java</l> - The top-level REST resource.
<br>This class routes HTTP requests to child resources:
<br><br>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/"</js>,
title=<js>"My Microservice"</js>,
description=<js>"Top-level resources page"</js>,
children={
HelloWorldResource.<jk>class</jk>,
ConfigResource.<jk>class</jk>,
LogsResource.<jk>class</jk>
}
)
<ja>@HtmlDocConfig</ja>(
widgets={
ContentTypeMenuItem.<jk>class</jk>,
StyleMenuItem.<jk>class</jk>
},
navlinks={
<js>"options: servlet:/?method=OPTIONS"</js>
}
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicRestServletGroup <jk>implements</jk> BasicUniversalConfig {
<jc>// No code</jc>
}
</p>
<li>
<l>mjm.cfg</l> - The external configuration file.
<br>Contains various useful settings.
<br>Can be used for your own resource configurations.
<br><br>
<p class='bini'>
<cc>#=======================================================================================================================
# Basic configuration file for REST microservices
# Subprojects can use this as a starting point.
#=======================================================================================================================</cc>
<cc>#=======================================================================================================================
# Jetty settings
#=======================================================================================================================</cc>
<cs>[Jetty]</cs>
<cc># Path of the jetty.xml file used to configure the Jetty server.</cc>
<ck>config</ck> = <cv>jetty.xml</cv>
<cc># Resolve Juneau variables in the jetty.xml file.</cc>
<ck>resolveVars</ck> = <cv>true</cv>
<cc># Port to use for the jetty server.
# You can specify multiple ports. The first available will be used. '0' indicates to try a random port.
# The resulting available port gets set as the system property "availablePort" which can be referenced in the
# jetty.xml file as "$S{availablePort}" (assuming resolveVars is enabled).</cc>
<ck>port</ck> = <cv>10000,0,0,0</cv>
<cc># Optionally specify your servlets here:
#servlets = org.apache.juneau.microservice.sample.RootResources</cc>
<cc>#=======================================================================================================================
# REST settings
#=======================================================================================================================</cc>
<cs>[REST]</cs>
<cc># Comma-delimited list of key-value pairs that represent locations of static files that can be served up by your @Rest-annotated
# classes. These are static files that are served up by the servlet under the specified sub-paths.
# For example, given the following setting...
# staticFiles = htdocs:my-docs,styles/my-styles
# ...the URI "/servletPath/htdocs/javadoc.css" resolves to the path "/my-docs/javadoc.css".
# This path can be relative to the working directory, classpath root, or package of your resource class.
# Used by the BasicRestConfig interface that defines the following value:
# staticFiles="$C{REST/staticFiles}"</cc>
<ck>staticFiles</ck> = htdocs:htdocs
<cc># Stylesheet to use for HTML views.
# Used by the BasicRestConfig interface that defines the following value:
# stylesheet="$C{REST/theme,servlet:/htdocs/themes/devops.css}"</cc>
<ck>theme</ck> = <cv>servlet:/htdocs/themes/devops.css</cv>
<cc># Various look-and-feel settings used in the BasicRestConfig interface.</cc>
<ck>headerIcon</ck> = <cv>servlet:/htdocs/images/juneau.png</cv>
<ck>headerLink</ck> = <cv>http://juneau.apache.org</cv>
<ck>footerIcon</ck> = <cv>servlet:/htdocs/images/asf.png</cv>
<ck>footerLink</ck> = <cv>http://www.apache.org</cv>
<ck>favicon</ck> = <cv>$C{REST/headerIcon}</cv>
<ck>header</ck> =
<cv>&lt;a href='$U{$C{REST/headerLink}}'&gt;
&lt;img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/&gt;
&lt;/a&gt;</cv>
<ck>footer</ck> =
<cv>&lt;a href='$U{$C{REST/footerLink}}'&gt;
&lt;img src='$U{$C{REST/footerIcon}}' style='float:right;padding-right:20px;height:32px'/&gt;
&lt;/a&gt;</cv>
<cc>#=======================================================================================================================
# Console settings
#=======================================================================================================================</cc>
<cs>[Console]</cs>
<ck>enabled</ck> = <cv>true</cv>
<cc># List of available console commands.
# These are classes that implements ConsoleCommand that allow you to submit commands to the microservice via
# the console.
# When listed here, the implementations must provide a no-arg constructor.
# They can also be provided dynamically by overriding the Microservice.createConsoleCommands() method.</cc>
<ck>commands</ck> =
<cv>org.apache.juneau.microservice.console.ExitCommand,
org.apache.juneau.microservice.console.RestartCommand,
org.apache.juneau.microservice.console.HelpCommand,
org.apache.juneau.microservice.console.ConfigCommand</cv>
<cc>#=======================================================================================================================
# Logger settings
#-----------------------------------------------------------------------------------------------------------------------
# See FileHandler Java class for details.
#=======================================================================================================================</cc>
<cs>[Logging]</cs>
...
<cc>#=======================================================================================================================
# System properties
#-----------------------------------------------------------------------------------------------------------------------
# These are arbitrary system properties that are set during startup.
#=======================================================================================================================</cc>
<cs>[SystemProperties]</cs>
<cc># Configure Jetty for StdErrLog Logging
# org.eclipse.jetty.util.log.class = org.eclipse.jetty.util.log.StrErrLog</cc>
<cc># Configure Jetty to log using java-util logging</cc>
<ck>org.eclipse.jetty.util.log.class</ck> = <cv>org.apache.juneau.microservice.jetty.JettyLogger</cv>
<cc># Jetty logging level
# Possible values: ALL, DEBUG, INFO, WARN, OFF</cc>
<ck>org.eclipse.jetty.LEVEL</ck> = <cv>WARN
<ck>derby.stream.error.file</ck> = <cv>$C{Logging/logDir}/derby-errors.log</cv>
</p>
<li>
<l>jetty.xml</l> - The Jetty configuration file.
<br>A bare-bones config file that can be extended to use any Jetty features.
<br><br>
<p class='bxml'>
<xt>&lt;Configure</xt> <xa>id</xa>=<xs>"ExampleServer"</xs> <xa>class</xa>=<xs>"org.eclipse.jetty.server.Server"</xs>&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"connectors"</xs><xt>&gt;</xt>
<xt>&lt;Array</xt> <xa>type</xa>=<xs>"org.eclipse.jetty.server.Connector"</xs><xt>&gt;</xt>
<xt>&lt;Item&gt;</xt>
<xt>&lt;New</xt> <xa>class</xa>=<xs>"org.eclipse.jetty.server.ServerConnector"</xs><xt>&gt;</xt>
<xt>&lt;Arg&gt;</xt>
<xt>&lt;Ref</xt> <xa>refid</xa>=<xs>"ExampleServer"</xs><xt>/&gt;</xt>
<xt>&lt;/Arg&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"port"</xs><xt>&gt;</xt>$S{availablePort,8080}<xt>&lt;/Set&gt;</xt>
<xt>&lt;/New&gt;</xt>
<xt>&lt;/Item&gt;</xt>
<xt>&lt;/Array&gt;</xt>
<xt>&lt;/Set&gt;</xt>
<xt>&lt;New</xt> <xa>id</xa>=<xs>"context"</xs> <xa>class</xa>=<xs>"org.eclipse.jetty.servlet.ServletContextHandler"</xs><xt>&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"contextPath"</xs><xt>&gt;/&lt;/Set&gt;</xt>
<xc>&lt;!-- Optionally specify your servlets here -->
&lt;!--Call name="addServlet"&gt;
&lt;Arg&gt;org.apache.juneau.microservice.sample.RootResources&lt;/Arg&gt;
&lt;Arg&gt;/*&lt;/Arg&gt;
&lt;/Call--></xc>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"sessionHandler"</xs><xt>&gt;</xt>
<xt>&lt;New</xt> <xa>class</xa>=<xs>"org.eclipse.jetty.server.session.SessionHandler"</xs><xt>/&gt;</xt>
<xt>&lt;/Set&gt;</xt>
<xt>&lt;/New&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"handler"</xs><xt>&gt;</xt>
<xt>&lt;New</xt> <xa>class</xa>=<xs>"org.eclipse.jetty.server.handler.HandlerCollection"</xs><xt>&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"handlers"</xs><xt>&gt;</xt>
<xt>&lt;Array</xt> <xa>type</xa>=<xs>"org.eclipse.jetty.server.Handler"</xs><xt>&gt;</xt>
<xt>&lt;Item&gt;</xt>
<xt>&lt;Ref</xt> <xa>refid</xa>=<xs>"context"</xs><xt>/&gt;</xt>
<xt>&lt;/Item&gt;</xt>
<xt>&lt;Item&gt;</xt>
<xt>&lt;New</xt> <xa>class</xa>=<xs>"org.eclipse.jetty.server.handler.DefaultHandler"</xs><xt>/&gt;</xt>
<xt>&lt;/Item&gt;</xt>
<xt>&lt;/Array&gt;</xt>
<xt>&lt;/Set&gt;</xt>
<xt>&lt;/New&gt;</xt>
<xt>&lt;/Set&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"requestLog"</xs><xt>&gt;</xt>
<xt>&lt;New</xt> <xa>id</xa>=<xs>"RequestLogImpl"</xs> <xa>class</xa>=<xs>"org.eclipse.jetty.server.NCSARequestLog"</xs><xt>&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"filename"</xs><xt>&gt;&lt;Property</xt> <xa>name</xa>=<xs>"jetty.logs"</xs> <xa>default</xa>=<xs>"$C{Logging/logDir,logs}"</xs><xt>/&gt;</xt>/jetty-requests.log<xt>&lt;/Set&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"filenameDateFormat</xs><xt>"&gt;</xt>yyyy_MM_dd<xt>&lt;/Set&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"LogTimeZone"</xs><xt>&gt;</xt>GMT<xt>&lt;/Set&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"retainDays"</xs><xt>&gt;</xt>90<xt>&lt;/Set&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"append"</xs><xt>&gt;</xt>false<xt>&lt;/Set&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"LogLatency"</xs><xt>&gt;</xt>true<xt>&lt;/Set&gt;</xt>
<xt>&lt;/New&gt;</xt>
<xt>&lt;/Set&gt;</xt>
<xt>&lt;Get</xt> <xa>name</xa>=<xs>"ThreadPool"</xs><xt>&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"minThreads"</xs> <xa>type</xa>=<xs>"int"</xs><xt>&gt;</xt>10<xt>&lt;/Set&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"maxThreads"</xs> <xa>type</xa>=<xs>"int"</xs><xt>&gt;</xt>100<xt>&lt;/Set&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"idleTimeout"</xs> <xa>type</xa>=<xs>"int"</xs><xt>&gt;</xt>60000<xt>&lt;/Set&gt;</xt>
<xt>&lt;Set</xt> <xa>name</xa>=<xs>"detailedDump"</xs><xt>&gt;</xt>true<xt>&lt;/Set&gt;</xt>
<xt>&lt;/Get&gt;</xt>
<xt>&lt;/Configure&gt;</xt>
</p>
</ul>
<p>
At this point, you're ready to start the microservice from your workspace.
</p>
</div>
</div><!-- END: 16.1 - my-jetty-microservice.mjm.Installing -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#my-jetty-microservice.mjm.Running' id='my-jetty-microservice.mjm.Running'>16.2 - Running in Eclipse</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 16.2 - my-jetty-microservice.mjm.Running -->
<div class='topic'>
<p>
The <l>mjm.launch</l> file is already provided to allow you to quickly start
your new microservice.
</p>
<p>
Go to <b>Run -> Run Configurations -> Java Application -> my-jetty-microservice</b> and click <b>Run</b>.
In your console view, you should see the following output:
</p>
<p class='bconsole'>
Running class 'JettyMicroservice' using config file 'mjm.cfg'.
Server started on port 10000
List of available commands:
exit -- Shut down service
restart -- Restarts service
help -- Commands help
>
</p>
<p>
Now open your browser and point to <l>http://localhost:10000</l>.
You should see the following:
</p>
<p class='bcode w400'>
http://localhost:10000
</p>
<img class='bordered w400' src='doc-files/mjm.Running.1.png'>
<p>
You can enter the command <c>exit</c> to shut it down.
</p>
</div>
</div><!-- END: 16.2 - my-jetty-microservice.mjm.Running -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#my-jetty-microservice.mjm.Building' id='my-jetty-microservice.mjm.Building'>16.3 - Building and Running from Command-Line</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 16.3 - my-jetty-microservice.mjm.Building -->
<div class='topic'>
<p>
The <l>pom.xml</l> file is a basic Maven build script for creating your microservice
as an executable uber-jar.
</p>
<p>
The easiest way to build your microservice is to run the following from the project root.
</p>
<p class='bconsole'>
mvn clean install
</p>
<p>
Your <c>target</c> directory should now contain the following files:
</p>
<ul>
<li><c>my-jetty-microservice-1.0.jar</c>
<li><c>mjm.cfg</c>
</ul>
<p>
To start from a command line, run the following command from inside your <c>target</c> directory:
</p>
<p class='bconsole'>
java -jar my-jetty-microservice-1.0.jar
</p>
<p>
You should see the following console output:
</p>
<p class='bconsole'>
Running class 'JettyMicroservice' using config file 'mjm.cfg'.
Server started on port 10000
List of available commands:
exit -- Shut down service
restart -- Restarts service
help -- Commands help
>
</p>
<p>
If you get this error message: <code class='snippet'>java.net.BindException: Address already in use</code>,
then this microservice is already running elsewhere and so it cannot bind to port 10000.
</p>
</div>
</div><!-- END: 16.3 - my-jetty-microservice.mjm.Building -->
</div><!-- END: 16 - my-jetty-microservice -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#my-springboot-microservice' id='my-springboot-microservice'>17 - my-springboot-microservice</a><span class='update'>created: 8.0.0</span></h2>
<div class='topic'><!-- START: 17 - my-springboot-microservice -->
<div class='topic'>
<h5 class='figure'>Starter Project Zip</h5>
<p class='bcode w500'>
my-springboot-microservice-9.0.0.zip
</p>
<p>
The <l>my-springboot-microservice.zip</l> file is a predefined starter Eclipse project for developing
REST microservices using the <a class='doclink' href='#juneau-rest-server-springboot'>juneau-rest-server-springboot</a> package with Spring Boot.
</p>
<p>
It includes a combination of the Juneau Core, Server, and Client APIs and all libraries needed to execute in a Java 1.8+ environment.
</p>
<p>
One significant difference is that we are not using the Juneau <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> API for our
application but instead using the existing Spring Boot API.
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#my-springboot-microservice.msm.Installing' id='my-springboot-microservice.msm.Installing'>17.1 - Installing in Eclipse</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 17.1 - my-springboot-microservice.msm.Installing -->
<div class='topic'>
<p>
Follow these instructions to create a new template project in Eclipse.
</p>
<ol class='spaced-list'>
<li>
Download the <c>my-springboot-microservice-9.0.0.zip</c> file from the downloads page
(located in the binaries) and import it into your workspace as an existing project:
<br><br>
<img class='bordered' src='doc-files/msm.Installing.1.png' style='width:524px'>
<li>
Select the archive file and import the project:
<br><br>
<img class='bordered' src='doc-files/msm.Installing.2.png' style='width:549px'>
<li>
In your workspace, you should now see the following project:
<br><br>
<img class='bordered' src='doc-files/msm.Installing.3.png' style='width:400px'>
</ol>
<p>
The important elements in this project are:
</p>
<ul class='spaced-list'>
<li>
<l>App.java</l> - The entry point.
<br>This class creates and starts our microservice.
<br>Note that we're using the existing Spring Boot application logic for the microservice and we're retrieving
our root resource as a spring bean.
<br>Only the top-level resource needs to be annotated with <dc>@JuneauRestRoot</dc>
<br><br>
<p class='bjava'>
<ja>@SpringBootApplication</ja>
<ja>@Controller</ja>
<jk>public class</jk> App {
<jk>public static void</jk> main(String[] args) {
<jk>new</jk> SpringApplicationBuilder(App.<jk>class</jk>)
.initializers(<jk>new</jk> JuneauRestInitializer(App.<jk>class</jk>))
.run(args);
}
<ja>@Bean @JuneauRestRoot</ja>
<jk>public</jk> RootResources getRootResources() {
<jk>return new</jk> RootResources();
}
}
</p>
<li>
<l>RootResources.java</l> - The top-level REST resource.
<br>This class routes HTTP requests to child resources.
<br>This is identical to the Jetty example.
<br><br>
<p class='bjava'>
<ja>@Rest</ja>(
path=<js>"/"</js>,
title=<js>"My Microservice"</js>,
description=<js>"Top-level resources page"</js>,
htmldoc=<ja>@HtmlDoc</ja>(
widgets={
ContentTypeMenuItem.<jk>class</jk>,
StyleMenuItem.<jk>class</jk>
},
navlinks={
<js>"options: servlet:/?method=OPTIONS"</js>
}
),
children={
HelloWorldResource.<jk>class</jk>,
ConfigResource.<jk>class</jk>,
LogsResource.<jk>class</jk>
}
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicRestServletGroup <jk>implements</jk> BasicUniversalConfig {
<jc>// No code</jc>
}
</p>
<li>
<l>juneau.cfg</l> - The configuration file.
<br>Contains various useful settings.
<br>Can be used for your own resource configurations.
<br>Note that the Jetty configuration is not present.
<br>Also it's located in the classpath so that our microservice can be built as a single executable jar.
<br><br>
<p class='bini'>
<cc>#=======================================================================================================================
# Basic configuration file for REST microservices
# Subprojects can use this as a starting point.
#=======================================================================================================================</cc>
<cc>#=======================================================================================================================
# REST settings
#=======================================================================================================================</cc>
<cs>[REST]</cs>
<cc># Comma-delimited list of key-value pairs that represent locations of static files that can be served up by your @Rest-annotated
# classes. These are static files that are served up by the servlet under the specified sub-paths.
# For example, given the following setting...
# staticFiles = htdocs:my-docs,styles/my-styles
# ...the URI "/servletPath/htdocs/javadoc.css" resolves to the path "/my-docs/javadoc.css".
# This path can be relative to the working directory, classpath root, or package of your resource class.
# Used by the BasicRestConfig interface that defines the following value:
# staticFiles="$C{REST/staticFiles}"</cc>
<ck>staticFiles</ck> = htdocs:htdocs
<cc># Stylesheet to use for HTML views.
# Used by the BasicRestConfig interface that defines the following value:
# stylesheet="$C{REST/theme,servlet:/htdocs/themes/devops.css}"</cc>
<ck>theme</ck> = <cv>servlet:/htdocs/themes/devops.css</cv>
<cc># Various look-and-feel settings used in the BasicRestConfig interface.</cc>
<ck>headerIcon</ck> = <cv>servlet:/htdocs/images/juneau.png</cv>
<ck>headerLink</ck> = <cv>http://juneau.apache.org</cv>
<ck>footerIcon</ck> = <cv>servlet:/htdocs/images/asf.png</cv>
<ck>footerLink</ck> = <cv>http://www.apache.org</cv>
<ck>favicon</ck> = <cv>$C{REST/headerIcon}</cv>
<ck>header</ck> =
<cv>&lt;a href='$U{$C{REST/headerLink}}'&gt;
&lt;img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/&gt;
&lt;/a&gt;</cv>
<ck>footer</ck> =
<cv>&lt;a href='$U{$C{REST/footerLink}}'&gt;
&lt;img src='$U{$C{REST/footerIcon}}' style='float:right;padding-right:20px;height:32px'/&gt;
&lt;/a&gt;</cv>
</p>
</ul>
<p>
At this point, you're ready to start the microservice from your workspace.
</p>
</div>
</div><!-- END: 17.1 - my-springboot-microservice.msm.Installing -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#my-springboot-microservice.msm.Running' id='my-springboot-microservice.msm.Running'>17.2 - Running in Eclipse</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 17.2 - my-springboot-microservice.msm.Running -->
<div class='topic'>
<p>
The <l>msm.launch</l> file is already provided to allow you to quickly start
your new microservice.
</p>
<p>
Go to <b>Run -> Run Configurations -> Java Application -> my-springboot-microservice</b> and click <b>Run</b>.
In your console view, you should see the following output:
</p>
<p class='bconsole'>
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.1.RELEASE)
...
INFO: Tomcat started on port(s): 8080 (http) with context path ''
Dec 21, 2012 12:30:00 AM org.springframework.boot.StartupInfoLogger logStarted
INFO: Started App in 1.999 seconds (JVM running for 2.999)
</p>
<p>
Now open your browser and point to <l>http://localhost:5000</l>.
You should see the following:
</p>
<p class='bcode w400'>
http://localhost:5000
</p>
<img class='bordered w400' src='doc-files/msm.Running.1.png'>
</div>
</div><!-- END: 17.2 - my-springboot-microservice.msm.Running -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#my-springboot-microservice.msm.Building' id='my-springboot-microservice.msm.Building'>17.3 - Building and Running from Command-Line</a><span class='update'>created: 8.0.0</span></h3>
<div class='topic'><!-- START: 17.3 - my-springboot-microservice.msm.Building -->
<div class='topic'>
<p>
The <l>pom.xml</l> file is a basic Maven build script for creating your microservice
as an executable uber-jar.
</p>
<p>
The easiest way to build your microservice is to run the following from the project root.
</p>
<p class='bconsole'>
mvn clean install
</p>
<p>
Your <c>target</c> directory should now contain the following files:
</p>
<ul>
<li><c>my-springboot-microservice-1.0.jar</c>
</ul>
<p>
To start from a command line, run the following command from inside your <c>target</c> directory:
</p>
<p class='bconsole'>
java -jar my-springboot-microservice-1.0.jar
</p>
<p>
You should see the following console output:
</p>
<p class='bconsole'>
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.1.RELEASE)
...
INFO: Tomcat started on port(s): 8080 (http) with context path ''
Dec 21, 2012 12:30:00 AM org.springframework.boot.StartupInfoLogger logStarted
INFO: Started App in 1.999 seconds (JVM running for 2.999)
</p>
</div>
</div><!-- END: 17.3 - my-springboot-microservice.msm.Building -->
</div><!-- END: 17 - my-springboot-microservice -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#juneau-petstore' id='juneau-petstore'>18 - juneau-petstore</a><span class='update'>created: 8.2.0, updated: <b>9.0.0</b></span></h2>
<div class='topic'><!-- START: 18 - juneau-petstore -->
<div class='topic'>
<p>
The <c>PetStore</c> application is an functional application meant to demonstrate using Juneau with Spring Boot
to create an end-to-end client/server REST API.
</p>
<p>
What makes Juneau unique is the ability to create Java interfaces that behave just like RPC but using REST
as the underlying protocol. And the technology it not tied to any platform so it can be used in any environment
by simply pulling in Maven dependencies. The server-side need only provide the ability to host a servlet.
</p>
<p>
Visit the <a class='doclink' href='https://github.com/apache/juneau-petstore'>GitHub project</a> hosting the application.
</p>
<p>
The project is broken down into the following subprojects:
</p>
<ul class='spaced-list'>
<li><c>juneau-petstore-api</c> - Contains the Java interface and DTOs for the petstore application.
<li><c>juneau-petstore-server</c> - Contains the server-side Java implementation of the petstore Java interface as a REST resource.
<li><c>juneau-petstore-client</c> - Contains the client-side Java proxy of the petstore Java interface.
</ul>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-petstore.jp.RunningTheApp' id='juneau-petstore.jp.RunningTheApp'>18.1 - Running the Pet Store App</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 18.1 - juneau-petstore.jp.RunningTheApp -->
<div class='topic'>
<p>
The Pet Store app is a Spring Boot application that can be started up by running the <c>App</c> class.
This starts the application on port 5000. It can also be started in a docker container using the following
instructions:
</p>
<ul class='spaced-list'>
<li>
Install <a class='doclink' href='https://docs.docker.com/install/'>docker</a> on your machine.
</li>
<li>
<p>
Clone the Petstore project on your machine.
</p>
<p class='bcode w800'>
git clone https://github.com/apache/juneau-petstore.git
</p>
</li>
<li>
<p>
Open terminal inside the project directory and run the below command to start the app.
</p>
<p class='bcode w800'>
docker build . -t petstore &amp;&amp; docker run -p 5000:5000 petstore
</p>
</li>
</ul>
</div>
</div><!-- END: 18.1 - juneau-petstore.jp.RunningTheApp -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-petstore.jp.juneau-petstore-api' id='juneau-petstore.jp.juneau-petstore-api'>18.2 - juneau-petstore-api</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 18.2 - juneau-petstore.jp.juneau-petstore-api -->
<div class='topic'>
<p>
The <c>juneau-petstore-api</c> module contains the Java interface of our application and the DTOs that go along
with it. These classes are meant to be shared between the server and client side code.
</p>
<p>
The <c>PetStore</c> class is our primary class for defining our application. It's a standard Java interface with
annotations used to describe how the methods map to REST calls.
</p>
<h5 class='figure'>PetStore.java</h5>
<p class='bcode w800'>
<ja>@Remote</ja>(path=<js>"/petstore"</js>)
<jk>public interface</jk> PetStore {
<jc>//------------------------------------------------------------------------------------------------------------------
// Pets
//------------------------------------------------------------------------------------------------------------------</jc>
<jd>/**
* Returns all pets in the database.
*
* @return All pets in the database.
* @throws NotAcceptable Unsupported <c>Accept</c> header specified.
*/</jd>
<ja>@RemoteGet</ja>(<js>"/pet"</js>)
<jk>public</jk> Collection<Pet> getPets() <jk>throws</jk> NotAcceptable;
<jd>/**
* Returns a pet from the database.
*
* @param petId The ID of the pet to retrieve.
* @return The pet.
* @throws IdNotFound Pet was not found.
* @throws NotAcceptable Unsupported <c>Accept</c> header specified.
*/</jd>
<ja>@RemoteGet</ja>(<js>"/pet/{petId}"</js>)
<jk>public</jk> Pet getPet(
<ja>@Path</ja>(
name=<js>"petId"</js>,
schema=<ja>@Schema</ja>(description=<js>"ID of pet to return"</js>)
)
<jk>long</jk> <jv>petId</jv>
) <jk>throws</jk> IdNotFound, NotAcceptable;
<jd>/**
* Adds a pet to the database.
*
* @param pet The pet data to add to the database.
* @return <code>Ok</code> if successful.
* @throws IdConflict ID already in use.
* @throws NotAcceptable Unsupported <c>Accept</c> header specified.
* @throws UnsupportedMediaType Unsupported <c>Content-Type</c> header specified.
*/</jd>
<ja>@RemotePost</ja>(<js>"/pet"</js>)
<jk>public long</jk> createPet(
<ja>@Content</ja>(
schema=<ja>@Schema</ja>(description=<js>"Pet object to add to the store"</js>)
)
CreatePet <jv>pet</jv>
) <jk>throws</jk> IdConflict, NotAcceptable, UnsupportedMediaType;
<jd>/**
* Updates a pet in the database.
*
* @param pet The pet data to add to the database.
* @return <code>Ok</code> if successful.
* @throws IdNotFound ID not found.
* @throws NotAcceptable Unsupported <c>Accept</c> header specified.
* @throws UnsupportedMediaType Unsupported <c>Content-Type</c> header specified.
*/</jd>
<ja>@RemotePut</ja>(<js>"/pet/{petId}"</js>)
<jk>public</jk> Ok updatePet(
<ja>@Content</ja>(
schema=<ja>@Schema</ja>(description=<js>"Pet object that needs to be added to the store"</js>)
)
UpdatePet <jv>pet</jv>
) <jk>throws</jk> IdNotFound, NotAcceptable, UnsupportedMediaType;
<jd>/**
* Find all pets with the matching statuses.
*
* @param status The statuses to match against.
* @return The pets that match the specified statuses.
* @throws NotAcceptable Unsupported <c>Accept</c> header specified.
*/</jd>
<ja>@RemoteGet</ja>(<js>"/pet/findByStatus"</js>)
<jk>public</jk> Collection&lt;Pet&gt; findPetsByStatus(
<ja>@Query</ja>(
name=<js>"status"</js>,
schema=<ja>@Schema</ja>(
description=<js>"Status values that need to be considered for filter."</js>,
required=<jk>true</jk>,
type=<js>"array"</js>,
collectionFormat=<js>"csv"</js>,
items=<ja>@Items</ja>(
type=<js>"string"</js>,
_enum=<js>"AVAILABLE,PENDING,SOLD"</js>,
_default=<js>"AVAILABLE"</js>
)
)
)
PetStatus[] <jv>status</jv>
) <jk>throws</jk> NotAcceptable;
<jd>/**
* Deletes the specified pet.
*
* @param apiKey Security key.
* @param petId ID of pet to delete.
* @return <code>Ok</code> if successful.
* @throws IdNotFound Pet not found.
* @throws NotAcceptable Unsupported <c>Accept</c> header specified.
*/</jd>
<ja>@RemoteDelete</ja>(<js>"/pet/{petId}"</js>)
<jk>public</jk> Ok deletePet(
<ja>@Header</ja>(
name=<js>"api_key"</js>,
schema=<ja>@Schema</ja>(
description=<js>"Security API key"</js>,
required=<jk>true</jk>
)
)
String <jv>apiKey</jv>,
<ja>@Path</ja>(
name=<js>"petId"</js>,
schema=<ja>@Schema(description=<js>"Pet id to delete"</js>)
)
<jk>long</jk> <jv>petId</jv>
) <jk>throws</jk> IdNotFound, NotAcceptable;
<jd>/**
* Deletes all pets in the database.
*
* @return <code>Ok</code> if successful.
*/</jd>
<ja>@RemoteDelete</ja>(<js>"/pet"</js>)
<jk>public</jk> Ok deleteAllPets();
<jc>//------------------------------------------------------------------------------------------------------------------
// Orders
//------------------------------------------------------------------------------------------------------------------</jc>
...
}
</p>
<p>
<ja>@Remote</ja> and <ja>@RemoteX</ja> are client-side annotations used to map the method calls to REST
and will be describe in the client code section.
</p>
<p>
<ja>@Path</ja> and <ja>@Body</ja> are used by both the client and server side code to map to REST artifacts on both
sides.
</p>
<p>
Both sets of annotations are provided by pulling in the Juneau dependency below:
<h5 class='figure'>Maven Dependency</h5>
<p class='bcode w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-marshall<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>9.x.x<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<p>
The <c>Pet</c> class is a DTO that gets serialized over the REST connection. It is also annotated with JPA annotations
so that they can easily be stored in a JPA datastore on the server side.
</p>
<h5 class='figure'>Pet.java</h5>
<p class='bcode w800'>
<ja>@Bean</ja>(typeName=<js>"Pet"</js>, properties=<js>"id,species,name,tags,price,status"</js>)
<ja>@Entity</ja>(name=<js>"PetstorePet"</js>)
<jk>public class</jk> Pet {
<ja>@Column @Id @GeneratedValue</ja>
<ja>@Schema</ja>(description=<js>"Unique identifier for this pet."</js>)
<ja>@Html</ja>(link=<js>"servlet:/pet/{id}"</js>)
<jk>private long</jk> <jf>id</jf>;
<ja>@Column</ja>(length=50)
<ja>@Schema</ja>(description=<js>"Pet name."</js>, minLength=3, maxLength=50)
<jk>private</jk> String <jf>name</jf>;
<ja>@Column</ja>
<ja>@Schema</ja>(description=<js>"Price of pet."</js>, maximum=<js>"999.99"</js>)
<ja>@Html</ja>(render=PriceRender.<jk>class</jk>)
<jk>private float</jk> <jf>price</jf>;
...
}
</p>
<p>
The annotations here are a combination of Juneau annotations for controlling marshalling (<ja>@Bean</ja>, <ja>@Html</ja>)
and documentation/validation (<ja>@Schema</ja>), and JPA annoations for database persistence (<ja>@Entity</ja>, <ja>@Column</ja>).
</p>
<div class='info'>
Most applications may choose to have separate classes for DTOs and JPA beans since you typically are not going to want
to expose server-side details to client-side code. In these examples however they were combined into the same classes for brevity.
</div>
</div>
</div><!-- END: 18.2 - juneau-petstore.jp.juneau-petstore-api -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-petstore.jp.juneau-petstore-client' id='juneau-petstore.jp.juneau-petstore-client'>18.3 - juneau-petstore-client</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 18.3 - juneau-petstore.jp.juneau-petstore-client -->
<div class='topic'>
<p>
The <c>juneau-petstore-client</c> module contains a single <c>Main</c> class used to instantiate the proxy against
our remote REST interface using the Java interface described above.
</p>
<h5 class='figure'>Main.java</h5>
<p class='bcode w800'>
<jk>public class</jk> Main {
<jk>public static void</jk> main(String[] <jv>args</jv>) {
<jc>// Create a RestClient with JSON serialization support.</jc>
RestClient <jv>restClient</jv> = RestClient.<jsm>create</jsm>().simpleJson().build();
<jc>// Instantiate our proxy.</jc>
PetStore <jv>petStore</jv> = <jv>restClient</jv>.getRemote(PetStore.<jk>class</jk>, <js>"http://localhost:5000"</js>);
<jc>// Print out the pets in the store.</jc>
Collection&lt;Pet&gt; <jv>pets</jv> = <jv>petStore</jv>.getPets();
<jc>// Pretty-print them to STDOUT.</jc>
SimpleJson.<jsf>DEFAULT_READABLE</jsf>.println(<jv>pets</jv>);
}
}
</p>
<p>
Notice how little code is necessary to construct a remote proxy.
</p>
</div>
</div><!-- END: 18.3 - juneau-petstore.jp.juneau-petstore-client -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#juneau-petstore.jp.juneau-petstore-server' id='juneau-petstore.jp.juneau-petstore-server'>18.4 - juneau-petstore-server</a><span class='update'>created: <b>9.0.0</b></span></h3>
<div class='topic'><!-- START: 18.4 - juneau-petstore.jp.juneau-petstore-server -->
<div class='topic'>
<p>
The <c>juneau-petstore-server</c> module contains all of the guts of the application. It's a standard Spring Boot
application with Juneau integration support. For brevity, the app and configuration classes are combined into
the following:
</p>
<h5 class='figure'>App.java</h5>
<p class='bcode w800'>
<ja>@SpringBootApplication</ja>
<ja>@EnableJpaRepositories</ja>(basePackages=<js>"org.apache.juneau.petstore"</js>)
<ja>@EnableCaching</ja>
<ja>@Controller</ja>
<jk>public class</jk> App {
<jc>//-----------------------------------------------------------------------------------------------------------------
// App
//-----------------------------------------------------------------------------------------------------------------</jc>
<jk>public static void</jk> main(String[] <jv>args</jv>) {
<jk>try</jk> {
<jk>new</jk> SpringApplicationBuilder(App.<jk>class</jk>).run(<jv>args</jv>);
} <jk>catch</jk> (Exception <jv>e</jv>) {
<jv>e</jv>.printStackTrace();
}
}
<jc>//-----------------------------------------------------------------------------------------------------------------
// Beans
//-----------------------------------------------------------------------------------------------------------------</jc>
<ja>@Bean</ja>
<jk>public</jk> PetStoreService petStoreService() {
<jk>return new</jk> PetStoreService();
}
<ja>@Bean</ja>
<jk>public</jk> RootResources rootResources() {
<jk>return new</jk> RootResources();
}
<ja>@Bean</ja>
<jk>public</jk> PetStoreResource petStoreResource() {
<jk>return new</jk> PetStoreResource();
}
<ja>@Bean</ja>
<jk>public</jk> ServletRegistrationBean<Servlet> getRootServlet(RootResources <jv>rootResources</jv>) {
<jk>return new</jk> ServletRegistrationBean<>(<jv>rootResources</jv>, <js>"/*"</js>);
}
}
</p>
<p>
Notice how cleanly Juneau servlets fit into Spring Boot. No special initializers are required
to integrate Juneau with Spring Boot.
</p>
<p>
The <c>RootResources</c> class is the top-level entry point into the REST API. It allows us to group
child resources. In our case though we only have one child resource...<c>PetStoreResource</c>:
</p>
<h5 class='figure'>RootResources.java</h5>
<p class='bcode w800'>
<ja>@Rest</ja>(
path=<js>"/*"</js>,
title=<js>"Root resources"</js>,
description=<js>"Example of a router resource page."</js>,
children={
PetStoreResource.<jk>class</jk>
}
)
<ja>@HtmlDocConfig</ja>(
widgets={
ContentTypeMenuItem.<jk>class</jk>
},
navlinks={
<js>"options: ?method=OPTIONS"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"source: $C{Source/gitHub}/org/apache/juneau/petstore/rest/$R{servletClassSimple}.java"</js>
},
aside={
<js>"&lt;div style='max-width:400px' class='text'&gt;"</js>,
<js>" &lt;p&gt;This is an example of a 'router' page that serves as a jumping-off point to child resources.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Resources can be nested arbitrarily deep through router pages.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Note the &lt;span class='link'&gt;options&lt;/span&gt; link provided that lets you see the generated swagger doc for this page.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Also note the &lt;span class='link'&gt;sources&lt;/span&gt; link on these pages to view the source code for the page.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;All content on pages in the UI are serialized POJOs. In this case, it's a serialized array of beans with 2 properties, 'name' and 'description'.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;Other features (such as this aside) are added through annotations.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
}
)
<jk>public class</jk> RootResources <jk>extends</jk> BasicSpringRestServletGroup <jk>implements</jk> BasicUniversalConfig {
<jk>private static final long</jk> <jsf>serialVersionUID</jsf> = 1L;
}
</p>
<p>
By extending from <c>BasicSpringRestServletGroup</c>, the root servlet hooks into the injection framework of Spring
to resolve spring beans such as the child resource <c>PetStoreResource</c>.
</p>
<p>
This page renders as follows:
</p>
<p class='bcode w800'>
http://localhost:5000
</p>
<img class='bordered w800' src='doc-files/RootResources.png'>
<p>
The <c>PetStoreResource</c> class is the REST implementation of our <c>PetStore</c> interface.
</p>
<h5 class='figure'>PetStoreResource.java</h5>
<p class='bcode w800'>
<ja>@Rest</ja>(
path=<js>"/petstore"</js>,
title=<js>"Petstore application"</js>,
description={
<js>"This is a sample server Petstore server based on the Petstore sample at Swagger.io."</js>,
<js>"You can find out more about Swagger at http://swagger.io."</js>,
},
swagger=<ja>@Swagger</ja>(
version=<js>"1.0.0"</js>,
title=<js>"Swagger Petstore"</js>,
termsOfService=<js>"You are on your own."</js>,
contact=<ja>@Contact</ja>(
name=<js>"Juneau Development Team"</js>,
email=<js>"dev@juneau.apache.org"</js>,
url=<js>"http://juneau.apache.org"</js>
),
license=<ja>@License</ja>(
name=<js>"Apache 2.0"</js>,
url=<js>"http://www.apache.org/licenses/LICENSE-2.0.html"</js>
),
externalDocs=<ja>@ExternalDocs</ja>(
description=<js>"Find out more about Juneau"</js>,
url=<js>"http://juneau.apache.org"</js>
),
tags={
<ja>@Tag</ja>(
name=<js>"pet"</js>,
description=<js>"Everything about your Pets"</js>,
externalDocs=<ja>@ExternalDocs</ja>(
description=<js>"Find out more"</js>,
url=<js>"http://juneau.apache.org"</js>
)
),
<ja>@Tag</ja>(
name=<js>"store"</js>,
description=<js>"Access to Petstore orders"</js>
),
<ja>@Tag</ja>(
name=<js>"user"</js>,
description=<js>"Operations about user"</js>,
externalDocs=<ja>@ExternalDocs</ja>(
description=<js>"Find out more about our store"</js>,
url=<js>"http://juneau.apache.org"</js>
)
)
}
),
staticFiles={<js>"htdocs:/htdocs"</js>}
)
<ja>@HtmlDocConfig</ja>(
widgets={
ContentTypeMenuItem.<jk>class</jk>,
},
navlinks={
<js>"up: request:/.."</js>,
<js>"options: servlet:/?method=OPTIONS"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"source: $C{Source/gitHub}/org/apache/juneau/petstore/rest/$R{servletClassSimple}.java"</js>
},
head={
<js>"&lt;link rel='icon' href='$U{servlet:/htdocs/cat.png}'/&gt;"</js> <jc>// Add a cat icon to the page.</jc>
},
header={
<js>"&lt;h1&gt;$R{resourceTitle}&lt;/h1&gt;"</js>,
<js>"&lt;h2&gt;$R{methodSummary}&lt;/h2&gt;"</js>,
<js>"$C{PetStore/headerImage}"</js>
},
aside={
<js>"&lt;div style='max-width:400px' class='text'&gt;"</js>,
<js>" &lt;p&gt;This page shows a standard nested REST resource.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;It shows how different properties can be rendered on the same bean in different views.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;It also shows examples of HtmlRender classes and @BeanProperty(format) annotations.&lt;/p&gt;"</js>,
<js>" &lt;p&gt;It also shows how the Queryable converter and query widget can be used to create searchable interfaces.&lt;/p&gt;"</js>,
<js>"&lt;/div&gt;"</js>
},
stylesheet=<js>"servlet:/htdocs/themes/dark.css"</js> <jc>// Use dark theme by default.</jc>
)
<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig, PetStore {
<ja>@Inject</ja>
<jk>private</jk> PetStoreService <jf>store</jf>;
<jd>/**
* Navigation page
*
* @return Navigation page contents.
*/</jd>
<ja>@RestGet</ja>(
path=<js>"/"</js>,
summary=<js>"Navigation page"</js>
)
<ja>@HtmlDocConfig</ja>(
style={
<js>"INHERIT"</js>, <jc>// Flag for inheriting resource-level CSS.</jc>
<js>"body { "</js>,
<js>"background-image: url('petstore/htdocs/background.jpg'); "</js>,
<js>"background-color: black; "</js>,
<js>"background-size: cover; "</js>,
<js>"background-attachment: fixed; "</js>,
<js>"}"</js>
}
)
<jk>public</jk> ResourceDescriptions getTopPage() {
<jk>return new</jk> ResourceDescriptions()
.append(<js>"pet"</js>, <js>"All pets in the store"</js>)
.append(<js>"store"</js>, <js>"Orders and inventory"</js>)
.append(<js>"user"</js>, <js>"Petstore users"</js>)
;
}
...
</p>
<p>
Clicking the <c>petstore</c> link on the root page takes you to our PetStore resource:
</p>
<p class='bcode w800'>
http://localhost:5000/petstore
</p>
<img class='bordered w800' src='doc-files/PetStore.png'>
<p>
The methods defined in our <c>PetStore</c> interface are implemented like so:
</p>
<h5 class='figure'>PetStoreResource.java</h5>
<p class='bcode w800'>
<ja>@Override</ja> <jc>/* PetStore */</jc>
<ja>@RestGet</ja>(
path=<js>"/pet"</js>,
summary=<js>"All pets in the store"</js>,
swagger=<ja>@OpSwagger</ja>(
tags=<js>"pet"</js>,
parameters={
Queryable.<jsf>SWAGGER_PARAMS</jsf> <jc>// Documents searching.</jc>
}
),
converters={Queryable.<jk>class</jk>} <jc>// Searching support.</jc>
)
<ja>@Bean</ja>(on=<js>"Pet"</js>, excludeProperties=<js>"tags,photo"</js>) <jc>// In this view, don't serialize tags/photos properties.</jc>
<jk>public</jk> Collection&lt;Pet&gt; getPets() <jk>throws</jk> NotAcceptable {
<jk>return</jk> <jf>store</jf>.getPets();
}
<ja>@Override</ja> <jc>/* PetStore */</jc>
<ja>@RestGet</ja>(
path=<js>"/pet/{petId}"</js>,
summary=<js>"Find pet by ID"</js>,
description=<js>"Returns a single pet"</js>,
swagger=<ja>@OpSwagger</ja>(
tags=<js>"pet"</js>
)
)
<jk>public</jk> Pet getPet(<jk>long</jk> <jv>petId</jv>) <jk>throws</jk> IdNotFound, NotAcceptable {
<jk>return</jk> <jf>store</jf>.getPet(<jv>petId</jv>);
}
<ja>@Override</ja> <jc>/* PetStore */</jc>
<ja>@RestPost</ja>(
path=<js>"/pet"</js>,
summary=<js>"Add a new pet to the store"</js>,
swagger=<ja>@OpSwagger</ja>(
tags=<js>"pet"</js>
),
roleGuard=<js>"ROLE_ADMIN || (ROLE_USER &amp;&amp; ROLE_WRITABLE)"</js> <jc>// Restrict access to this method.</jc>
)
<jk>public long</jk> createPet(CreatePet <jv>pet</jv>) <jk>throws</jk> IdConflict, NotAcceptable, UnsupportedMediaType {
<jk>return</jk> <jf>store</jf>.create(<jv>pet</jv>).getId();
}
...
</p>
<p>
After running the <c>Main</c> method in the client code to populate the database, the page renders as follows:
</p>
<p class='bcode w800'>
http://localhost:5000/petstore/pet
</p>
<img class='bordered w800' src='doc-files/PetStore_pets.png'>
<p>
The <l>OPTIONS</l> menu items takes you to the auto-generated Swagger UI for the application:
</p>
<p class='bcode w900'>
http://localhost:10000/petstore/pet?method=OPTIONS
</p>
<img class='bordered w900' src='doc-files/9a.png'>
<p>
Since we've defined tags on our annotations, the pet-related operations are all grouped under the <l>pet</l> tag:
</p>
<img class='bordered w900' src='doc-files/9b.png'>
<p>
Information for all HTTP parts is automatically generated:
</p>
<img class='bordered w900' src='doc-files/9h.png'>
<p>
The schema models for POJO models is available in the <l>Responses</l> section of an operation:
</p>
<img class='bordered w900' src='doc-files/9c.png'>
<p>
Auto-generated examples are available for all supported languages:
</p>
<img class='bordered w900' src='doc-files/9d.png'>
<p>
For example, <l>application/json+simple</l>:
</p>
<img class='bordered w900' src='doc-files/9e.png'>
<p>
Examples can be derived in a number of ways. In our case, we've defined a static method on our <l>Pet</l>
class annotated with <ja>@Example</ja>:
</p>
<h5 class='figure'>Pet.java</h5>
<p class='bcode w800'>
<ja>@Example</ja>
<jk>public static</jk> Pet example() {
<jk>return new</jk> Pet()
.id(123)
.species(Species.<jsf>DOG</jsf>)
.name(<js>"Doggie"</js>)
.tags(<js>"friendly"</js>,<js>"smart"</js>)
.status(PetStatus.<jsf>AVAILABLE</jsf>);
}
</p>
<p>
Similar functionality exists for request bodies as well:
</p>
<img class='bordered w900' src='doc-files/9f.png'>
<p>
At the bottom of the page is a listing of the POJO models in the app:
</p>
<img class='bordered w900' src='doc-files/9g.png'>
</div>
</div><!-- END: 18.4 - juneau-petstore.jp.juneau-petstore-server -->
</div><!-- END: 18 - juneau-petstore -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#Glossaries' id='Glossaries'>19 - Glossaries</a><span class='update'>created: 8.1.3</span></h2>
<div class='topic'><!-- START: 19 - Glossaries -->
<div class='topic'>
<p>
</p>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Glossaries.g.LanguageSupport' id='Glossaries.g.LanguageSupport'>19.1 - Language Support</a><span class='update'>created: 8.1.3</span></h3>
<div class='topic'><!-- START: 19.1 - Glossaries.g.LanguageSupport -->
<div class='topic'>
<table class='styled w1000'>
<tr>
<th>Language</th><th>Serializers</th><th>Parsers</th><th>Marshalls</th><th>Documentation</th>
</tr>
<tr>
<td><c>text/csv</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/csv/CsvSerializer.html" title="class in org.apache.juneau.csv"><code>CsvSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/csv/CsvParser.html" title="class in org.apache.juneau.csv"><code>CsvParser</code></a></ul></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td><c>text/html</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a><li class='jc'><a href="org/apache/juneau/html/HtmlStrippedDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlStrippedDocSerializer</code></a><li class='jc'><a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/html/HtmlParser.html" title="class in org.apache.juneau.html"><code>HtmlParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/Html.html" title="class in org.apache.juneau.marshaller"><code>Html</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall.jm.HtmlDetails'>HTML Details</a></td>
</tr>
<tr>
<td><c>text/html+schema</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/html/HtmlSchemaSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSchemaSerializer</code></a><li class='jc'><a href="org/apache/juneau/html/HtmlSchemaDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSchemaDocSerializer</code></a></ul></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td><a class='doclink' href='#juneau-marshall.jm.HtmlDetails'>HTML Details</a></td>
</tr>
<tr>
<td><c>application/json</c><br><c>text/json</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a><li class='jc'><a href="org/apache/juneau/json/JsonSerializer.Readable.html" title="class in org.apache.juneau.json"><code>JsonSerializer.Readable</code></a><li class='jc'><a href="org/apache/juneau/json/JsonSerializer.ReadableSafe.html" title="class in org.apache.juneau.json"><code>JsonSerializer.ReadableSafe</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/Json.html" title="class in org.apache.juneau.marshaller"><code>Json</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall.jm.JsonDetails'>JSON Details</a></td>
</tr>
<tr>
<td><c>application/json+simple</c><br><c>text/json+simple</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/json/SimpleJsonSerializer.html" title="class in org.apache.juneau.json"><code>SimpleJsonSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/SimpleJson.html" title="class in org.apache.juneau.marshaller"><code>SimpleJson</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall.jm.JsonDetails.jm.SimplifiedJson'>Simplified JSON</a></td>
</tr>
<tr>
<td><c>application/json+schema</c><br><c>text/json+schema</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/json/JsonSchemaSerializer.html" title="class in org.apache.juneau.json"><code>JsonSchemaSerializer</code></a></ul></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td><a class='doclink' href='#juneau-marshall.jm.JsonSchemaDetails'>JSON-Schema Support</a></td>
</tr>
<tr>
<td><c>octal/msgpack</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/msgpack/MsgPackSerializer.html" title="class in org.apache.juneau.msgpack"><code>MsgPackSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/msgpack/MsgPackParser.html" title="class in org.apache.juneau.msgpack"><code>MsgPackParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/MsgPack.html" title="class in org.apache.juneau.marshaller"><code>MsgPack</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall.jm.MsgPackDetails'>MessagePack Details</a></td>
</tr>
<tr>
<td><c>text/n3</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/N3Serializer.html" title="class in org.apache.juneau.jena"><code>N3Serializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/N3Parser.html" title="class in org.apache.juneau.jena"><code>N3Parser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/N3.html" title="class in org.apache.juneau.marshaller"><code>N3</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall-rdf'>juneau-marshall-rdf</a></td>
</tr>
<tr>
<td><c>text/n-triple</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/NTripleSerializer.html" title="class in org.apache.juneau.jena"><code>NTripleSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/NTripleParser.html" title="class in org.apache.juneau.jena"><code>NTripleParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/NTriple.html" title="class in org.apache.juneau.marshaller"><code>NTriple</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall-rdf'>juneau-marshall-rdf</a></td>
</tr>
<tr>
<td><c>text/openapi</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/OpenApi.html" title="class in org.apache.juneau.marshaller"><code>OpenApi</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall.jm.OpenApiDetails'>OpenAPI Details</a></td>
</tr>
<tr>
<td><c>text/plain</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/plaintext/PlainTextSerializer.html" title="class in org.apache.juneau.plaintext"><code>PlainTextSerializer</code></a></ul></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td><c>text/xml+rdf<c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/RdfXmlSerializer.html" title="class in org.apache.juneau.jena"><code>RdfXmlSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/RdfXmlParser.html" title="class in org.apache.juneau.jena"><code>RdfXmlParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/RdfXml.html" title="class in org.apache.juneau.marshaller"><code>RdfXml</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall-rdf'>juneau-marshall-rdf</a></td>
</tr>
<tr>
<td><c>text/xml+rdf+abbrev</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/RdfXmlAbbrevSerializer.html" title="class in org.apache.juneau.jena"><code>RdfXmlAbbrevSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/RdfXmlParser.html" title="class in org.apache.juneau.jena"><code>RdfXmlParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/RdfXmlAbbrev.html" title="class in org.apache.juneau.marshaller"><code>RdfXmlAbbrev</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall-rdf'>juneau-marshall-rdf</a></td>
</tr>
<tr>
<td><c>text/xml+soap</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/soap/SoapXmlSerializer.html" title="class in org.apache.juneau.soap"><code>SoapXmlSerializer</code></a></ul></td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td><c>text/turtle</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/TurtleSerializer.html" title="class in org.apache.juneau.jena"><code>TurtleSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/jena/TurtleParser.html" title="class in org.apache.juneau.jena"><code>TurtleParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/Turtle.html" title="class in org.apache.juneau.marshaller"><code>Turtle</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall-rdf'>juneau-marshall-rdf</a></td>
</tr>
<tr>
<td><c>text/uon</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/Uon.html" title="class in org.apache.juneau.marshaller"><code>Uon</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall.jm.UonDetails'>UON Details</a></td>
</tr>
<tr>
<td><c>application/x-www-form-urlencoded</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/UrlEncoding.html" title="class in org.apache.juneau.marshaller"><code>UrlEncoding</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall.jm.UrlEncodingDetails'>URL-Encoding Details</a></td>
</tr>
<tr>
<td><c>text/xml</c></td>
<td><ul><li class='jc'><a href="org/apache/juneau/xml/XmlSerializer.html" title="class in org.apache.juneau.xml"><code>XmlSerializer</code></a><li class='jc'><a href="org/apache/juneau/xml/XmlDocSerializer.html" title="class in org.apache.juneau.xml"><code>XmlDocSerializer</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/xml/XmlParser.html" title="class in org.apache.juneau.xml"><code>XmlParser</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/marshaller/Xml.html" title="class in org.apache.juneau.marshaller"><code>Xml</code></a></ul></td>
<td><a class='doclink' href='#juneau-marshall.jm.XmlDetails'>XML Details</a></td>
</tr>
</table>
</div>
</div><!-- END: 19.1 - Glossaries.g.LanguageSupport -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Glossaries.g.Annotations' id='Glossaries.g.Annotations'>19.2 - Annotations</a><span class='update'>created: 8.1.3</span></h3>
<div class='topic'><!-- START: 19.2 - Glossaries.g.Annotations -->
<h5 class='topic'>Serialization Annotations (used to modify how artifacts are marshalled)</h5>
<div class='topic'>
<table class='styled w1000'>
<tr>
<th>Annotation</th><th>Description</th><th>Used On</th><th>Used By</th>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>Bean</code></a></ul></td>
<td><ul><li>Classes</ul></td>
<td>All serializers and parsers</td>
<td>Tailors how beans get marshalled.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/Beanc.html" title="annotation in org.apache.juneau.annotation"><code>Beanc</code></a></ul></td>
<td><ul><li>Bean constructors</ul></td>
<td>All serializers and parsers</td>
<td>Identifies bean constructors and property args.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/BeanIgnore.html" title="annotation in org.apache.juneau.annotation"><code>BeanIgnore</code></a></ul></td>
<td><ul><li>Classes<li>Fields<li>Methods</ul></td>
<td>All serializers and parsers</td>
<td>Prevents artifacts from being interpreted as beans/bean components.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/Beanp.html" title="annotation in org.apache.juneau.annotation"><code>Beanp</code></a></ul></td>
<td><ul><li>Methods<li>Fields<li>Constructor args</ul></td>
<td>All serializers and parsers</td>
<td>Tailors how bean properties get marshalled.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/Builder.html" title="annotation in org.apache.juneau.annotation"><code>Builder</code></a></ul></td>
<td><ul><li>Classes</ul></td>
<td>All parsers</td>
<td>Identifies a class as a builder for a POJO class.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/csv/annotation/Csv.html" title="annotation in org.apache.juneau.csv.annotation"><code>Csv</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/csv/CsvSerializer.html" title="class in org.apache.juneau.csv"><code>CsvSerializer</code></a><li class='jc'><a href="org/apache/juneau/csv/CsvParser.html" title="class in org.apache.juneau.csv"><code>CsvParser</code></a></ul></td>
<td>CSV-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/Example.html" title="annotation in org.apache.juneau.annotation"><code>Example</code></a></ul></td>
<td><ul><li>Static methods<li>Static fields<li>Classes</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/json/JsonSchemaSerializer.html" title="class in org.apache.juneau.json"><code>JsonSchemaSerializer</code></a></ul></td>
<td>Identifies examples for POJOs.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/html/annotation/Html.html" title="annotation in org.apache.juneau.html.annotation"><code>Html</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a><li class='jc'><a href="org/apache/juneau/html/HtmlParser.html" title="class in org.apache.juneau.html"><code>HtmlParser</code></a></ul></td>
<td>HTML-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/html/annotation/HtmlLink.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlLink</code></a></ul></td>
<td><ul><li>Classes</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a></ul></td>
<td>Defines how to construct hyperlinks on objects.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/json/annotation/Json.html" title="annotation in org.apache.juneau.json.annotation"><code>Json</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a><li class='jc'><a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a></ul></td>
<td>JSON-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/msgpack/annotation/MsgPack.html" title="annotation in org.apache.juneau.msgpack.annotation"><code>MsgPack</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/msgpack/MsgPackSerializer.html" title="class in org.apache.juneau.msgpack"><code>MsgPackSerializer</code></a><li class='jc'><a href="org/apache/juneau/msgpack/MsgPackParser.html" title="class in org.apache.juneau.msgpack"><code>MsgPackParser</code></a></ul></td>
<td>MessagePack-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/Name.html" title="annotation in org.apache.juneau.annotation"><code>Name</code></a></ul></td>
<td><ul><li>Constructor args</ul></td>
<td>All parsers</td>
<td>Maps constructor args to property names.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/NameProperty.html" title="annotation in org.apache.juneau.annotation"><code>NameProperty</code></a></ul></td>
<td><ul><li>Methods<li>Fields</ul></td>
<td>All parsers</td>
<td>Identifies a 'name' property.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/oapi/annotation/OpenApi.html" title="annotation in org.apache.juneau.oapi.annotation"><code>OpenApi</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a><li class='jc'><a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a></ul></td>
<td>OpenAPI-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/ParentProperty.html" title="annotation in org.apache.juneau.annotation"><code>ParentProperty</code></a></ul></td>
<td><ul><li>Methods<li>Fields</ul></td>
<td>All parsers</td>
<td>Identifies a 'parent' property.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/plaintext/annotation/PlainText.html" title="annotation in org.apache.juneau.plaintext.annotation"><code>PlainText</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/plaintext/PlainTextSerializer.html" title="class in org.apache.juneau.plaintext"><code>PlainTextSerializer</code></a><li class='jc'><a href="org/apache/juneau/plaintext/PlainTextParser.html" title="class in org.apache.juneau.plaintext"><code>PlainTextParser</code></a></ul></td>
<td>PlainText-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/jena/annotation/Rdf.html" title="annotation in org.apache.juneau.jena.annotation"><code>Rdf</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td>All RDF serializers and parsers</td>
<td>RDF-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/jena/annotation/RdfSchema.html" title="annotation in org.apache.juneau.jena.annotation"><code>RdfSchema</code></a></ul></td>
<td><ul><li>Packages</ul></td>
<td>All RDF serializers and parsers</td>
<td>Identifies the default RDF namespaces at the package level.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/soap/annotation/SoapXml.html" title="annotation in org.apache.juneau.soap.annotation"><code>SoapXml</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/soap/SoapXmlSerializer.html" title="class in org.apache.juneau.soap"><code>SoapXmlSerializer</code></a></ul></td>
<td>SOAP/XML-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/Swap.html" title="annotation in org.apache.juneau.annotation"><code>Swap</code></a></ul></td>
<td><ul><li>Classes<li>Bean getters/setters<li>Fields</ul></td>
<td>All serializers and parsers</td>
<td>Associates swaps and surrogates with POJOs and bean properties.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/uon/annotation/Uon.html" title="annotation in org.apache.juneau.uon.annotation"><code>Uon</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a><li class='jc'><a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a></ul></td>
<td>UON-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/Uri.html" title="annotation in org.apache.juneau.annotation"><code>Uri</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td>HTML and XML serializers</td>
<td>Identifies a class or bean property as a URI.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/urlencoding/annotation/UrlEncoding.html" title="annotation in org.apache.juneau.urlencoding.annotation"><code>UrlEncoding</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a><li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a></ul></td>
<td>URL-Encoding-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/xml/annotation/Xml.html" title="annotation in org.apache.juneau.xml.annotation"><code>Xml</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields</ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/xml/XmlSerializer.html" title="class in org.apache.juneau.xml"><code>XmlSerializer</code></a><li class='jc'><a href="org/apache/juneau/xml/XmlParser.html" title="class in org.apache.juneau.xml"><code>XmlParser</code></a></ul></td>
<td>XML-specific tweaks.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/xml/annotation/XmlSchema.html" title="annotation in org.apache.juneau.xml.annotation"><code>XmlSchema</code></a></ul></td>
<td><ul><li>Packages</ul></td>
<td>XML serializers and parsers</td>
<td>Identifies the default XML namespaces at the package level.</td>
</tr>
</table>
</div>
<h5 class='topic'>Configuration Annotations (used to modify how serializers/parsers behave)</h5>
<div class='topic'>
<table class='styled w800'>
<tr>
<th>Annotation</th><th>Configures</th>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/annotation/BeanConfig.html" title="annotation in org.apache.juneau.annotation"><code>BeanConfig</code></a></ul></td>
<td>All serializers and parsers</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/csv/annotation/CsvConfig.html" title="annotation in org.apache.juneau.csv.annotation"><code>CsvConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/csv/CsvSerializer.html" title="class in org.apache.juneau.csv"><code>CsvSerializer</code></a><li class='jc'><a href="org/apache/juneau/csv/CsvParser.html" title="class in org.apache.juneau.csv"><code>CsvParser</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/html/annotation/HtmlConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a><li class='jc'><a href="org/apache/juneau/html/HtmlParser.html" title="class in org.apache.juneau.html"><code>HtmlParser</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlDocConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/json/annotation/JsonConfig.html" title="annotation in org.apache.juneau.json.annotation"><code>JsonConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a><li class='jc'><a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/jsonschema/annotation/JsonSchemaConfig.html" title="annotation in org.apache.juneau.jsonschema.annotation"><code>JsonSchemaConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/json/JsonSchemaSerializer.html" title="class in org.apache.juneau.json"><code>JsonSchemaSerializer</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/msgpack/annotation/MsgPackConfig.html" title="annotation in org.apache.juneau.msgpack.annotation"><code>MsgPackConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/msgpack/MsgPackSerializer.html" title="class in org.apache.juneau.msgpack"><code>MsgPackSerializer</code></a><li class='jc'><a href="org/apache/juneau/msgpack/MsgPackParser.html" title="class in org.apache.juneau.msgpack"><code>MsgPackParser</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/oapi/annotation/OpenApiConfig.html" title="annotation in org.apache.juneau.oapi.annotation"><code>OpenApiConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/oapi/OpenApiSerializer.html" title="class in org.apache.juneau.oapi"><code>OpenApiSerializer</code></a><li class='jc'><a href="org/apache/juneau/oapi/OpenApiParser.html" title="class in org.apache.juneau.oapi"><code>OpenApiParser</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/parser/annotation/ParserConfig.html" title="annotation in org.apache.juneau.parser.annotation"><code>ParserConfig</code></a></ul></td>
<td>All parsers</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/plaintext/annotation/PlainTextConfig.html" title="annotation in org.apache.juneau.plaintext.annotation"><code>PlainTextConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/plaintext/PlainTextSerializer.html" title="class in org.apache.juneau.plaintext"><code>PlainTextSerializer</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/jena/annotation/RdfConfig.html" title="annotation in org.apache.juneau.jena.annotation"><code>RdfConfig</code></a></ul></td>
<td>All RDF serializers and parsers</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/serializer/annotation/SerializerConfig.html" title="annotation in org.apache.juneau.serializer.annotation"><code>SerializerConfig</code></a></ul></td>
<td>All serializers</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/soap/annotation/SoapXmlConfig.html" title="annotation in org.apache.juneau.soap.annotation"><code>SoapXmlConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/soap/SoapXmlSerializer.html" title="class in org.apache.juneau.soap"><code>SoapXmlSerializer</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/uon/annotation/UonConfig.html" title="annotation in org.apache.juneau.uon.annotation"><code>UonConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a><li class='jc'><a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/urlencoding/annotation/UrlEncodingConfig.html" title="annotation in org.apache.juneau.urlencoding.annotation"><code>UrlEncodingConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a><li class='jc'><a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a></ul></td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/xml/annotation/XmlConfig.html" title="annotation in org.apache.juneau.xml.annotation"><code>XmlConfig</code></a></ul></td>
<td><ul><li class='jc'><a href="org/apache/juneau/xml/XmlSerializer.html" title="class in org.apache.juneau.xml"><code>XmlSerializer</code></a><li class='jc'><a href="org/apache/juneau/xml/XmlParser.html" title="class in org.apache.juneau.xml"><code>XmlParser</code></a></ul></td>
</tr>
</table>
</div>
<h5 class='topid'>Common REST Annotations (used on both client-side and server-side)</h5>
<div class='topic'>
<table class='styled w800'>
<tr>
<th>Annotation</th><th>Used On</th><th>Description</th>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/Content.html" title="annotation in org.apache.juneau.http.annotation"><code>Content</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields<li>Parameters</ul></td>
<td>HTTP request/response body.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields<li>Parameters</ul></td>
<td>HTTP form data parameter.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/HasFormData.html" title="annotation in org.apache.juneau.http.annotation"><code>HasFormData</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields<li>Parameters</ul></td>
<td>HTTP form data parameter is present.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/HasQuery.html" title="annotation in org.apache.juneau.http.annotation"><code>HasQuery</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields<li>Parameters</ul></td>
<td>HTTP query parameter is present.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields<li>Parameters</ul></td>
<td>HTTP header.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields<li>Parameters</ul></td>
<td>HTTP path part.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Fields<li>Parameters</ul></td>
<td>HTTP query parameter.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>Request</code></a></ul></td>
<td><ul><li>Classes<li>Parameters</ul></td>
<td>Identifies an interface to use to interact with HTTP parts of an HTTP request through a bean.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>Response</code></a></ul></td>
<td><ul><li>Classes<li>Methods<li>Parameters</ul></td>
<td>Identifies an interface to use to interact with HTTP parts of an HTTP response through a bean.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/http/annotation/StatusCode.html" title="annotation in org.apache.juneau.http.annotation"><code>StatusCode</code></a></ul></td>
<td><ul><li>Methods<li>Parameters</ul></td>
<td>Denotes a method as an HTTP response status code on a <ja>@Response</ja>-annotated bean.</td>
</tr>
</table>
</div>
<h5 class='topic'>REST Server-only Annotations</h5>
<div class='topic'>
<table class='styled w800'>
<tr>
<th>Annotation</th><th>Used On</th><th>Description</th>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/rest/annotation/Attr.html" title="annotation in org.apache.juneau.rest.annotation"><code>Attr</code></a></ul></td>
<td><ul><li>Parameters</ul></td>
<td>Request attribute.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a></ul></td>
<td><ul><li>Classes</ul></td>
<td>Identifies and configures REST resource classes.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/rest/annotation/RestHook.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestHook</code></a></ul></td>
<td><ul><li>Methods</ul></td>
<td>Identifies REST lifecycle hook methods.</td>
</tr>
<tr>
<td><ul style='margin-left:20px'><li class='ja'><a href="org/apache/juneau/rest/annotation/RestOp.html" title="annotation in org.apache.juneau.rest.annotation"><code>RestOp</code></a></ul></td>
<td><ul><li>Methods</ul></td>
<td>Identifies and configures REST resource class methods.</td>
</tr>
</table>
</div>
</div><!-- END: 19.2 - Glossaries.g.Annotations -->
</div><!-- END: 19 - Glossaries -->
<!-- ==================================================================================================== -->
<h2 class='topic' onclick='toggle(this)'><a href='#Security' id='Security'>20 - Security Best-Practices</a></h2>
<div class='topic'><!-- START: 20 - Security -->
<div class='topic'>
<p>
Security is always an ongoing concern in any library.
If you discover any security vulnerabilities in this code, please refer to the instructions found here:
</p>
<ul class='spaced-list'>
<li class='extlink'><a class='doclink' href='http://www.apache.org/security'>SECURITY</a>
</ul>
</div>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Security.s.Marshall' id='Security.s.Marshall'>20.1 - juneau-marshall</a><span class='update'>created: 8.2.0</span></h3>
<div class='topic'><!-- START: 20.1 - Security.s.Marshall -->
<h5 class='topic'>Demarshalling vulnerabilities</h5>
<div class='topic'>
<p>
One common security vulnerability is the ability to create arbitrary Java object instances through crafted
user input. For example, support for constructing POJOs based on an input attribute defining a
fully-qualified class name like <js>"{class:'com.foo.MyBean',...}"</js>
</p>
<p>
Fortunately, Juneau does not support an open-ended <js>"class</js> attribute.
As a rule, it should not be possible to create arbitrary POJOs by any of the parsers.
The demarshalled object types are inferred via reflection of the class objects passed in through the parser
method (e.g. <c>JsonParser.<jsf>DEFAULT</jsf>.parse(input, MyBean.<jk>class</jk>)</c>).
As long as the <c>Class</c> object passed into this method is not constructed from user-generated input,
it should be free from demarshalling vulnerabilities.
</p>
<p>
The following example shows a potential vector that circumvents the restriction above:
</p>
<p class='bjava'>
<jc>// Don't do this!</jc>
Class <jv>c</jv> = Class.<jsf>forName</jsf>(<jv>someUserInputString</jv>);
JsonParser.<jsf>DEFAULT</jsf>.parse(<jv>input</jv>, <jv>c</jv>); <jc>// Oops! Security hole!</jc>
</p>
<p>
Juneau does support something similar to a <js>"class"</js> attribute that allows you to define the
POJO type at runtime.
This is the <js>"type"</js> attribute.
The difference is that it's not possible to specify fully-qualified class names in <js>"type"</js> attributes,
and instead can only specify type keys defined through bean dictionaries.
Instead of serializing the fully-qualified class names in the output, we instead serialize type
names that represent those POJO types.
i.e. instead of <js>"class='com.foo.MyBean'"</js>, we instead serialize <js>"type='MyBeanIdentifier'"</js>.
Since bean types are defined at compile time, it's impossible to instantiate arbitrary POJOs.
</p>
<p>
POJO types of generalized input are also inferred through swaps.
Again, since the POJO types are hardcoded at compile time, these should not be subject to demarshalling
vulnerabilities. However, it is possible to circumvent this through your swap implementation as shown
below:
</p>
<p class='bjava'>
<jc>// Don't do this!</jc>
<jk>public class</jk> MyInsecureSwap <jk>extends</jk> ObjectSwap&lt;JsonMap,Object&gt; {
<jk>public</jk> Object swap(BeanSession <jv>session</jv>, JsonMap <jv>input</jv>) <jk>throws</jk> Exception {
<jc>// Security hole!</jc>
<jk>return</jk> Class.<jsf>forName</jsf>(<jv>input</jv>.getString(<js>"class"</js>)).newInstance();
}
}
</p>
<p>
All other parsers (JSON, URL-Encoding, MessagePack, etc...) work the same way in determining POJO types, so
should be safe from demarshalling vulnerabilities.
</p>
</div>
<h5 class='topic'>Dependent libraries</h5>
<div class='topic'>
<p>
When accessing security vulnerabilities of any library, dependent libraries must also be taken into account:
</p>
<ul>
<li>The JSON, HTML, MsgPack, URL-Encoding, and UON parsers are written from scratch and do not rely on
any other parsing technologies.
<li>The XML and HTML parsers uses the built-in Java StAX parser.
This *should* be free from vulnerabilities.
<li>The RDF parsers rely on Apache Jena 2.7.1.
As of <c>7.0.1</c>, no known security vulnerabilities exist that affect Juneau at this time.
</ul>
</div>
</div><!-- END: 20.1 - Security.s.Marshall -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Security.s.Svl' id='Security.s.Svl'>20.2 - juneau-svl</a><span class='update'>created: 8.2.0</span></h3>
<div class='topic'><!-- START: 20.2 - Security.s.Svl -->
<div class='topic'>
<p>
Care must be used when defining new <a href="org/apache/juneau/svl/Var.html" title="class in org.apache.juneau.svl"><code>Vars</code></a> using the SVL API since mistakes
could potentially expose system properties, environment variables, or even file system files.
</p>
<p>
For recap, the SVL support allows you to embed variables of the form <js>"$X{key}"</js> inside strings that
get resolved to other strings. The resolved strings themselves can also contain variables that also
get recursively resolved.
</p>
<p>
An example of a potential security hole is shown below that could potentially expose any file on a file
system through a REST request:
</p>
<p class='bjava'>
<jk>public</jk> String doUnsafeGet(RestRequest <jv>req</jv>) {
<jc>// Security hole!</jc>
<jk>return</jk> <jv>req</jv>.getVarResolver().resolve(<js>"$RQ{foo}"</js>);
}
</p>
<p>
This code is simply echoing the value of the <c>foo</c> query parameter.
Now say for example that a bad actor passes in the query string <js>"foo=$F{/some/file/on/file/system}"</js>.
The <c>$F</c> variable allows you to resolve the contents of files using SVL, and is provided
by default using the built-in variable resolver returned by the <c>RestRequest</c> object.
You've potentially just exposed the contents of that file through your REST interface.
</p>
<p>
In reality, the above security hole does not exist because of the following restrictions:
</p>
<ul class='spaced-list'>
<li>
<c>Vars</c> have two methods <a href="org/apache/juneau/svl/Var.html#allowNested--"><code>Var.allowNested()</code></a> and
<a href="org/apache/juneau/svl/Var.html#allowRecurse--"><code>Var.allowRecurse()</code></a> that can be overridden to prevent recursive processing
of string variables. These are both <jk>false</jk> for the <c>$R</c> variable, so the <c>$F</c>
variable in the result will never get processed and instead be treated as plain text.
<li>
The <c>$F</c> variable only allows you to retrieve files within the JVM starting directory.
</ul>
<p>
Even though the built-in Juneau variables are safe, special care is needed when defining your own custom
variables. If your variable resolves user input in any way, it's HIGHLY recommended that you override the
<a href="org/apache/juneau/svl/Var.html#allowNested--"><code>Var.allowNested()</code></a> and <a href="org/apache/juneau/svl/Var.html#allowRecurse--"><code>Var.allowRecurse()</code></a>
methods to prevent recursive handling of variables.
</p>
</div>
</div><!-- END: 20.2 - Security.s.Svl -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#Security.s.Rest' id='Security.s.Rest'>20.3 - juneau-rest-server</a><span class='update'>created: 8.2.0</span></h3>
<div class='topic'><!-- START: 20.3 - Security.s.Rest -->
<div class='topic'>
<p>
Denial of service attacks can be alleviated through the <a href="org/apache/juneau/rest/annotation/Rest.html#maxInput--"><code>maxInput()</code></a>
setting. Arbitrarily-large input will trigger an exception before causing out-of-memory errors.
The default value for this setting is 100MB.
</p>
<p>
Since the parsers do not use intermediate DOMs and instead parse directly into Java objects,
deeply nested data structures will almost always trigger stack overflow errors long before memory consumption
becomes an issue. However, this is NOT true of the RDF parsers that use an intermediate DOM. If parsing
RDF, you may want to consider lowering the max-input value above.
</p>
</div>
</div><!-- END: 20.3 - Security.s.Rest -->
</div><!-- END: 20 - Security -->
<h2 class='topic' onclick='toggle(this)'><a href='#ReleaseNotes' id='ReleaseNotes'>Release Notes</a></h2>
<div class='topic'>
<h5 class='toc'>Release Notes</h5>
<ul class='toc'>
<li><p><a class='doclink' href='#5.0.0.0'>5.0.0.0 (Jun 11, 2012)</a></p>
<li><p><a class='doclink' href='#5.0.0.1'>5.0.0.1 (Jun 14, 2012)</a></p>
<li><p><a class='doclink' href='#5.0.0.2'>5.0.0.2 (Sept 28, 2012)</a></p>
<li><p><a class='doclink' href='#5.0.0.3'>5.0.0.3 (Oct 3, 2012)</a></p>
<li><p><a class='doclink' href='#5.0.0.4'>5.0.0.4 (Oct 7, 2012)</a></p>
<li><p><a class='doclink' href='#5.0.0.5'>5.0.0.5 (Oct 29, 2012)</a></p>
<li><p><a class='doclink' href='#5.0.0.6'>5.0.0.6 (Oct 30, 2012)</a></p>
<li><p><a class='doclink' href='#5.0.0.7'>5.0.0.7 (Jan 20, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.8'>5.0.0.8 (Jan 30, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.9'>5.0.0.9 (Feb 26, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.10'>5.0.0.10 (Mar 7, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.11'>5.0.0.11 (Mar 8, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.12'>5.0.0.12 (Mar 10, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.13'>5.0.0.13 (Mar 14, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.14'>5.0.0.14 (Mar 23, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.15'>5.0.0.15 (Mar 24, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.16'>5.0.0.16 (Mar 25, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.17'>5.0.0.17 (Mar 25, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.18'>5.0.0.18 (Mar 27, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.19'>5.0.0.19 (Apr 1, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.20'>5.0.0.20 (Apr 7, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.21'>5.0.0.21 (Apr 9, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.22'>5.0.0.22 (Apr 12, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.23'>5.0.0.23 (Apr 14, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.24'>5.0.0.24 (May 9, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.25'>5.0.0.25 (May 11, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.26'>5.0.0.26 (Jun 5, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.27'>5.0.0.27 (July 7, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.28'>5.0.0.28 (July 9, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.29'>5.0.0.29 (Aug 2, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.30'>5.0.0.30 (Aug 8, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.31'>5.0.0.31 (Aug 9, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.32'>5.0.0.32 (Oct 5, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.33'>5.0.0.33 (Oct 20, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.34'>5.0.0.34 (Nov 10, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.35'>5.0.0.35 (Nov 26, 2013)</a></p>
<li><p><a class='doclink' href='#5.0.0.36'>5.0.0.36 (Dec 18, 2013)</a></p>
<li><p><a class='doclink' href='#5.1.0.0'>5.1.0.0 (Jan 18, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.1'>5.1.0.1 (Jan 25, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.2'>5.1.0.2 (Apr 27, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.3'>5.1.0.3 (Jun 28, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.4'>5.1.0.4 (Aug 25, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.5'>5.1.0.5 (Sept 1, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.6'>5.1.0.6 (Sept 21, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.7'>5.1.0.7 (Oct 5, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.8'>5.1.0.8 (Oct 25, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.9'>5.1.0.9 (Dec 1, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.10'>5.1.0.10 (Dec 23, 2014)</a></p>
<li><p><a class='doclink' href='#5.1.0.11'>5.1.0.11 (Feb 14, 2015)</a></p>
<li><p><a class='doclink' href='#5.1.0.12'>5.1.0.12 (Mar 28, 2015)</a></p>
<li><p><a class='doclink' href='#5.1.0.13'>5.1.0.13 (Apr 24, 2015)</a></p>
<li><p><a class='doclink' href='#5.1.0.14'>5.1.0.14 (May 10, 2015)</a></p>
<li><p><a class='doclink' href='#5.1.0.15'>5.1.0.15 (May 24, 2015)</a></p>
<li><p><a class='doclink' href='#5.1.0.16'>5.1.0.16 (June 28, 2015)</a></p>
<li><p><a class='doclink' href='#5.1.0.17'>5.1.0.17 (Aug 3, 2015)</a></p>
<li><p><a class='doclink' href='#5.1.0.18'>5.1.0.18 (Aug 5, 2015)</a></p>
<li><p><a class='doclink' href='#5.1.0.19'>5.1.0.19 (Aug 15, 2015)</a></p>
<li><p><a class='doclink' href='#5.1.0.20'>5.1.0.20 (Sept 5, 2015)</a></p>
<li><p><a class='doclink' href='#5.2.0.0'>5.2.0.0 (Dec 30, 2015)</a></p>
<li><p><a class='doclink' href='#5.2.0.1'>5.2.0.1 (Mar 23, 2016)</a></p>
<li><p><a class='doclink' href='#6.0.0'>6.0.0 (Oct 3, 2016)</a></p>
<li><p><a class='doclink' href='#6.0.1'>6.0.1 (Jan 3, 2017)</a></p>
<li><p><a class='doclink' href='#6.1.0'>6.1.0 (Feb 25, 2017)</a></p>
<li><p><a class='doclink' href='#6.2.0'>6.2.0 (Apr 28, 2017)</a></p>
<li><p><a class='doclink' href='#6.3.0'>6.3.0 (Jun 30, 2017)</a></p>
<li><p><a class='doclink' href='#6.3.1'>6.3.1 (Aug 1, 2017)</a></p>
<li><p><a class='doclink' href='#6.4.0'>6.4.0 (Oct 5, 2017)</a></p>
<li><p><a class='doclink' href='#7.0.0'>7.0.0 (Oct 25, 2017)</a></p>
<li><p><a class='doclink' href='#7.0.1'>7.0.1 (Dec 24, 2017)</a></p>
<li><p><a class='doclink' href='#7.1.0'>7.1.0 (Mar 08, 2018)</a></p>
<li><p><a class='doclink' href='#7.2.0'>7.2.0 (Sept 25, 2018)</a></p>
<li><p><a class='doclink' href='#7.2.1'>7.2.1 (Oct 23, 2018)</a></p>
<li><p><a class='doclink' href='#7.2.2'>7.2.2 (Nov 7, 2018)</a></p>
<li><p><a class='doclink' href='#8.0.0'>8.0.0 (Jan 01, 2019)</a></p>
<li><p><a class='doclink' href='#8.1.0'>8.1.0 (Aug 21, 2019)</a></p>
<li><p><a class='doclink' href='#8.1.1'>8.1.1 (Sept 20, 2019)</a></p>
<li><p><a class='doclink' href='#8.1.2'>8.1.2 (Dec 01, 2019)</a></p>
<li><p><a class='doclink' href='#8.1.3'>8.1.3 (Jan 20, 2020)</a></p>
<li><p><a class='doclink' href='#8.2.0'>8.2.0 (Oct 14, 2020)</a></p>
<li><p><a class='doclink' href='#9.0.0'>9.0.0 (TBD)</a></p>
</ul>
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.0' id='5.0.0.0'>5.0.0.0 (Jun 11, 2012)</a></h3>
<div class='topic'><!-- START: 5.0.0.0 -->
<div class='topic'>
<p>
Version 5.0 marks a major release milestone for the Juno/JJSON library.
It is now available for download from iRAM under the name "Juno (previously JJSON)".
The Juno Starters Guide has been updated to reflect new functionality in this release.
</p>
<ul class='spaced-list'>
<li>
New name.<br>
Unfortunately, "JJSON" was already trademarked by another similar library.
Therefore, it's been renamed "Juno" (after the Roman goddess and wife of Jupiter) which does not appear to have any similar trademark issues (crosses fingers).
The name is also a play on the word "Uno", indicating that this is a single simple unifying interface of several kinds of technology.
</li>
<li>
Simplified APIs for working with beans.<br>
Significant improvements have been made to the parsers to make it easier to convert serialized POJOs back into their original forms.
</li>
<li>
Serializer/Parser classes now directly subclass from <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a>.<br>
In previous releases, if you wanted to change the way beans were handled by the serializers and parsers, you had to construct a separate bean map factory and pass it to the serializer or parser.
Now, you can call the bean map factory methods directly on the serializer or parser class.
</li>
<li>
Simplified Filter API for handling non-standard POJOs.<br>
The API for handling non-standard POJOs has been simplified by introducing the concept of a <dc>Transform</dc> class, which is associated with the <c>BeanContext</c> class (and thus the Serializer and Parser classes too) through the <c>BeanContext.addTransforms(Class[])</c> method.<br>
Two new subclasses of <dc>Transform</dc>:
<ul>
<li><dc>org.apache.juneau.transform.BeanFilter</dc> - Filter POJO beans.</li>
<li><dc>org.apache.juneau.transform.PojoSwap</dc> - Filter POJOs that aren't beans.</li>
</ul>
This new API replaces the previous separate <c>Cast</c> and <c>BeanFilter</c> APIs which were considerably more complicated and puts them under a common API.
</li>
<li>
Elimination of <c>_class</c> attributes in parsable output.<br>
One of the complaints about the previous version of JJSON was that if you wanted to have the resulting JSON or XML be parsable back into beans, you had to enable the <js>"addClassAttrs"</js> property on the bean map factory class so that <js>"_class"</js> attributes could be added to the output.<br>
This requirement is virtually eliminated in v5. In many cases, the parsers are able to determine through reflection what the correct target type is based on the top-level class passed in on the parse method.
</li>
<li>
Performance improvements.<br>
Several significant performance improvements have been made in this release.
<ul>
<li>
New Reader-based JSON parser.<br>
Previously, the JSON parser required that the entire JSON text be loaded into memory as a String before being parsed.
The new JSON parser is Reader-based which significantly reduces memory consumption.
</li>
<li>
New StAX-based XML parser.<br>
The old XML parser was based on DOM. The new XML parser uses a StAX parser which significantly reduces memory consumption.
</li>
<li>
Caching of reflection data in the <c>BeanMap</c> API.<br>
The number of reflection calls have been significantly reduced in the <c>BeanMap</c> API code.
Reflection is used to determine the class types of property values on beans.
This information is now cached and persisted so that the reflection API calls to determine class types are only performed the first time a bean type is encountered.
</li>
<li>
Automatic support for GZIP compression/decompression in <c>RestServlets</c>.<br>
This is completely transparent to the developer.
The output writer is negotiated by the framework to automatically handle compression and charset requests without the developer needing to know anything about it.
</li>
</ul>
</li>
<li>
Cognos/XML support.
</li>
<li>
JSON-schema support.
</li>
<li>
New <dc>org.apache.juneau.utils.PojoIntrospector</dc> class.
</li>
<li>
Significant REST servlet API improvements.
<ul>
<li>
Defining child resources is considerably simpler now.
In addition to the standard doX() methods for handling the requests for the current resource, you can also define getX() methods for returning child resources which automatically become available under the child URL specified by the getter name.
</li>
<li>
Initialization of the child resources occurs automatically when the parent resource initialization occurs.
</li>
<li>
Other improvments have been made in the area of automatic negotiation of input and output type streams.
For example, automatic support is provided for GZIP (<c>Accept-Encoding: gzip</c>) and charsets (e.g <c>Accept-Charset: SJIS</c>) on both incoming and outgoing data.
It's all transparent from a developers perspective.
The developer simply working with POJOs, and all details about content types, encoding, charsets, and so forth are handled by the framework.
</li>
<li>
Support for generating complex <c>OPTIONS</c> pages for resources.
</li>
</ul>
</li>
<li>
Automatic support for SOAP XML output on <js>"text/soap+xml"</js> requests against <c>RestServlet</c>.
</li>
<li>
Support for XML namespaces.
</li>
<li>
Support for setting the XML root element name by either passing in a parameter on the serializer, or by specifying it via a <ja>@Bean</ja> annotation.
</li>
<li>
Support for loading beans directly from Readers and Strings.
</li>
<li>
Parsing support for POJOs of type <c>Enum</c>.
</li>
<li>
Significant improved support for various flavors of parameterized types, such as subclasses of parameterized types (e.g. <c>MyBeanList <jk>extends</jk> LinkedList&lt;MyBean&gt;</c>).
</li>
<li>
Improved ordering of bean properties (should now be ordered as they are defined in the class).
</li>
<li>
Various default filters provided:
<ul>
<li>byte[]&lt;-->Base64 encoded strings</li>
<li>Date/Calendar&lt;-->ISO8601/RFC822/Long</li>
</ul>
</li>
<li>
New <a href="org/apache/juneau/html/HtmlParser.html" title="class in org.apache.juneau.html"><code>HtmlParser</code></a> and <a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a> classes.
</li>
<li>
HtmlSerializer now produces XHTML.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.1' id='5.0.0.1'>5.0.0.1 (Jun 14, 2012)</a></h3>
<div class='topic'><!-- START: 5.0.0.1 -->
<div class='topic'>
<p>
Juno 5.0.0.1 is a moderate update.
</p>
<ul class='spaced-list'>
<li>
New support for generating XML-Schema documents from POJO models.
</li>
<li>
New support for serializing to RDF/XML.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.1 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.2' id='5.0.0.2'>5.0.0.2 (Sept 28, 2012)</a></h3>
<div class='topic'><!-- START: 5.0.0.2 -->
<div class='topic'>
<p>
Juno 5.0.0.2 is a minor update.
</p>
<ul class='spaced-list'>
<li>
Improvements to Javadocs. Most of the information in the Juno Starters Guide wiki has been moved into the overview and package-level javadocs.<br>
Since the information is now written in HTML, you can now copy and paste the code examples directly from the Javadocs.<br>
The code examples are also syntax-highlighted using CSS.
</li>
<li>
Support for defining default XML namespaces on packages and classes for the XML and RDF serializers.
</li>
<li>
Restructured the packages along content type support (e.g. all JSON support moved to <c>org.apache.juneau.json</c>).
</li>
<li>
Automatic support for parsing maps with <c>Enum</c> keys, and parsing <c>Enum</c> strings.<br>
This was previously possible using filters but now it's built-in for all the parsers.
</li>
<li>
Replaced the <c>ObjectList.toXArray()</c> methods with a new <c>elements(Class&lt;T&gt; type)</c> method that's more efficient and avoids creating an unnecessary array.
</li>
<li>
Support for parsing into beans with read-only properties.<br>
New <dc>@BeanConstructor</dc> annotation allows you to specify bean property values to be passed in through a constructor.
</li>
<li>
Separated the rest library into separate independent client and server libraries.<br>
Use one, use both, it's up to you.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.2 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.3' id='5.0.0.3'>5.0.0.3 (Oct 3, 2012)</a></h3>
<div class='topic'><!-- START: 5.0.0.3 -->
<div class='topic'>
<p>
Juno 5.0.0.3 is a minor update.
</p>
<ul class='spaced-list'>
<li>
Support for parsing into read-only beans (i.e. beans with only getters, property values set through constructor args).<br>
To support this, the <dc>@BeanConstructor</dc> annotation has been added.
</li>
<li>
Merged separate settings classes back into their base classes (simplifies the API).
</li>
<li>
<dc>SerializerGroups</dc> and <dc>ParserGroups</dc> now share <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContexts</code></a> to reduce memory consumption of class type metadata.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.3 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.4' id='5.0.0.4'>5.0.0.4 (Oct 7, 2012)</a></h3>
<div class='topic'><!-- START: 5.0.0.4 -->
<div class='topic'>
<p>
Juno 5.0.0.4 is a minor update.
</p>
<ul class='spaced-list'>
<li>
New <dc>@RestMethod</dc> annotation on <dc>org.apache.juneau.rest.RestServlet</dc> methods.<br>
Allows the usage of URL pattern matching and automatic conversion of URL variables to arguments passed to method handlers.<br>
See <dc>org.apache.juneau.rest.RestServlet</dc> for more information.
</li>
<li>
Enhancements to <dc>BeanContext.convertToType(Object,Class)</dc> to be able to convert <c>Strings</c> to classes with
<c>fromString(String)</c>/<c>valueOf(String)</c> static methods or <c>T(String)</c> constructors.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.4 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.5' id='5.0.0.5'>5.0.0.5 (Oct 29, 2012)</a></h3>
<div class='topic'><!-- START: 5.0.0.5 -->
<div class='topic'>
<p>
Juno 5.0.0.5 is a major update.
</p>
<ul class='spaced-list'>
<li>New <c><ja>@RestChild</ja></c> annotation for identifying child resources.</li>
<li>
New <c>traversable</c> and <c>filterable</c> attributes added to <dc>@RestMethod</dc> annotation.<br>
Eliminates the need for <dc>PojoResource</dc> and <dc>FilteredRestResource</dc> classes.
</li>
<li>Simplified client API. Easier to use when making multiple connections to the same server.</li>
<li>Support for pluggable authentication in the client API.</li>
<li>Support for authenticating against Jazz Team Servers.</li>
<li>Support for rendering package-level Javadocs in REST resources.</li>
<li>Support for parsing of header values into specific object types.</li>
<li>Changed default XML representation to not include JSON-type attributes. Produces cleaner XML.</li>
<li>
New <c>resourceUri</c> attributed added to <ja>@Bean</ja> annotation to associate beans with resource URIs.
<ul>
<li>Used for automatically creating hyperlinks in <a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a>.</li>
<li>Used for automatically creating <xa>uri</xa> attributes in <a href="org/apache/juneau/xml/XmlSerializer.html" title="class in org.apache.juneau.xml"><code>XmlSerializer</code></a>.</li>
<li>Used for automatically creating <xa>rdf:about</xa> attributes in <c>RdfXmlSerializer</c>.</li>
</ul>
</li>
</ul>
</div>
</div><!-- END: 5.0.0.5 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.6' id='5.0.0.6'>5.0.0.6 (Oct 30, 2012)</a></h3>
<div class='topic'><!-- START: 5.0.0.6 -->
<div class='topic'>
<p>
Juno 5.0.0.6 is a minor update that fixes a small bug in 5.0.0.5.
</p>
</div>
</div><!-- END: 5.0.0.6 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.7' id='5.0.0.7'>5.0.0.7 (Jan 20, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.7 -->
<div class='topic'>
<p>
Juno 5.0.0.7 is a major update.
</p>
<h5 class='topic w800'>Core API updates</h5>
<ul class='spaced-list'>
<li>Combined previous 3 libraries into a single library.</li>
<li>
New <a href="org/apache/juneau/parser/ParserListener.html" title="class in org.apache.juneau.parser"><code>ParserListener</code></a> class.<br>
Adds ability to find and process unknown bean properties during parsing.
</li>
<li>
Enhancements to <a href="org/apache/juneau/xml/XmlParser.html" title="class in org.apache.juneau.xml"><code>XmlParser</code></a>:
<ul>
<li>Coalescing support</li>
<li>Validations support</li>
<li>Support for replacing entity references</li>
<li>Resolver support</li>
<li>Event allocator support</li>
<li>Trim-whitespace support</li>
</ul>
</li>
<li>
Enhanced XML support:
<ul>
<li>
New <a href="org/apache/juneau/xml/annotation/Xml.html#format--"><code>@Xml.format</code></a> annotation.<br>
Controls how POJOs get serialized to XML.<br>
Also allows you to collapse collections and arrays.
</li>
<li>
New <c>@Xml.namespaces</c> annotation.<br>
Namespaces can be defined at package, class, method, or field levels.
</li>
<li>
New <c>@Xml.nsUri</c> annotation.<br>
Shortcut for specifying namespace URIs.
</li>
<li>
New <c>@Xml.valAttr</c> annotation.<br>
Serializes a bean property value as an attribute.
</li>
<li>Ability to override XS and XSI namespaces on XML and RDF/XML serializers.</li>
<li>Ability to override RDF namespace on RDF/XML serializer.</li>
<li>New more-efficient namespace resolution.</li>
</ul>
</li>
<li>
New configurable property classes for everything are now structured better and easier to locate and identify through the following new classes:
<ul>
<li><a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a></li>
<li><dc>SerializerContext</dc></li>
<li><dc>ParserContext</dc></li>
</ul>
</li>
<li>
Enhancements to <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a>:
<ul>
<li>
Ability to mark bean properties as hidden using <dc>@BeanProperty(hidden)</dc> so that they don't get serialized.
</li>
<li>
Simplified <c>ClassType</c> <a href="org/apache/juneau/ClassMeta.html" title="class in org.apache.juneau"><code>ClassMeta</code></a> API.<br>
Combined 4 classes into a single class.
</li>
<li>
New <dc>@Bean.filter</dc> and <dc>@BeanProperty.filter</dc> annotations.<br>
Used for defining filters on bean classes and bean properties instead of just globally through <c>BeanContext.addTransforms(Class[])</c>.
</li>
<li>
New <a href="org/apache/juneau/PropertyNamer.html" title="interface in org.apache.juneau"><code>PropertyNamer</code></a> API / <a href="org/apache/juneau/annotation/Bean.html#propertyNamer--"><code>@Bean.propertyNamer</code></a> annotation.<br>
Used for customizing bean property names.
</li>
<li>
New <dc>@BeanProperty.beanUri</dc> and <dc>@BeanProperty.id</dc> annotations.<br>
Used for associating beans with URLs and IDs.<br>
Used by XML serializer to add a url attribute on a bean element.<br>
Used by RDF/XML serializer to construct <c>rdf:resource</c> attributes.
</li>
<li>
New <dc>BeanProperty.properties()</dc> annotation.
Used for limiting properties on child elements.
</li>
</ul>
</li>
<li>
Automatic support for <a href="https://docs.oracle.com/javase/8/docs/api/java/net/URL.html?is-external=true" title="class or interface in java.net"><code>URL</code></a> and <a href="https://docs.oracle.com/javase/8/docs/api/java/net/URI.html?is-external=true" title="class or interface in java.net"><code>URI</code></a> objects.
<ul>
<li>Converted to hrefs in HTML.</li>
<li>Converted to url attributes in XML.</li>
<li>Converted to resource:about attributes in RDF/XML.</li>
</ul>
</li>
<li>
Improvements to Javadocs.
</li>
<li>
Improved <code>org.apache.juneau.utils.PojoQuery</code> support.
</li>
</ul>
<h5 class='topic w800'>REST client updates</h5>
<ul class='spaced-list'>
<li>GZIP compression support.</li>
<li>Bug fixes.</li>
</ul>
<h5 class='topic w800'>REST server updates</h5>
<ul class='spaced-list'>
<li>
Support for overriding bean context and serializer properties in a REST method call through new <dc>RestResponse.setProperty(String,Object)</dc> method.<br>
For example, allows you to control whitespace options on a per-request basis.
</li>
<li>
Several new annotations on REST servlets:
<ul>
<li><dc>@RestResource.filters</dc> - Associate post-formatting filters on a resource level.</li>
<li><dc>@RestResource.guards</dc> - Associate resource-level guards.</li>
<li><dc>@RestResource.messages</dc> - Associate a resource bundle with a REST servlet. Comes with several convenience methods for looking up messages for the client locale.</li>
<li><dc>@RestResource.properties</dc> - Override default bean context, serializer, and parser properties though an annotation.</li>
</ul>
</li>
<li>
Several new annotations on REST methods:
<ul>
<li><c>@RestMethod(filters)</c> - Associate post-formatting filters on a method level.</li>
<li><dc>@RestMethod(guards)</dc> - Associate method-level guards.</li>
</ul>
</li>
<li>
New annotations on REST method parameters with automatic conversion:
<ul>
<li><dc>@Attr</dc> - A parameter or URL variable value as a parsed POJO.</li>
<li><dc>@Param</dc> - A query parameter value as a parsed POJO.</li>
<li><dc>@PathRemainder</dc>- The remainder after a URL pattern match as a String.</li>
<li><dc>@Header</dc> - An HTTP header value as a parsed POJO.</li>
<li><dc>@Content</dc> - The HTTP content as a parsed POJO.</li>
<li><a href="org/apache/juneau/rest/annotation/Method.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Method</code></a> - The HTTP method name as a String.</li>
</ul>
</li>
<li>
HTTP response content POJOs can now simply be returned from methods instead of calling <dc>RestResponse.setOutput(Object)</dc>.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.7 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.8' id='5.0.0.8'>5.0.0.8 (Jan 30, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.8 -->
<div class='topic'>
<p>
Juno 5.0.0.8 is a minor update.
</p>
<ul class='spaced-list'>
<li>
New <a href="org/apache/juneau/config/package-summary.html"><code>INI file</code></a> support.
<ul>
<li>Makes reading, updating, and manipulating INI configuration files a snap. </li>
<li>Supports automatic conversion of data types in line with the functionality of the rest of the product.</li>
<li>Comments and layout of INI files are persisted during saves. </li>
</ul>
</li>
</ul>
</div>
</div><!-- END: 5.0.0.8 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.9' id='5.0.0.9'>5.0.0.9 (Feb 26, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.9 -->
<div class='topic'>
<p>
Juno 5.0.0.9 is a moderate update.
</p>
<h5 class='topic w800'>Core API changes</h5>
<ul class='spaced-list'>
<li>
<a href="org/apache/juneau/config/package-summary.html"><code>INI config file support</code></a>:
<ul>
<li>A convenient API for reading, writing, and manipulating INI files.</li>
<li>Ability to convert INI files to batch and shell environment variables.</li>
<li>Command-line interface for updating INI files.</li>
<li>Support for encoded INI file values.</li>
</ul>
</li>
<li>Support for fluent-style bean setters (setters that return the bean itself).</li>
<li>Ability to use <a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a> annotation to override bean identification settings.</li>
<li>New <dc>ObjectMap.cast(Class)</dc> method to convert <c>ObjectMaps</c> directly to beans.</li>
</ul>
<h5 class='topic w800'>REST server API changes</h5>
<ul class='spaced-list'>
<li>Build-in default <c>OPTIONS</c> pages.</li>
<li>New <dc>@RestResource.defaultRequestHeaders</dc> and <dc>@RestResource.defaultResponseHeaders</dc> annotations.</li>
<li>New <dc>@RestMethod(serializers)</dc> and <dc>@RestMethod(parsers)</dc> annotations.</li>
<li>New <dc>@RestMethod(properties)</dc> annotation.</li>
<li>New <dc>@RestMethod(defaultRequestHeaders)</dc> annotation.</li>
<li>New <dc>@RestMethod(matchers)</dc> annotation and <code>org.apache.juneau.rest.RestMatcher</code> class.</li>
<li><c>Readers</c> and <c>InputStreams</c> can be specified on <dc>@Content</dc> annotated parameters.</li>
<li>New <dc>@HasParam</dc> annotation.</li>
<li>Full RFC2616 support for matching <c>Accept</c> headers to serializers.</li>
</ul>
<h5 class='topic w800'>Other notes</h5>
<ul class='spaced-list'>
<li>Smaller library size (460kB).</li>
</ul>
</div>
</div><!-- END: 5.0.0.9 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.10' id='5.0.0.10'>5.0.0.10 (Mar 7, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.10 -->
<div class='topic'>
<p>
Juno 5.0.0.10 is a minor update.
</p>
<h5 class='topic w800'>Core API changes</h5>
<ul class='spaced-list'>
<li>New <dc>ObjectMap.findKeyIgnoreCase(String)</dc> method.
<li>HtmlSerializer will now create 2-dimensional tables for collections of mixed beans/maps if all object have the same set of property names/keys.</li>
</ul>
<h5 class='topic w800'>REST server API changes</h5>
<ul class='spaced-list'>
<li>New <c>RestServletProperties</c> class that defines all the class-level properties that can be set on the servlet.</li>
<li>Properties can be set through <dc>@RestResource.properties</dc> annotation, or new <dc>RestServlet.setProperty(String,Object)</dc> method.</li>
<li>New <js>"?noTrace"</js> URL parameter to prevent stack traces from being logged (for JUnit testing of error conditions).</li>
<li>New <c>RestServletProperties.REST_useStackTraceHashes</c> property to prevent the same stack trace from being logged multiple times.</li>
<li>New <c>RestServletProperties.REST_renderResponseStackTraces</c> property for preventing stack traces in responses for security reasons.</li>
<li>New overridable <c>RestServlet.onError(HttpServletRequest,HttpServletResponse,RestException,boolean)</c> and <dc>RestServlet.onSuccess(RestRequest,RestResponse,long)</dc> methods for plugging in your own logging and peformance monitoring.</li>
<li>Eliminated <c>RestServlet.getInitParams()</c> method, since it's now redundant with <dc>RestServlet.getProperties()</dc>.</li>
<li>Header parameters passed as URL parameters are now case-insensitive.</li>
</ul>
</div>
</div><!-- END: 5.0.0.10 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.11' id='5.0.0.11'>5.0.0.11 (Mar 8, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.11 -->
<div class='topic'>
<p>
Juno 5.0.0.11 is a moderate update.
</p>
<h5 class='topic w800'>REST server API changes</h5>
<ul class='spaced-list'>
<li>
New <c>UrlEncodingRestSerializer</c> and <c>UrlEncodingRestParser</c> classes.<br>
Allows parsing form posts directly to POJOs.
</li>
<li>
Support for <c>Accept</c> and <c>Content-Type</c> <js>"application/x-www-form-urlencoded"</js> added by default on <dc>org.apache.juneau.rest.BasicRestServlet</dc>.
</li>
<li>
New <dc>RestServlet.renderError(HttpServletRequest,HttpServletResponse,RestException)</dc> method to allow customized handling of response errors.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.11 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.12' id='5.0.0.12'>5.0.0.12 (Mar 10, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.12 -->
<div class='topic'>
<p>
Juno 5.0.0.12 is a minor update.
</p>
<h5 class='topic w800'>Core API changes</h5>
<ul class='spaced-list'>
<li>
Relaxed method naming conventions when using <dc>@BeanProperty</dc> annotation.<br>
Methods with zero parameters are interpreted as getters, and methods with one parameter are interpreted as setters.<br>
Eliminated the <c>BeanProperty.method</c> annotation, since it's now unnecessary.
</li>
</ul>
<h5 class='topic w800'>REST server API changes</h5>
<ul class='spaced-list'>
<li>
Significantly improved response error messages.<br>
Older messages were rather cryptic. Error conditions should be much easier to debug now.
</li>
<li>
New <c>PlainTextRestSerializer</c> class for serializing <js>"plain/text"</js> requests.<br>
Useful for debugging purposes.
</li>
<li>
<c>Readers</c> and <c>InputStreams</c> can now be passed in as <dc>@Content</dc> parameters if you need direct access to the HTTP body content without involving the parsers.<br>
Equivalent to previously calling <a href="org/apache/juneau/rest/RestRequest.html#getInputStream--"><code>RestRequest.getInputStream()</code></a> and <a href="org/apache/juneau/rest/RestRequest.html#getReader--"><code>RestRequest.getReader()</code></a>.
</li>
<li>
Improved support for the <c>?debug</c> parameter.<br>
Dumps better information to the log file, such as all header parameters.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.12 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.13' id='5.0.0.13'>5.0.0.13 (Mar 14, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.13 -->
<div class='topic'>
<p>
Juno 5.0.0.13 is a minor update.
</p>
<h5 class='topic w800'>Core API changes</h5>
<ul class='spaced-list'>
<li>
New support for relative URIs.
<ul>
<li>URIs of the form <js>"foo/bar"</js> are interpreted as relative to the context root of the web application.</li>
<li>URIs of the form <js>"/foo/bar"</js> are interpreted as relative to the HTTP authority (e.g. <js>"http://myhost:9080"</js>).</li>
</ul>
</li>
<li>
New <c>SerializerContext.SERIALIZER_uriContext</c> and <c>SerializerContext.SERIALIZER_uriAuthority</c> serializer properties for specifying values for relative URIs.
</li>
<li>
New <dc>@URI</dc> annotation that allows you to specify classes and bean properties as URLs that aren't <c>java.net.URI</c> or <c>java.net.URL</c>.
</li>
<li>
New <dc>HtmlSerializer.HTML_uriAnchorText</dc> HTML serializer property for tailoring how anchor text is rendered.
</li>
<li>
Renamed <c>BeanProperty#uri</c> annotation to <c>BeanProperty#beanUri</c> to make it clear that this property represents the URI of the bean itself instead of an arbitrary property containing a URI.
</li>
<li>
Removed <c>BeanProperty#id</c> annotation.
</li>
</ul>
<h5 class='topic w800'>REST server API changes</h5>
<ul class='spaced-list'>
<li>
Improvements to <dc>org.apache.juneau.rest.RestServlet</dc> to automatically handle relative URIs in POJOs.
<ul>
<li><c>SerializerContext.SERIALIZER_uriContext</c> property set by default to web app context root.</li>
<li><c>SerializerContext.SERIALIZER_uriAuthority</c> property set by default to the request scheme+hostname+port.</li>
</ul>
</li>
<li>
Fixed bug involving <c>Accept-Charset</c> header in Chrome that prevented HTML output from rendering correctly in that browser.<br>
<c>Accept-Charset</c> handling should now be fully W3C compliant.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.13 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.14' id='5.0.0.14'>5.0.0.14 (Mar 23, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.14 -->
<div class='topic'>
<p>
Juno 5.0.0.14 is a major update.
</p>
<p>
The biggest change is that the <c>RestSerializer</c>, <c>RestParser</c>, <c>RestSerializerGroup</c>, and <c>RestParserGroup</c> classes have been eliminated entirely.<br>
Instead, the existing <a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a>, <a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a>, <dc>org.apache.juneau.serializer.SerializerGroup</dc>, and <dc>org.apache.juneau.parser.ParserGroup</dc> classes of the core API have been augmented to replace them.
</p>
<p>
Adoptions will be required if you have previously used these classes.
</p>
<h5 class='topic w800'>Core API changes</h5>
<ul class='spaced-list'>
<li>
New <c>org.apache.juneau.serializer</c> package.
<ul>
<li>Entirely reworked class hierarchy to make it easier to define new serializers.</li>
<li>New <a href="org/apache/juneau/serializer/WriterSerializer.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer</code></a> base class for defining character-based serializers.</li>
<li>New <a href="org/apache/juneau/serializer/OutputStreamSerializer.html" title="class in org.apache.juneau.serializer"><code>OutputStreamSerializer</code></a> base class for defining byte-based serializers.</li>
<li>Updated <dc>org.apache.juneau.serializer.SerializerGroup</dc> class with full support for RFC2616 <c>Accept-Content</c> headers.</li>
<li>Improved cloning support on serializers and serializer groups.</li>
</ul>
</li>
<li>
New <c>org.apache.juneau.parser</c> package.
<ul>
<li>Entirely reworked class hierarchy to make it easier to define new parsers.</li>
<li>New <a href="org/apache/juneau/parser/ReaderParser.html" title="class in org.apache.juneau.parser"><code>ReaderParser</code></a> base class for defining character-based parsers.</li>
<li>New <a href="org/apache/juneau/parser/InputStreamParser.html" title="class in org.apache.juneau.parser"><code>InputStreamParser</code></a> base class for defining byte-based parsers.</li>
<li>Improved cloning support on parsers and parser groups.</li>
</ul>
</li>
<li>
New <c>org.apache.juneau.swap</c> package.
<ul>
<li>Cleaner class structure.</li>
<li>Improved <dc>org.apache.juneau.transform.BeanFilter</dc> class for defining property filters on beans.</li>
<li>Improved <code>org.apache.juneau.utils.PojoQuery</code> class for defining filters on objects (previously called <c>ObjectFilter</c>).</li>
</ul>
</li>
<li>
New <c>org.apache.juneau.encoders</c> package.
<ul>
<li>Defines API for <a href="org/apache/juneau/encoders/Encoder.html" title="class in org.apache.juneau.encoders"><code>Encoders</code></a> for enabling compression in REST servlets and clients.</li>
<li>Previously, gzip compression was enabled by default. This new API allows you to plug in your own compression algorithms.</li>
<li>New <a href="org/apache/juneau/encoders/GzipEncoder.html" title="class in org.apache.juneau.encoders"><code>GzipEncoder</code></a> class for enabling gzip compression.</li>
<li>New <dc>org.apache.juneau.encoders.EncoderGroup</dc> class for managing multiple encoders and finding them based on RFC2616 <c>Accept-Encoding</c> header values.</li>
</ul>
</li>
<li>
New <c>org.apache.juneau.plaintext</c> package.
<ul>
<li>New <a href="org/apache/juneau/plaintext/PlainTextSerializer.html" title="class in org.apache.juneau.plaintext"><code>PlainTextSerializer</code></a> and <a href="org/apache/juneau/plaintext/PlainTextParser.html" title="class in org.apache.juneau.plaintext"><code>PlainTextParser</code></a> classes for serializing/parsing text/plain content.</li>
</ul>
</li>
<li>
New <c>org.apache.juneau.jso</c> package.
<ul>
<li>New <dc>org.apache.juneau.jso.JsoSerializer</dc> class for serializing <c>application/x-java-serialized-object</c> content.</li>
</ul>
</li>
<li>
New <c>org.apache.juneau.soap</c> package.
<ul>
<li>New <a href="org/apache/juneau/soap/SoapXmlSerializer.html" title="class in org.apache.juneau.soap"><code>SoapXmlSerializer</code></a> class for serializing <c>text/xml+soap</c> content.</li>
</ul>
</li>
<li>
Improved cloning support on the <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a> class.
<ul>
<li>Better caching. Improved caching performance.</li>
</ul>
</li>
<li>
<c>JsonMap</c> and <c>JsonList</c> changed to <dc>org.apache.juneau.ObjectMap</dc> and <dc>org.apache.juneau.ObjectList</dc> to better reflect that they're not limited to just JSON support.
</li>
<li>
Renamed <c>PojoSwap</c> to <code>org.apache.juneau.utils.PojoQuery</code> to not confuse it with the new Filter API.
</li>
</ul>
<h5 class='topic w800'>REST server API changes</h5>
<ul class='spaced-list'>
<li>
Eliminated <c>org.apache.juneau.rest.serializers</c> and <c>org.apache.juneau.rest.parsers</c> packages.
<ul>
<li>All existing REST serializers and parsers merged into the core API.</li>
</ul>
</li>
</ul>
<h5 class='topic w800'>REST client API changes</h5>
<ul class='spaced-list'>
<li>
Simplified <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> API.
<ul>
<li>You can now only specify a single serializer or parser per client. This significantly simplifies the code.</li>
<li>Support for <a href="org/apache/juneau/encoders/Encoder.html" title="class in org.apache.juneau.encoders"><code>Encoders</code></a>.</li>
</ul>
</li>
<li>
Eliminated <c>RestCmdLine</c> (since it's essentially redundant with CURL).
</li>
</ul>
</div>
</div><!-- END: 5.0.0.14 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.15' id='5.0.0.15'>5.0.0.15 (Mar 24, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.15 -->
<div class='topic'>
<p>
Juno 5.0.0.15 is a moderate update.
</p>
<ul class='spaced-list'>
<li>
Juno-Wink integration components that have been requested by many for a long time!<br>
Refer to <dc>org.apache.juneau.rest.jaxrs</dc> for information.
</li>
<li>
New <dc>@Produces</dc> annotation in place of <c>ISerializer.getMediaTypes()</c> for specifying what media types a serializer produces.<br>
Available when subclassing from <a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a>.
</li>
<li>
New <dc>@Consumes</dc> annotation in place of <c>IParser.getMediaTypes()</c> for specifying what media types a parser consumes.<br>
Available when subclassing from <a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a>.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.15 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.16' id='5.0.0.16'>5.0.0.16 (Mar 25, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.16 -->
<div class='topic'>
<p>
Juno 5.0.0.16 is a minor update.
</p>
<ul class='spaced-list'>
<li>
New <dc>@Properties</dc> REST method parameter annotation that can be used to get the runtime properties map through a parameter instead of through <a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a>.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.16 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.17' id='5.0.0.17'>5.0.0.17 (Mar 25, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.17 -->
<div class='topic'>
<p>
Juno 5.0.0.17 is a minor update.
</p>
<ul class='spaced-list'>
<li>
Charset now passed as a parameter to <c>IOutputStreamSerializer.serialize()</c> and <c>IInputStreamParser.parse()</c>.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.17 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.18' id='5.0.0.18'>5.0.0.18 (Mar 27, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.18 -->
<div class='topic'>
<p>
Juno 5.0.0.18 is a moderate update.
</p>
<p>
The biggest change is the introduction of the <a href="org/apache/juneau/jena/RdfSerializer.html" title="class in org.apache.juneau.jena"><code>RdfSerializer</code></a> class that uses Jena to generate RDF/XML, RDF/XML-ABBREV, N-Tuple, N3, and Turtle output.
</p>
<p>
This code should be considered prototype-quality, and subject to change in the future.<br>
There are plans of adding an equivalent <c>RdfParser</c> class in the future, so the serializer logic may need to be tweaked to allow POJOs to be reconstituted correctly in the parser.
</p>
<p>
The <c>RdfXmlSerializer</c> class should be considered deprecated for now.<br>
However, I'm keeping it around, since it's considerably faster and uses far less memory than the Jena-based serializer since it serializes directly from POJOs to RDF/XML.<br>
It may or may not be removed in the future depending on demand.
</p>
<h5 class='topic w800'>Other changes</h5>
<ul class='spaced-list'>
<li>
New <dc>org.apache.juneau.jso.JsoParser</dc> class.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.18 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.19' id='5.0.0.19'>5.0.0.19 (Apr 1, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.19 -->
<div class='topic'>
<p>
Juno 5.0.0.19 is a minor update.
</p>
<ul class='spaced-list'>
<li>
New methods on <dc>org.apache.juneau.rest.RestServlet</dc>:
<ul>
<li><dc>RestServlet.onPreCall(RestRequest)</dc></li>
<li><dc>RestServlet.onPostCall(RestRequest,RestResponse)</dc></li>
</ul>
</li>
<li>
<jsf>TRIM_NULLS</jsf> setting changed to <dc>SerializerContext.SERIALIZER_trimNullProperties</dc>.<br>
New property default is <jk>true</jk>.
Only applies to bean properties, not map or collection entries.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.19 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.20' id='5.0.0.20'>5.0.0.20 (Apr 7, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.20 -->
<div class='topic'>
<p>
Juno 5.0.0.20 is a major update.
</p>
<h5 class='topic w800'>Core API changes</h5>
<ul class='spaced-list'>
<li>
New Jena-based <a href="org/apache/juneau/jena/RdfSerializer.html" title="class in org.apache.juneau.jena"><code>RdfSerializer</code></a> for serializing POJOs to RDF/XML, RDF/XML-ABBREV, N-Triple, Turtle, and N3.<br>
Serializes ANY POJOs to RDF, even simple objects and primitives.
</li>
<li>
New Jena-based <a href="org/apache/juneau/jena/RdfParser.html" title="class in org.apache.juneau.jena"><code>RdfParser</code></a> for parsing RDF/XML, RDF/XML-ABBREV, N3, Turtle, and N-Triple back into POJOs.
</li>
<li>
<dc>XmlSerializerContext.XML_autoDetectNamespaces</dc> default changed to <jk>true</jk>.<br>
The old default value would cause XML with unmapped namespaces if you didn't manually specify them via the <dc>XmlSerializerContext.XML_namespaces</dc> annotation.<br>
While setting the default to <jk>true</jk> is somewhat slower (since the serializer must crawl the POJO tree to find namespaces), the benefits of having it work out-of-the-box outweighs the performance concerns.<br>
For developers concerned about performance, they can always change it back to false and specify the namespaces themselves.
</li>
</ul>
<h5 class='topic w800'>REST server API changes</h5>
<ul class='spaced-list'>
<li>
Allow inheritance of <dc>@RestResource</dc> annotation.<br>
Serializers, parsers, filters, properties , guards, and converters definitions are automatically inherited from parent classes and interfaces.
</li>
<li>
Enhancements to <dc>@RestMethod</dc> annotation:
<ul>
<li>
New <c>RestMethod.filters()</c> annotation for defining POJO filters at the method level.
</li>
<li>
New <dc>RestMethod.serializersInherit()</dc> and <dc>RestMethod.parsersInherit()</dc> annotations for controlling how serializers and parsers (and associated filters and properties) are inherited from the class.<br>
This replaces the previous <c>addSerializers</c> and <c>addParsers</c> annotations.
</ul>
</li>
<li>
New <dc>RestServletJenaDefault</dc> servlet that includes serialization/parsing support for all Jena-based serializers and parsers.
</li>
<li>
New <dc>DefaultJenaProvider</dc> JAX-RS provider that includes serialization/parsing support for all Jena-based serializers and parsers.
</li>
<li>
Eliminated <c>RestServletChild</c> class.<br>
It's redundant with the introduction of inheritable annotations.
</li>
<li>
New methods on <dc>org.apache.juneau.rest.RestServlet</dc>:
<ul>
<li><c>RestServlet.createConfigFactory()</c></li>
<li><c>RestServlet.createSerializers()</c></li>
<li><c>RestServlet.createParsers()</c></li>
</ul>
These augment the existing <c>getBeanContext()</c> / <c>getSerializers()</c> / <c>getParsers()</c> methods.
</li>
</ul>
<h5 class='topic w800'>REST client API changes</h5>
<ul class='spaced-list'>
<li>
New <c>RestCall.setDateHeader(String,Object)</c> method for setting ISO8601 datetime headers.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.20 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.21' id='5.0.0.21'>5.0.0.21 (Apr 9, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.21 -->
<div class='topic'>
<p>
Juno 5.0.0.21 is a minor update.
</p>
<h5 class='topic w800'>Core API changes</h5>
<ul class='spaced-list'>
<li>
New <dc>HtmlDocSerializerContext.HTMLDOC_navlinks</dc> annotation for addint links to HTML page views.
</li>
<li>
Renamed the properties in <dc>HtmlDocSerializerContext</dc> for clarity.
</li>
</ul>
<h5 class='topic w800'>Servlet API changes</h5>
<ul class='spaced-list'>
<li>
Added new <c>RestServlet.addDefaultProperties(ObjectMap,RestRequest)</c> method for programatically adding properties to the property map per request.
</li>
<li>
Added the following new properties in the properties map to make them easily available to serializers and parsers (since they don't have access to the HTTP request object).<br>
Note that the <c>SerializerContext.SERIALIZER_uriAuthority</c> and <c>SerializerContext.SERIALIZER_uriContext</c> properties were previously available.
<ul>
<li><c>RestServletProperties.REST_servletPath</c></li>
<li><c>RestServletProperties.REST_pathInfo</c></li>
<li><c>RestServletProperties.REST_method</c></li>
</ul>
</li>
<li>
Path variables annotated with <dc>@Attr</dc> are now automatically URL-decoded.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.21 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.22' id='5.0.0.22'>5.0.0.22 (Apr 12, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.22 -->
<div class='topic'>
<p>
Juno 5.0.0.22 is a minor update.
</p>
<h5 class='topic w800'>Core API changes</h5>
<ul class='spaced-list'>
<li>
New <c><ja>@Property</ja>.nls()</c> annotation for specifying localized property values.<br>
For example, allows you to set the <jsf>HTMLDOC_title</jsf> and <jsf>HTMLDOC_description</jsf> properties to localized values pulled from a resource bundle.<br>
See the <c>AddressBookResource</c> class for an example.
</li>
</ul>
<h5 class='topic w800'>REST Servlet API changes</h5>
<ul class='spaced-list'>
<li>Fix a bug where the <c>&amp;Content</c> query parameter was not always parsed correctly.</li>
</ul>
</div>
</div><!-- END: 5.0.0.22 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.23' id='5.0.0.23'>5.0.0.23 (Apr 14, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.23 -->
<div class='topic'>
<p>
Juno 5.0.0.23 is a minor update.
</p>
<ul class='spaced-list'>
<li>
Simplified <dc>Cognos</dc> support.
</li>
<li>
Fixed bug where <c><ja>@Xml</ja></c> annotation was not being inherited by inner classes.
</li>
<li>
Javadoc stylesheet improvements.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.23 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.24' id='5.0.0.24'>5.0.0.24 (May 9, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.24 -->
<div class='topic'>
<p>
Juno 5.0.0.24 is a major update.
</p>
<h5 class='topic w800'>Core API updates</h5>
<ul class='spaced-list'>
<li>
New support for <a href="org/apache/juneau/dto/atom/package-summary.html"><code>ATOM</code></a>.
<ul>
<li>New <c>AtomFeedResource</c> class added to sample war.
</ul>
</li>
<li>
New <dc>XmlFormat.CONTENT</dc> enum value.<br>
Allows bean properties to be persisted as XML element text.
</li>
<li>
New <dc>XmlContentHandler</dc> class and <dc>@Xml.contentHandler</dc> annotation.<br>
Allows customized serialization and parsing of beans to XML element text.<br>
Added for support of ATOM text content that must support both plain text and embedded XHTML.
</li>
<li>
New <a href="org/apache/juneau/xml/annotation/XmlSchema.html" title="annotation in org.apache.juneau.xml.annotation"><code>@XmlSchema</code></a> and updated <a href="org/apache/juneau/xml/annotation/XmlNs.html" title="annotation in org.apache.juneau.xml.annotation"><code>@XmlNs</code></a> annotations to better mimic JAXB.
</li>
<li>
Removed <c><ja>@Xml</ja>.valAttr</c> annotation since it's now redundant with <c><ja>@Xml</ja>(format=<jsf>CONTENT</jsf>)</c>.
</li>
<li>
Fixed timezone bug in <dc>org.apache.juneau.transforms.CalendarSwap</dc>.
</li>
<li>
Simplified <c>Serializer.serialize(Object,Object,SerializerContext)</c> method.
</li>
<li>
Fixed bug where lists returned by <dc>ObjectMap.getObjectList(String)</dc> were not updatable.
</li>
<li>
Eliminated old RDF/XML serializer.
</li>
</ul>
<h5 class='topic w800'>Documentation updates</h5>
<ul>
<li>New <a href="org/apache/juneau/json/package-summary.html"><code>JSON Support Overview</code></a> document.</li>
<li>New <a href="org/apache/juneau/xml/package-summary.html"><code>XML Support Overview</code></a> document.</li>
<li>New <a href="org/apache/juneau/jena/package-summary.html"><code>RDF Languages Support Overview</code></a> document.</li>
<li>New <a href="org/apache/juneau/dto/atom/package-summary.html"><code>ATOM Support Overview</code></a> document.</li>
</ul>
</div>
</div><!-- END: 5.0.0.24 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.25' id='5.0.0.25'>5.0.0.25 (May 11, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.25 -->
<div class='topic'>
<p>
Juno 5.0.0.25 is a minor update.
</p>
<h5 class='topic w800'>Core API updates</h5>
<ul class='spaced-list'>
<li>
New <a href="org/apache/juneau/dto/ResultSetList.html" title="class in org.apache.juneau.dto"><code>ResultSetList</code></a> DTO for serializing SQL result sets to JSON/XML/HTML and so forth.
</li>
<li>
New <c>SqlQueryResource</c> class in the sample war for demonstrating the <c>ResultSetList</c> DTO.
</li>
</ul>
<h5 class='topic w800'>Server API updates</h5>
<ul class='spaced-list'>
<li>
Fixed issue with media type for CSS files being reported as <js>"text/plain"</js> instead of <js>"text/css"</js>.
</li>
<li>
Moved initialization of class properties to before the call to <c>Servlet.init()</c> so that <c>getProperties()</c> can be called during servlet initialization.
</li>
<li>
New <c><ja>@Property</ja>.type</c> annotation with support for using system properties as resource properties.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.25 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.26' id='5.0.0.26'>5.0.0.26 (Jun 5, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.26 -->
<div class='topic'>
<p>
Juno 5.0.0.26 is a minor update.
</p>
<ul class='spaced-list'>
<li>
FindBug fixes.
</li>
<li>
Changed the way child REST resources are defined.<br>
Eliminated the <ja>@RestChild</ja> annotation on getter methods and replaced it with <dc>@RestResource(children)</dc> defined on the resource class itself.<br>
Child resource paths are specified through <dc>@RestResource(path)</dc>.
</li>
<li>
New <dc>ChildResourceDescriptions</dc> bean for automatically generating the contents of router resource pages.
</li>
<li>
Changed <c><ja>@RestMethod</ja>.pattern()</c> to <dc>@RestMethod(path)</dc> for naming consistency.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.26 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.27' id='5.0.0.27'>5.0.0.27 (July 7, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.27 -->
<div class='topic'>
<p>
Juno 5.0.0.27 is a moderate update.
</p>
<ul class='spaced-list'>
<li>
Fixed some HTML formatting issues in <a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a>.
</li>
<li>
<dc>org.apache.juneau.rest.BasicRestServlet</dc> now includes <a href="org/apache/juneau/plaintext/PlainTextSerializer.html" title="class in org.apache.juneau.plaintext"><code>PlainTextSerializer</code></a> and <a href="org/apache/juneau/plaintext/PlainTextParser.html" title="class in org.apache.juneau.plaintext"><code>PlainTextParser</code></a> for plain-text support.
</li>
<li>
Child resources now render on default <c>OPTIONS</c> pages through new method <dc>ResourceOptions.getChildren()</dc>.
</li>
<li>
Changes to <a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a>/<a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a> to reduce the need for quoted string values.<br>
More changes are likely in this area of the code to support multipart form posts.
</li>
<li>
FindBugs fixes.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.27 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.28' id='5.0.0.28'>5.0.0.28 (July 9, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.28 -->
<div class='topic'>
<p>
Juno 5.0.0.28 is a moderate update.
</p>
<ul class='spaced-list'>
<li>
Fixes an <c>OutOfMemoryError</c> and performance issue caused by incorrect caching of class metadata.
</li>
<li>
Added <c>WriterSerializer.serialize(Object,Writer)</c> convenience method for serializing directly to a writer.<br>
Applies to all serializers.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.28 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.29' id='5.0.0.29'>5.0.0.29 (Aug 2, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.29 -->
<div class='topic'>
<p>
Juno 5.0.0.29 is a moderate update.
</p>
<ul class='spaced-list'>
<li>
Revamped the API for filter support:
<ul>
<li>Updated <dc>org.apache.juneau.transform.BeanFilter</dc> class to mirror the <a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a> annotation.</li>
<li>Introduced support for bean <dc>subtypes</dc>. </li>
<li>Replaced <c><ja>@Bean</ja>(filter=xxx)</c> with new <dc>@Transform</dc> annotation.</li>
</ul>
</li>
<li>
Revamped URL-Encoding support.<br>
The old URL-Encoding serializer and parser simply used the JSON serializer/parser with a thin URL-encoding top layer.<br>
The new URL-Encoding serialize and parser was written from scratch and is considerably more consistent in design and output.
</li>
<li>
Improved number parsing.<br>
The new number parser should handle any valid numeric syntax for decimals and floats that Java itself supports.
</li>
<li>
<a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a> LAX mode now quotes reserved word attributes.
</li>
<li>
New predefined DateFilters with millisecond precision:
<ul>
<li><c>org.apache.juneau.swaps.DateSwap.ISO8601DTP</c></li>
<li><c>org.apache.juneau.swaps.DateSwap.ISO8601DTZP</c></li>
</ul>
</li>
</ul>
</div>
</div><!-- END: 5.0.0.29 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.30' id='5.0.0.30'>5.0.0.30 (Aug 8, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.30 -->
<div class='topic'>
<p>
Juno 5.0.0.30 is a minor update.
</p>
<ul class='spaced-list'>
<li>
Fixed bug involving beans using <dc>Bean.subTypes()</dc> annotation in addition to <c>subTypes</c> property.
</li>
<li>
Modified the JSON parser to handle non-existent JSON values to get around an issue where Cognos was generating invalid JSON.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.30 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.31' id='5.0.0.31'>5.0.0.31 (Aug 9, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.31 -->
<div class='topic'>
<p>
Juno 5.0.0.31 is a moderate update.
</p>
<ul class='spaced-list'>
<li>
Simplified the <a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a> and <a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a> class hierarchies.<br>
This reverses a previous change that added a bunch of interfaces in these APIs (and subsequently required compiling with Java 7 to get around a compiler bug).<br>
The new class hierarchy is much simpler to understand.
</li>
<li>
Added <dc>org.apache.juneau.transforms.XMLGregorianCalendarSwap</dc> to convert these to ISO8601 strings during serialization, and vice versa during parsing.
</li>
<li>
Added a strict mode to <a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a>.
</li>
<li>
Added default <a href="org/apache/juneau/json/JsonParser.html#DEFAULT_STRICT"><code>JsonParser.DEFAULT_STRICT</code></a> parser.
</li>
</ul>
</div>
</div><!-- END: 5.0.0.31 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.32' id='5.0.0.32'>5.0.0.32 (Oct 5, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.32 -->
<div class='topic'>
<p>
Juno 5.0.0.32 is a moderate update.
</p>
<ul class='spaced-list'>
<li>
New support for generating and consuming fully-compliant JSON-Schema documents.<br>
See <dc>org.apache.juneau.dto.jsonschema</dc> for information.
</li>
<li>
New methods added to <a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a>:
<ul>
<li><c>org.apache.juneau.parser.Parser.parseMap(Object,int,Class,Class,Class)</c></li>
<li><c>org.apache.juneau.parser.Parser.parseCollection(Object,int,Class,Class)</c></li>
</ul>
</li>
<li>
<a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a> annotation can now be defined on interfaces and inherited by subclasses.
</li>
<li>
Support for customizing serialized values for <c>Enums</c> through overriding <c>toString()</c> and <c>fromString()</c> on the enum class.<br>
Previously used <c>Enum.valueOf()</c> to convert strings back into <c>Enums</c>.<br>
Used for JSON-Schema support to allow <a href="org/apache/juneau/dto/jsonschema/JsonType.html" title="enum in org.apache.juneau.dto.jsonschema"><code>JsonType</code></a> enum to be serialized to lowercase per the specification (e.g. <js>"string"</js> instead of <js>"STRING"</js>).
</li>
<li>
<dc>Cognos</dc> DTOs now have fluent-style bean setters.
</li>
<li>
Support for generic bean objects whose type was erased at compile time.<br>
Previous behavior gave you an error message that the type could not be determined.<br>
New behavior assumes a type of <c>Object</c> when the type is erased.
</li>
<li>
Bug fixes:
<ul>
<li>
When duplicate fluent-style setters were defined with different parameter types (e.g. <c>setFoo(Foo f)</c>, <c>setFoo(Bar b)</c>), the <a href="org/apache/juneau/BeanMap.html" title="class in org.apache.juneau"><code>BeanMap</code></a> API would sometime choose the wrong setter as the bean property setter. <br>
Now validates that the setter being chosen is the one whose return type matches the property getter.
</li>
<li>
Passing in <c>Accept</c> GET parameters with <js>'+'</js> (e.g. <c>&amp;Accept=text/json+simple</c>) wasn't working anymore.<br>
The <c>Accept</c> parameter is supposed to interpret spaces as <js>'+'</js> to allow you to not have to write <c>&amp;Accept=text/json%2Bsimple</c>.
</li>
<li>
Parsers would not set bean properties of abstract type <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Number.html?is-external=true" title="class or interface in java.lang"><code>Number</code></a>.<br>
Now it detects the numeric type based on input and sets the value accordingly.
</li>
</ul>
</li>
</ul>
</div>
</div><!-- END: 5.0.0.32 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.33' id='5.0.0.33'>5.0.0.33 (Oct 20, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.33 -->
<div class='topic'>
<p>
Juno 5.0.0.33 is a moderate update.
</p>
<ul class='spaced-list'>
<li>
Removed generic parameter from <a href="org/apache/juneau/serializer/WriterSerializer.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer</code></a> class.
<ul>
<li>
Many of the examples in the documentation were written as follows, which resulted in "unchecked" compile warnings:<br>
<c>WriterSerializer s = <jk>new</jk> JsonSerializer();</c><br>
These compile warnings will now go away.
</li>
</ul>
</li>
<li>
New settings in BeanContext. These can be applied to all serializers/parsers.
<ul>
<li><dc>BEAN_ignoreInvocationExceptionsOnGetters</dc>
<li><dc>BEAN_ignoreInvocationExceptionsOnSetters</dc>
<li><dc>BEAN_notBeanPackages_add</dc>
<li><dc>BEAN_notBeanPackages_remove</dc>
</ul>
</li>
<li>
Eliminated <c>addNotBeanClassPatterns(String...)</c> methods throughout API since these are now controlled by <dc>BEAN_notBeanPackages_add</dc> / <dc>BEAN_notBeanPackages_remove</dc> properties.
</li>
<li>
New settings in <c>RestServletProperties</c>.
<ul>
<li><c>RestServletProperties.REST_trimTrailingUriSlashes</c><br>
Also removed <c>RestRequest.getRequestURI(boolean trimTrailingSlashes)</c> method which is now redundant with this property.
<li><c>RestServletProperties.REST_pathInfoBlankForNull</c><br>
Also removed <c>RestRequest.getPathInfo(boolean returnBlankForNull)</c> method which is now redundant with this property.
</ul>
</li>
<li>
New JSON-Schema <a href="org/apache/juneau/dto/jsonschema/JsonSchemaMap.html" title="class in org.apache.juneau.dto.jsonschema"><code>JsonSchemaMap</code></a> class for supporting linked schemas.
</li>
<li>
Serializers will no longer throw an exception when <c>maxDepth</c> setting is reached, and will instead simply ignore content below the specified depth.<br>
While the old behavior was as-designed, the new behavior is more in-line with expected behavior.
</li>
<li>
Added support for HTTP header <js>"X-Response-Headers"</js> to <dc>org.apache.juneau.rest.RestServlet</dc>. <br>
Allows you to specify one or more headers that should be returned on the response from the servlet.<br>
For example, to get a page to automatically refresh every 1 second, you can append the following to a URL: <c>?x-response-headers={Refresh=1}</c>
</li>
<li>
Removed <c>HtmlDocSerializerContext.<jsf>HTML_REFRESH</jsf></c> setting that added a Refresh meta tag to HTML documents, since this can now be controlled through <c>X-Response-Headers</c>.
</li>
<li>
Small improvements to samples.
<ul>
<li><c>PhotosResource</c> now includes a default entry.
</ul>
</li>
</ul>
</div>
</div><!-- END: 5.0.0.33 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.34' id='5.0.0.34'>5.0.0.34 (Nov 10, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.34 -->
<div class='topic'>
<p>
Juno 5.0.0.34 is a moderate update.
</p>
<ul class='spaced-list'>
<li>
New support for runtime-replaced variables in REST resource properties:
<p class='bcode'>
<ja>@RestResource</ja>(
messages=<js>"nls/Messages"</js>,
properties={
<ja>@Property</ja>(name=<js>"label"</js>,value=<js>"$L{servletTitle}"</js>), <jc>// Localized variable in Messages.properties</jc>
<ja>@Property</ja>(name=<js>"javaVendor"</js>,value=<js>"$S{java.vendor}"</js>), <jc>// System property</jc>
<ja>@Property</ja>(name=<js>"foo"</js>,value=<js>"bar"</js>),
<ja>@Property</ja>(name=<js>"bar"</js>,value=<js>"baz"</js>),
<ja>@Property</ja>(name=<js>"v1"</js>,value=<js>"$R{foo}"</js>), <jc>// Request variable. value="bar"</jc>
<ja>@Property</ja>(name=<js>"v2"</js>,value=<js>"$R{$R{foo}}"</js>) <jc>// Nested request variable. value="baz"</jc>
}
)
</p>
See <c>RestServlet.createRequestVarResolver(RestRequest)</c> for more information.
</li>
<li>
Eliminated <ja>@Property.type</ja> annotation which was the old way of specifying NLS variables that got resolved at runtime.
</li>
<li>
New methods on <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>:
<ul>
<li><dc>RestRequest.getVarResolver()</dc></li>
<li><dc>RestRequest.getServletURI()</dc></li>
<li><dc>RestRequest.getRequestParentURI()</dc></li>
</ul>
</li>
<li>
New methods on <a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a>:
<ul>
<li><c>RestResponse.sendRedirect(CharSequence)</c>
</ul>
</li>
<li>
New methods on <dc>org.apache.juneau.rest.RestServlet</dc> that allow easier customization by subclasses:
<ul>
<li><dc>RestServlet.createConfigFactory()</dc></li>
<li><dc>RestServlet.createConverters()</dc></li>
<li><dc>RestServlet.createDefaultRequestHeaders()</dc></li>
<li><dc>RestServlet.createDefaultResponseHeaders()</dc></li>
<li><dc>RestServlet.createEncoders()</dc></li>
<li><dc>RestServlet.createFilters()</dc></li>
<li><dc>RestServlet.createGuards()</dc></li>
<li><dc>RestServlet.createMimetypesFileTypeMap()</dc></li>
<li><dc>RestServlet.createParsers()</dc></li>
<li><dc>RestServlet.createProperties()</dc></li>
<li><dc>RestServlet.createRequestProperties(ObjectMap,RestRequest)</dc></li>
<li><dc>RestServlet.createRequestVarResolver(RestRequest)</dc></li>
<li><dc>RestServlet.createSerializers()</dc></li>
<li><dc>RestServlet.createUrlEncodingParser()</dc></li>
</ul>
</li>
<li>
Changed <c>RestServletNls</c> to use <c>ResourceDescription/MethodDescription</c>
instead of <c>RestResource/RestMethod</c>
</li>
<li>
New property <c>RestServletProperties.REST_htDocsFolder</c>.<br>
New support for serving up static documents from classpath through REST interface.
</li>
<li>
Exception APIs now use <a href="https://docs.oracle.com/javase/8/docs/api/java/text/MessageFormat.html?is-external=true" title="class or interface in java.text"><code>MessageFormat</code></a> (e.g. <js>"{0}"</js>) for message variables instead of <js>"%s"</js>.
</li>
<li>
New <a href="org/apache/juneau/annotation/Bean.html#stopClass--"><code>@Bean.stopClass</code></a> annotation for specifying stop classes for bean properties.
</li>
<li>
New <dc>BeanFilter.setStopClass(Class)</dc> which is the program equivalent to the annotation above.
</li>
<li>
New methods on <a href="org/apache/juneau/dto/ResultSetList.html" title="class in org.apache.juneau.dto"><code>ResultSetList</code></a>:
<ul>
<li><c>ResultSetList.handleBlob(Blob)</c></li>
<li><c>ResultSetList.handleClob(Clob)</c></li>
</ul>
</ul>
</div>
</div><!-- END: 5.0.0.34 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.35' id='5.0.0.35'>5.0.0.35 (Nov 26, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.35 -->
<div class='topic'>
<p>
Juno 5.0.0.35 is a minor update.
</p>
<ul class='spaced-list'>
<li><dc>RestGuard.guard(RestRequest,RestResponse)</dc> now returns a boolean to allow redirects to login pages.
<li>Fixed bug in RestServlet where occasional false positive "duplicate method with same name and path" errors were occurring.
</ul>
</div>
</div><!-- END: 5.0.0.35 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.0.0.36' id='5.0.0.36'>5.0.0.36 (Dec 18, 2013)</a></h3>
<div class='topic'><!-- START: 5.0.0.36 -->
<div class='topic'>
<p>
Juno 5.0.0.36 is a minor update.
</p>
<ul class='spaced-list'>
<li>Implemented <c>org.apache.juneau.urlencoding.UrlEncodingParser.parseArgs(Reader,int,ClassMeta[])</c>.
<li><c>name</c> parameter of <dc>ResourceDescription.ResourceDescription(String,String,String)</dc>.
is now automatically URL-encoded so that the name can contain special characters (e.g. <js>"foo/bar(baz)"</js>).
<li>Support for URL-matching and path info containing encoded characters (e.g. <js>'/'</js>) now supported.
<li>Removed some lazy-initialization of bean information in <a href="org/apache/juneau/ClassMeta.html" title="class in org.apache.juneau"><code>ClassMeta</code></a> that allowed the removal of
some synchronized blocks.
<li>Improved support of <dc>BeanContext.getClassMetaFromString(String)</dc>.
Now supports primitive arrays such as <js>"long[]"</js> in addition to the previous support for the equivalent <js>"[J"</js>.
<li>Various new convenience methods added to <a href="org/apache/juneau/internal/StringUtils.html" title="class in org.apache.juneau.internal"><code>StringUtils</code></a> and <a href="org/apache/juneau/internal/ClassUtils.html" title="class in org.apache.juneau.internal"><code>ClassUtils</code></a>.
</ul>
</div>
</div><!-- END: 5.0.0.36 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.0' id='5.1.0.0'>5.1.0.0 (Jan 18, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.0 -->
<div class='topic'>
<p>
Juno 5.1.0.0 is a major update.
</p>
<h5 class='topic w800'>Major changes</h5>
<ul class='spaced-list'>
<li>Brand new REST client API that uses Apache HttpClient for HTTP communication.<br>
The new client API is simply a thin layer on top of <c>HttpClient</c> that performs
serialization and parsing using Juno parsers but leaves all the details of the HTTP connection
to the Apache code. <br>
See the <dc>org.apache.juneau.rest.client</dc> package for details.
<li>New <c>org.apache.juneau.rest.client.jazz</c> package and <c>org.apache.juneau.rest.client.jazz.JazzRestClient</c> class
for performing REST operations against Jazz servers.<br>
Includes improved support for FORM authentication, and better SSL certificate validation.
<li>Completely redesigned URL-Encoding support.<br>
See <dc>org.apache.juneau.urlencoding</dc> package for details.
<li>Changes to Parser API.
<ul>
<li>Removal of <c>ExtendedReaderParser</c> abstract class and moved methods into
<a href="org/apache/juneau/parser/ReaderParser.html" title="class in org.apache.juneau.parser"><code>ReaderParser</code></a> class.
<li>Removal of <c>DataFormat</c> class from API since it was no longer necessary
due to API change above.
<li>Removal of <c>ParserStringReader</c> class.<br>
This was a reader optimized to work with <c>String</c> input.<br>
However, it could interfere with garbage collection of the original string object.<br>
Instead, the existing <a href="org/apache/juneau/parser/ParserReader.html" title="class in org.apache.juneau.parser"><code>ParserReader</code></a> was enhanced to work
well with <c>String</c> input, and tests show no significant performance differences.
<li>New <c>org.apache.juneau.parser.Parser.parse(Object,int,ClassMeta)</c> convenience method added.
</ul>
</ul>
<h5 class='topic w800'>Other changes</h5>
<ul class='spaced-list'>
<li>Various new methods added to <a href="org/apache/juneau/internal/StringUtils.html" title="class in org.apache.juneau.internal"><code>StringUtils</code></a> and <a href="org/apache/juneau/internal/ClassUtils.html" title="class in org.apache.juneau.internal"><code>ClassUtils</code></a>.
<li>Improved support on <dc>BeanContext.getClassMetaFromString(String)</dc>.<br>
Now supports resolving <c>"long[]"</c>, and so forth.
<li><dc>ResourceDescription</dc> name parameter is now automatically URL-encoded in links.
<li><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> now correctly handles cases involving URL-encoded characters in the
path info portion of URLs (e.g. <c>http://host/contextRoot/foo%2Fbar</c>).
<li>Removed lazy-initialization that required locking in <a href="org/apache/juneau/ClassMeta.html" title="class in org.apache.juneau"><code>ClassMeta</code></a>.
<li>New <c>BeanContext.setDefaultParser(ReaderParser)</c> method added for specifying
a default parser to use in a bean context (used when converting beans to <c>Strings</c> using
<dc>BeanContext.convertToType(Object,Class)</dc>.
Old behavior simply used the default JSON serializer in these cases.
<li>More consistent handling of exceptions across all parsers.
<li>Minor changes to <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> class.
<ul>
<li>Changed the order of parameters on <dc>RestRequest.getParameter(String,Class)</dc>.
<li>Added <c>RestRequest.getMapParameter(String,Class,Class,Class)</c> and
<c>RestRequest.getCollectionParameter(String,Class,Class)}</c> methods.
</ul>
</ul>
</div>
</div><!-- END: 5.1.0.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.1' id='5.1.0.1'>5.1.0.1 (Jan 25, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.1 -->
<div class='topic'>
<p>
Juno 5.1.0.1 is a minor update.
</p>
<ul class='spaced-list'>
<li>Addressed some behavioral differences between Tomcat and WAS.
<ul>
<li>Query parameter lookup is now always case-insensitive (per WAS behavior).
<li>Consistent handling of redirect requests (Tomcat and WAS handle relative redirect paths differently).
</ul>
<li>Fixed bug involving incorrect resolution of overlapping URL match patterns.
<li>Overall improvements in HTTP request parameter and header value resolution.
<li>Made workspace changes so as not to be dependent on the WAS test environment being loaded.
<li>Renamed <ja>@Remainder</ja> annotation to <dc>@PathRemainder</dc>.
<li>Fixed bug involving incorrect calculation of <c>pathInfo</c> on child resources.
</ul>
</div>
</div><!-- END: 5.1.0.1 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.2' id='5.1.0.2'>5.1.0.2 (Apr 27, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.2 -->
<div class='topic'>
<p>
Juno 5.1.0.2 is a minor update.
</p>
<ul class='spaced-list'>
<li>Fixed issue preventing <c>&amp;Accept-Language</c> from being used as a GET parameter.
<li>Minor XSS vulnerability fix.
<li>Empty results on HTML pages now shows <js>"no results"</js> instead of a blank page.
<li>Fixed issues preventing REST pages from rendering HTML in newer versions of Internet Explorer.
<li>Changed <c>RestServletProperties.REST_allowMethodParam</c> to be disabled by default.
</ul>
</div>
</div><!-- END: 5.1.0.2 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.3' id='5.1.0.3'>5.1.0.3 (Jun 28, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.3 -->
<div class='topic'>
<p>
Juno 5.1.0.3 is a moderate update.
</p>
<h5 class='topic w800'>Core API updates</h5>
<ul class='spaced-list'>
<li>Ability to detect and use non-public bean classes, getters/setters, and fields using the following new properties:
<ul>
<li><dc>BeanContext.BEAN_beanConstructorVisibility</dc> - Control which bean constructors are visible to Juno.
<li><dc>BeanContext.BEAN_beanClassVisibility</dc> - Control which bean classes are interpreted as beans to Juno.
<li><dc>BeanContext.BEAN_beanFieldVisibility</dc> - Control which fields are visible to Juno as bean properties.
<li><dc>BeanContext.BEAN_beanMethodVisibility</dc> - Control which getters/setters are visible to Juno as bean properties.
</ul>
Removed <c>BeanContext.<jsf>INCLUDE_BEAN_FIELD_PROPERTIES</jsf></c> and <c>BeanContext.<jsf>INCLUDE_BEAN_METHOD_PROPERTIES</jsf></c> properties, since ignoring fields and methods
can be accomplished by setting the appropriate properties above to <a href="org/apache/juneau/Visibility.html#NONE"><code>NONE</code></a>.
Also, the <dc>@BeanProperty</dc> annotation can now be used on non-public fields/getters/setters to override
the default behavior defined by the <c>VISIBILITY</c> properties identified above. This is a convenient way of identifying protected or
private fields or methods as bean properties. Previously, you could only identify public fields/getters/setters using this annotation.
</li>
<li>New <dc>BeanContext.BEAN_useJavaBeanIntrospector</dc> property that lets Juno use the Java bean <c>Introspector</c>
class to determine bean properties. In the previous release, the method for determining bean properties was a mixture of Juno-based and Introspector-based.
Now it's either pure Juno-based or pure Introspector-based. The result is considerably cleaner code and consistent behavior.
<li>New <a href="org/apache/juneau/annotation/BeanIgnore.html" title="annotation in org.apache.juneau.annotation"><code>@BeanIgnore</code></a> annotation. Replaces the previous <dc>@BeanProperty(hidden=true)</dc> annotation
for ignoring bean properties. Can also be used on classes that look like beans so that they're not treated as beans.
<li>Support for parsing into non-static member classes. This applies to all parsers.
<li>New <a href="org/apache/juneau/json/annotation/Json.html#wrapperAttr--"><code>@Json(wrapperAttr)</code></a> annotation that automatically wraps beans and objects in a wrapper
attribute when serializing to or parsing from JSON.
<li>Changed the default ordering of bean properties to be in parent-to-child class order.
<li>New <dc>readProperty()</dc> and <dc>writeProperty()</dc>
methods added to <dc>org.apache.juneau.transform.BeanFilter</dc> class to allow individualized serialization and parsing behavior on a class-by-class basis.
<li>Eliminated previous restriction where bean subtype attributes had to be listed first in JSON objects when using the <dc>Bean.subTypeProperty()</dc> annotation.
The previous behavior was not strictly JSON-compliant since JSON objects are supposed to consist of unordered lists of key/value pairs.
While targeted for JSON, the restriction is also lifted for all other parsers.
<li>New fluent-style <a href="org/apache/juneau/BeanMap.html#load-java.lang.String-"><code>BeanMap.load()</code></a> methods for initializing bean maps.
<li><a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a> will now embed the data portion of the output in a <c><xt>&lt;div</xt> <xa>id</xa>=<xs>'data'</xs><xt>&gt;</xt></c> element to make it easier to extract the data portion of the page in Javascript in browsers.
</ul>
<h5 class='topic w800'>REST Server API updates</h5>
<ul class='spaced-list'>
<li>New <dc>RestRequest.getJavaMethod()</dc> method for getting access to the method used to handle a request.
Useful for accessing the method name or annotations during requests, such as in calls to <dc>RestGuard.guard(RestRequest,RestResponse)</dc>.
<li>Fixed bug when using Jetty where you tried to read text input after a header was written.
<li>Added new string variables <dc>$A{...}</dc> (request attributes) and <dc>$P{...}</dc> (request parameters) to <c>RestServlet.createRequestVarResolver(RestRequest)</c>.
</ul>
</div>
</div><!-- END: 5.1.0.3 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.4' id='5.1.0.4'>5.1.0.4 (Aug 25, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.4 -->
<div class='topic'>
<p>
Juno 5.1.0.4 is a minor update.
</p>
<ul class='spaced-list'>
<li>New <dc>RestServlet.getPath()</dc> method.
<li>New <c>SerializerContext.getJavaMethod()</c> and <c>ParserContext.getJavaMethod()</c>
to allow access to REST methods that invoked the serializers or parsers.
For example, can be used to access additional annotations on REST methods to perform special handing
during serialization or parsing.
<li>Better behavior on overriding of filters in <c>BeanContext.addTransforms(Class[])</c>.
Previously, adding multiple conflicting filters resulted in random behavior.
Now filters are overridden when multiple matching filters are applied.
<li>Allow <dc>HtmlDocSerializerContext</dc> properties to be set via <dc>Serializer.setProperty(String,Object)</dc>.
Previously, these could only be defined through override properties (e.g. through REST class and method annotations).
<li>Fixed memory leak in XML parser.
</ul>
</div>
</div><!-- END: 5.1.0.4 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.5' id='5.1.0.5'>5.1.0.5 (Sept 1, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.5 -->
<div class='topic'>
<p>
Juno 5.1.0.5 is a moderate update.
</p>
<ul class='spaced-list'>
<li>New <dc>Redirect</dc> class that simplifies performing redirections in REST methods.
<li>New pluggable <code>org.apache.juneau.rest.ResponseHandler</code> class and <dc>@RestResource(responseHandlers)</dc> annotation
for defining customer response handlers for special kinds of POJOs.
<li>New method <dc>UrlEncodingSerializer.serializeUrlPart(Object)</dc> method.
<li>New method <dc>RestRequest.getServletURIBuilder()</dc> for construcing servlet-based URLs more efficiently.
<li>New method <a href="org/apache/juneau/rest/RestResponse.html#getNegotiatedOutputStream--"><code>RestResponse.getNegotiatedOutputStream()</code></a> that uses encoders if a match is found,
and <a href="org/apache/juneau/rest/RestResponse.html#getOutputStream--"><code>RestResponse.getOutputStream()</code></a> that just return the underlying output stream without any modifications.
<li>Fixed bug where some properties were not being propagated correctly when using <dc>CoreObject.setProperties(ObjectMap)</dc>
on serializer and parser subclasses.
<li>Fixed bug in <a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a> where URL keys in Maps were not being serialized as hyperlinks.
<li>Fixed bug in <a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a> where <js>"_class"</js> and <js>"items"</js> attributes were not quoted in strict mode when using SERIALIZER_addClassAttrs feature.
<li>Fixed bug where <c>Content-Encoding</c> and<c>Character-Encoding</c> headers were being set when calling <a href="org/apache/juneau/rest/RestResponse.html#getOutputStream--"><code>RestResponse.getOutputStream()</code></a>.
These should not be set if interacting with the output streams at a low level.
<li>Eliminated various convenience <c>RestResponse.sendRedirect(...)</c> methods due to the introduction of the <dc>Redirect</dc> class.
</ul>
</div>
</div><!-- END: 5.1.0.5 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.6' id='5.1.0.6'>5.1.0.6 (Sept 21, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.6 -->
<div class='topic'>
<p>
Juno 5.1.0.6 is a moderate update.
</p>
<ul class='spaced-list'>
<li>Simplified API for <dc>org.apache.juneau.transform.PojoSwap</dc>.
Since it's rarely used, the <c>beanContext</c> parameter was replaced with a <dc>PojoSwap.getBeanContext()</dc> method on
the class.
<li>New simplified way of defining POJO filters without needing to extend <dc>org.apache.juneau.transform.PojoSwap</dc>.
See <dc>org.apache.juneau.transform.SurrogateSwap</dc> for details.
<li>New <a href="org/apache/juneau/html/annotation/Html.html" title="annotation in org.apache.juneau.html.annotation"><code>@Html</code></a> annotation.
Will allow the definition of standard XHTML DTOs in future releases.
For now, <dc>Img</dc> is an example of defining an XHTML element using Juno DTOs.
<li><a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a> now ignores trailing <c>';'</c> characters in input so that it can
parse strings of the form <js>"var x = {'foo':'bar'};"</js>.
<li>New <c>TumblrParserResource</c> in the samples war file showing how to combine the REST client and server APIs into a single
resource in order to download Tumblr blogs and convert the response into any supported response content type.
</ul>
</div>
</div><!-- END: 5.1.0.6 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.7' id='5.1.0.7'>5.1.0.7 (Oct 5, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.7 -->
<div class='topic'>
<p>
Juno 5.1.0.7 is a moderate update.
</p>
<ul class='spaced-list'>
<li>Improved error handling.
<li>New <dc>ParserContext.PARSER_debug</dc> and <dc>SerializerContext.SERIALIZER_debug</dc>.
settings for logging additional information for debugging problems.
<li>New <dc>SERIALIZER_ignoreRecursions</dc> setting for explicitly ignoring recursions when
serializing models. Previously, the <jsf>SERIALIZER_detectRecursions</jsf> setting did this but now it simply looks for recursions
and throws exceptions when they occur.
<li>Improved handling of <c>StackOverflowErrors</c>. When <jsf>SERIALIZER_detectRecursions</jsf> is enabled, a useful error message
is displayed showing the exact chain of objects that resulted in the stack overflow.
<li>Bug fixes in <a href="org/apache/juneau/dto/ResultSetList.html" title="class in org.apache.juneau.dto"><code>ResultSetList</code></a> for Oracle and SQL Server.
<li>Serializers and parsers can now access HTTP request attributes, parameters, and headers through <c>SerializerContext.getProperties()</c> and
<c>ParserContext.getProperties()</c>.
<li>Removed media-type and encoding attributes from <dc>SerializerContext</dc> and <dc>ParserContext</dc>
since these are now available through context properties, and are typically not used.
<li><a href="org/apache/juneau/xml/XmlParser.html" title="class in org.apache.juneau.xml"><code>XmlParser</code></a> now accepts <c>application/xml</c>.
<li>Improved handling of bean property serialization when multiple matching pojo filters for the bean property class exist.
<li>Improved concurrency on BeanContext class.
<li>Fixed bug in <dc>org.apache.juneau.rest.converters.Traversable</dc> that was causing it to be executed even if the servlet extra path info was empty.
<li>Fixed bug in <dc>org.apache.juneau.rest.converters.Traversable</dc> where it was not picking up filters and properties defined on REST Java methods.
</ul>
</div>
</div><!-- END: 5.1.0.7 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.8' id='5.1.0.8'>5.1.0.8 (Oct 25, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.8 -->
<div class='topic'>
<p>
Juno 5.1.0.8 is a moderate update, focused primarily on performance improvements.
</p>
<ul class='spaced-list'>
<li>Improved performance on JSON and URL-Encoding parsers by approximately 50% on large data sets.
<ul>
<li>Rewrote <a href="org/apache/juneau/parser/ParserReader.html" title="class in org.apache.juneau.parser"><code>ParserReader</code></a> class to handle it's own buffering.
The change allowed several optimizations to be made when dealing with JSON and URL-Encoding
text by avoiding char array copies.
<li>Added a <c>estimatedSize</c> parameter to the <a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a> parse methods to
optimize buffering when the input size is known beforehand.
</ul>
</li>
<li>Revamped the <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a> API to perform better in multi-threaded environments.
<ul>
<li>Introduced a new <c>BeanPropertyStore</c> class that handles creation of <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a> objects.
This allows <c>BeanContext</c> objects to be considered immutable, and therefore cacheable/reusable by the framework.
While this was technically possible to cache these objects beforehand, it relied on a locking mechanism to prevent bean contexts
from being modified after being created. The new mechanism is much more straightforward.
</ul>
</li>
<li>Modifications to the <dc>org.apache.juneau.rest.client</dc> APIs to make it easier to work with custom Apache HTTP clients.
<ul>
<li>Added overridable <dc>RestClient.createHttpClient()</dc> to allow customized subclasses to construct customized HTTP clients.
<li>Removed the <c>DefaultRestClient</c> class since it's now fully redundant with <c>RestClient</c>.
<li>Added <c>RestClient.shutdown()</c> method for cleaning up the internal HTTP client when you're done using a REST client.
</ul>
</li>
</ul>
</div>
</div><!-- END: 5.1.0.8 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.9' id='5.1.0.9'>5.1.0.9 (Dec 1, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.9 -->
<div class='topic'>
<p>
Juno 5.1.0.9 is a major update.
There weren't very many code changes but the source has been made a part of Jazz Foundation.
This required some restructuring of the project.
The project on Jazz Hub will eventually be discontinued.
However, the libraries on IBM Community Source will continue to be updated regularly.
</p>
<ul class='spaced-list'>
<li>Project split up into 3 separate bundles:
<ul>
<li><c>org.apache.juneau</c> - Core serializers and parsers.
<li><c>org.apache.juneau.rest</c> - REST server component.
<li><c>org.apache.juneau.rest.client</c> - REST client component.
</ul>
<li>Code changes to facilitate breaking up bundles:
<ul>
<li><c>org.apache.juneau.rest.labels.Link</c> class moved to <dc>Link</dc>.
<li>References to <c>org.apache.juneau.rest.RestException</c> in <a href="org/apache/juneau/encoders/Encoder.html" title="class in org.apache.juneau.encoders"><code>Encoder</code></a> class changed to <c>IOException</c>.
</ul>
<li>Changed configuration names for consistency with Jazz Framework.
<li><dc>RestClient.execute(HttpUriRequest)</dc> method that allows subclasses to handle their own HTTP request execution.
<li>Changes in <c>JazzRestClient</c> to handle introduction of SSO support in v6.
<li><c>&amp;plainText</c> debug feature was broken.
<li>Removed double-buffering in <c>RestRequest</c>.
<li>Metadata cleanup, Find Bug fixes.
</ul>
</div>
</div><!-- END: 5.1.0.9 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.10' id='5.1.0.10'>5.1.0.10 (Dec 23, 2014)</a></h3>
<div class='topic'><!-- START: 5.1.0.10 -->
<div class='topic'>
<p>
Juno 5.1.0.10 is a moderate update.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li>Major changes to URL-Encoded serializer and parser.
<ul>
<li>Logic for serializing and parsing URL-Encoded key-value pairs moved to <a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a> and <a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a> classes.
<li>Logic for serializing and parsing URL-Encoded values moved to new <a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a> and <a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a> classes.
</ul>
</li>
<li>Fix bug where <c>BeanRuntimeExceptions</c> weren't being thrown on subsequent calls to <a href="org/apache/juneau/BeanContext.html#getClassMeta-java.lang.Class-"><code>BeanContext.getClassMeta(Class)</code></a>.
<li>Moved logic for <c>BeanContext.getPrimitiveDefault(Class)</c> to new <a href="org/apache/juneau/ClassMeta.html#getPrimitiveDefault--"><code>ClassMeta.getPrimitiveDefault()</code></a> method for performance reasons.
<li>Fixed bug in <dc>BeanContext.addTransforms(Class[])</dc> that would cause filter order to get messed up.
<li><a href="org/apache/juneau/ClassMeta.html#newInstance--"><code>ClassMeta.newInstance()</code></a> can now create array instances.
<li>Fixed indentation bugs in <a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a>.
<li>Fixed issue in <a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a> where newlines were not being converted into line breaks.
<li>New <a href="org/apache/juneau/serializer/WriterSerializer.html#toString-java.lang.Object-"><code>WriterSerializer.toString(Object)</code></a> method that's identical to the serialize method but throws <c>RuntimeExceptions</c> to make the serializer easier to use for debugging.
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>Fixed major issue that prevented parsing URL-Encoded form posts into POJOs.
Calling <dc>HttpServlet.getParameter(String)</dc> was forcing the underlying servlet code to process the HTTP body itself, preventing the <c>UrlEncodingSerializer</c>
class from being able to parse the content. Updated code no longer inadvertantly calls this method.
<li>New <dc>RestRequest.getQueryParameter(String)</dc>, <dc>RestRequest.hasQueryParameter(String)</dc>, and <dc>RestRequest.hasAnyQueryParameters(String[])</dc>
methods that only look for parameters in the URL query string to prevent loading and parsing of URL-Encoded form posts.
<li>New <dc>@QParam</dc> and <dc>@HasQParam</dc> annotations for accessing query parameters from the URL query string.
<li><c>&amp;plainText</c> parameter can now specify a false value.
<li>Removed properties parameters from <dc>RestServlet.onPreCall(RestRequest)</dc> and <dc>RestServlet.onPostCall(RestRequest,RestResponse)</dc> methods
since the properties are already accessible through <c>RestRequest.getProperties()</c>.
<li>Added <a href="org/apache/juneau/uon/UonSerializer.html" title="class in org.apache.juneau.uon"><code>UonSerializer</code></a> and <a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a> to serializer and parser lists on
<dc>org.apache.juneau.rest.BasicRestServlet</dc> and <dc>RestServletJenaDefault</dc>.
</ul>
<h5 class='topic w800'>Client</h5>
<ul class='spaced-list'>
<li>Moved to Apache HttpClient 4.3 to match Jazz 6.0.
<li>Renamed <c>RestResponseEntity</c> to <dc>org.apache.juneau.rest.client.RestRequestEntity</dc>.
<li>Improved performance on URL-Encoded form posts by serializing directly to output stream instead of serialized to string first.
<li>New methods on <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> class that makes it easier to associate serializer and parser attributes with registered serializer and parser:
<ul>
<li><dc>RestClient.setProperty(String,Object)</dc>
<li><dc>RestClient.setProperties(ObjectMap)</dc>
<li><dc>RestClient.addNotBeanClasses(Class[])</dc>
<li><dc>RestClient.addTransforms(Class[])</dc>
<li><dc>RestClient.addImplClass(Class,Class)</dc>
</ul>
<li>Renamed <c>RestClient.shutdown()</c> to <a href="org/apache/juneau/rest/client/RestClient.html#close--"><code>RestClient.close()</code></a> to mirror change in Apache API.
</ul>
<h5 class='topic w800'>Samples</h5>
<ul class='spaced-list'>
<li>New <c>CodeFormatterResource</c> for quickly formatting Java and XML code samples in Javadocs.
<li>New <c>UrlEncodedFormResource</c> for showing how to work with URL-Encoded form posts.
</ul>
</div>
</div><!-- END: 5.1.0.10 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.11' id='5.1.0.11'>5.1.0.11 (Feb 14, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.11 -->
<div class='topic'>
<p>
Juno 5.1.0.11 is a moderate update.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li>Additions to <a href="org/apache/juneau/html/annotation/Html.html" title="annotation in org.apache.juneau.html.annotation"><code>@Html</code></a> bean annotation.
<ul>
<li>New <a href="org/apache/juneau/html/annotation/Html.html#noTables--"><code>@Html(noTables)</code></a> annotation that prevents
arrays/Collections from being serialized as tables.
<li>New <a href="org/apache/juneau/html/annotation/Html.html#noTableHeaders--"><code>@Html(noTableHeaders)</code></a> annotation that prevents
HTML tables from having header rows.
</ul>
</li>
<li>Several improvements to URL-Encoding support.
<ul>
<li>Improved whitespace handling in <a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a>.
<li>New <dc>UonParserContext.UON_whitespaceAware</dc> property for controlling whether whitespace is ignored.
<li>New <dc>UrlEncodingContext.URLENC_expandedParams</dc> property for controlling whether arrays/Collections
should be serialized/parsed as multi-part parameters.
<li>New <a href="org/apache/juneau/urlencoding/annotation/UrlEncoding.html#expandedParams--"><code>@UrlEncoding(expandedParams)</code></a>
annotation that specifies that bean properties of type array/Collection be serialized as multi-part parameters (e.g. <c>&amp;key=val1&amp;key=val2</c>).
</ul>
</li>
<li>New <dc>JsonSerializerContext.JSON_escapeSolidus</dc> property for controlling whether slash characters should be escaped.
<li>New <dc>org.apache.juneau.internal.TeeOutputStream</dc> and <dc>org.apache.juneau.internal.TeeWriter</dc> classes.
<li>New <a href="org/apache/juneau/ClassMeta.html#isInstance-java.lang.Object-"><code>ClassMeta.isInstance(Object)</code></a> method.
<li>Performance improvements when using the <a href="org/apache/juneau/BeanMap.html#add-java.lang.String-java.lang.Object-"><code>BeanMap.add(String,Object)</code></a> method.
Array properties are stored in a temporary list cache until <a href="org/apache/juneau/BeanMap.html#getBean--"><code>BeanMap.getBean()</code></a> is called.
<li>New <dc>BeanPropertyMeta.add(BeanMap,Object)</dc> method for adding values to Collection and array properties.
<li>Config INI files now support keys with name <js>"*"</js>.
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>REST method parameters can now be generic types (e.g. <dc><ja>@Param</ja>(<js>"foo"</js>) Map&lt;String,Integer&gt; foo</dc>).
This applies to headers, attributes, and parameters.
<li>New <dc>@Param(multipart)</dc>
and <dc>@Query(multipart)</dc> annotations
for handling multi-part GET and POST parameters.
<li>GET parameters are now CASE-SENSITIVE per W3C standards.
<ul>
<li>
<li><c>&amp;Content</c> must now be specified as <c>&amp;content</c>.
<li><c>&amp;Method</c> must now be specified as <c>&amp;method</c>.
<li><c>&amp;debug</c> must now be specified as <c>&amp;debug=true</c>.
<li><c>&amp;plainText</c> must now be specified as <c>&amp;plainText=true</c>.
<li><c>&amp;notrace</c> must now be specified as <c>&amp;noTrace=true</c>.
</ul>
</li>
<li>Performance improvements around query parameters.
<li>New methods on <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> for handling multi-part parameters:
<ul>
<li><dc>RestRequest.getParameters(String,Class)</dc>
<li><dc>RestRequest.getQueryParameters(String,Class)</dc>
</ul>
</li>
<li>Fixed Jetty issue in <a href="org/apache/juneau/rest/RestResponse.html#setHeader-java.lang.String-java.lang.String-"><code>RestResponse.setHeader(String,String)</code></a> where setting
the <c>Content-Type</c> through this method was inconsistent with the behavior in WAS/Tomcat.
<li><c>&amp;noTrace=true</c> now prevents any errors from being logged in log file.
<li>Workaround for Jetty issue where <c>ServletContext.getContextPath()</c> always ends with <js>"null"</js>.
<li><c>RestServletProperties.REST_allowMethodParam</c> is now <jk>true</jk> by default on all subclasses
of <dc>org.apache.juneau.rest.BasicRestServlet</dc> and <dc>RestServletJenaDefault</dc>.
</ul>
<h5 class='topic w800'>Client</h5>
<ul class='spaced-list'>
<li>New method <dc>RestCall.allowRedirectsOnPosts(boolean)</dc>.
<li>New method <c>RestCall.peekInputStream()</c> allows you to read response bodies without interrupting execution flow.
<li>New method <dc>RestCall.toString()</dc> now useful for debugging purposes.
Shows all request/response headers and bodies.
<li><dc>org.apache.juneau.rest.client.RestCallException</dc> now includes <c>HttpResponse</c> object for easier debugging.
<li>New method <c>RestClient.addListener(RestClientListener)</c> for registering request/response listeners.
<li>New <dc>RestClient.setClassLoader(ClassLoader)</dc> method.
<li>TLS support in <c>JazzRestClient</c>.
</ul>
<h5 class='topic w800'>Other changes</h5>
<ul class='spaced-list'>
<li><c>samples.ear</c> and <c>samples.war</c> projects
have been replaced with an OSGi bundle with activated servlets in <c>juno.samples</c>.
</ul>
</div>
</div><!-- END: 5.1.0.11 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.12' id='5.1.0.12'>5.1.0.12 (Mar 28, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.12 -->
<div class='topic'>
<p>
Juno 5.1.0.12 is a minor update.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li>Fixed <dc>ConfigFile.isEmpty()</dc> method.
<li>Changed behavior on <a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a> to not treat <js>'~'</js> characters as escapes
unless followed by one of the following characters: <c>( ) , $ = ~</c>.
</ul>
<h5 class='topic w800'>Client</h5>
<ul class='spaced-list'>
<li>New class <dc>org.apache.juneau.rest.client.RestCallInterceptor</dc>.
Allows responses to be inspected and modified before being processed.
Replaces <c>RestClientListener</c> class.
<li>Minor connection cleanup fixes.
</ul>
</div>
</div><!-- END: 5.1.0.12 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.13' id='5.1.0.13'>5.1.0.13 (Apr 24, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.13 -->
<div class='topic'>
<p>
Juno 5.1.0.13 is a minor update.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li><a href="org/apache/juneau/ClassMeta.html#newInstance--"><code>ClassMeta.newInstance()</code></a> method can now create new instances of arrays.
<li>Arguments passed to <dc>Link</dc> are now serialized using <a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a>, so arbitrary POJOs can now be passed as arguments.
<li>New date filters: <c>org.apache.juneau.swaps.Datefilter.ISO8601DTZP</c> and <c>org.apache.juneau.swaps.Datefilter.SimpleP</c>.
<li>New <dc>HtmlDocSerializerContext.HTMLDOC_nowrap</dc> setting for <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a> class.
Adds <js>"* {white-space:nowrap}"</js> to the style header to prevent word wrapping.
<li>Fixed bug in <a href="org/apache/juneau/uon/UonParser.html" title="class in org.apache.juneau.uon"><code>UonParser</code></a> where passing in a blank value on an array or collection type in a form post would cause a <c>ClassCastException</c>.
New behavior creates an empty array or <c>Collection</c>.
<li>Improved implementation of <dc>UrlEncodingSerializer.serializeUrlPart(Object)</dc> method.
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li><code>org.apache.juneau.rest.RestConverter</code> API fixed to handle the existence of POJO filters.
<dc>org.apache.juneau.rest.converters.Introspectable</dc>/<dc>org.apache.juneau.rest.converters.Queryable</dc>/<dc>org.apache.juneau.rest.converters.Traversable</dc> classes can now work with filtered POJOs.
<li><dc>@RestResource(messages)</dc> annotation can now be defined on super and subclasses so that NLS messages can be defined in multiple resource bundles.
<li>Performance improvements in <c>RestServletNls</c> class.
<li>Fixed bug where two REST java methods mapped to the same path pattern wasn't triggering an exception when it was supposed to.
</ul>
<h5 class='topic w800'>Client</h5>
<ul class='spaced-list'>
<li>New <dc>RestCall.setRedirectMaxAttempts(int)</dc> method to prevent endless redirection loops.
<li>New <dc>RestCall.setRetryable(int,long,RetryOn)</dc> method to automatically retry on failed connection attempts.
<li>New <c>RestCallInterceptor.onRetry(RestCall,int,HttpRequest,HttpResponse)</c> method for listening in on retry attempts.
</ul>
</div>
</div><!-- END: 5.1.0.13 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.14' id='5.1.0.14'>5.1.0.14 (May 10, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.14 -->
<div class='topic'>
<p>
Juno 5.1.0.14 is a moderate update.
</p>
<p>
The major addition is support for <dc>Remoteable Services</dc>, the ability
to invoke server-side POJO methods through client-side proxy interfaces.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li>Simplified <dc>org.apache.juneau.utils.PojoIntrospector</dc> class.
<li>New <dc>ClassUtils.getMethodSignature(Method)</dc> method.
</ul>
<h5 class='topic w800'>Client</h5>
<ul class='spaced-list'>
<li>New methods in <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> for working with remoteable services:
<ul>
<li><dc>RestClient.setRemoteableServletUri(String)</dc>
<li><dc>RestClient.getRemoteableProxy(Class)</dc>
</ul>
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>Added a default OPTIONS page to <dc>org.apache.juneau.rest.BasicRestServlet</dc> and <dc>RestServletJenaDefault</dc>.
<li><c>RestServletProperties.REST_allowMethodParam</c> has been enhanced to allow you to
explicitly specify which HTTP methods can be used in the <c>&amp;method</c> parameter.
<li>New methods added to <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>:
<ul>
<li><dc>RestRequest.getParser()</dc>
<li><dc>RestRequest.getReaderParser()</dc>
</ul>
</ul>
</div>
</div><!-- END: 5.1.0.14 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.15' id='5.1.0.15'>5.1.0.15 (May 24, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.15 -->
<div class='topic'>
<p>
Juno 5.1.0.15 is a minor update.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li>New properties in <dc>SerializerContext</dc>:
<ol>
<li><dc>SerializerContext.SERIALIZER_relativeUriBase</dc>
<li><dc>SerializerContext.SERIALIZER_absolutePathUriBase</dc>
</ol>
These replace the <c>SERIALIZER_uriAuthority</c> and <c>SERIALIZER_uriContext</c> properties.
</li>
<li>Improvements in <a href="org/apache/juneau/csv/CsvSerializer.html" title="class in org.apache.juneau.csv"><code>CsvSerializer</code></a>.
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>New properties in <c>RestServletProperties</c>:
<ol>
<li><c>REST_defaultCharset</c>
<li><c>REST_servletURI</c>
<li><c>REST_relativeServletURI</c>
</ol>
<li>Improvements involving path calculations when servlets deployed outside of a war file with a context root.
</ul>
<h5 class='topic w800'>Client</h5>
<ul class='spaced-list'>
<li>New methods in <dc>org.apache.juneau.rest.client.RestCall</dc>:
<ol>
<li><dc>RestRequest.getHeader(String,Class)</dc>
<li><dc>RestRequest.getHeader(String,Object,Class)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getQueryParameter(String,Class)</dc>
<li><dc>RestRequest.getQueryParameter(String,Object,Class)</dc>
<li><dc>)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getQueryParameters(String,Class)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getFormDataParameter(String,Class)</dc>
<li><dc>RestRequest.getFormDataParameter(String,Object,Class)</dc>
<li><dc>RestRequest.getFormDataParameters(String,Class)</dc>
<li><dc>)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getPathParameter(String,Class)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getBody(Class)</dc>
<li><dc>)</dc>
</ol>
</li>
</ul>
</div>
</div><!-- END: 5.1.0.15 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.16' id='5.1.0.16'>5.1.0.16 (June 28, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.16 -->
<div class='topic'>
<p>
Juno 5.1.0.16 is a moderate update.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li>New methods on <a href="org/apache/juneau/ClassMeta.html" title="class in org.apache.juneau"><code>ClassMeta</code></a> that eliminates language-specific code in
the general class metadata.
<ul>
<li><dc>ClassMeta.getXmlMeta()</dc>
<li><dc>ClassMeta.getJsonMeta()</dc>
<li><dc>ClassMeta.getHtmlMeta()</dc>
<li><dc>ClassMeta.getUrlEncodingMeta()</dc>
<li><dc>ClassMeta.getRdfMeta()</dc>
</ul>
<li>New <a href="org/apache/juneau/dto/jsonschema/JsonType.html#ANY"><code>JsonType.ANY</code></a> enum.
<li>New <dc>@Html(asPlainText)</dc> annotation.
<li>New <dc>HtmlDocSerializerContext.HTMLDOC_cssImports</dc> property.
<li>Significant changes to RDF support.
<ul>
<li>New <a href="org/apache/juneau/jena/annotation/Rdf.html" title="annotation in org.apache.juneau.jena.annotation"><code>@Rdf</code></a> and <a href="org/apache/juneau/jena/annotation/RdfSchema.html" title="annotation in org.apache.juneau.jena.annotation"><code>@RdfSchema</code></a>
annotations. These replace the use of defining namespaced through the XML annotations, and allows XML and RDF to be
serialized using different namespaces.
<li>Support for serializing arrays/collections as RDF bags, RDF lists, and multi-valued properties.
<li>Fixed warning message about <js>"tab"</js> setting when using the N3/Turtle serializers.
</ul>
<li>New <dc>SerializerContext.SERIALIZER_sortCollections</dc> and
<dc>SerializerContext.SERIALIZER_sortMaps</dc> properties.
<li>FindBug fixes.
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>New <dc>RestRequest.getServletParentURI()</dc> method.
<li>New <c>$R{servletParentURI}</c> variable.
<li>Removed final modifier from <dc>ChildResourceDescriptions</dc>.
</ul>
<h5 class='topic w800'>Samples</h5>
<ul class='spaced-list'>
<li>Added source code links to examples.
</ul>
</div>
</div><!-- END: 5.1.0.16 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.17' id='5.1.0.17'>5.1.0.17 (Aug 3, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.17 -->
<div class='topic'>
<p>
Juno 5.1.0.17 is a major update.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li><a href="org/apache/juneau/BeanMap.html#get-java.lang.Object-"><code>BeanMap.get(Object)</code></a> and <a href="org/apache/juneau/BeanMap.html#put-java.lang.String-java.lang.Object-"><code>BeanMap.put(String,Object)</code></a> now
automatically performs filtering if filters are defined on the bean property or bean property class.
<ul>
<li>Deleted the following methods which are now unnecessary:
<ul>
<li><c>BeanMap.getFiltered(String)</c>
<li><c>BeanMap.putFiltered(String,Object)</c>
<li><c>BeanMapEntry.getFiltered(String)</c>
<li><c>BeanMapEntry.putFiltered(String,Object)</c>
<li><c>BeanMapEntry.putFiltered(String,Object)</c>
<li><c>BeanPropertyMeta.getFiltered()</c>
<li><c>BeanPropertyMeta.setFiltered(Object)</c>
<li><c>BeanPropertyMeta.getTransformedClassMeta()</c>
</ul>
<li><a href="org/apache/juneau/BeanPropertyMeta.html#getClassMeta--"><code>BeanPropertyMeta.getClassMeta()</code></a> now returns the filtered type of the property.
</ul>
<li><dc>StringVarResolver</dc> now has support for chained resolvers.
<li><dc>StringVarResolver</dc> now resolves variables inside resolved values.
i.e. if a resolved variable value itself contains a variable, it now resolves that variable too.
<li>Fixed bug where inner interface classes being used in <dc>RestResource.filters()</dc> were being
interpreted as surrogate classes because they have hidden 1-arg constructors due to being inner classes.
<li>Fixed bug in <a href="org/apache/juneau/internal/MultiSet.html" title="class in org.apache.juneau.internal"><code>MultiSet</code></a> where exception was being thrown if last set was empty.
<li>New <dc>org.apache.juneau.utils.ZipFileList</dc> class for providing efficiently zipped directories through the REST interface.
<li>New <c>RdfProperties.RDF_useXmlNamespaces</c> property.
<li>New <dc>XmlParserContext.XML_preserveRootElement</dc> property.
<li>Worked around bug in Sun VM on OS/X where XML parser was throwing an exception when trying to set a reporter.
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>New <dc>ZipFileListResponseHandler</dc> class.
<li>Simplified labels in servlet resource bundles:
<ul>
<li><c>"[ClassName].ResourceDescription"</c> is now <c>"[ClassName].label"</c>.
<li><c>"[ClassName].MethodDescription.[methodName]"</c> is now <c>"[ClassName].[methodName]"</c>.
</ul>
<li>Several changes to <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>:
<ul>
<li>Added new methods:
<ul>
<li><dc>RestRequest.getQueryParameterMap()</dc>
<li><dc>RestRequest.getQueryParameterNames()</dc>
<li><dc>RestRequest.getPathInfoUndecoded()</dc>
<li><dc>RestRequest.getPathRemainderUndecoded()</dc>
<li><dc>RestRequest.getTrimmedRequestURI()</dc>
<li><dc>RestRequest.getTrimmedRequestURL()</dc>
<li><dc>RestRequest.getServletTitle()</dc>
<li><dc>RestRequest.getServletDescription()</dc>
<li><dc>RestRequest.getMethodDescription()</dc>
</ul>
<li>Behavior changes to <a href="org/apache/juneau/rest/RestRequest.html#getPathInfo--"><code>RestRequest.getPathInfo()</code></a> to follow Servlet specs.
Returns <jk>null</jk> instead of blank for no path info.
<li><dc>RestRequest.getPathRemainder()</dc> now automatically decodes the path remainder.
Use <dc>RestRequest.getPathRemainderUndecoded()</dc> to get the unencoded path remainder.
<li>Bug fixes in <dc>RestRequest.getRequestParentURI()</dc> when servlet is mapped to <js>"/*"</js>.
<li>Bug fixes in <dc>RestRequest.getServletURI()</dc> when servlet is mapped to <js>"/*"</js>.
</ul>
<li>New string replacement variables:
<ul>
<li><c>$R{contextPath}</c> - Returns value from <a href="org/apache/juneau/rest/RestRequest.html#getContextPath--"><code>RestRequest.getContextPath()</code></a>
<li><c>$R{methodDescription}</c> - Returns value from <dc>RestRequest.getMethodDescription()</dc>
<li><c>$R{resourceTitle}</c> - Returns value from <dc>RestRequest.getServletTitle()</dc>
<li><c>$R{resourceDescription}</c> - Returns value from <dc>RestRequest.getServletDescription()</dc>
<li><c>$R{trimmedRequestURI}</c> - Returns value from <dc>RestRequest.getTrimmedRequestURI()</dc>
<li><c>$E{var}</c> - Environment variables.
</ul>
<li>Added methods <dc>RestServlet.getDescription(RestRequest)</dc> and <dc>RestServlet.getLabel(RestRequest)</dc>.
<li><dc>org.apache.juneau.rest.BasicRestServlet</dc> and <dc>RestServletJenaDefault</dc> now provide default HTML titles
and descriptions:
<p class='bcode'>
<ja>@Property</ja>(name=<jsf>HTMLDOC_title</jsf>, value=<js>"$R{resourceTitle}"</js>),
<ja>@Property</ja>(name=<jsf>HTMLDOC_description</jsf>, value=<js>"$R{resourceDescription}"</js>)
</p>
<li>Options pages on <dc>org.apache.juneau.rest.BasicRestServlet</dc> and <dc>RestServletJenaDefault</dc> now provide default descriptions and back links:
and descriptions:
<p class='bcode'>
<ja>@Property</ja>(name=<jsf>HTMLDOC_navlinks</jsf>, value=<js>"{back:'$R{servletURI}"</js>),
<ja>@Property</ja>(name=<jsf>HTMLDOC_description</jsf>, value=<js>"Resource options"</js>)
</p>
<li>New <dc>org.apache.juneau.rest.BasicRestServletGroup</dc> class.
<li>Removed <c>RestServletProperties.REST_trimTrailingUriSlashes</c> and <c>RestServletProperties.REST_pathInfoBlankForNull</c>.
<li>New annotations for providing labels and descriptions. Useful if you don't plan on having to support other languages, so you don't
want to provide labels in resource bundles.
<ul>
<li><dc>RestResource.label()</dc>
<li><dc>@RestResource(description)</dc>
<li><dc>@RestMethod(description)</dc>
<li><dc>RestMethod.responses()</dc>
<li><dc>Attr.description()</dc>
<li><dc>Content.description()</dc>
<li><dc>HasParam.description()</dc>
<li><dc>HasQParam.description()</dc>
<li><dc>Header.description()</dc>
<li><dc>Param.description()</dc>
<li><dc>QParam.description()</dc>
</ul>
<li>Support for sorting resources by name in <dc>ChildResourceDescriptions</dc>.
</ul>
<h5 class='topic w800'>Samples</h5>
<ul class='spaced-list'>
<li>Added <c>/tempDir/upload</c> showing how to use <c>ServletFileUpload</c> with multipart form posts.
</ul>
</div>
</div><!-- END: 5.1.0.17 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.18' id='5.1.0.18'>5.1.0.18 (Aug 5, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.18 -->
<div class='topic'>
<p>
Juno 5.1.0.18 is a minor update affecting the server component only.
</p>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>Fixed bug where localized strings weren't resolving when using chained resource bundles.
<li>Servlet and method labels and descriptions can now contain embedded string variables.
<li>New <dc>RestMethod.input()</dc> and <dc>RestMethod.responses()</dc>
annotations.
These replace the various <c>description</c> annotations added 2 days ago with a simpler design.
<li>New methods on <dc>org.apache.juneau.rest.RestServlet</dc>:
<ul>
<li><dc>RestServlet.getMethodDescription(String,RestRequest)</dc> so that subclasses
can override the method description in the OPTIONS page.
<li><dc>RestServlet.createRequestVarResolver(RestRequest)</dc> so that subclasses
can override and augment the variable resolver.
<li><dc>RestServlet.resolveChild(Class)</dc> and <dc>RestServlet.replaceChild(RestServlet)</dc>
classes that allows customized resolution of servlet instances (e.g. if services are defined in OSGi).
</ul>
<li>Reverted the <dc>MethodDescription</dc> back to 5.1.0.16 since it was being used by someone.
</ul>
</div>
</div><!-- END: 5.1.0.18 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.19' id='5.1.0.19'>5.1.0.19 (Aug 15, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.19 -->
<div class='topic'>
<p>
Juno 5.1.0.19 is a minor update in terms of core functionality.
But it introduces a <dc>Microservices</dc> project for building REST microservices and docker containers.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li>Beans can now be serialized to and parsed from <dc>ObjectMaps</dc>.
See <dc>Serializing to ObjectMaps</dc> for details.
<li>New <dc>ObjectMap.include(String[])</dc> and <dc>ObjectMap.exclude(String[])</dc> methods.
<li><a href="org/apache/juneau/html/annotation/Html.html" title="annotation in org.apache.juneau.html.annotation"><code>@Html</code></a> annotations can now be applied to bean properties.
<li>New <code>org.apache.juneau.utils.IOPipe</code> utility class.
<li>Behavior change on <dc>StringVarResolver</dc>. <jk>null</jk> input now results in blank strings instead of <jk>null</jk>.
</ul>
<h5 class='topic w800'>Client</h5>
<ul class='spaced-list'>
<li>New <dc>RestClient.doCallback(String)</dc> method.
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>New <a href="org/apache/juneau/rest/RestRequest.html#getHeaders--"><code>RestRequest.getHeaders()</code></a> method.
<li>New <c>RestResponse.getUnbufferedWriter()</c> method.
<li>Fixed bug that was preventing <c>x-response-headers</c> parameter from working correctly.
<li>Added <a href="org/apache/juneau/annotation/Bean.html#properties--"><code>@Bean.properties</code></a> annotations to the various
classes in <c>org.apache.juneau.rest.labels</c> so that the order of the bean properties are consistent
on all JVMs. On IBM JVMs this is unnecessary because the order of the properties as defined in the class
are stored in the bytecode. Other JVMs such as OpenJRE do not implement this feature causing the bean
properties to be in random order.
<li>New <dc>ResourceDescription.ResourceDescription(RestRequest,String,String)</dc> constructor.
</ul>
</div>
</div><!-- END: 5.1.0.19 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.1.0.20' id='5.1.0.20'>5.1.0.20 (Sept 5, 2015)</a></h3>
<div class='topic'><!-- START: 5.1.0.20 -->
<div class='topic'>
<p>
Juno 5.1.0.20 is a moderate update.
The biggest improvement is the ability to associate external INI config files with REST servlets using the <dc>ConfigFile</dc> functionality.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li>Significant API changes to <c>org.apache.juneau.config</c> API.
<ul>
<li><dc>ConfigFile</dc> is now thread safe and can be shared across multiple threads.
<li>New <dc>ConfigMgr</dc> class for managing configuration files.
<li>Serializers and parsers can be associated with config files for storing and retrieving POJOs.
Default support provided for JSON.
</ul>
</li>
<li>New <a href="org/apache/juneau/html/SimpleHtmlWriter.html" title="class in org.apache.juneau.html"><code>SimpleHtmlWriter</code></a> class.
Can be used for simple HTML DOM construction.
<li>New <dc>org.apache.juneau.utils.ProcBuilder</dc> class for calling external processes.
<li>New <dc>ObjectMap.remove(Class,String,Object)</dc> method.
<li><js>"class='link'"</js> added to links generated by <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a>.
<li>New <dc>EncoderGroup.append(EncoderGroup)</dc> method.
<li>New <c>HtmlDocSerializerContext.HTMLDOC_addLinks</c> configuration property.
<li>Modified the <c>Parser.createContext(ObjectMap,Method,Object)</c> method.
Outer context objects can be passed in to create instances of non-static inner classes.
<li>Fixed bug in <a href="org/apache/juneau/html/HtmlStrippedDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlStrippedDocSerializer</code></a> where exception was thrown when trying to serialize primitive arrays.
<li><a href="org/apache/juneau/json/JsonParser.html" title="class in org.apache.juneau.json"><code>JsonParser</code></a> now handles parsing JSON boolean/numeric values as strings to bean properties of type boolean or number.
<li><a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer</code></a> and <a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a> now
represent arrays and collections as key-value pairs where the keys are numbers (e.g. <js>"?0=foo&amp;1=bar"</js>).
<li>Various internal improvements to <code>org.apache.juneau.utils.IOPipe</code>.
<li>New <dc>ReflectionUtils.getResource(Class,String)</dc> method.
<li><a href="org/apache/juneau/internal/StringUtils.html#parseNumber-java.lang.String-java.lang.Class-"><code>StringUtils.parseNumber(String,Class)</code></a> now returns zero for empty strings.
This affects the way most parsers handle blank values.
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>You can now parse into non-static inner classes of a servlet for parameters/attributes/content.
Useful if you like to define your marshaller beans inside your servlet.
<li>Changes to <dc>org.apache.juneau.rest.RestServlet</dc>:
<ul>
<li>New methods for accessing external INI config files:<br>
<dc>RestServlet.getConfig()</dc><br>
<dc>RestServlet.createConfigFile()</dc>
<li>New <js>"$C{...}"</js> variable that resolve to INI config file values.
<li>New <js>"$UE{...}"</js> variable that URL-encodes the value inside the variable.
<li>New convenience methods for retrieving classpath resource files:<br>
<dc>RestServlet.getResource(String)</dc><br>
<dc>RestServlet.getResourceAsString(String)</dc><br>
<dc>RestServlet.getResource(Class,String,String)</dc>.
Useful if you want to load predefined POJOs from JSON files in your classpath.
<li>New <dc>RestServlet.handleNotFound(int,RestRequest,RestResponse)</dc> method for customized handling
of when a resource or method was not found.
</ul>
<li><dc>org.apache.juneau.rest.BasicRestServlet</dc> now automatically processes <js>"/favicon.ico"</js> requests by
overriding the new <dc>RestServlet.handleNotFound(int,RestRequest,RestResponse)</dc> method.
<li>New <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> methods:
<ul>
<li><dc>RestRequest.resolveVars(String)</dc>
<li><c>RestRequest.getVarResource(String)</c>
<li><dc>RestRequest.getConfig()</dc>
</ul>
<li>New <a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a> methods:
<ul>
<li><a href="org/apache/juneau/rest/RestResponse.html#getDirectWriter-java.lang.String-"><code>RestResponse.getDirectWriter(String)</code></a>.
<li><a href="org/apache/juneau/rest/RestResponse.html#getNegotiatedWriter--"><code>RestResponse.getNegotiatedWriter()</code></a>.
<c>getWriter()</c> now returns an unnegotiated writer.
<c>getUnbufferedWriter()</c> has been removed.
</ul>
<li>New <dc>@RestMethod(encoders)</dc> and
<dc>RestMethod.inheritEncoders()</dc> annotations.
Allows encoders to be fine-tuned at the method level.
<li>New <dc>@RestResource(config)</dc> annotation for associating external <dc>ConfigFile</dc> config files with servlets.
<li><dc>ResourceLink</dc>.
<li>New <c>org.apache.juneau.rest.matcher</c> package for commonly-used <code>RestMatchers</code>:
<ul>
<li><dc>matchers.MultipartFormDataMatcher</dc>
<li><dc>matchers.UrlEncodedFormMatcher</dc>
</ul>
</ul>
<h5 class='topic w800'>Microservice</h5>
<ul class='spaced-list'>
<li>New juneau-microservice.jar file that encapsulates all 3 juneau jars with code necessary for creating fast and efficent jetty-powered REST microservices.<br>
Contains the following:
<ul>
<li>Jetty 8.0
<li>Apache HttpClient 4.3.5
<li>Apache Commons FileUpload 1.3.1
</ul>
<li>Microservice now supports Java 6 (previously required Java 7)
</ul>
</div>
</div><!-- END: 5.1.0.20 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.2.0.0' id='5.2.0.0'>5.2.0.0 (Dec 30, 2015)</a></h3>
<div class='topic'><!-- START: 5.2.0.0 -->
<div class='topic'>
<p>
Juno 5.2.0.0 is a major update.
Major changes have been made to the microservice architecture and config INI file APIs.
</p>
<h5 class='topic w800'>Core</h5>
<ul class='spaced-list'>
<li>Significant changes and enhancements to the <c>org.apache.juneau.config</c> API.
<ul>
<li>More consistent handling of comma-delimited lists of objects.
<li>New methods in <dc>ConfigFile</dc>:
<ul>
<li><dc>ConfigFile.getStringArray(String)</dc>,<dc>ConfigFile.getStringArray(String,String[])</dc>
<li><dc>ConfigFile.getSectionAsBean(String,Class)</dc> - Instantiate a new bean with property values in the specified section..
<li><dc>ConfigFile.writeProperties(String,Object,boolean,Class[])</dc> - Copy the properties in a config file section into properties on an existing bean or POJO.
<li><dc>ConfigFile.getSectionMap(String)</dc> - Get all the resolved values in a section.
<li><dc>ConfigFile.containsNonEmptyValue(String)</dc>
<li><dc>ConfigFile.isEncoded(String)</dc>
<li><dc>ConfigFile.addListener(ConfigFileListener)</dc> - Listen for modification events on the config file.
<li><dc>ConfigFile.merge(ConfigFile)</dc> - Merge the contents of another config file into this config file.
<li><dc>ConfigFile.getResolving()</dc>, <dc>ConfigFile.getResolving(StringVarResolver)</dc> - Return an instance of the config file that resolves string variables.
Much more efficient than the previous design since the same underlying config file object is shared.
<li><dc>ConfigFile.toWritable()</dc> - Wraps the config file in a <dc>org.apache.juneau.Writable</dc> interface so that it can be serialized by the REST interface as a plain-text INI file instead of as a serialized POJO.
<li><dc>ConfigFile.getInt(String)</dc> - Now supports <js>"M"</js> and <js>"K"</js> to identify millions and thousands.
</ul>
<li>New methods in <dc>ConfigMgr</dc>:
<ul>
<li><dc>ConfigMgr.create()</dc>, <dc>ConfigMgr.create(Reader)</dc>, <dc>ConfigMgr.create(File)</dc>
<li><dc>ConfigMgr.deleteAll()</dc>
</ul>
<li>New methods in <dc>Section</dc>:
<ul>
<li><dc>Section.setParent(ConfigFileImpl)</dc> - Used by parsers to set the config file for this section.
<li><dc>Section.setName(String)</dc> - Used by parsers to set the name for this section.
</ul>
<li>New interfaces:
<ul>
<li><dc>org.apache.juneau.config.ConfigFileListener</dc>
<li><dc>org.apache.juneau.config.SectionListener</dc>
<li><dc>org.apache.juneau.config.EntryListener</dc>
</ul>
<li><dc>org.apache.juneau.config.Encoder</dc> methods have access to field names to use them as salt values.
<li>The name of the default section is now <js>"default"</js>. Before it was just <jk>null</jk>.
<li><dc>org.apache.juneau.config.XorEncoder</dc> XOR key can be overridden through the <js>"org.apache.juneau.config.XorEncoder.key"</js> system property.
</ul>
<li>Support for converting Strings to POJOs if the POJO class has any of the following static methods:
<ul>
<li><c>fromString(String)</c>
<li><c>valueOf(String)</c> (e.g. enums)
<li><c>parse(String)</c> (e.g. logging <c>Level</c> class)
<li><c>parseString(String)</c>
<li><c>forName(String)</c> (e.g. <c>Class</c> and <c>Charset</c> classes)
</ul>
<li>Support for parsing into objects with unbound type variables.
For example, if you have a class <c>Pair&lt;S,T&gt;</c> and you try to parse into this
class (e.g. <c>parser.parse(in, Pair.<jk>class</jk>)</c>), the unbound type variables
is interpreted as <c>Object</c> instead of throwing an exception.
<li>Support for serializing/parsing the following new types:
<ul>
<li><c>AtomicInteger</c>
<li><c>AtomicLong</c>
<li><c>BigInteger</c>
<li><c>BigDecimal</c>
</ul>
<li>Parsers have been enhanced to allow parent POJOs and field names to be passed into child POJOs.
New <a href="org/apache/juneau/annotation/NameProperty.html" title="annotation in org.apache.juneau.annotation"><code>@NameProperty</code></a> and <a href="org/apache/juneau/annotation/ParentProperty.html" title="annotation in org.apache.juneau.annotation"><code>@ParentProperty</code></a>
annotations are provided for identifying methods for setting names and parent POJOs on child POJOs.
For example, the config file <dc>Section</dc> class represents a section
in a config file. It needs to know it's own name and have a link to the <dc>ConfigFile</dc>
that it belongs to. With these new annotations, config files can be reconstructed using any of the parsers.
<li>New classes and interfaces:
<ul>
<li><dc>org.apache.juneau.Streamable</dc> interface for identifying objects that can be serialized directly to an output stream.
<li><dc>org.apache.juneau.Writable</dc> interface for identifying objects that can be serialized directly to a writer.
<li><dc>StringObject</dc> class that can be used for delayed object serialization.
<li><dc>ByteArrayCache</dc>
<li><dc>org.apache.juneau.internal.ByteArrayInOutStream</dc>
<li><a href="org/apache/juneau/internal/FileUtils.html" title="class in org.apache.juneau.internal"><code>FileUtils</code></a>
<li><a href="org/apache/juneau/internal/ThrowableUtils.html" title="class in org.apache.juneau.internal"><code>ThrowableUtils</code></a>
<li><dc>StringVarMultipart</dc>
<li><dc>StringVarWithDefault</dc>
</ul>
<li>New fields on <dc>org.apache.juneau.ObjectList</dc>:
<ul>
<li><dc>ObjectList.EMPTY_LIST</dc>
</ul>
<li>New fields and methods on <dc>org.apache.juneau.ObjectMap</dc>:
<ul>
<li><dc>ObjectMap.EMPTY_MAP</dc>
<li><dc>ObjectMap.getStringArray(String)</dc>
<li><dc>ObjectMap.getStringArray(String,String[])</dc>
<li><dc>ObjectMap.putIfNull(String,Object)</dc>
<li><dc>ObjectMap.putIfEmpty(String,Object)</dc>
</ul>
<li>New methods in <a href="org/apache/juneau/internal/ArrayUtils.html" title="class in org.apache.juneau.internal"><code>ArrayUtils</code></a>:
<ul>
<li><dc>ArrayUtils.contains(Object,Object[])</dc>
<li><dc>ArrayUtils.indexOf(Object,Object[])</dc>
<li><dc>ArrayUtils.toPrimitiveArray(Object)</dc>
</ul>
<li>New methods in <a href="org/apache/juneau/internal/IOUtils.html" title="class in org.apache.juneau.internal"><code>IOUtils</code></a>:
<ul>
<li><dc>IOUtils.pipe(Reader,Writer)</dc>
<li><a href="org/apache/juneau/internal/IOUtils.html#read-java.io.File-"><code>IOUtils.read(File)</code></a>
<li><dc>IOUtils.readFile(String)</dc>
<li><dc>IOUtils.write(File,Reader)</dc>
</ul>
<li>New methods on <dc>org.apache.juneau.utils.PojoRest</dc>:
<ul>
<li><dc>PojoRest.get(Class,String,Object)</dc>
<li><dc>PojoRest.getString(String)</dc>
<li><dc>PojoRest.getString(String,String)</dc>
<li><dc>PojoRest.getInt(String)</dc>
<li><dc>PojoRest.getInt(String,Integer)</dc>
<li><dc>PojoRest.getLong(String)</dc>
<li><dc>PojoRest.getLong(String,Long)</dc>
<li><dc>PojoRest.getBoolean(String)</dc>
<li><dc>PojoRest.getBoolean(String,Boolean)</dc>
<li><dc>PojoRest.getMap(String)</dc>
<li><dc>PojoRest.getMap(String,Map)</dc>
<li><dc>PojoRest.getList(String)</dc>
<li><dc>PojoRest.getList(String,List)</dc>
<li><dc>getObjectMap(String)</dc>
<li><dc>getObjectMap(String,ObjectMap)</dc>
<li><dc>getObjectList(String)</dc>
<li><dc>getObjectList(String,ObjectList)</dc>
</ul>
<li>New methods on <dc>org.apache.juneau.utils.ProcBuilder</dc>:
<ul>
<li><dc>ProcBuilder.pipeTo(Writer,boolean)</dc>
<li><dc>ProcBuilder.pipeTo(Writer)</dc>
<li><dc>ProcBuilder.logTo(Writer,boolean)</dc>
<li><dc>ProcBuilder.logTo(Writer)</dc>
<li><dc>ProcBuilder.logTo(Level,Logger)</dc>
<li><dc>ProcBuilder.maxExitStatus(int)</dc>
</ul>
<li>New methods on <a href="org/apache/juneau/internal/StringUtils.html" title="class in org.apache.juneau.internal"><code>StringUtils</code></a>:
<ul>
<li><dc>StringUtils.isEmpty(Object)</dc>
<li><a href="org/apache/juneau/internal/StringUtils.html#nullIfEmpty-java.lang.String-"><code>StringUtils.nullIfEmpty(String)</code></a>
<li><a href="org/apache/juneau/internal/StringUtils.html#base64EncodeToString-java.lang.String-"><code>StringUtils.base64EncodeToString(String)</code></a>
<li><a href="org/apache/juneau/internal/StringUtils.html#base64Encode-byte:A-"><code>StringUtils.base64Encode(byte[])</code></a>
<li><a href="org/apache/juneau/internal/StringUtils.html#base64DecodeToString-java.lang.String-"><code>StringUtils.base64DecodeToString(String)</code></a>
<li><a href="org/apache/juneau/internal/StringUtils.html#base64Decode-java.lang.String-"><code>StringUtils.base64Decode(String)</code></a>
<li><dc>StringUtils.generateUUID(int)</dc>
<li><a href="org/apache/juneau/internal/StringUtils.html#trim-java.lang.String-"><code>StringUtils.trim(String)</code></a>
<li><dc>StringUtils.parseISO8601Date(String)</dc>
<li><a href="org/apache/juneau/internal/StringUtils.html#replaceVars-java.lang.String-java.util.Map-"><code>StringUtils.replaceVars(String,Map)</code></a>
<li><dc>StringUtils.pathStartsWith(String,String)</dc>
<li><dc>StringUtils.pathStartsWith(String,String[])</dc>
</ul>
<li>New <dc>StringVar.doResolve(String)</dc> method.
<li>New <dc>StringVarResolver.DEFAULT</dc> field.
<li>Eliminated dependency on <c>javax.mail.internet.MimeUtility</c> by implementing our own <a href="org/apache/juneau/internal/StringUtils.html#base64Encode-byte:A-"><code>StringUtils.base64Encode(byte[])</code></a> method.
<li><dc>org.apache.juneau.transforms.CalendarSwap</dc> and <dc>org.apache.juneau.transforms.DateSwap</dc> classes now handle blank input better. Returns <jk>null</jk> instead of throwing an exception.
<li><a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a> specifies the default CSS location as <c>/servletPath/style.css</c> instead of <c>/servletPath/htdocs/juneau.css</c>.
This coincides with enhancements made in the server code for specifying styles.
<li><a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a> wraps output in two div tags instead of one (e.g. <c>&lt;div class='outerdata'&gt;&lt;div class='data' id='data'&gt;...&lt;/div&gt;&lt;/div&gt;</c>).
Needed for supporting the new devops look-and-feel.
<li>Fixed indentation inconsistencies in <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a>.
<li>Renamed <dc>HtmlSchemaSerializer</dc> to <dc>HtmlSchemaDocSerializer</dc>.
<li>RDF serializers and parsers now support <c>RdfProperties.RDF_looseCollection</c> loose collections.
<li>RDF parser handles case where resources point to themselves (an unfortunate behavior in JFS RDF documents).
<li>JSON parser with throw an exception in strict mode if it encounters numbers that are valid in Java but invalid in JSON (e.g. octal, hexadecimal numbers).
<li><a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a> methods now check for <jk>null</jk> input.
<li><dc>org.apache.juneau.serializer.SerializerGroup</dc> and <dc>org.apache.juneau.parser.ParserGroup</dc> ignores serializers and parsers if they throw <c>NoClassDefFoundErrors</c>.
<li><a href="org/apache/juneau/urlencoding/UrlEncodingParser.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingParser</code></a> creates lists if the same attribute name is encountered more than once. Before it would just replace the previous value with the new value.
<li>New <dc>UrlEncodingSerializer.DEFAULT_SIMPLE_EXPANDED</dc> serializer.
<li>Changes to <dc>Args</dc>:
<ul>
<li><c>getMainArg(int)</c> changed to <dc>Args.getArg(int)</dc>.
Non-existent arguments are returned as <jk>null</jk> instead of blank strings.
This is more inline with the behavior of the rest of the library.
<li>New <dc>Args.hasArg(int)</dc> method.
</ul>
<li>Removed <c>org.apache.juneau.utils.CharsetUtils</c> class.
<li>Removed <c>org.apache.juneau.utils.ConcurrentIdentityList</c> class.
<li>Fixed bug in <code>org.apache.juneau.internal.MultiIterable</code> class.
<li><dc>org.apache.juneau.utils.PojoIntrospector</dc> must now be instantiated with a <c>ReaderParser</c>.
Simplifies the API on the class.
<li><dc>org.apache.juneau.utils.PojoRest</dc> must now be instantiated with a <c>ReaderParser</c>.
Simplifies the API on the class.
<li><dc>org.apache.juneau.utils.MessageBundle</dc> and <c>SafeResourceMultiBundle</c> moved from server component.
<li>Several bug fixes and performance improvements in <dc>StringVarResolver</dc>.
<li>Various enhancements to <dc>org.apache.juneau.internal.TeeWriter</dc> and <dc>org.apache.juneau.internal.TeeOutputStream</dc>.
<li>Renamed <dc>CharSet</dc> to <a href="org/apache/juneau/internal/AsciiSet.html" title="class in org.apache.juneau.internal"><code>AsciiSet</code></a>.
<li><dc>org.apache.juneau.serializer.SerializerGroup</dc> and <dc>org.apache.juneau.parser.ParserGroup</dc> now ignores <c>NoClassDefFoundErrors</c>
so that resources that include Jena support can continue to operate even if the Jena libraries are not present.
<li>New <a href="org/apache/juneau/internal/FileUtils.html#createTempFile-java.lang.String-"><code>FileUtils.createTempFile(String)</code></a> method.
<li>New <code>org.apache.juneau.utils.PojoQuery</code> modified to handle bean getters that throw exceptions.
</ul>
<h5 class='topic w800'>Client</h5>
<ul class='spaced-list'>
<li>Upgraded to use Apache HttpClient 4.5.
<li>New classes:
<ul>
<li><dc>org.apache.juneau.rest.client.AllowAllRedirects</dc>
<li><dc>org.apache.juneau.rest.client.HttpMethod</dc>
<li><dc>org.apache.juneau.rest.client.ResponsePattern</dc>
<li><dc>org.apache.juneau.rest.client.SimpleX509TrustManager</dc>
<li><dc>SSLOpts</dc>
</ul>
<li>Removed <c>org.apache.juneau.rest.client.LaxRedirectStrategy</c>. Use HTTP Client equivalent.
<li>New methods on <dc>org.apache.juneau.rest.client.RestCall</dc>:
<ul>
<li><dc>RestCall.addInterceptor(RestCallInterceptor)</dc>
<li><dc>RestCall.pipeTo(Writer)</dc>
<li><dc>RestCall.pipeTo(Writer,boolean)</dc>
<li><dc>RestCall.pipeTo(String,Writer,boolean)</dc>
<li><dc>RestCall.getWriter(String)</dc>
<li><dc>RestCall.pipeTo(OutputStream)</dc>
<li><dc>RestCall.pipeTo(OutputStream,boolean)</dc>
<li><dc>RestCall.pipeTo(String,OutputStream,boolean)</dc>
<li><dc>RestCall.getOutputStream(String)</dc>
<li><dc>RestCall.byLines()</dc>
<li><dc>RestCall.captureResponse()</dc>
<li><dc>RestCall.successPattern(String)</dc>
<li><dc>RestCall.failurePattern(String)</dc>
<li><dc>RestCall.addResponsePattern(ResponsePattern)</dc>
<li><dc>RestCall.run()</dc> - Renamed from <c>execute()</c>.
<li><dc>RestCall.getCapturedResponse()</dc>
<li><dc>RestCall.getResponsePojoRest(Class)</dc>
<li><dc>RestCall.getResponsePojoRest()</dc>
<li><dc>RestCall.logTo(Level,Logger)</dc>
<li><dc>RestCall.setConfig(RequestConfig)</dc>
</ul>
<li>New lifecycle listener methods on <dc>org.apache.juneau.rest.client.RestCallInterceptor</dc>:
<ul>
<li><dc>RestCallInterceptor.onInit(RestCall)</dc>
<li><dc>RestCallInterceptor.onClose(RestCall)</dc>
</ul>
<li>New methods on <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a>:
<ul>
<li><dc>RestClient.setBasicAuth(String,int,String,String)</dc>
<li><dc>RestClient.logTo(Level,Logger)</dc>
<li><dc>RestClient.setRootUrl(String)</dc>
<li><dc>RestClient.enableSSL(SSLOpts)</dc>
<li><dc>RestClient.enableLaxSSL()</dc>
<li><dc>RestClient.doCall(HttpMethod,Object,Object)</dc>
<li><dc>RestClient.createHttpClientBuilder()</dc>
</ul>
<li>New passthrough methods on <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> defined on <c>HttpClientBuilder</c>:
<ul>
<li><dc>RestClient.setRedirectStrategy(RedirectStrategy)</dc>
<li><dc>RestClient.setDefaultCookieSpecRegistry(Lookup)</dc>
<li><dc>RestClient.setRequestExecutor(HttpRequestExecutor)</dc>
<li><dc>RestClient.setSSLHostnameVerifier(HostnameVerifier)</dc>
<li><dc>RestClient.setPublicSuffixMatcher(PublicSuffixMatcher)</dc>
<li><dc>RestClient.setSSLContext(SSLContext)</dc>
<li><dc>RestClient.setSSLSocketFactory(LayeredConnectionSocketFactory)</dc>
<li><dc>RestClient.setMaxConnTotal(int)</dc>
<li><dc>RestClient.setMaxConnPerRoute(int)</dc>
<li><dc>RestClient.setDefaultSocketConfig(SocketConfig)</dc>
<li><dc>RestClient.setDefaultConnectionConfig(ConnectionConfig)</dc>
<li><dc>RestClient.setConnectionTimeToLive(long,TimeUnit)</dc>
<li><dc>RestClient.setConnectionManager(HttpClientConnectionManager)</dc>
<li><dc>RestClient.setConnectionManagerShared(boolean)</dc>
<li><dc>RestClient.setConnectionReuseStrategy(ConnectionReuseStrategy)</dc>
<li><dc>RestClient.setKeepAliveStrategy(ConnectionKeepAliveStrategy)</dc>
<li><dc>RestClient.setTargetAuthenticationStrategy(AuthenticationStrategy)</dc>
<li><dc>RestClient.setProxyAuthenticationStrategy(AuthenticationStrategy)</dc>
<li><dc>RestClient.setUserTokenHandler(UserTokenHandler)</dc>
<li><dc>RestClient.disableConnectionState()</dc>
<li><dc>RestClient.setSchemePortResolver(SchemePortResolver)</dc>
<li><dc>RestClient.setUserAgent(String)</dc>
<li><dc>RestClient.setDefaultHeaders(Collection)</dc>
<li><dc>RestClient.addInterceptorFirst(HttpResponseInterceptor)</dc>
<li><dc>RestClient.addInterceptorLast(HttpResponseInterceptor)</dc>
<li><dc>RestClient.addInterceptorFirst(HttpRequestInterceptor)</dc>
<li><dc>RestClient.addInterceptorLast(HttpRequestInterceptor)</dc>
<li><dc>RestClient.disableCookieManagement()</dc>
<li><dc>RestClient.disableContentCompression()</dc>
<li><dc>RestClient.disableAuthCaching()</dc>
<li><dc>RestClient.setHttpProcessor(HttpProcessor)</dc>
<li><dc>RestClient.setRetryHandler(HttpRequestRetryHandler)</dc>
<li><dc>RestClient.disableAutomaticRetries()</dc>
<li><dc>RestClient.setProxy(HttpHost)</dc>
<li><dc>RestClient.setRoutePlanner(HttpRoutePlanner)</dc>
<li><dc>RestClient.disableRedirectHandling()</dc>
<li><dc>RestClient.setConnectionBackoffStrategy(ConnectionBackoffStrategy)</dc>
<li><dc>RestClient.setBackoffManager(BackoffManager)</dc>
<li><dc>RestClient.setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy)</dc>
<li><dc>RestClient.setDefaultCookieStore(CookieStore)</dc>
<li><dc>RestClient.setDefaultCredentialsProvider(CredentialsProvider)</dc>
<li><dc>RestClient.setDefaultAuthSchemeRegistry(Lookup)</dc>
<li><dc>RestClient.setContentDecoderRegistry(Map)</dc>
<li><dc>RestClient.setDefaultRequestConfig(RequestConfig)</dc>
<li><dc>RestClient.useSystemProperties()</dc>
<li><dc>RestClient.evictExpiredConnections()</dc>
<li><dc>RestClient.evictIdleConnections(long,TimeUnit)</dc>
</ul>
<li><c>JazzRestClient</c> now supports OIDC authentication.
<li>These classes are now deprecated and will be removed in a future release:
<ul>
<li><c>org.apache.juneau.rest.client.jazz.CertificateStore</c>
<li><c>org.apache.juneau.rest.client.jazz.ICertificateValidator</c>
<li><c>org.apache.juneau.rest.client.jazz.ITrustStoreProvider</c>
<li><c>org.apache.juneau.rest.client.jazz.LenientCertificateValidator</c>
<li><c>org.apache.juneau.rest.client.jazz.SharedTrustStoreProvider</c>
<li><c>org.apache.juneau.rest.client.jazz.ValidatingX509TrustManager</c>
</ul>
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>New <dc>ReaderResource</dc> class.
Represents the contents of a text file with convenience methods for resolving
<dc>StringVar</dc> variables and adding HTTP response headers.
REST Java methods can return instances of these to serialize <c>Readers</c>
containing text with <dc>StringVarResolver</dc> variables in them.
<li>New <dc>StreamResource</dc> class.
REST Java methods can return instances of these to serialize <c>OutputStreams</c>.
<li>Fixed a bug in the stack trace hash algorithm in <dc>org.apache.juneau.rest.RestException</dc>.
<li>New methods in <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>:
<ul>
<li><dc>RestRequest.getReaderResource(String)</dc> - Replaces <c>getVarResource(String)</c>.
<li><dc>RestRequest.getReaderResource(String,boolean)</dc>
<li><dc>RestRequest.getReaderResource(String,boolean,String)</dc>
</ul>
<li>Changes in <a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a>:
<ul>
<li>Don't set <c>Content-Encoding: identity</c> when no encoding is used. Some clients don't interpret it correctly.
</ul>
<li>New methods in <dc>org.apache.juneau.rest.RestServlet</dc>:
<ul>
<li><dc>RestServlet.getChildClasses()</dc> - Programmatic equivalent to <dc>@RestResource(children)</dc> annotation.
<li><dc>RestServlet.shouldLog(HttpServletRequest,HttpServletResponse,RestException)</dc>
<li><dc>RestServlet.shouldLogStackTrace(HttpServletRequest,HttpServletResponse,RestException)</dc>
<li><dc>RestServlet.logObjects(Level,String,Object[])</dc>
<li><dc>RestServlet.resolveStaticFile(String)</dc>
<li><dc>RestServlet.createStyleSheet()</dc>
<li><dc>RestServlet.createFavIcon()</dc>
<li><dc>RestServlet.createStaticFilesMap()</dc>
<li><dc>RestServlet.getConfigMgr()</dc>
</ul>
<li>Removed <dc>org.apache.juneau.jso.JsoParser</dc>
from <dc>org.apache.juneau.rest.BasicRestServlet</dc> and <dc>RestServletJenaDefault</dc>.
These may represent a security risk if not handled correctly, so removed
them as a precaution.
<li>Removed <c>RestServletProperties.REST_htDocsFolder</c>. Replaced with <dc>@RestResource(staticFiles)</dc>}.
<li>New annotations on <dc>@RestResource</dc>.
<ul>
<li><dc>RestResource.stylesheet()</dc>
<li><dc>RestResource.favicon()</dc>
<li><dc>@RestResource(staticFiles)</dc>
</ul>
<li>Eliminated <c>org.apache.juneau.rest.jaxrs.JsonProvider</c> class.
Some JAX-RS implementations use code scanning to find providers, so if you were using <c>DefaultJenaProvider</c>, it would
pick up <c>JsonProvider</c> as well. It's easy enough to create your own implementation if needed.
<li>OPTIONS pages now specify <c>consumes</c> and <c>produces</c> fields instead of <c>accept</c> and <c>contentType</c> which was confusing.
<li>Eliminated <c>properties</c> from OPTIONS pages.
<li>New <dc>ResourceLink.ResourceLink(String,RestRequest,String,Object[])</dc> constructor.
<li>New response handlers:
<ul>
<li><dc>StreamableHandler</dc> - Allows REST Java methods to return instances of <dc>org.apache.juneau.Streamable</dc>.
<li><dc>WritableHandler</dc> - Allows REST Java methods to return instances of <dc>org.apache.juneau.Writable</dc>.
</ul>
<li>New DevOps stylesheet.
<li>Servlet initialization and HTTP requests are now logged at <JSF>FINE</JSF> level.
<li>Added <jk>abstract</jk> modifier on various <l>RestServlet</l> subclasses to indicate that they're meant to be subclassed.
<li>New <dc>RestUtils.trimPathInfo(StringBuffer,String,String)</dc> method.
</ul>
<h5 class='topic w800'>Microservice</h5>
<ul class='spaced-list'>
<li>Completely revamped API.
<li>New <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> class that serves as a generic
interface for microservices and their lifecycles.
<li>New <dc>RestMicroservice</dc> class that implements a microservice
consisting of a REST interface.
<ul>
<li>REST resources and configuration settings can be defined through either manifest files
or config files.
<li>Enhanced logging support.
<li>Easy-to-configure SSL support.
<li>BASIC auth support.
<li>Automatic restartability if the config file changes.
</ul>
<li>Eliminated <c>org.apache.juneau.microservice.Main</c> class. This is replaced by
the microservice classes defined above.
<li><dc>Resource</dc> and <dc>ResourceGroup</dc>
classes now support the following new string variables:
<ul>
<li><js>"$A{key,default}""</js> - Command line arguments.
<li><js>"$MF{key,default}""</js> - Manifest file entries.
</ul>
<li>CSS stylesheet now configurable through config file entry <js>"REST/stylesheet"</js>.
<li>New <dc>BasicRestServletJena</dc> class if you want your REST interface to support RDF.
<li>Eliminated the following classes:
<ul>
<li><c>org.apache.juneau.microservice.RootResource</c>
<li><c>org.apache.juneau.microservice.SampleResource</c>
</ul>
<li>New predefined reusable resources:
<ul>
<li><a href="org/apache/juneau/microservice/resources/ConfigResource.html" title="class in org.apache.juneau.microservice.resources"><code>ConfigResource</code></a> - REST resource for viewing and editing microservice config file.
<li><a href="org/apache/juneau/microservice/resources/LogsResource.html" title="class in org.apache.juneau.microservice.resources"><code>LogsResource</code></a> - REST resource for viewing log files.
<li><a href="org/apache/juneau/microservice/resources/SampleRootResource.html" title="class in org.apache.juneau.microservice.resources"><code>SampleRootResource</code></a> - Sample REST resource that contains the config and logs resource as children.
<li><a href="org/apache/juneau/microservice/resources/ShutdownResource.html" title="class in org.apache.juneau.microservice.resources"><code>ShutdownResource</code></a> - REST resource for stopping the microservice JVM. Useful for testing purposes.
</ul>
</ul>
<h5 class='topic w800'>Samples</h5>
<ul class='spaced-list'>
<li>Converted to a REST microservice.
<li>Look-and-feel changed to IBM DevOps.
</ul>
<h5 class='topic w800'>Documentation Updates</h5>
<ul class='spaced-list'>
<li><dc>org.apache.juneau.microservice</dc> - New package-level javadoc.
<li><dc>org.apache.juneau.config</dc> - New package-level javadoc.
<li><dc>StringVarResolver</dc> - New documentation.
<li><dc>org.apache.juneau.rest.client</dc> - New package-level javadoc.
<li><dc>Overview / Samples</dc> - New section.
<li><dc>org.apache.juneau.swap / Stop Classes</dc> - New section.
<li><dc>org.apache.juneau.rest</dc> - Extensive updates.
</ul>
</div>
</div><!-- END: 5.2.0.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#5.2.0.1' id='5.2.0.1'>5.2.0.1 (Mar 23, 2016)</a></h3>
<div class='topic'><!-- START: 5.2.0.1 -->
<div class='topic'>
<p>
Juno 5.2.0.1 is a moderate update.
</p>
<h5 class='topic w800'>com.ibm.team.juno</h5>
<ul class='spaced-list'>
<li>Improved support for multi-line values in config files.
Any line that begins with whitespace is interpreted as a continuation of the previous line.
<li>Support for <js>'\uXXXX'</js> character sequences in config files.
<li>Fixed issue in <a href="org/apache/juneau/xml/XmlSerializer.html" title="class in org.apache.juneau.xml"><code>XmlSerializer</code></a> where <js>'\r'</js> and <js>'\n'</js> characters were not being handled per XML specs.
<li>New methods on <dc>org.apache.juneau.ObjectList</dc>:
<ul>
<li><dc>ObjectList.getAt(Class,String)</dc>
<li><dc>ObjectList.putAt(String,Object)</dc>
<li><dc>ObjectList.postAt(String,Object)</dc>
<li><dc>ObjectList.deleteAt(String)</dc>
</ul>
<li>New methods on <dc>org.apache.juneau.ObjectMap</dc>:
<ul>
<li><dc>ObjectMap.getAt(Class,String)</dc>
<li><dc>ObjectMap.putAt(String,Object)</dc>
<li><dc>ObjectMap.postAt(String,Object)</dc>
<li><dc>ObjectMap.deleteAt(String)</dc>
</ul>
<li><dc>@ThreadSafe</dc> annotation.
<li>New <c>ClassFilter</c> class.
<li><dc>ConfigFile.getResolving(StringVarResolver,boolean)</dc> method.
<li><dc>ConfigFile.getStringVar()</dc> method.
<li>New <dc>ParserContext.PARSER_trimStrings</dc> property.
<li>New <dc>SerializerContext.SERIALIZER_trimStrings</dc> property.
<li><dc>Args.getStringVar()</dc> method.
<li>New <a href="org/apache/juneau/utils/ManifestFile.html" title="class in org.apache.juneau.utils"><code>ManifestFile</code></a> class
<li>New <dc>org.apache.juneau.utils.MessageBundle</dc> class. Replaces <l>SafeResourceBundle</l>/<l>SafeResourceMultiBundle</l>/<l>RestNls</l>.
<li>New <dc>StringMapVar</dc> class.
<li>New <dc>StringVars</dc> class with reusable common <dc>StringVar</dc> instances.
<li>New <dc>org.apache.juneau.internal.JuneauLogger</dc> class.
<li>Default value for <dc>XmlParserContext.XML_trimWhitespace</dc> changed to <jk>true</jk>.
</ul>
<h5 class='topic w800'>Server</h5>
<ul class='spaced-list'>
<li>New methods on <a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>:
<ul>
<li><a href="org/apache/juneau/rest/RestContext.html#getMessages--"><code>RestContext.getMessages()</code></a>
</ul>
</ul>
<h5 class='topic w800'>Client</h5>
<ul class='spaced-list'>
<li>Fixed potential issue in <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> where the HTTP connection pool could end up exhausted if an error occurred.
<li>Improved thread safety on <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a>.
<li>New warning message is logged if a <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> is garbage collected without being closed:
<js>"WARNING: RestClient garbage collected before it was finalized."</js>
</ul>
</div>
</div><!-- END: 5.2.0.1 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#6.0.0' id='6.0.0'>6.0.0 (Oct 3, 2016)</a></h3>
<div class='topic'><!-- START: 6.0.0 -->
<div class='topic'>
<p>
Juneau 6.0.0 is a major update.
</p>
<p>
The major change is rebranding from "Juno" to "Juneau" in preparation for donation to the Apache Foundation.
</p>
<h5 class='topic w800'>org.apache.juneau</h5>
<ul class='spaced-list'>
<li>Major changes around how serializer and parser class properties are defined to improve performance
and concurrency.
<ul>
<li>New <code>org.apache.juneau.PropertyStore</code> class - Used for creating context objects.
<li>New <a href="org/apache/juneau/Context.html" title="class in org.apache.juneau"><code>Context</code></a> class - Read-only configurations for serializers and parsers.
<li>New <code>org.apache.juneau.Session</code> class - One-time use objects used by serializers and parsers.
<li>All context context properties can now also be specified via system properties.
</ul>
</li>
<li>Refactored serializer and parser APIs for more consistency between stream-based and character-based serializers
and parsers.
<ul>
<li>More consistent handling of exceptions.
<li>More consistent method declarations.
</ul>
<li>Refactored var resolver API and added them to a new package - <c>org.apache.juneau.svl</c>.
<ul>
<li>Support for stream-based variables - <a href="org/apache/juneau/svl/StreamedVar.html" title="class in org.apache.juneau.svl"><code>StreamedVar</code></a>.
<li>Added support for context and session objects.
</ul>
<li>Eliminated <js>"_class"</js> properties and replaced them with <js>"_type"</js> properties.
The class properties were a little-used feature where we would serialize fully-qualified class names when the class type could not be inferred through reflection.
It's been replaced with bean type names and bean dictionaries.
Instead of class names, we serialize <js>"_type"</js> properties whose name is the type name defined on the bean being serialized.
The parsers use a 'dictionary' of bean classes to resolve those names to actual bean classes.
The following features were added to enable this support:
<ul>
<li><a href="org/apache/juneau/annotation/Bean.html#typeName--"><code>@Bean(typeName)</code></a> - Annotation that defines an identifying name for a bean class.
<li><dc>BeanFilterBuilder.typeName(String)</dc> - Programmatic equivalent to annotation above.
<li><dc>BeanContext.BEAN_beanDictionary</dc> - List of bean classes that make up the bean dictionary for lookup
during parsing.
<li><dc>BEAN_beanTypePropertyName</dc> - The overridable type property name. Default is <js>"_type"</js>.
<li><dc>@BeanProperty(beanDictionary)</dc> - Define a type dictionary
for a particular bean property value. This overrides the value specified using <dc>BeanContext.BEAN_beanDictionary</dc>.
<li><dc>SerializerContext.SERIALIZER_addBeanTypeProperties</dc> - Controls whether type properties are serialized.
</ul>
In addition, the <a href="org/apache/juneau/annotation/Bean.html#typeName--"><code>@Bean(typeName)</code></a> value replaces the <c>@Xml(name)</c> annotation, and the
<js>"type"</js> and <js>"_class"</js> attributes in the XML and HTML serializers have been standardized on a single <js>"_type"</js> attribute.
<li>Refactor bean filter support to use <dc>org.apache.juneau.transform.BeanFilterBuilder</dc> class.
Allows the <c>BeanFilter</c> class to use final fields.
<li><a href="org/apache/juneau/msgpack/package-summary.html"><code>MessagePack</code></a> support.
<li>Serializers can now serialize directly to <a href="https://docs.oracle.com/javase/8/docs/api/java/io/File.html?is-external=true" title="class or interface in java.io"><code>Files</code></a>.
See <a href="org/apache/juneau/serializer/Serializer.html#serialize-java.lang.Object-java.lang.Object-"><code>Serializer.serialize(Object,Object)</code></a>
<li>Parsers can now parse directly from <a href="https://docs.oracle.com/javase/8/docs/api/java/io/File.html?is-external=true" title="class or interface in java.io"><code>Files</code></a> and other types.
See <a href="org/apache/juneau/parser/Parser.html#parse-java.lang.Object-org.apache.juneau.ClassMeta-"><code>Parser.parse(Object,ClassMeta)</code></a>
<li>Parsers will automatically covert numeric input to POJOs that have numeric constructors (e.g. <c>java.util.Date</c>).
<li>Renamed 'Filters' to 'BeanFilters' and 'PojoSwaps'. Filters is just too overloaded a term.
<li>Internal utility classes moved to a new <c>org.apache.juneau.internal</c> package.
These internal utility classes are not meant for consumption outside the Juneau codebase.
<li>New methods on <a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a>:
<ul>
<li><c>org.apache.juneau.parser.Parser.createSession(ObjectMap,Method,Object)</c>
<li><dc>Parser.getMediaRanges()</dc>
</ul>
</li>
<li>New methods on <a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a>:
<ul>
<li><c>org.apache.juneau.serializer.Serializer.createSession(ObjectMap,Method)</c>
<li><dc>Serializer.getMediaRanges()</dc>
</ul>
</li>
<li>New <a href="org/apache/juneau/annotation/Bean.html#sort--"><code>@Bean(sort)</code></a> annotation.
<li>Added <ja>@Bean.properties</ja> annotations on various DTO beans to make the ordering consistent
between IBM and Oracle JVMs.<br>
IBM JVMs maintain the order of methods in a class, whereas Oracle JVMs do not.
<li>Serializers and parsers now automatically convert <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html?is-external=true" title="class or interface in java.lang"><code>Class</code></a> objects to readable names via <dc>ClassUtils.getReadableClassName(Class)</dc>.
<li>Eliminated the <c>ClassFilter</c> class since it's no longer needed.
<li>Code and concurrency improvements to <dc>org.apache.juneau.serializer.SerializerGroup</dc> and <dc>org.apache.juneau.parser.ParserGroup</dc>.
<li>Various enhancements to <dc>BeanContext.convertToType(Object,Class)</dc>.
<li>New properties on <a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a>:
<ul>
<li><dc>HtmlSerializerContext.HTML_detectLinksInStrings</dc> - Automatically detect hyperlinks in strings.
<li><dc>HtmlSerializerContext.HTML_lookForLabelParameters</dc> - Specify anchor text by appending <c>&amp;label=MyLabel</c> to URL.
<li><dc>HtmlSerializerContext.HTML_labelParameter</dc> - Specify what URL parameter to use as the anchor text label.
<li><dc>HtmlSerializerContext.URI_ANCHOR</dc> option for <dc>HtmlSerializerContext.HTML_uriAnchorText</dc>.
</ul>
</li>
<li>Removed generics from <a href="org/apache/juneau/BeanPropertyMeta.html" title="class in org.apache.juneau"><code>BeanPropertyMeta</code></a>.
<li>Introduced new classes to eliminate the references to language-specific metadata in the core metadata classes:
<ul>
<li><dc>ClassMetaExtended</dc> / <dc>ClassMeta.getExtendedMeta(Class)</dc>
<li><dc>BeanMetaExtended</dc> /<dc>BeanMeta.getExtendedMeta(Class)</dc>
<li><dc>BeanPropertyMetaExtended</dc> / <dc>BeanPropertyMeta.getExtendedMeta(Class)</dc>
</ul>
</li>
<li>Renamed <c>@Transform</c> annotation to <dc>@Pojo</dc> so that it can be used for various POJO-related behavior, not just associating transforms.
<li>Introduced <a href="org/apache/juneau/dto/swagger/package-summary.html"><code>Swagger DTOs</code></a>.
</ul>
<h5 class='topic w800'>org.apache.juneau.rest</h5>
<ul class='spaced-list'>
<li>OPTIONS pages replaced with Swagger documents.
Lots of changes related to supporting Swagger.
<ul>
<li>Annotation name changes to conform to Swagger specs: <ja>@Attr</ja>-><ja>@Path</ja>, <ja>@QParam</ja>-><ja>@Query</ja>, <ja>@Param</ja>-><ja>@FormData</ja>, <ja>@Content</ja>-><ja>@Body</ja>
<li>Eliminated <c>ResourceOptions</c> and related code.
<li>New annotations and related methods:
<ul>
<li><dc>@RestResource(title)</dc> / <dc>RestInfoProvider.getTitle(RestRequest)</dc>
<li><dc>@RestResource(description)</dc> / <dc>RestInfoProvider.getDescription(RestRequest)</dc>
<li><dc>@RestResource(termsOfService)</dc> / <dc>RestInfoProvider.getTermsOfService(RestRequest)</dc>
<li><dc>@RestResource(contact)</dc> / <dc>RestInfoProvider.getContact(RestRequest)</dc>
<li><dc>@RestResource(license)</dc> / <dc>RestInfoProvider.getLicense(RestRequest)</dc>
<li><dc>@RestResource(version)</dc> / <dc>RestInfoProvider.getVersion(RestRequest)</dc>
<li><dc>@RestResource(tags)</dc> / <dc>RestInfoProvider.getTags(RestRequest)</dc>
<li><dc>@RestResource(externalDocs)</dc> / <dc>RestInfoProvidergetExternalDocs(RestRequest)</dc>
<li><dc>@RestMethod(summary)</dc> / <dc>RestInfoProvider.getMethodSummary(String,RestRequest)</dc>
<li><dc>@RestMethod(description)</dc> /<dc>RestInfoProvider.getMethodDescription(String,RestRequest)</dc>
<li><dc>@RestMethod(externalDocs)</dc>
<li><dc>@RestMethod(tags)</dc>
<li><dc>@RestMethod(deprecated)</dc>
<li><dc>@RestMethod(parameters)</dc>
<li><dc>@RestMethod(responses)</dc>
</ul>
</li>
</ul>
<li>New <dc>RestServletContext.paramFormat</dc> context property.
<li>New/updated methods on <dc>org.apache.juneau.rest.RestServlet</dc>:
<ul>
<li><dc>RestServlet.createProperties()</dc>
<li><dc>RestServlet.createBeanContext(ObjectMap,Class[],Class[])</dc>
<li><dc>RestServlet.createBeanFilters()</dc>
<li><dc>RestServlet.createPojoSwaps()</dc>
<li><dc>RestServlet.createParsers(ObjectMap,Class[],Class[])</dc>
<li><dc>RestServlet.createUrlEncodingSerializer(ObjectMap,Class[],Class[])</dc>
<li><dc>RestServlet.createUrlEncodingParser(ObjectMap,Class[],Class[])</dc>
<li><dc>RestServlet.createConverters(ObjectMap)</dc>
<li><dc>RestServlet.createDefaultRequestHeaders(ObjectMap)</dc>
<li><dc>RestServlet.createDefaultResponseHeaders(ObjectMap)</dc>
<li><dc>RestServlet.createEncoders(ObjectMap)</dc>
<li><dc>RestServlet.createGuards(ObjectMap)</dc>
<li><dc>RestServlet.createMimetypesFileTypeMap(ObjectMap)</dc>
<li><dc>RestServlet.createResponseHandlers(ObjectMap)</dc>
</ul>
</li>
<li>New client-version annotations:
<ul>
<li><dc>RestResource.clientVersionHeader</dc> - The name of the header used to identify the client version.
<li><dc>RestMethod.clientVersion</dc> - The client version range applied to a Java method.
</ul>
</li>
</ul>
<h5 class='topic w800'>org.apache.juneau.rest.client</h5>
<ul class='spaced-list'>
<li>Removed the <c>JazzRestClient</c> class.
<li>New method <dc>RestClient.setClientVersion(String)</dc>.
</ul>
</div>
</div><!-- END: 6.0.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#6.0.1' id='6.0.1'>6.0.1 (Jan 3, 2017)</a></h3>
<div class='topic'><!-- START: 6.0.1 -->
<div class='topic'>
<p>
Juneau 6.0.1 is a minor update.
</p>
<h5 class='topic w800'>org.apache.juneau</h5>
<ul class='spaced-list'>
<li>General improvements to JSON parser.
<ul>
<li>Several fixes to handle obscure edge cases.
</ul>
<li>New properties in <dc>ParserContext</dc>.
<ul>
<li><dc>ParserContext.PARSER_strict</dc>
<li><dc>ParserContext.PARSER_inputStreamCharset</dc>
<li><dc>ParserContext.PARSER_fileCharset</dc>
</ul>
<li>Removed <c>JsonParserContext.JSON_strictMode</c>. Replaced by <c>PARSER_strict</c>.
<li><c><jk>byte[]</jk></c> arrays can now be passed to <a href="org/apache/juneau/parser/Parser.html#parse-java.lang.Object-java.lang.Class-"><code>Parser.parse(Object,Class)</code></a> for reader-based parsers.
</ul>
</div>
</div><!-- END: 6.0.1 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#6.1.0' id='6.1.0'>6.1.0 (Feb 25, 2017)</a></h3>
<div class='topic'><!-- START: 6.1.0 -->
<div class='topic'>
<p>
Juneau 6.1.0 is a major update.
</p>
<p>
In particular, this release cleans up the <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a> API to match
the <code>org.apache.juneau.PropertyStore</code>/<a href="org/apache/juneau/Context.html" title="class in org.apache.juneau"><code>Context</code></a>/<code>org.apache.juneau.Session</code> paradigm
previously used in the serializer and parser APIs.
It also makes several improvements to the HTML and XML serialization support and introduces HTML5 DTO beans.
</p>
<h5 class='topic w800'>org.apache.juneau</h5>
<ul class='spaced-list'>
<li>Improvements to XML serialization support.
<ul>
<li>New supported XML formats:
<ul>
<li><a href="org/apache/juneau/xml/annotation/XmlFormat.html#ATTRS"><code>XmlFormat.ATTRS</code></a> format can now be applied to bean classes to have all bean properties serialized
as attributes instead of elements by default.
<li><a href="org/apache/juneau/xml/annotation/XmlFormat.html#ELEMENT"><code>XmlFormat.ELEMENT</code></a> format can now be applied to bean properties to override the <a href="org/apache/juneau/xml/annotation/XmlFormat.html#ATTRS"><code>XmlFormat.ATTRS</code></a>
setting above on specific bean properties.
<li>New <a href="org/apache/juneau/xml/annotation/XmlFormat.html#ELEMENTS"><code>XmlFormat.ELEMENTS</code></a> format can be applied to a bean property of type array/Collection to represent the child elements.
<li>New <a href="org/apache/juneau/xml/annotation/XmlFormat.html#MIXED"><code>XmlFormat.MIXED</code></a> format can be applied to a bean property of type array/Collection to represent mixed content (text + child elements).
<li>New <a href="org/apache/juneau/xml/annotation/XmlFormat.html#MIXED_PWS"><code>XmlFormat.MIXED_PWS</code></a> format. Identical to <jsf>MIXED</jsf> except preserves whitespace.
<li>New <a href="org/apache/juneau/xml/annotation/XmlFormat.html#TEXT"><code>XmlFormat.TEXT</code></a> format can be applied to a bean property of a single object to represent a text node as a child.
<li>New <a href="org/apache/juneau/xml/annotation/XmlFormat.html#TEXT_PWS"><code>XmlFormat.TEXT_PWS</code></a> format. Identical to <jsf>TEXT</jsf> except preserves whitespace.
<li>New <a href="org/apache/juneau/xml/annotation/XmlFormat.html#XMLTEXT"><code>XmlFormat.XMLTEXT</code></a> format that's identical to <a href="org/apache/juneau/xml/annotation/XmlFormat.html#TEXT"><code>XmlFormat.TEXT</code></a> except
XML content is not escaped and serialized directly as the child content. The parser will reconvert this to the original XML text during parsing.
</ul>
<li>New support methodology and other improvements to <dc>org.apache.juneau.xml</dc> documentation.
<li>Eliminated unnecessary <xt>&lt;string&gt;</xt> elements.
<li>Eliminated <dc>XmlContentHandler</dc> class.
<li>Parser efficiency improvements through reuse of string builders.
<li>Reworked and simplified the default XML serializers. The <a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT"><code>XmlSerializer.DEFAULT</code></a> serializer now has namespaces disabled,
and <a href="org/apache/juneau/xml/XmlSerializer.html#DEFAULT_NS"><code>XmlSerializer.DEFAULT_NS</code></a> has namespaces enabled. The 'XML-JSON' serializers have been eliminated.
<li>Eliminated the <c>addJsonTypeAttrs</c> and <c>addJsonStringTypeAttrs</c> settings.
<li>Namespace support is now disabled by default.
</ul>
<li>Significant modifications and improvements to HTML serialization support.
<ul>
<li>Parser converted from <c>XMLEventReader</c>-based to <c>XMLStreamReader</c>.
<li>Eliminated many unnecessary type tags and <xt>&lt;string&gt;</xt> elements and improved the readable layout.
The new format is much leaner.
<li>New exhaustive support methodology section added to <dc>org.apache.juneau.html</dc> documentation.
</ul>
<li>New HTML5 DTO support: <dc>org.apache.juneau.dto.html5</dc>.
<li><a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a> class split into separate <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a> and <a href="org/apache/juneau/BeanSession.html" title="class in org.apache.juneau"><code>BeanSession</code></a> classes.
<ul>
<li>Session object meant to be single-use that can be discarded after use and contains session-level object cache and overridable Locale and TimeZone.
</ul>
<li><dc>SerializerContext</dc> and <dc>ParserContext</dc>
now extend directly from <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a>.
<li><a href="org/apache/juneau/serializer/SerializerSession.html" title="class in org.apache.juneau.serializer"><code>SerializerSession</code></a> and <a href="org/apache/juneau/parser/ParserSession.html" title="class in org.apache.juneau.parser"><code>ParserSession</code></a>
now extend directly from <a href="org/apache/juneau/BeanSession.html" title="class in org.apache.juneau"><code>BeanSession</code></a>.
<li>New settings in <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a>:
<ul>
<li><dc>BEAN_debug</dc> - Debug setting. Replaces individual debug properties in the serializer and parser contexts.
<li><dc>BEAN_locale</dc> - Specifies a default locale at the context level.
<li><dc>BEAN_timeZone</dc> - Specifies a default timezone at the context level.
<li><dc>BEAN_mediaType</dc> - Specifies a default media type at the context level.
</ul>
<li>Improvements to Parser class:
<ul>
<li>Simplified the parse methods (e.g. <c>parseMap()</c>, <c>parseCollection()</c>)
by replacing them with two simple methods:
<ul>
<li><a href="org/apache/juneau/parser/Parser.html#parse-java.lang.Object-java.lang.Class-"><code>Parser.parse(Object,Class)</code></a> - Normal method.
<li><a href="org/apache/juneau/parser/Parser.html#parse-java.lang.Object-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>Parser.parse(Object,Type,Type...)</code></a> - Method for parsing into parameterized maps and collections.
</ul>
Using these methods, you can construct arbitrarily complex objects consisting of maps and collections.
You could do this before but it required constructing a <c>ClassMeta</c> object.
<br>For example:
<p class='bcode'>
<jc>// Old way:</jc>
ClassMeta&lt;?&gt; cm = parser.getMapClassMeta(
HashMap.<jk>class</jk>,
String.<jk>class</jk>,
parser.getCollectionClassMeta(
LinkedList.<jk>class</jk>,
MyBean.<jk>class</jk>
)
);
Map&lt;String,List&lt;MyBean&gt;&gt; map = (Map&lt;String,List&lt;MyBean&gt;&gt;)parser.parse(input, cm);
<jc>// New way:</jc>
Map&lt;String,List&lt;MyBean&gt;&gt; map = parser.parse(input, HashMap.<jk>class</jk>, String.<jk>class</jk>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>);
</p>
<li>Arbitrarily-complex parameterized maps and collections can now be parsed without the need for creating intermediate <c>ClassMeta</c> objects.
<li>No need for casting anymore if you were using the old <c>parseMap()</c> and <c>parseCollection()</c> methods!
<li>Changes allow me to eliminate <c>BeanContext.normalizeClassMeta()</c> method.
<li>Convenience methods added for setting parser properties:
<p class='bcode'>
<jc>// Old way:</jc>
<jk>new</jk> JsonParser().setProperty(<jsf>PARSER_strict</jsf>, <jk>true</jk>).setProperty(<jsf>BEAN_locale</jsf>, mylocale);
<jc>// New way:</jc>
<jk>new</jk> JsonParser().setStrict(<jk>true</jk>).setLocale(mylocale);
</p>
</ul>
<li>Improvements to Serializer class:
<ul>
<li>Convenience methods added for setting serializer properties:
<p class='bcode'>
<jc>// Old way:</jc>
<jk>new</jk> JsonSerializer().setProperty(<jsf>JSON_simpleMode</jsf>, <jk>true</jk>).setProperty(<jsf>SERIALIZER_quoteChar</jsf>, <js>'"'</js>);
<jc>// New way:</jc>
<jk>new</jk> JsonSerializer().setSimpleMode(<jk>true</jk>).setQuoteChar(<js>'"'</js>);
</p>
</ul>
<li>Simplified <dc>org.apache.juneau.transform.PojoSwap</dc> class. Now just two methods:
<ul>
<li><dc>PojoSwap.swap(BeanSession,Object)</dc>
<li><dc>PojoSwap.unswap(BeanSession,Object,ClassMeta)</dc>
</ul>
<li>General code improvements made to <a href="org/apache/juneau/ClassMeta.html" title="class in org.apache.juneau"><code>ClassMeta</code></a> class.
<ul>
<li>All fields are now final which should improve overall performance.
<li>Replaced support for <c>toObjectMap()</c> and <c>fromObjectMap()/T(ObjectMap)</c> methods with
generalized <c>swap(BeanSession)</c>/<c>unswap(BeanSession,X)</c>/<c>T(BeanSession,X)</c> methods.<br>
See new section <dc>Swap methods</dc> for information.
</ul>
<li>Session-level media type now available through <a href="org/apache/juneau/BeanSession.html#getMediaType--"><code>BeanSession.getMediaType()</code></a> method.
Allows for swaps and serializer/parser behavior to be tailored to individual media types.
<li>Several new <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a> and <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a> swaps:
<ul>
<li><dc>org.apache.juneau.transforms.CalendarSwap.ToString</dc>,<dc>org.apache.juneau.transforms.DateSwap.ToString</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang"><code>Strings</code></a> using the <code>Date.toString()</code> method.
<li><dc>org.apache.juneau.transforms.CalendarSwap.ISO8601DT</dc>,<dc>org.apache.juneau.transforms.DateSwap.ISO8601DT</dc> - To ISO8601 date-time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.ISO8601DTZ</dc>,<dc>org.apache.juneau.transforms.DateSwap.ISO8601DTZ</dc> - Same as <jsf>ISO8601DT</jsf>, except always serializes in GMT.
<li><dc>org.apache.juneau.transforms.CalendarSwap.ISO8601DTP</dc>,<dc>org.apache.juneau.transforms.DateSwap.ISO8601DTP</dc> - Same as <jsf>ISO8601DT</jsf> except with millisecond precision.
<li><dc>org.apache.juneau.transforms.CalendarSwap.ISO8601DTPZ</dc>,<dc>org.apache.juneau.transforms.DateSwap.ISO8601DTPZ</dc> - Same as <jsf>ISO8601DTZ</jsf> except with millisecond precision.
<li><dc>org.apache.juneau.transforms.CalendarSwap.RFC2822DT</dc>,<dc>org.apache.juneau.transforms.DateSwap.RFC2822DT</dc> - To RFC2822 date-time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.RFC2822DTZ</dc>,<dc>org.apache.juneau.transforms.DateSwap.RFC2822DTZ</dc> - Same as <jsf>RFC2822DT</jsf>, except always serializes in GMT.
<li><dc>org.apache.juneau.transforms.CalendarSwap.RFC2822D</dc>,<dc>org.apache.juneau.transforms.DateSwap.RFC2822D</dc> - To RFC2822 date strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateTimeSimple</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateTimeSimple</dc> - To simple <js>"yyyy/MM/dd HH:mm:ss"</js> date-time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateSimple</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateSimple</dc> - To simple <js>"yyyy/MM/dd"</js> date strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.TimeSimple</dc>,<dc>org.apache.juneau.transforms.DateSwap.TimeSimple</dc> - To simple <js>"HH:mm:ss"</js> time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateFull</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateFull</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#FULL" title="class or interface in java.text"><code>DateFormat.FULL</code></a> date strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateLong</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateLong</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#LONG" title="class or interface in java.text"><code>DateFormat.LONG</code></a> date strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateMedium</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateMedium</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#MEDIUM" title="class or interface in java.text"><code>DateFormat.MEDIUM</code></a> date strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateShort</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateShort</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#SHORT" title="class or interface in java.text"><code>DateFormat.SHORT</code></a> date strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.TimeFull</dc>,<dc>org.apache.juneau.transforms.DateSwap.TimeFull</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#FULL" title="class or interface in java.text"><code>DateFormat.FULL</code></a> time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.TimeLong</dc>,<dc>org.apache.juneau.transforms.DateSwap.TimeLong</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#LONG" title="class or interface in java.text"><code>DateFormat.LONG</code></a> time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.TimeMedium</dc>,<dc>org.apache.juneau.transforms.DateSwap.TimeMedium</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#MEDIUM" title="class or interface in java.text"><code>DateFormat.MEDIUM</code></a> time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.TimeShort</dc>,<dc>org.apache.juneau.transforms.DateSwap.TimeShort</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#SHORT" title="class or interface in java.text"><code>DateFormat.SHORT</code></a> time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateTimeFull</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateTimeFull</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#FULL" title="class or interface in java.text"><code>DateFormat.FULL</code></a> date-time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateTimeLong</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateTimeLong</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#LONG" title="class or interface in java.text"><code>DateFormat.LONG</code></a> date-time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateTimeMedium</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateTimeMedium</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#MEDIUM" title="class or interface in java.text"><code>DateFormat.MEDIUM</code></a> date-time strings.
<li><dc>org.apache.juneau.transforms.CalendarSwap.DateTimeShort</dc>,<dc>org.apache.juneau.transforms.DateSwap.DateTimeShort</dc> - To <a href="https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html?is-external=true#SHORT" title="class or interface in java.text"><code>DateFormat.SHORT</code></a> date-time strings.
</ul>
<li>New method <dc>SerializerGroup.getSerializerMatch(String)</dc> that returns the matched serializer and media type.
<li>New method <dc>ParserGroup.getParserMatch(String)</dc> that returns the matched parser and media type.
<li>New method <dc>EncoderGroup.getEncoderMatch(String)</dc> that returns the matched encoder and encoding.
<li>General improvements to Bean Dictionary support.
<ul>
<li>New <a href="org/apache/juneau/BeanDictionaryList.html" title="class in org.apache.juneau"><code>BeanDictionaryList</code></a> class can be used for defining reusable sets of bean dictionaries consisting
of classes annotated with <a href="org/apache/juneau/annotation/Bean.html#typeName--"><code>@Bean(typeName)</code></a>.
<li>New <a href="org/apache/juneau/BeanDictionaryMap.html" title="class in org.apache.juneau"><code>BeanDictionaryMap</code></a> class can be used for defining reusable sets of bean dictionaries consisting
of classes not annotated with <a href="org/apache/juneau/annotation/Bean.html#typeName--"><code>@Bean(typeName)</code></a>.
<li>New <dc>@Bean(beanDictionary)</dc> annotation.
</ul>
<li>Removed restriction on getters and setters to be prefixed with "getX/setX/isX" if a <dc>@BeanProperty(name)</dc> annotation is used.
<li>Improvements to ATOM DTO:
<ul>
<li>New <a href="org/apache/juneau/dto/atom/AtomBuilder.html" title="class in org.apache.juneau.dto.atom"><code>AtomBuilder</code></a> class.
<li>New setter method names for a better fluent design.
<li>Updated <dc>org.apache.juneau.dto.atom</dc> documentation.
</ul>
<li>New <dc>org.apache.juneau.transform.MapSwap</dc> and <dc>org.apache.juneau.transform.StringSwap</dc> classes.
<li>New <a href="org/apache/juneau/serializer/WriterSerializer.html#println-java.lang.Object-"><code>WriterSerializer.println(Object)</code></a> method. Useful for debugging purposes.
<li>New <a href="org/apache/juneau/BeanContext.html#getClassMeta-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>BeanContext.getClassMeta(Type,Type...)</code></a> and <a href="org/apache/juneau/BeanSession.html#getClassMeta-java.lang.reflect.Type-java.lang.reflect.Type...-"><code>BeanSession.getClassMeta(Type,Type...)</code></a>
methods for retrieving Map and Collection class metas.
Replaces the various <c>getMapClassMeta()</c>/<c>getCollectionClassMeta()</c> methods.
<li>New section added to this document: <dc>Juneau Data Transfer Objects (org.apache.juneau.dto)</dc>
<li>Modified the UON specification to work with mixed content.
<ul>
<li>The new specification is considerably cleaner and eliminates the need for separate normal/simple modes.
<br>It also allows for arbitrary whitespace to be added to the output without any confusion.
<li>Eliminated the <c>UonParser.<jsf>DEFAULT_WS_AWARE</jsf></c> and <c>UrlEncodingParser.<jsf>DEFAULT_WS_AWARE</jsf></c> parsers.
<br>The normal <a href="org/apache/juneau/uon/UonParser.html#DEFAULT"><code>UonParser.DEFAULT</code></a> and <a href="org/apache/juneau/urlencoding/UrlEncodingParser.html#DEFAULT"><code>UrlEncodingParser.DEFAULT</code></a> parsers will now handle whitespace.
<li>Eliminated the <c>UonParserContext.<jsf>UON_whitespaceAware</jsf></c> configuration setting.
<li>Eliminated the <c>UonSerializer.<jsf>DEFAULT_SIMPLE</jsf></c>, <c>UonSerializer.<jsf>DEFAULT_SIMPLE_ENCODING</jsf></c>
and <c>UrlEncodingSerializer.<jsf>DEFAULT_SIMPLE</jsf></c>
serializers since there is no separate simple mode anymore.
<li>Eliminated the <c>UonParserContext.<jsf>UON_simpleMode</jsf></c> configuration setting.
</ul>
<li>Added new <dc>OutputStreamSerializer.serializeToHex(Object)</dc> method.
<br>Useful mostly for testing purposes.
<br>Equivalently, the <a href="org/apache/juneau/parser/Parser.html#parse-java.lang.Object-java.lang.Class-"><code>Parser.parse(Object,Class)</code></a> method can now
read the output from this method.
<li>Eliminated the <c><ja>@Bean</ja>(subTypeProperty)</c> and <c><ja>@Bean</ja>(subTypes)</c> annotations
and replaced them with the ability to define subtypes using the existing <dc>@Bean(beanDictionary)</dc>
annotation on parent classes and interfaces.
<br>This has the added benefit of simplifying the overall code.
<li>The <dc>SerializerContext.SERIALIZER_addBeanTypeProperties</dc> setting is now enabled by default.
<li>Combined the <c>SERIALIZER_addIndentation</c>/<c>JSON_addWhitespace</c>/<c>UON_addWhitespace</c>
properties into a single <dc>SerializerContext.SERIALIZER_useWhitespace</dc> setting.
</ul>
<h5 class='topic w800'>org.apache.juneau.rest</h5>
<ul class='spaced-list'>
<li><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> now passes locale and timezone to serializers/parsers/transforms.
<li><dc>RestRequest.getTimeZone()</dc> method.
<li>Standardized the following methods in <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> to remove dependency on <c>ClassMeta</c>
objects and eliminate the need for casts:
<ul>
<li><dc>RestRequest.getHeader(String,Class)</dc>
<li><dc>RestRequest.getHeader(String,Object,Class)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getQueryParameter(String,Class)</dc>
<li><dc>RestRequest.getQueryParameter(String,Object,Class)</dc>
<li><dc>)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getQueryParameters(String,Class)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getFormDataParameter(String,Class)</dc>
<li><dc>RestRequest.getFormDataParameter(String,Object,Class)</dc>
<li><dc>RestRequest.getFormDataParameters(String,Class)</dc>
<li><dc>)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getPathParameter(String,Class)</dc>
<li><dc>)</dc>
<li><dc>RestRequest.getBody(Class)</dc>
<li><dc>)</dc>
</ul>
<li>New methods on <dc>org.apache.juneau.rest.client.NameValuePairs</dc>
<li>Fixed issue where whitespace was not added to UON/URL-Encoding output when <c>&amp;plainText=true</c> specified.
</ul>
</div>
</div><!-- END: 6.1.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#6.2.0' id='6.2.0'>6.2.0 (Apr 28, 2017)</a></h3>
<div class='topic'><!-- START: 6.2.0 -->
<div class='topic'>
<p>
Juneau 6.2.0 is a major update.
</p>
<h5 class='topic w800'>org.apache.juneau</h5>
<ul class='spaced-list'>
<li>
Revamped the serializer, parser classes to use builders for creation.
Serializers and parsers are now unmodifiable objects once they are created.
This is a breaking code change that will require adoption.
<p class='bcode'>
<jc>/* Creating a new serializer or parser */ </jc>
<jc>// Old way</jc>
WriterSerializer s = <jk>new</jk> JsonSerializer().setUseWhitespace(<jk>true</jk>).pojoSwaps(BSwap.<jk>class</jk>).lock();
<jc>// New way</jc>
WriterSerializer s = JsonSerializer.<jsm>create</jsm>().ws().pojoSwaps(BSwap.<jk>class</jk>).build();
<jc>/* Cloning an existing serializer or parser */ </jc>
<jc>// Old way</jc>
WriterSerializer s = SimpleJsonSerializer.<jsf>DEFAULT</jsf>
.clone().setUseWhitespace(<jk>true</jk>).pojoSwaps(BSwap.<jk>class</jk>).lock();
<jc>// New way</jc>
WriterSerializer s = SimpleJsonSerializer.<jsf>DEFAULT</jsf>
.builder().ws().pojoSwaps(BSwap.<jk>class</jk>).build();
</p>
<li>Also introduced the following builder classes and related architecture changes to make the built objects unmodifiable:
<ul>
<li><dc>org.apache.juneau.serializer.SerializerGroup.Builder</dc>
<li><dc>org.apache.juneau.parser.ParserGroup.Builder</dc>
<li><dc>org.apache.juneau.encoders.EncoderGroup.Builder</dc>
</ul>
<li>Revamped the config file API to use a build: <dc>ConfigFileBuilder</dc>.
<li>Removed the <dc>Lockable</dc> interface.
<li>New <c>addBeanTypeProperties</c> setting added to serializers to override the
<dc>SerializerContext.SERIALIZER_addBeanTypeProperties</dc> setting
for individual serializers in a serializer group:
<ul>
<li><dc>HtmlSerializerContext.HTML_addBeanTypeProperties</dc>
<li><dc>JsonSerializerContext.JSON_addBeanTypeProperties</dc>
<li><dc>MsgPackSerializerContext.MSGPACK_addBeanTypeProperties</dc>
<li><dc>UonSerializerContext.UON_addBeanTypeProperties</dc>
<li><dc>XmlSerializerContext.XML_addBeanTypeProperties</dc>
<li><dc>RdfSerializerContext.RDF_addBeanTypeProperties</dc>
</ul>
<li>UON notation serializers and parsers moved into the new <c>org.apache.juneau.uon</c> package.
<li>New <a href="org/apache/juneau/xml/annotation/XmlFormat.html#VOID"><code>XmlFormat.VOID</code></a> format to identify HTML void elements.
<li>Tweaks to HTML5 support.
<ul>
<li>Fixed handling of empty non-void elements in HTML serializer.
<li>Added <c>style()</c> override methods to all elements.
</ul>
<li>Improvements to Swagger support.
<ul>
<li>New <a href="org/apache/juneau/dto/swagger/SwaggerBuilder.html" title="class in org.apache.juneau.dto.swagger"><code>SwaggerBuilder</code></a> class.
<li>Fluent-style setters added to the Swagger beans.
<li>Added Swagger examples <dc>here</dc> and in the <dc>org.apache.juneau.dto.swagger</dc> javadocs.
</ul>
<li>Improvements to <a href="org/apache/juneau/svl/VarResolver.html" title="class in org.apache.juneau.svl"><code>VarResolver</code></a>.
<ul>
<li>New <a href="org/apache/juneau/svl/vars/IfVar.html" title="class in org.apache.juneau.svl.vars"><code>$IF</code></a> variable for if-else block logic.
<li><dc>$SWITCH</dc> variable for switch block logic.
<li>Whitespace wasn't being ignored in some cases.
</ul>
<li><a href="org/apache/juneau/html/HtmlParser.html" title="class in org.apache.juneau.html"><code>HtmlParser</code></a> can now parse full body contents generated by <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a>.
<li>Parse-args supported added to <a href="org/apache/juneau/msgpack/MsgPackParser.html" title="class in org.apache.juneau.msgpack"><code>MsgPackParser</code></a> to allow it to be used in remoteable proxies.
<li>Added some convenience classes for constructing collections using a fluent interface:
<ul>
<li><dc>AList</dc>
<li><dc>ASet</dc>
<li><dc>AMap</dc>
</ul>
<li>New <a href="org/apache/juneau/annotation/Bean.html#typePropertyName--"><code>@Bean(typePropertyName)</code></a> annotation allows you to
specify the name of the <js>"_type"</js> property at the class level.
<li>New methods added to HTML5 container beans:
<ul>
<li><a href="org/apache/juneau/dto/html5/HtmlElementContainer.html#getChild-int...-"><code>HtmlElementContainer.getChild(int...)</code></a>
<li><a href="org/apache/juneau/dto/html5/HtmlElementMixed.html#getChild-int...-"><code>HtmlElementMixed.getChild(int...)</code></a>
</ul>
<li>New common serializer setting: <dc>SerializerContext.SERIALIZER_abridged</dc>.
<li>Support for defining interface proxies against 3rd-party REST interfaces.
<br>New package <dc>org.apache.juneau.remoteable</dc> for all remoteable proxy interface annotations.
<br><ja>@Remoteable</ja> annotation has been moved to this package.
<li>Updated doc: <dc>6 - Remoteable Services</dc>
<li>New doc: <dc>6.1 - Interface proxies against 3rd-party REST interfaces</dc>
<li>New URL-encoding serializer setting: <dc>UrlEncodingSerializerContext.URLENC_paramFormat</dc>.
<li>New methods on <a href="org/apache/juneau/urlencoding/UrlEncodingSerializer.Builder.html" title="class in org.apache.juneau.urlencoding"><code>UrlEncodingSerializer.Builder</code></a>:
<ul>
<li><dc>Builder.paramFormat(String)</dc>
<li><dc>Builder.plainTextParams()</dc>
</ul>
</ul>
<h5 class='topic w800'>org.apache.juneau.rest</h5>
<ul class='spaced-list'>
<li><dc>@RestResource</dc> annotation can now be applied to
any class! You're no longer restricted to subclassing your resources from <dc>org.apache.juneau.rest.RestServlet</dc>.
<br>This is a major enhancement in the API. Anything you could do by subclassing from <c>RestServlet</c>
should have an equivalent for non-<c>RestServlet</c> classes.
<br>The only restriction is that the top-level resource must subclass from <c>RestServlet</c>.
Child resources do not.
<br><br>
The majority of code has been split up into two separate classes:
<ul>
<li><dc>RestConfig</dc> - A modifiable configuration of a resource. Subclasses from <code>ServletConfig</code>.
<li><a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a> - A read-only configuration that's the result of a snapshot of the config.
</ul>
<br><br>
The <dc>org.apache.juneau.rest.RestServlet</dc> class now has the following initialization method that allows you to override
the config settings define via annotations:
<ul>
<li><dc>RestServlet.init(RestConfig)</dc> - A modifiable configuration of a resource.
</ul>
Non-<c>RestServlet</c> classes must have one of the following to allow it to be instantiated:
<ul>
<li>A <c><jk>public</jk> T(RestConfig)</c> constructor.
<li>A <c><jk>public</jk> T()</c> constructor.
<li>The parent resource must have a customized <dc>org.apache.juneau.rest.RestResourceResolver</dc> for instantiating it.
</ul>
<br>
Non-<c>RestServlet</c> classes can optionally include the following init methods to gain access to the config and context:
<ul>
<li><dc><jk>public</jk> init(RestConfig)</dc>
<li><dc><jk>public</jk> init(RestContext)</dc>
</ul>
<li>New annotations added to <dc>@RestResource</dc> to allow non-<c>RestServlet</c>
resources to do the same as subclassing directly from <c>RestServlet</c>:
<ul>
<li><dc>RestResource.resourceResolver()</dc>
- Specify a <dc>org.apache.juneau.rest.RestResourceResolver</dc> class for resolving child resources.
<li><dc>RestResource.callHandler()</dc>
- Specify a <dc>org.apache.juneau.rest.RestCallHandler</dc> class for handling the lifecycle of a REST call.
<li><dc>RestResource.infoProvider()</dc>
- Specify a <dc>org.apache.juneau.rest.RestInfoProvider</dc> class for customizing title/description/Swagger information on a REST resource.
<li><dc>RestResource.logger()</dc>
- Specify a <dc>org.apache.juneau.rest.RestLogger</dc> class for handling logging.
</ul>
<li>New annotations added to <dc>@RestResource</dc> and <dc>@RestMethod</dc>
to simplify defining page title, text, and links on HTML views:
<ul>
<li><dc>@RestResource(pageTitle)</dc>
<li><dc>@RestMethod(pageTitle)</dc>
<li><dc>@RestResource(pageText)</dc>
<li><dc>@RestMethod(pageText)</dc>
<li><dc>@RestResource(pageLinks)</dc>
<li><dc>@RestMethod(pageLinks)</dc>
</ul>
<p class='bcode'>
<jc>// Old method</jc>
<ja>@RestResource</ja>(
properties={
<ja>@Property</ja>(name=<jsf>HTMLDOC_title</jsf>, value=<js>"System properties resource"</js>),
<ja>@Property</ja>(name=<jsf>HTMLDOC_description</jsf>, value=<js>"REST interface for performing CRUD operations on system properties."</js>),
<ja>@Property</ja>(name=<jsf>HTMLDOC_navlinks</jsf>, value=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>)
}
)
<jc>// New method</jc>
<ja>@RestResource</ja>(
pageTitle=<js>"System properties resource"</js>,
pageDescription=<js>"REST interface for performing CRUD operations on system properties."</js>,
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>
)
</p>
<p>
Typically you're going to simply want to use the <c>title</c> and <c>description</c> annotations
which apply to both the page title/text and the swagger doc:
</p>
<p class='bcode'>
<ja>@RestResource</ja>(
title=<js>"System properties resource"</js>,
description=<js>"REST interface for performing CRUD operations on system properties."</js>,
pageLinks=<js>"{up:'$R{requestParentURI}',options:'?method=OPTIONS'}"</js>
)
</p>
<li><dc>RestResource.stylesheet()</dc> can now take in a comma-delimited list of stylesheet paths.
<li><dc>StreamResource</dc> can now contain multiple sources from a variety of source types (e.g. <c><jk>byte</jk>[]</c> arrays, <c>InputStreams</c>, <c>Files</c>, etc...)
and is now immutable. It also includes a new <dc>StreamResourceBuilder</dc> class.
<li>Simplified remoteable proxies using the <c><ja>@RestMethod</ja>(name=<js>"PROXY"</js>)</c> annotation on REST methods.
Used to expose interface proxies without the need for <dc>RemoteableServlet</dc>.
<p class='bcode'>
<jc>// Server side</jc>
<ja>@RestMethod</ja>(name=<js>"PROXY"</js>, path=<js>"/myproxy/*"</js>)
<jk>public</jk> IAddressBook getProxy() {
<jk>return</jk> <jf>addressBook</jf>;
}
<jc>// Client side</jc>
RestClient client = RestClient.<jsm>create</jsm>().rootUrl(<jf>samplesUrl</jf>).build();
IAddressBook ab = client.getRemoteableProxy(IAddressBook.<jk>class</jk>, <js>"/addressBook/myproxy"</js>);
</p>
See <dc>@RestMethod(name)</dc> for more information.
<li><a href="org/apache/juneau/rest/RestRequest.html#toString--"><code>RestRequest.toString()</code></a> can be called at any time to view the headers and content of the request
without affecting functionality. Very useful for debugging.
<li><dc>@RestMethod(name)</dc> annotation is now optional. Defaults to <js>"GET"</js>.
</ul>
<h5 class='topic w800'>org.apache.juneau.rest.client</h5>
<ul class='spaced-list'>
<li>Revamped the client API to use builders.
<li>New doc: <dc>1.5 - Debugging</dc>
<li>The <c>RestClient</c> class <c>doX(Object url)</c> methods now handle HttpClient <c>URIBuilder</c> instances.
<li>New methods added/updated to <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a>:
<ul>
<li><dc>RestClient.getRemoteableProxy(Class,Object)</dc> - For interface proxies defined using <c><ja>@RestMethod</ja>(name=<js>"PROXY"</js>)</c>.
<li><dc>RestClient.getRemoteableProxy(Class,Object,Serializer,Parser)</dc> - Same as above but overrides the serializer and parser defined on the client.
<li><dc>RestClient.doPost(Object)</dc>
<li><dc>RestClient.doCall(HttpMethod,Object,Object)</dc> - Can now pass in instances of <dc>org.apache.juneau.rest.client.NameValuePairs</dc> for easy form posts.
<br>This extends to all methods that take in the input.
</ul>
<li>New methods on <dc>org.apache.juneau.rest.client.RestCall</dc>:
<ul>
<li><dc>uri(Object)</dc>
<li><dc>query(String,Object,boolean,PartSerializer)</dc>
<li><dc>query(String,Object)</dc>
<li><dc>queryIfNE(String,Object)</dc>
<li><dc>query(Map)</dc>
<li><dc>queryIfNE(Map)</dc>
<li><dc>query(String)</dc>
<li><dc>formData(String,Object,boolean,PartSerializer)</dc>
<li><dc>formData(String,Object)</dc>
<li><dc>formDataIfNE(String,Object)</dc>
<li><dc>formData(Map)</dc>
<li><dc>formDataIfNE(Map)</dc>
<li><dc>header(String,Object,boolean,PartSerializer)</dc>
<li><dc>header(String,Object)</dc>
<li><dc>headerIfNE(String,Object)</dc>
<li><dc>headers(Map)</dc>
<li><dc>headersIfNE(Map)</dc>
<li><dc>host(String)</dc>
<li><dc>port(int)</dc>
<li><dc>userInfo(String,String)</dc>
<li><dc>userInfo(String)</dc>
<li><dc>scheme(String)</dc>
</ul>
<li>New methods added to <a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>:
<ul>
<li><a href="org/apache/juneau/rest/client/RestClient.Builder.html#executorService-java.util.concurrent.ExecutorService-boolean-"><code>executorService(ExecutorService,boolean)</code></a>
<li><dc>Builder.paramFormat(String)</dc>
<li><dc>Builder.plainTextParams()</dc>
<li><a href="org/apache/juneau/rest/client/RestClient.Builder.html#noTrace--"><code>noTrace()</code></a> - Adds a <c>No-Trace: true</c> header on all requests to prevent
the servlet from logging errors.
<br>Useful for testing scenarios when you don't want the console to end up showing errors done on purpose.
<li><a href="org/apache/juneau/rest/client/RestClient.Builder.html#debug--"><code>debug()</code></a> now adds a <c>Debug: true</c> header on all requests.
</ul>
<li>New methods added/updated to <dc>org.apache.juneau.rest.client.RestCall</dc>:
<ul>
<li><dc>runFuture()</dc>
<li><dc>getResponseFuture(Class)</dc>
<li><dc>getResponseFuture(Type,Type...)</dc>
<li><dc>getResponseAsStringFuture()</dc>
<li><dc>serializer(Serializer)</dc> - Override the serializer defined on the client for a single call.
<li><dc>parser(Parser)</dc> - Override the parser defined on the client for a single call.
<li><dc>input(Object)</dc> - Now accepts instances of <dc>org.apache.juneau.rest.client.NameValuePairs</dc>.
<li><dc>getResponse(Class)</dc> - Can now pass in any of the following:
<ul>
<li><code>HttpResponse</code> - Returns the raw <c>HttpResponse</c> returned by the inner <c>HttpClient</c>.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a> - Returns access to the raw reader of the response.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a> - Returns access to the raw input stream of the response.
</ul>
</ul>
<li>New methods added to <dc>org.apache.juneau.rest.client.NameValuePairs</dc>:
<ul>
<li><dc>append(String,Object)</dc>
<li><dc>append(String,Object,PartSerializer)</dc>
</ul>
<li><dc>org.apache.juneau.rest.client.RetryOn</dc> is now an abstract class with an additional method:
<ul>
<li><dc>onResponse(HttpResponse)</dc>
</ul>
</ul>
<h5 class='topic w800'>org.apache.juneau.microservice</h5>
<ul class='spaced-list'>
<li><js>"REST/port"</js> configuration setting can now be a comma-limited list of port numbers to try.
<br>You can also specify one or more <c>0</c>s to try a random port.
<li>Methods added to <dc>RestMicroservice</dc> class:
<ul>
<li><dc>getPort()</dc>
<li><dc>getURI()</dc>
<li>Override methods added from <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> class for easier method chaining.
</ul>
</ul>
</div>
</div><!-- END: 6.2.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#6.3.0' id='6.3.0'>6.3.0 (Jun 30, 2017)</a></h3>
<div class='topic'><!-- START: 6.3.0 -->
<div class='topic'>
<p>
Juneau 6.3.0 is a major update with significant new functionality for defining proxy interfaces against
arbitrary 3rd-party REST interfaces.
</p>
<h5 class='topic w800'>org.apache.juneau</h5>
<ul class='spaced-list'>
<li>
New package: <a href="org/apache/juneau/http/package-summary.html"><code>org.apache.juneau.http</code></a>.
<li>
Support for dynamic beans. See <dc>@BeanProperty(name)</dc>.
<li>
New doc: <dc>2.8 - Virtual Beans</dc>
<li>
New doc: <dc>2.13 - Comparison with Jackson</dc>
<li>
All parsers now allow for numeric types with <js>'K'</js>/<js>'M'</js>/<js>'G'</js> suffixes to represent
kilobytes, megabytes, and gigabytes.
<p class='bcode'>
<jc>// Example</jc>
<jk>int</jk> i = JsonParser.<jsf>DEFAULT</jsf>.parse(<js>"123M"</js>); <jc>// 123MB</jc>
</p>
<li>New/modified methods on <dc>ConfigFile</dc>:
<ul>
<li><dc>ConfigFile.put(String,String,String,boolean)</dc>
<li><dc>ConfigFile.put(String,String,Object,Serializer,boolean,boolean)</dc>
<li><dc>)</dc>
<li><dc>)</dc>
<li><dc>ConfigFile.getObject(String,Class)</dc>
<li><dc>ConfigFile.getObject(String,Parser,Class)</dc>
<li><dc>)</dc>
<li><dc>)</dc>
<li><dc>ConfigFile.getObject(String,String,Class)</dc>
<li><dc>ConfigFile.getObject(String,String,Parser,Class)</dc>
<li><dc>)</dc>
<li><dc>)</dc>
<li><dc>ConfigFile.getObjectWithDefault(String,Object,Class)</dc>
<li><dc>ConfigFile.getObjectWithDefault(String,Parser,Object,Class)</dc>
</ul>
<li>New ability to interact with config file sections with proxy interfaces with new method <dc>ConfigFile.getSectionAsInterface(String,Class)</dc>.
<li><dc>@BeanProperty</dc> annotation can now be applied to getters
and setters defined on interfaces.
<li>New methods on <a href="org/apache/juneau/serializer/SerializerSession.html" title="class in org.apache.juneau.serializer"><code>SerializerSession</code></a> and <a href="org/apache/juneau/parser/ParserSession.html" title="class in org.apache.juneau.parser"><code>ParserSession</code></a>
for retrieving context and runtime-override properties:
<ul>
<li><dc>Session.getProperty(String)</dc>
<li><dc>Session.getProperty(String,String)</dc>
<li><dc>Session.getProperty(Class,String)</dc>
<li><dc>Session.getProperty(Class,String,Object)</dc>
</ul>
<li>New <dc>org.apache.juneau.serializer.PartSerializer</dc> interface particularly tailored to HTTP
headers, query parameters, form-data parameters, and path variables.
<br>Allows easy user-defined serialization of these objects.
<br>The interface can be used in the following locations:
<ul>
<li><dc>Builder.partSerializer(Class)</dc>
<li><dc>Path.serializer</dc>
<li><dc>Query.serializer</dc>
<li><dc>QueryIfNE.serializer</dc>
<li><dc>FormData.serializer</dc>
<li><dc>FormDataIfNE.serializer</dc>
<li><dc>Header.serializer</dc>
<li><dc>HeaderIfNE.serializer</dc>
</ul>
<li>Across-the-board improvements to the URI-resolution support (i.e. how URIs get serialized).
<ul>
<li>New support for resolving URIs with the following newly-recognized protocols:
<ul>
<li><js>"context:/..."</js> - Relative to context-root of the application.
<li><js>"servlet:/..."</js> - Relative to the servlet URI.
<li><js>"request:/..."</js> - Relative to the request URI.
</ul>
For example, currently we define HTML page links using variables and servlet-relative URIs...
<p class='bcode'>
pages=<js>"{up:'$R{requestParentURI}', options:'?method=OPTIONS', upload:'upload'}"</js>
</p>
With these new protocols, we can define them like so:
<p class='bcode'>
links=<js>"{top:'context:/', up:'request:/..' ,options:'servlet:/?method=OPTIONS', upload:'servlet:/upload'}"</js>
</p>
The old method of using variables and servlet-relative URIs will still be supported but using
these new protocols should (hopefully) be easier to understand.
<br>
These protocols work on all serialized URL and URI objects, as well as classes and properties
annotated with <dc>@URI</dc>.
<li>New classes:
<ul>
<li><a href="org/apache/juneau/UriContext.html" title="class in org.apache.juneau"><code>UriContext</code></a>
<li><a href="org/apache/juneau/UriRelativity.html" title="enum in org.apache.juneau"><code>UriRelativity</code></a>
<li><a href="org/apache/juneau/UriResolution.html" title="enum in org.apache.juneau"><code>UriResolution</code></a>
<li><a href="org/apache/juneau/UriResolver.html" title="class in org.apache.juneau"><code>UriResolver</code></a>
</ul>
<li>New configuration properties:
<li><dc>SerializerContext.SERIALIZER_uriContext</dc>
<li><dc>SerializerContext.SERIALIZER_uriRelativity</dc>
<li><dc>SerializerContext.SERIALIZER_uriResolution</dc>
<li><dc>SerializerContext.SERIALIZER_maxIndent</dc>
</ul>
<li>New annotation property: <dc>@BeanProperty(value)</dc>.
<br>The following two annotations are considered equivalent:
<p class='bcode'>
<ja>@BeanProperty</ja>(name=<js>"foo"</js>)
<ja>@BeanProperty</ja>(<js>"foo"</js>)
</p>
<li>Fixed a race condition in ClassMeta.
<li><jsf>URLENC_paramFormat</jsf> has been moved to <dc>UonSerializer.UON_paramFormat</dc>,
and the UON/URL-Encoding serializers will now always serialize all values as plain text.
<br>This means that arrays and maps are converted to simple comma-delimited lists.
<li>Listener APIs added to serializers and parsers:
<ul>
<li><a href="org/apache/juneau/serializer/SerializerListener.html" title="class in org.apache.juneau.serializer"><code>SerializerListener</code></a>
<li><a href="org/apache/juneau/serializer/Serializer.Builder.html#listener-java.lang.Class-"><code>Serializer.Builder.listener(Class)</code></a>
<li><dc>@RestResource(serializerListener)</dc>
<li><dc>RestConfig.serializerListener(Class)</dc>
<li><a href="org/apache/juneau/parser/ParserListener.html" title="class in org.apache.juneau.parser"><code>ParserListener</code></a>
<li><a href="org/apache/juneau/parser/Parser.Builder.html#listener-java.lang.Class-"><code>Parser.Builder.listener(Class)</code></a>
<li><dc>@RestResource(parserListener)</dc>
<li><dc>RestConfig.parserListener(Class)</dc>
<li><dc>Builder.listeners(Class,Class)</dc>
</ul>juneau-examples-core.import1.pngjuneau-examples-core.import1.png
<li>The <dc>BEAN_debug</dc> flag will now capture parser input and make it
available through the <dc>ParserSession.getInputAsString()</dc> method so that it can be used
in the listeners.
<li>Significant new functionality introduced to the HTML serializer.
<br>Lots of new options for customizing the HTML output.
<ul>
<li>New <a href="org/apache/juneau/html/annotation/Html.html#render--"><code>@Html(render)</code></a> annotation and <a href="org/apache/juneau/html/HtmlRender.html" title="class in org.apache.juneau.html"><code>HtmlRender</code></a> class that allows you
to customize the HTML output and CSS style on bean properties:
<br><img class='bordered' src='doc-files/ReleaseNotes.630.1.png'>
<br>Annotation can be applied to POJO classes and bean properties.
<li>Several new properties for customizing parts of the HTML page:
<ul>
<li><dc>HtmlDocSerializerContext.HTMLDOC_title</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_description</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_branding</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_header</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_nav</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_aside</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_footer</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_noResultsMessage</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_cssUrl</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_css</dc>
<li><dc>HtmlDocSerializerContext.HTMLDOC_template</dc>
</ul>
<li>New interface <a href="org/apache/juneau/html/HtmlDocTemplate.html" title="interface in org.apache.juneau.html"><code>HtmlDocTemplate</code></a> that allows full control over rendering
of HTML produced by <a href="org/apache/juneau/html/HtmlDocSerializer.html" title="class in org.apache.juneau.html"><code>HtmlDocSerializer</code></a>.
</ul>
<li><a href="org/apache/juneau/annotation/NameProperty.html" title="annotation in org.apache.juneau.annotation"><code>@NameProperty</code></a> and <a href="org/apache/juneau/annotation/ParentProperty.html" title="annotation in org.apache.juneau.annotation"><code>@ParentProperty</code></a>
can now be applied to fields.
<li>New properties on <a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a>:
<ul>
<li><dc>BEAN_includeProperties</dc>
<li><dc>BEAN_excludeProperties</dc>
</ul>
<li>New annotation property: <dc>@BeanProperty(format)</dc>.
</ul>
<h5 class='topic w800'>org.apache.juneau.rest</h5>
<ul class='spaced-list'>
<li>
MAJOR enhancements made to the REST API.
<li>
The <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> class functionality has been broken up into the following
functional pieces to reduce its complexity:
<ul>
<li><dc>RestRequest.getBody()</dc> - The request body.
<li><a href="org/apache/juneau/rest/RestRequest.html#getHeaders--"><code>RestRequest.getHeaders()</code></a> - The request headers.
<li><dc>RestRequest.getQuery()</dc> - The request query parameters.
<li><dc>RestRequest.getFormData()</dc> - The request form data parameters.
<li><dc>RestRequest.getPathMatch()</dc> - The path variables and remainder.
</ul>
The following classes have been introduced:
<ul>
<li><dc>org.apache.juneau.rest.RequestBody</dc>
<li><dc>org.apache.juneau.rest.RequestHeaders</dc>
<li><dc>org.apache.juneau.rest.RequestQuery</dc>
<li><dc>org.apache.juneau.rest.RequestFormData</dc>
<li><dc>org.apache.juneau.rest.RequestPath</dc>
</ul>
<li>
The un-annotated parameter types that can be passed in through REST Java methods has been significantly expanded.
<br>For reference, the previous supported types were:
<ul>
<li><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a> - The request object.
<li><code>HttpServletRequest</code> - The superclass of <c>RestRequest</c>.
<li><a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a> - The response object.
<li><code>HttpServletResponse</code> - The superclass of <c>RestResponse</c>.
</ul>
The new supported types are:
<ul>
<li><dc>Accept</dc>
<li><dc>AcceptCharset</dc>
<li><dc>AcceptEncoding</dc>
<li><dc>AcceptLanguage</dc>
<li><dc>Authorization</dc>
<li><dc>CacheControl</dc>
<li><dc>Connection</dc>
<li><dc>ContentLength</dc>
<li><dc>ContentType</dc>
<li><dc>Date</dc>
<li><dc>Expect</dc>
<li><dc>From</dc>
<li><dc>Host</dc>
<li><dc>IfMatch</dc>
<li><dc>IfModifiedSince</dc>
<li><dc>IfNoneMatch</dc>
<li><dc>IfRange</dc>
<li><dc>IfUnmodifiedSince</dc>
<li><dc>MaxForwards</dc>
<li><dc>Pragma</dc>
<li><dc>ProxyAuthorization</dc>
<li><dc>Range</dc>
<li><dc>Referer</dc>
<li><dc>TE</dc>
<li><dc>UserAgent</dc>
<li><dc>Upgrade</dc>
<li><dc>Via</dc>
<li><dc>Warning</dc>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html?is-external=true" title="class or interface in java.util"><code>TimeZone</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStream</code></a>
<li><code>ServletInputStream</code>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Reader</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html?is-external=true" title="class or interface in java.io"><code>OutputStream</code></a>
<li><code>ServletOutputStream</code>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/io/Writer.html?is-external=true" title="class or interface in java.io"><code>Writer</code></a>
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html?is-external=true" title="class or interface in java.util"><code>ResourceBundle</code></a> - Client-localized resource bundle.
<li><dc>org.apache.juneau.utils.MessageBundle</dc> - A resource bundle with additional features.
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html?is-external=true" title="class or interface in java.util"><code>Locale</code></a> - Client locale.
<li><dc>org.apache.juneau.rest.RequestHeaders</dc> - API for accessing request headers.
<li><dc>org.apache.juneau.rest.RequestQuery</dc> - API for accessing request query parameters.
<li><dc>org.apache.juneau.rest.RequestFormData</dc> - API for accessing request form data.
<li><dc>org.apache.juneau.rest.RequestPath</dc> - API for accessing path variables.
<li><dc>org.apache.juneau.rest.RequestBody</dc> - API for accessing request body.
<li><a href="org/apache/juneau/http/HttpMethod.html" title="class in org.apache.juneau.http"><code>HttpMethod</code></a> - The method name matched (when using <c><ja>@RestMethod</ja>(name=<js>"*"</js>)</c>)
<li><a href="https://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html?is-external=true" title="class or interface in java.util.logging"><code>Logger</code></a> - The logger to use for logging.
<li><dc>org.apache.juneau.internal.JuneauLogger</dc> - Logger with additional features.
<li><a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a> - The resource read-only context.
<li><a href="org/apache/juneau/parser/Parser.html" title="class in org.apache.juneau.parser"><code>Parser</code></a> - The parser matching the request content type.
<li><a href="org/apache/juneau/dto/swagger/Swagger.html" title="class in org.apache.juneau.dto.swagger"><code>Swagger</code></a> - The auto-generated Swagger doc.
<li><dc>ConfigFile</dc> - The external config file for the resource.
</ul>
So, for example...
<p class='bcode'>
<jd>/** Old way */</jd>
<ja>@RestMethod</ja>(name=<js>"*"</js>, path=<js>"/example1/{a1}/{a2}/{a3}/*"</js>)
<jk>public</jk> String example1(
<ja>@Method</ja> String method,
<ja>@Path</ja>(<js>"a1"</js>) String a1,
<ja>@Path</ja>(<js>"a2"</js>) <jk>int</jk> a2,
<ja>@Path</ja>(<js>"a3"</js>) 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>@Header</ja>(<js>"Accept-Language"</js>) String lang,
<ja>@Header</ja>(<js>"Accept"</js>) String accept
)
<jd>/** New way */</jd>
<ja>@RestMethod</ja>(name=<js>"*"</js>, path=<js>"/example2/{a1}/{a2}/{a3}/*"</js>)
<jk>public</jk> String example2(
HttpMethod httpMethod,
RequestPathParams pathParams,
RequestQuery query,
AcceptLanguage acceptLanguage,
Accept accept
)
</p>
<li>
A new annotation <dc>@RestResource(paramResolvers)</dc>}
that allows you to define your own custom Java method parameter resolvers.
<li>
Fixed bug where Writer returned by <a href="org/apache/juneau/rest/RestResponse.html#getWriter--"><code>RestResponse.getWriter()</code></a> was not being flushed automatically
at the end of the HTTP call.
<li>
New annotations added to <dc>@RestMethod</dc>:
<ul>
<li><dc>defaultQuery()</dc>
<li><dc>defaultFormData()</dc>
<li><dc>bpIncludes()</dc>
<li><dc>bpExcludes()</dc>
</ul>
<li>
Default values on header, query, and form-data annotations:
<ul>
<li><dc>@Header(def)</dc> - Default header value.
<li><dc>@Query(def)</dc> - Default query parameter value.
<li><dc>@FormData(def)</dc> - Default form data parameter value.
</ul>
<li>
New attributes on <dc>@RestResource</dc>:
<ul>
<li><dc>serializerListener()</dc>
<li><dc>parserListener()</dc>
<li><dc>widgets()</dc>
<li><dc>swagger()</dc>
<li><dc>htmldoc()</dc>
</ul>
<li>
New attributes on <dc>@RestMethod</dc>:
<ul>
<li><dc>widgets()</dc>
<li><dc>swagger()</dc>
<li><dc>htmldoc()</dc>
</ul>
<li>
New string vars:
<ul>
<li><a href="org/apache/juneau/rest/vars/UrlVar.html" title="class in org.apache.juneau.rest.vars"><code>UrlVar</code></a> - Resolve <js>"$U{...}"</js> variables to URLs.
<li><dc>org.apache.juneau.rest.vars.WidgetVar</dc> - Resolve <js>"$W{...}"</js> variables to widget contents.
</ul>
<li>
New methods on <dc>RestConfig</dc>:
<ul>
<li><dc>setHtmlTitle(String)</dc>
<li><dc>setHtmlDescription(String)</dc>
<li><dc>setHtmlBranding(String)</dc>
<li><dc>setHtmlHeader(String)</dc>
<li><dc>setHtmlLinks(String)</dc>
<li><dc>setHtmlNav(String)</dc>
<li><dc>setHtmlAside(String)</dc>
<li><dc>setHtmlFooter(String)</dc>
<li><dc>setHtmlCss(String)</dc>
<li><dc>setHtmlCssUrl(String)</dc>
<li><dc>setHtmlNoWrap(boolean)</dc>
<li><dc>setHtmlNoResultsMessage(String)</dc>
<li><dc>setHtmlTemplate(Class)</dc>
<li><dc>setHtmlTemplate(HtmlDocTemplate)</dc>
<li><dc>addWidget(Class)</dc>
</ul>
<li>
New methods on <a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a>:
<ul>
<li><dc>setHtmlTitle(Object)</dc>
<li><dc>setHtmlDescription(Object)</dc>
<li><dc>setHtmlBranding(Object)</dc>
<li><dc>setHtmlHeader(Object)</dc>
<li><dc>setHtmlLinks(Object)</dc>
<li><dc>setHtmlNav(Object)</dc>
<li><dc>setHtmlAside(Object)</dc>
<li><dc>setHtmlFooter(Object)</dc>
<li><dc>setHtmlCss(Object)</dc>
<li><dc>setHtmlCssUrl(Object)</dc>
<li><dc>setHtmlNoWrap(boolean)</dc>
<li><dc>setHtmlNoResultsMessage(Object)</dc>
<li><dc>setHtmlTemplate(Class)</dc>
<li><dc>setHtmlTemplate(HtmlDocTemplate)</dc>
</ul>
<li>
<c>&amp;plainText=true</c> parameter now works on byte-based serializers by converting the output to hex.
<li>
New classes for widget support:
<ul>
<li><a href="org/apache/juneau/rest/widget/Widget.html" title="class in org.apache.juneau.rest.widget"><code>Widget</code></a>
<li><dc>PoweredByJuneauWidget</dc>
<li><dc>ContentTypeLinksColumnWidget</dc>
<li><dc>ContentTypeLinksRowWidget</dc>
<li><dc>QueryWidget</dc>
</ul>
<li>
<c>devops.css</c> cleaned up.
<li>
Removed a bunch of URL-related methods from <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>.
These all have equivalents in <a href="org/apache/juneau/rest/RestRequest.html#getUriContext--"><code>RestRequest.getUriContext()</code></a>.
<li>
New annotation attributes:
<ul>
<li><a href="org/apache/juneau/http/annotation/Query.html#name--"><code>@Query(name)</code></a>
<li><a href="org/apache/juneau/http/annotation/FormData.html#name--"><code>@FormData(name)</code></a>
<li><a href="org/apache/juneau/http/annotation/Header.html#name--"><code>@Header(name)</code></a>
<li><a href="org/apache/juneau/http/annotation/Path.html#name--"><code>@Path(name)</code></a>
<li><a href="org/apache/juneau/http/annotation/HasQuery.html#name--"><code>@HasQuery(name)</code></a>
<li><a href="org/apache/juneau/http/annotation/HasFormData.html#name--"><code>@HasFormData(name)</code></a>
</ul>
</li>
</ul>
<h5 class='topic w800'>org.apache.juneau.rest.client</h5>
<ul class='spaced-list'>
<li>
New <dc>org.apache.juneau.remoteable.Path</dc> annotation for specifying path variables on remoteable interfaces.
<li>
New <dc>@RequestBean</dc> annotation for specifying beans with remoteable annotations
defined on properties.
<li>
The following annotations (and related methods on RestCall) can now take <c>NameValuePairs</c> and beans as input
when using <js>"*"</js> as the name.
<br><dc>org.apache.juneau.remoteable.FormData</dc>,<dc>org.apache.juneau.remoteable.FormDataIfNE</dc>,
<dc>org.apache.juneau.remoteable.Query</dc>,<dc>org.apache.juneau.remoteable.QueryIfNE</dc>,
<dc>org.apache.juneau.remoteable.Header</dc>,<dc>org.apache.juneau.remoteable.HeaderIfNE</dc>
</ul>
<h5 class='topic w800'>org.apache.juneau.microservice</h5>
<ul class='spaced-list'>
</ul>
<h5 class='topic w800'>org.apache.juneau.examples.rest</h5>
<ul class='spaced-list'>
<li>
Many code enhancements make to examples to reflect new functionality.
<li>All pages now render aside comments to help explain what feature they're trying to explain using the
new features that allow you to customize various elements of the page.
<br>
<img class='bordered' width='50%' src='doc-files/ReleaseNotes.630.2.png'>
</ul>
</div>
</div><!-- END: 6.3.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#6.3.1' id='6.3.1'>6.3.1 (Aug 1, 2017)</a></h3>
<div class='topic'><!-- START: 6.3.1 -->
<div class='topic'>
<p>
Juneau 6.3.1 is a minor release.
</p>
<h5 class='topic w800'>org.apache.juneau</h5>
<ul class='spaced-list'>
<li>
<code>org.apache.juneau.utils.PojoQuery</code> improvements.
<li>
New <dc>RemoteMethod.returns()</dc> annotation.
<br>Allows you to specify whether the remote method returns the HTTP body or status code.
<li>
Fixed bugs with <dc>BEAN_includeProperties</dc> and <dc>BEAN_excludeProperties</dc> settings.
<li>
New/modified settings in <dc>HtmlDocSerializerContext</dc>:
<ul>
<li><dc>HTMLDOC_script</dc>
<li><dc>HTMLDOC_style</dc> - Was <jsf>HTMLDOC_css</jsf>.
<li><dc>HTMLDOC_stylesheet</dc> - Was <jsf>HTMLDOC_cssUrl</jsf>. Now an array.
</ul>
<li>
New <dc>ResourceFinder</dc> utility class.
Allows you to search for resources up the parent hierarchy chain.
Also allows you to search for localized resources.
<li>
Eliminated the following properties from <dc>HtmlDocSerializerContext</dc>:
<jsf>HTMLDOC_title</jsf>, <jsf>HTMLDOC_description</jsf>, <jsf>HTMLDOC_description</jsf>
<br>See below on changes to simplify HTML headers.
<li>
<a href="org/apache/juneau/svl/Var.html" title="class in org.apache.juneau.svl"><code>Var</code></a> implementations can now throw exceptions and will be converted to
<js>""{exceptionMessage}"</js> values.
</ul>
<h5 class='topic w800'>org.apache.juneau.rest</h5>
<ul class='spaced-list'>
<li>
New 'light' stylesheet:
<br><img src='doc-files/ReleaseNotes.631.LightStyle.png'>
<br>Compared with previous 'devops':
<br><img src='doc-files/ReleaseNotes.631.DevopsStyle.png'>
<br>For those nolstalgic for old times, there's also 'original':
<br><img src='doc-files/ReleaseNotes.631.OriginalStyle.png'>
<li>
Simplified the stylesheets and HTML code.
<br>For example, the nav links are now an ordered list of elements which makes rendering as as side-bar
(for example) easier to do in CSS.
<li>
Modifications to the following <ja>@HtmlDoc</ja> annotations:
<ul>
<li><dc>navlinks()</dc> - Now an array of strings instead of a JSON object. Simplified syntax.
<br>For example:
<p class='bcode'>
<jc>// Old syntax</jc>
htmldoc=<ja>@HtmlDoc</ja>(
links=<js>"{"</js>
+ <js>"up:'request:/..',"</js>
+ <js>"options:'servlet:/?method=OPTIONS',"</js>
+ <js>"contentTypes:'$W{ContentTypeMenuItem}',"</js>
+ <js>"styles:'$W{StyleMenuItem}',"</js>
+ <js>"source:'$C{Source/gitHub}/org/apache/juneau/examples/rest/PetStoreResource.java'"</js>
+ <js>"}"</js>
)
<jc>// New syntax</jc>
htmldoc=<ja>@HtmlDoc</ja>(
navlinks={
<js>"up: request:/.."</js>,
<js>"options: servlet:/?method=OPTIONS"</js>,
<js>"$W{ContentTypeMenuItem}"</js>,
<js>"$W{StyleMenuItem}"</js>,
<js>"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/PetStoreResource.java"</js>
}
)
</p>
Previous syntax will still work but you're encouraged to use the simplified syntax.
<li>Several annotations are now arrays of strings instead of simple strings.
Values are simply concatenated with newlines which makes multi-line values cleaner.
<ul>
<li><dc>header()</dc>
<li><dc>nav()</dc>
<li><dc>aside()</dc>
<li><dc>footer()</dc>
<li><dc>script()</dc>
<li><dc>style()</dc>
</ul>
Additionally, the <js>"INHERIT"</js> string literal can be used to combine the value with
the value defined on the servlet or parent class. Links can also be inserted at specific
index positions.
</ul>
<li>
Improvements made to the <a href="org/apache/juneau/rest/widget/Widget.html" title="class in org.apache.juneau.rest.widget"><code>Widget</code></a> API.
<ul>
<li>
You can now add arbitrary CSS and Javascript along with your widgets through new methods:
<ul>
<li><dc>Widget.getHtml(RestRequest)</dc>
<li><dc>Widget.getScript(RestRequest)</dc>
<li><dc>Widget.getStyle(RestRequest)</dc>
</ul>
</li>
<li>
Declaration of widgets moved to <dc>@HtmlDoc(widgets)</dc>
instead of separately on <dc>@RestResource</dc> and <ja>@RestMethod</ja> annotations.
<li>
<a href="org/apache/juneau/rest/widget/Widget.html#getName--"><code>Widget.getName()</code></a> now defaults to the simple class name.
<br>So now you can just refer to the class name: <js>"$W{ContentTypeMenuItem}"</js>.
<li>
Renamed widgets:
<ul>
<li><c>PoweredByApacheWidget</c> -> <c>PoweredByApache</c>
<li><c>PoweredByJuneauWidget</c> -> <c>PoweredByJuneau</c>
</ul>
<li>
New <a href="org/apache/juneau/rest/widget/MenuItemWidget.html" title="class in org.apache.juneau.rest.widget"><code>MenuItemWidget</code></a> can be used as a starting point for creatint pull-down menu items.
<li>
New <a href="org/apache/juneau/rest/widget/ContentTypeMenuItem.html" title="class in org.apache.juneau.rest.widget"><code>ContentTypeMenuItem</code></a> widget that provides a pull-down menu
with hyperlinks for all supported languages for that page:
<br><img src='doc-files/ReleaseNotes.631.ContentTypeMenuItem.png'>
<li>
Improved <a href="org/apache/juneau/rest/widget/QueryMenuItem.html" title="class in org.apache.juneau.rest.widget"><code>QueryMenuItem</code></a> widget that provides a pull-down menu
of a search/view/order-by/page form:
<br><img src='doc-files/ReleaseNotes.631.QueryMenuItem.png'>
<br>Fields are now pre-filled with current query parameters.
<li>
New <a href="org/apache/juneau/rest/widget/ThemeMenuItem.html" title="class in org.apache.juneau.rest.widget"><code>ThemeMenuItem</code></a> widget that provides a pull-down menu
with hyperlinks to show the content in the default stylesheets:
<br><img src='doc-files/ReleaseNotes.631.StyleMenuItem.png'>
</ul>
<li>
New/modified annotations on <dc>@HtmlDoc</dc>:
<ul>
<li><dc>style()</dc> - Renamed from <c>css()</c>.
<li><dc>stylesheet()</dc> - Renamed from <c>cssUrl()</c>.
<br>Can now be a comma-delimited list of URLs.
<li><dc>script()</dc> - Add arbitrary Javascript to page header.
</ul>
<li>
Bug fix with <dc>@HtmlDoc(nowrap)</dc> so that the setting only applies
to the data contents, not the whole page.
<li>
Two convenience methods added to <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>:
<ul>
<li><dc>RestRequest.attr(String,Object)</dc>
<li><dc>RestRequest.prop(String,Object)</dc>
</ul>
</li>
<li>
Annotations added:
<ul>
<li><dc>@RestResource(siteName)</dc>
<li><dc>@RestResource(flags)</dc>
<li><dc>@RestMethod(flags)</dc>
</ul>
</li>
<li>
Eliminated the <dc>@RestResource(stylesheet)</dc> annotation.
It's no longer needed now that you can easily specify styles via <ja>@Htmldoc</ja>.
<li>
Eliminated the following annotations since they are now redundant with <dc>@HtmlDoc(header)</dc>:
<ul>
<li><c>title()</c>
<li><c>description()</c>
<li><c>branding()</c>
</ul>
Instead, the <dc>org.apache.juneau.rest.BasicRestServlet</dc> class defines the following default header
that can be easily overridden:
<p class='bcode'>
htmldoc=<ja>@HtmlDoc</ja>(
header={
<js>"&lt;h1&gt;$R{resourceTitle}&lt;/h1&gt;"</js>,
<js>"&lt;h2&gt;$R{methodSummary,resourceDescription}&lt;/h2&gt;"</js>,
<js>"&lt;a href='http://juneau.apache.org'&gt;&lt;img src='$U{servlet:/htdocs/juneau.png}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/&gt;&lt;/a&gt;"</js>
}
)
</p>
Note that the subtitle first tries using the method summary and then the servlet description.
<li>
New <a href="org/apache/juneau/rest/vars/FileVar.html" title="class in org.apache.juneau.rest.vars"><code>$F</code></a> variable resolver for resolving the contents of
files in the classpath.
<br>The <c>DockerRegistryResource</c> examples shows how it can be used to pull in a localized
file from the classpath to populate the aside section of a page.
<p class='bcode'>
htmldoc=<ja>@HtmlDoc</ja>(
<jc>// Pull in aside contents from file.</jc>
aside=<js>"$F{resources/DockerRegistryResourceAside.html}"</js>
)
</p>
<li>
New <dc>ReaderResource.toCommentStrippedString()</dc> method.
<li>
The <c>bpIncludes()</c> and <c>bpExcludes()</c> annotations on <ja>@RestMethod</ja>
has been replaced with the following:
<ul>
<li><dc>bpi()</dc> - Now an array of simplified values instead of LAX JSON.
<li><dc>bpx()</dc> - Now an array of simplified values instead of LAX JSON.
</ul>
<li>
Two new variables added to <c>$R</c> variable: <js>"$R{servletClass}"</js>, <js>"$R{servletClassSimple}"</js>
</ul>
<h5 class='topic w800'>org.apache.juneau.rest.examples</h5>
<ul class='spaced-list'>
<li>
Added CONTENT-TYPE and STYLES menu items to most pages.
<li>
Added improved QUERY menu item to PetStore page.
</ul>
</div>
</div><!-- END: 6.3.1 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#6.4.0' id='6.4.0'>6.4.0 (Oct 5, 2017)</a></h3>
<div class='topic'><!-- START: 6.4.0 -->
<div class='topic'>
<p>
The major change in this release is the project structure.
</p>
<p>
The library now consists of the following artifacts found in the Maven group <c>"org.apache.juneau"</c>:
</p>
<table class='styled w800'>
<tr>
<th>Category</th><th>Maven Artifacts</th><th>Description</th><th>Prereqs</th>
</tr>
<tr class='dark bb'>
<td rowspan='5' style='text-align:center;font-weight:bold;padding:20px;'>Juneau Core</td>
<td class='code'>juneau-marshall</td>
<td>Serializers and parsers for:
<ul style='margin:0px 10px;'>
<li>JSON
<li>XML
<li>HTML
<li>UON
<li>URL-Encoding
<li>MessagePack
<li>SOAP/XML
<li>CSV
<li>BSON (coming soon)
<li>YAML (coming soon)
<li>Protobuf (coming soon)
</ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Java 6
</ul>
</td>
</tr>
<tr class='dark bb'>
<td class='code'>juneau-marshall-rdf</td>
<td>
Serializers and parsers for:
<ul style='margin:0px 10px;'>
<li>RDF/XML
<li>RDF/XML-Abbrev
<li>N-Triple
<li>Turtle
<li>N3
</ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Java 6
<li>Apache Jena 2.7.1
</ul>
</td>
</tr>
<tr class='dark bb'>
<td class='code'>juneau-dto</td>
<td>
Data Transfer Objects for:
<ul style='margin:0px 10px;'>
<li>HTML5
<li>Atom
<li>Cognos
<li>JSON-Schema
<li>Swagger 2.0
</ul>
</td>
<td><ul style='margin:0px 10px;'><li>Java 6</li></ul></td>
</tr>
<tr class='dark bb'>
<td class='code'>juneau-svl</td>
<td>
Simple Variable Language API
</td>
<td><ul style='margin:0px 10px;'><li>Java 6</li></ul></td>
</tr>
<tr class='dark bb'>
<td class='code'>juneau-config</td>
<td>
Configuration file API
</td>
<td><ul style='margin:0px 10px;'><li>Java 6</li></ul></td>
</tr>
<tr class='light bb'>
<td rowspan='3' style='text-align:center;font-weight:bold;padding:20px;'>Juneau REST</td>
<td class='code'>juneau-rest-server</td>
<td>
REST Servlet API
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Java 6
<li>Servlet 3.1
</ul>
</td>
</tr>
<tr class='light bb'>
<td class='code'>juneau-rest-server-jaxrs</td>
<td>
Optional JAX-RS support
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Java 6
<li>JAX-RS 2.0
</ul>
</td>
</tr>
<tr class='light bb'>
<td class='code'>juneau-rest-client</td>
<td>
REST Client API
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Java 6
<li>Apache HttpClient 4.5
</ul>
</td>
</tr>
<tr class='dark bb'>
<td rowspan='2' style='text-align:center;font-weight:bold;padding:20px;'>Juneau Microservice</td>
<td class='code'>juneau-microservice-server</td>
<td>
REST Microservice Server API
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Java 8
<li>Eclipse Jetty 9.4.3
</ul>
</td>
</tr>
<tr class='dark bb'>
<td class='code'>juneau-microservice-template</td>
<td>
Developer template project
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Java 8
<li>Eclipse Jetty 9.4.3
</ul>
</td>
</tr>
<tr class='light bb'>
<td rowspan='2' style='text-align:center;font-weight:bold;padding:20px;'>Examples</td>
<td class='code'><c>juneau-examples-core</c></td>
<td>
Core code examples
</td>
<td></td>
</tr>
<tr class='light bb'>
<td class='code'><c>juneau-examples-rest</c></td>
<td>
REST code examples
</td>
<td></td>
</tr>
<tr class='dark bb'>
<td rowspan='1' style='text-align:center;font-weight:bold;padding:20px;'>Juneau All</td>
<td class='code'><c>juneau-all</c></td>
<td>
Combination of the following:
<ul style='margin:0px 10px;'>
<li>juneau-marshall
<li>juneau-dto
<li>juneau-svl
<li>juneau-config
<li>juneau-rest-server
<li>juneau-rest-client
</ul>
</td>
<td>
<ul style='margin:0px 10px;'>
<li>Java 6
<li>Servlet 3.1
<li>Apache HttpClient 4.5
</ul>
</td>
</tr>
</table>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
Improvements to swap support.
<ul>
<li>New <a href="org/apache/juneau/annotation/Swap.html" title="annotation in org.apache.juneau.annotation"><code>@Swap</code></a> annotation.
<br>Replaces the <c>@Pojo</c> and <dc>@BeanProperty(swap)</dc> annotations.
<li>Support for per-media-type swaps.
<br>Programmatic example:
<p class='bcode'>
<ja>@Swap</ja>(MyJsonOnlySwap.<jk>class</jk>)
<jk>public class</jk> MyPojo {}
<jk>public class</jk> MyJsonOnlySwap <jk>extends</jk> PojoSwap&lt;MyPojo,String&gt; {
<jk>public</jk> MediaType[] forMediaTypes() {
<jk>return</jk> MediaType.<jsm>forStrings</jsm>(<js>"&#42;/json"</js>);
}
<jk>public</jk> String swap(BeanSession session, MyPojo o) <jk>throws</jk> Exception {
<jk>return</jk> <js>"It's JSON!"</js>;
}
</p>
<br>Annotated example:
<p class='bcode'>
<ja>@Swap</ja>(impl=ToStringSwap.<jk>class</jk>, mediaTypes=<js>"&#42;/json"</js>)
<jk>public class</jk> MyBean { ... }
<jk>public class</jk> ToStringSwap <jk>extends</jk> PojoSwap&lt;Object,String&gt; {
<jk>public</jk> String swap(BeanSession session, Object o) <jk>throws</jk> Exception {
<jk>return</jk> o.toString();
}
}
</p>
<li>Support for templated swaps which provide additional context information for a swap.
<br>The following is an example of a templated swap class used to serialize POJOs to HTML using FreeMarker:
<p class='bcode'>
<jc>// Our abstracted templated swap class.</jc>
<jk>public abstract class</jk> FreeMarkerSwap <jk>extends</jk> PojoSwap&lt;Object,Reader&gt; {
<jk>public</jk> MediaType[] forMediaTypes() {
<jk>return</jk> MediaType.<jsm>forStrings</jsm>(<js>"&#42;/html"</js>);
}
<jk>public</jk> Reader swap(BeanSession session, Object o, String template) <jk>throws</jk> Exception {
<jk>return</jk> getFreeMarkerReader(template, o); <jc>// Some method that creates raw HTML.</jc>
}
}
</p>
<p class='bcode'>
<ja>@Swap</ja>(impl=FreeMarkerSwap.<jk>class</jk>, template=<js>"MyPojo.div.ftl"</js>)
<jk>public class</jk> MyPojo {}
</p>
<li>New <dc>@Swaps</dc> annotation for defining multiple swaps
against the same POJO when they're differentiated by media types:
<p class='bcode'>
<ja>@Swaps</ja>(
{
<ja>@Swap</ja>(MyJsonSwap.<jk>class</jk>),
<ja>@Swap</ja>(MyXmlSwap.<jk>class</jk>),
<ja>@Swap</ja>(MyOtherSwap.<jk>class</jk>)
}
)
<jk>public class</jk> MyPojo {}
</p>
</ul>
<li>
New <dc>org.apache.juneau.transform.Surrogate</dc> interface for identifying surrogate classes.
<li>
Serializers can now serialize to <a href="https://docs.oracle.com/javase/8/docs/api/java/util/StringBuilder.html?is-external=true" title="class or interface in java.util"><code>StringBuilders</code></a>.
<li>
Serializers now serialize the contents of <a href="https://docs.oracle.com/javase/8/docs/api/java/io/Reader.html?is-external=true" title="class or interface in java.io"><code>Readers</code></a> and <a href="https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html?is-external=true" title="class or interface in java.io"><code>InputStreams</code></a>
directly to the output stream or writer.
<br>When used with conjunction with <c>PojoSwaps</c>, this can be used to provide customized
output for specific content types.
<p class='bcode'>
<ja>@Pojo</ja>(swap=MyBeanSwap.<jk>class</jk>)
<jk>public class</jk> MyBean {...}
<jk>public class</jk> MyBeanSwap <jk>extends</jk> PojoSwap&lt;MyBean,Object&gt; {
<jk>public</jk> Object swap(BeanSession session, MyPojo o) <jk>throws</jk> Exception {
MediaType mt = session.getMediaType();
<jk>if</jk> (mt.hasSubType(<js>"json"</js>))
<jk>return new</jk> StringReader(<js>"{foo:'bar'}"</js>); <jc>// Custom JSON output</jc>
<jk>return</jk> o; <jc>// Otherwise treat as normal bean</jc>
}
}
<jc>// Produces "{foo:'bar'}"</jc>
String json = SimpleJsonSerializer.<jsf>DEFAULT</jsf>
.toString(<jk>new</jk> MyBean());
</p>
<br>This feature helps with the implementation of language-agnostic template support such as for
using FreeMaker to serialize POJOs to HTML.
<li>
<a href="org/apache/juneau/serializer/SerializerSession.html" title="class in org.apache.juneau.serializer"><code>SerializerSession</code></a> and <a href="org/apache/juneau/parser/ParserSession.html" title="class in org.apache.juneau.parser"><code>ParserSession</code></a>
objects are now reusable if used within the same thread.
<p class='bcode'>
<jc>// Old way (still works)</jc>
JsonSerializer.<jsf>DEFAULT</jsf>.serialize(writer1, pojo1);
JsonSerializer.<jsf>DEFAULT</jsf>.serialize(writer2, pojo2);
<jc>// Same but using a session object</jc>
SerializerSession session = JsonSerializer.<jsf>DEFAULT</jsf>.createSession();
<jk>try</jk> {
session.serialize(writer1, pojo1);
session.serialize(writer2, pojo2);
} <jk>finally</jk> {
session.close();
}
</p>
This is mostly an internal change and doesn't affect the existing APIs.
<li>
<dc>PojoSwap.swap(BeanSession,Object)</dc> and <dc>PojoSwap.unswap(BeanSession,Object,ClassMeta)</dc>
can now throw arbitrary exceptions instead of having to wrap them in <c>SerializeException</c>/<c>ParseException</c>.
<li>
New <dc>org.apache.juneau.utils.CalendarUtils</dc> class that encapsulates serialization/parsing logic from <dc>org.apache.juneau.transforms.CalendarSwap</dc> and
<dc>org.apache.juneau.transforms.DateSwap</dc>.
<li>
New annotation <a href="org/apache/juneau/html/annotation/Html.html#anchorText--"><code>Html.anchorText()</code></a>.
<li>
New methods on <dc>org.apache.juneau.ObjectList</dc>:
<ul>
<li><dc>get(int,Class)</dc>
<li><dc>get(int,Type,Type...)</dc>
<li><dc>getMap(int,Class,Class)</dc>
<li><dc>getList(int,Class)</dc>
</ul>
<li>
New methods on <dc>org.apache.juneau.ObjectMap</dc>:
<ul>
<li><dc>get(String,Class)</dc>
<li><dc>get(String,Type,Type...)</dc>
<li><dc>getWithDefault(String,Object)</dc>
<li><dc>getWithDefault(String,Object,Class)</dc>
<li><dc>getWithDefault(String,Object,Type,Type...)</dc>
<li><dc>getSwapped(String,PojoSwap)</dc>
<li><dc>getAt(String,Class)</dc>
<li><dc>getAt(String,Type,Type...)</dc>
<li><dc>getMap(String,Class,Class,Map)</dc>
<li><dc>getList(String,Class,List)</dc>
</ul>
<li>
New methods on <dc>org.apache.juneau.utils.PojoRest</dc>:
<ul>
<li><dc>get(String,Class)</dc>
<li><dc>get(String,Type,Type...)</dc>
<li><dc>getWithDefault(String,Object)</dc>
<li><dc>getWithDefault(String,Object,Class)</dc>
<li><dc>getWithDefault(String,Object,Type,Type...)</dc>
</ul>
<li>
Fixed bug where <a href="org/apache/juneau/BeanSession.html#getMediaType--"><code>BeanSession.getMediaType()</code></a> wasn't returning a value.
<li>
Eliminated the <ja>@Consumes</ja> and <ja>@Produces</ja> annotations.
<br>The supported media types are now passed in through the constructors.
<br>This was changed to eliminate a performance issue where a field could not be set as final because
the call to <c>getClass()</c> to retrieve the annotation value could not be called before calling
the <c><jk>super</jk>()</c> method.
<li>
New class: <dc>org.apache.juneau.utils.PojoMerge</dc>
<li>
New doc: <dc>2.6.2 - @Pojo annotation</dc>
<li>
New doc: <dc>2.6.5 - Serializing Readers and InputStreams</dc>
</ul>
<h5 class='topic w800'>juneau-dto</h5>
<ul class='spaced-list'>
<li>
<a href="org/apache/juneau/dto/html5/HtmlElementMixed.html#children-java.lang.Object...-"><code>HtmlElementMixed.children(Object...)</code></a> can now take in collections
of objects.
<li>
The DTO beans can now be serialized to strings of their typical language by calling the <c>toString()</c> method.
<br>For example, <c>Swagger.toString()</c> produces JSON and the HTML5 <c>Form.toString()</c>
produces HTML.
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
Revamped and simplified servlet and REST-call lifecycle handling through new
<a href="org/apache/juneau/rest/annotation/RestHook.html" title="annotation in org.apache.juneau.rest.annotation"><code>@RestHook</code></a> annotation.
<ul>
<li>The <dc>RestServlet.init(ServletConfig)</dc> method is now final and can
no longer be extended.
<br>Instead, use <a href="org/apache/juneau/rest/annotation/HookEvent.html#INIT"><code>HookEvent.INIT</code></a> or
<a href="org/apache/juneau/rest/annotation/HookEvent.html#POST_INIT"><code>HookEvent.POST_INIT</code></a> for initialization.
<li>The following methods on <dc>org.apache.juneau.rest.RestServlet</dc> have been removed:
<ul>
<li><c>init(RestConfig)</c>
- Use <a href="org/apache/juneau/rest/annotation/HookEvent.html#INIT"><code>HookEvent.INIT</code></a> instead.
<li><c>onSuccess(RestRequest, RestResponse, long)</c>
- Use <a href="org/apache/juneau/rest/annotation/HookEvent.html#END_CALL"><code>HookEvent.END_CALL</code></a> instead.
<li><c>onPreCall(RestRequest)</c>
- Use <a href="org/apache/juneau/rest/annotation/HookEvent.html#PRE_CALL"><code>HookEvent.PRE_CALL</code></a> instead.
<li><c>onPostCall(RestRequest, RestResponse)</c>
- Use <a href="org/apache/juneau/rest/annotation/HookEvent.html#POST_CALL"><code>HookEvent.POST_CALL</code></a> instead.
</ul>
</ul>
<li>
Simplified <a href="org/apache/juneau/rest/widget/MenuItemWidget.html" title="class in org.apache.juneau.rest.widget"><code>MenuItemWidget</code></a>.
<br>Exposes an abstract method <dc>getContent(RestRequest)</dc> that
can return raw HTML via readers or char-sequences, or any other object (such as HTML5 beans) that will
get converted to HTML using <a href="org/apache/juneau/html/HtmlSerializer.html#DEFAULT"><code>HtmlSerializer.DEFAULT</code></a>.
<li>
<dc>org.apache.juneau.rest.RestResourceResolver</dc> instances are now inherited from parent resources to child resources
unless explicitly overridden at the child level.
<br>It's also been changed to an interface.
<li>New annotations on <dc>@RestResource</dc>:
<ul>
<li><dc>resourceResolver()</dc>
<br>Allows you to specify a resource resolver on the servlet context to make it easier to work with
dependency injection frameworks.
<li><dc>contextPath()</dc> -
<br>Allows you to override the context path value inherited from the servlet container.
<li><dc>allowHeaderParams()</dc> -
<br>Replaces the <c>RestContext.REST_allowHeaderParams</c> setting.
<li><dc>allowMethodParam()</dc> -
<br>Replaces the <c>RestContext.REST_allowMethodParam</c> setting.
<li><dc>allowBodyParam()</dc> -
<br>Replaces the <c>RestContext.REST_allowBodyParam</c> setting.
<li><dc>renderResponseStackTraces()</dc> -
<br>Replaces the <c>RestContext.REST_xxx</c> setting.
<li><dc>useStackTraceHashes()</dc> -
<br>Replaces the <c>RestContext.REST_useStackTraceHashes</c> setting.
<li><dc>defaultCharset()</dc> -
<br>Replaces the <c>RestContext.REST_defaultCharset</c> setting.
<li><dc>paramFormat()</dc> -
<br>Replaces the <c>RestContext.REST_paramFormat</c> setting.
</ul>
<li>New annotations on <dc>@RestMethod</dc>:
<ul>
<li><dc>defaultCharset()</dc> -
<br>Replaces the <c>RestContext.REST_defaultCharset</c> setting.
<li><dc>RestMethod.paramFormat()</dc> -
<br>Replaces the <c>RestContext.REST_paramFormat</c> setting.
</ul>
<li>
The following implementation classes can now be defined as non-static inner classes of servlets/resources:
<ul>
<li><a href="org/apache/juneau/rest/widget/Widget.html" title="class in org.apache.juneau.rest.widget"><code>Widget</code></a>
<li><code>org.apache.juneau.rest.RestConverter</code>
<li><dc>org.apache.juneau.rest.RestGuard</dc>
<li><code>org.apache.juneau.rest.ResponseHandler</code>
<li><dc>org.apache.juneau.rest.RestCallHandler</dc>
<li><dc>org.apache.juneau.rest.RestInfoProvider</dc>
<li><dc>org.apache.juneau.rest.RestResourceResolver</dc>
<li><dc>org.apache.juneau.rest.RestLogger</dc>
<li><a href="org/apache/juneau/html/HtmlDocTemplate.html" title="interface in org.apache.juneau.html"><code>HtmlDocTemplate</code></a>
</ul>
<li>
New tooltip template: <a href="org/apache/juneau/rest/widget/Tooltip.html" title="class in org.apache.juneau.rest.widget"><code>Tooltip</code></a>
<li>
New dark theme:
<br><img src='doc-files/ReleaseNotes.632.DarkStyle.png'>
<li>
Stylesheet selection now stored in HTTP session when passed in via <c>?stylesheet</c> query parameter.
<li>
New doc: <dc>Lifecycle Hooks</dc>
<li>
Eliminated the <c>RestServletJenaDefault</c> class to remove the Jena dependency class on
the <c>juneau-rest-server</c> artifact.
<br>It's simple enough to simply extend <c>BasicRestServlet</c> and add the RDF serializers and
parsers.
</ul>
<h5 class='topic w800'>juneau-microservice</h5>
<ul class='spaced-list'>
<li>
The microservice has been significantly modified to be configured via a <c>jetty.xml</c> file
for maximum flexibility instead of the hodge-podge of support in the config file.
<br>Top-level servlets should now be defined in the provided <c>jetty.xml</c> file.
<li>
New methods on <dc>RestMicroservice</dc>:
<ul>
<li><dc>addServlet(Servlet,String)</dc>
<li><dc>addServletAttribute(String,Object)</dc>
<li><dc>getServer()</dc>
<li><dc>getInstance()</dc>
<li><dc>getPort()</dc>
<li><dc>getContextPath()</dc>
<li><dc>getProtocol()</dc>
<li><dc>getHostName()</dc>
</ul>
<li>
New methods on <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a>:
<ul>
<li><a href="org/apache/juneau/microservice/Microservice.html#getInstance--"><code>getInstance()</code></a>
</ul>
<li>
New class <dc>JettyLogger</dc> for directing Jetty logging to the
java.util.logging framework.
<li>
New class <dc>DebugResource</dc> for viewing and generating
Jetty thread dumps through REST calls.
</ul>
<h5 class='topic w800'>org.apache.juneau.rest.examples</h5>
<ul class='spaced-list'>
<li>
New example of adding a menu-item widget to the Pet Store resource (including tooltips):
<br><img src='doc-files/ReleaseNotes.632.PetStoreAdd.png'>
</ul>
</div>
</div><!-- END: 6.4.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#7.0.0' id='7.0.0'>7.0.0 (Oct 25, 2017)</a></h3>
<div class='topic'><!-- START: 7.0.0 -->
<div class='topic'>
<p>
This release ups the Java prerequisite to Java 7.
</p>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
New class <dc>org.apache.juneau.http.HttpMethodName</dc> with valid static string HTTP method names.
</ul>
<h5 class='topic w800'>juneau-dto</h5>
<ul class='spaced-list'>
<li>
Class <c>org.apache.juneau.dto.Link</c> renamed to <a href="org/apache/juneau/dto/LinkString.html" title="class in org.apache.juneau.dto"><code>LinkString</code></a>.
Helps avoid confusion since there are other Link classes in the library.
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
Annotation <c><ja>@HtmlDoc</ja>(links)</c> renamed to <dc>navlinks</dc>.
<li>
New annotation <dc>@HtmlDoc(head)</dc>.
<br>Allows you to specify arbitrary HTML content in the <xt>&lt;head&gt;</xt> section of the page.
<li>
Removed annotation <c><ja>@HtmlDoc</ja>(favIcon)</c>.
<br>This was a discouraged way of defining fav-icons anyway, and with the addition of
<c><ja>@HtmlDoc</ja>(head)</c>, you can define them using:
<p class='bcode'>
head={
<js>"&lt;link rel='icon' href='$U{servlet:/htdocs/juneau.png}'/&gt;"</js>
}
</p>
<li>
Removed several of the HTMLDOC-related methods from the <c>RestResponse/RestConfig/RestContext</c>
classes and moved it into the new <dc>org.apache.juneau.rest.HtmlDocBuilder</dc> class.
</ul>
</div>
</div><!-- END: 7.0.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#7.0.1' id='7.0.1'>7.0.1 (Dec 24, 2017)</a></h3>
<div class='topic'><!-- START: 7.0.1 -->
<div class='topic'>
<p>
This release is a minor update.
It includes the following prereq updates:
</p>
<ul class='spaced-list'>
<li>Apache HttpClient: 4.5.3 to 4.5.4
<li>Eclipse Jetty: 9.4.6.v20170531 to 9.4.8.v20171121
</ul>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>New static <c>create()</c> methods for builders on serializers and parsers.
<br>This simplifies the syntax of creation of serializers and parsers by scratch.
<p class='bcode'>
<jc>// Old way</jc>
JsonSerializer s1 = <jk>new</jk> JsonSerializer.Builder().ws().build();
<jc>// New way</jc>
JsonSerializer s2 = JsonSerializer.<jsm>create</jsm>().ws().build();
</p>
<br>The same static create methods have also been added to the following classes:
<ul>
<li><dc>SerializerGroup.create()</dc>
<li><dc>ParserGroup.create()</dc>
<li><dc>EncoderGroup.create()</dc>
<li><a href="org/apache/juneau/rest/client/RestClient.html#create--"><code>RestClient.create()</code></a>
<li><dc>ConfigFile.create()</dc>
</ul>
<li>
The order of the parameters in <a href="org/apache/juneau/serializer/SerializerSession.html#serialize-java.lang.Object-java.lang.Object-"><code>SerializerSession.serialize(Object,Object)</code></a>
has been change to match <a href="org/apache/juneau/serializer/Serializer.html#serialize-java.lang.Object-java.lang.Object-"><code>Serializer.serialize(Object,Object)</code></a>.
<li>
Fixed some bugs in the XML parser related to whitespace and comments.
</ul>
<h5 class='topic w800'>juneau-svl</h5>
<ul class='spaced-list'>
<li>New methods on <a href="org/apache/juneau/svl/Var.html" title="class in org.apache.juneau.svl"><code>Var</code></a> class to restrict when nested and embedded variables
are resolved.
<ul>
<li><a href="org/apache/juneau/svl/Var.html#allowNested--"><code>Var.allowNested()</code></a>
<li><a href="org/apache/juneau/svl/Var.html#allowRecurse--"><code>Var.allowRecurse()</code></a>
</ul>
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
New <dc>@RestResource(maxInput)</dc> and
<dc>@RestMethod(maxInput)</dc> for alleviating
potential DoS attacks.
</ul>
<h5 class='topic w800'>juneau-microservice-server</h5>
<ul class='spaced-list'>
<li>
New pluggable console commands.
<br>When you start up the microservice, you'll now see the following:
<p class='bcode'>
Running class 'RestMicroservice' using config file 'examples.cfg'.
Server started on port 10000
List of available commands:
exit -- Shut down service
restart -- Restarts service
help -- Commands help
echo -- Echo command
&gt; <span style='color:green'>help help</span>
NAME
help -- Commands help
SYNOPSIS
help [command]
DESCRIPTION
When called without arguments, prints the descriptions of all available commands.
Can also be called with one or more arguments to get detailed information on a command.
EXAMPLES
List all commands:
&gt; help
List help on the help command:
&gt; help help
&gt;
</p>
<p>
Commands are pluggable and extensible through the config file.
<p class='bcode'>
<cc>#=======================================================================================================================
# Console settings
#=======================================================================================================================</cc>
<cs>[Console]</cs>
<ck>enabled</ck> = <cv>true</cv>
<cc># List of available console commands.
# These are classes that implements ConsoleCommand that allow you to submit commands to the microservice via
# the console.
# When listed here, the implementations must provide a no-arg constructor.
# They can also be provided dynamically by overriding the Microservice.createConsoleCommands() method.</cc>
<ck>commands</ck> =
<cv>org.apache.juneau.microservice.console.ExitCommand,
org.apache.juneau.microservice.console.RestartCommand,
org.apache.juneau.microservice.console.HelpCommand</cv>
</p>
<ul>
<li>New classes:
<ul>
<li><a href="org/apache/juneau/microservice/console/ConsoleCommand.html" title="class in org.apache.juneau.microservice.console"><code>ConsoleCommand</code></a>
<li><a href="org/apache/juneau/microservice/console/ExitCommand.html" title="class in org.apache.juneau.microservice.console"><code>ExitCommand</code></a>
<li><a href="org/apache/juneau/microservice/console/RestartCommand.html" title="class in org.apache.juneau.microservice.console"><code>RestartCommand</code></a>
<li><a href="org/apache/juneau/microservice/console/HelpCommand.html" title="class in org.apache.juneau.microservice.console"><code>HelpCommand</code></a>
</ul>
<li>New methods on <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a>
<ul>
<li><a href="org/apache/juneau/microservice/Microservice.html#startConsole--"><code>startConsole()</code></a>
<li><dc>createConsoleCommands()</dc>
<li><a href="org/apache/juneau/microservice/Microservice.html#getConsoleReader--"><code>getConsoleReader()</code></a>
<li><a href="org/apache/juneau/microservice/Microservice.html#getConsoleWriter--"><code>getConsoleWriter()</code></a>
</ul>
</ul>
<li>
Console input reader and output writer can now be overridden.
<li>
Console strings are now internationalized.
</ul>
</div>
</div><!-- END: 7.0.1 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#7.1.0' id='7.1.0'>7.1.0 (Mar 08, 2018)</a></h3>
<div class='topic'><!-- START: 7.1.0 -->
<div class='topic'>
<p>
Version 7.1.0 is a major update with major implementation refactoring across all aspects of the product.
</p>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
Significant improvements made to the internals of the Serializer and Parser classes.
<ul>
<li>
Caching improvements on serializers and parsers have reduced execution time of the core
JUnits by approximately 1/3.
<br>The 17000+ JUnit tests now execute in less than 10 seconds and have a cache-reuse hit rate
of 98% (164104 serializers/parsers/bean-contexts retrieved but only 1801 created from scratch).
<li>
All the various separate <c>Context</c> classes (e.g. <c>JsonSerializerContext</c>) have been folded into
their respective serializer or parser classes (e.g. <c>JsonSerializer</c>).
<br>Additionally, these classes are their own bean contexts.
<br>For example, the class hierarchy of <c>JsonSerializer</c> is now:
<ul class='doctree'>
<li class='jac'><a href="org/apache/juneau/Context.html" title="class in org.apache.juneau"><code>Context</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/BeanContext.html" title="class in org.apache.juneau"><code>BeanContext</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.html" title="class in org.apache.juneau.serializer"><code>Serializer</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializer.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/json/JsonSerializer.html" title="class in org.apache.juneau.json"><code>JsonSerializer</code></a>
</ul>
</ul>
</ul>
</ul>
</ul>
All <c>Context</c> objects are thread-safe and read-only.
<li>
Session objects also now have a consistent class hierarchy.
<br>For example, the class hierarchy of <c>JsonSerializerSession</c> is now:
<ul class='doctree'>
<li class='jac'><code>org.apache.juneau.Session</code>
<ul>
<li class='jc'><a href="org/apache/juneau/BeanSession.html" title="class in org.apache.juneau"><code>BeanSession</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/SerializerSession.html" title="class in org.apache.juneau.serializer"><code>SerializerSession</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/WriterSerializerSession.html" title="class in org.apache.juneau.serializer"><code>WriterSerializerSession</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/json/JsonSerializerSession.html" title="class in org.apache.juneau.json"><code>JsonSerializerSession</code></a>
</ul>
</ul>
</ul>
</ul>
</ul>
Session objects are transient objects that live for the duration of a single parse.
<li>
Builder objects also now have a consistent class hierarchy.
<br>For example, the class hierarchy of <c>JsonSerializer.Builder</c> is now:
<ul class='doctree'>
<li class='jac'><a href="org/apache/juneau/Context.Builder.html" title="class in org.apache.juneau"><code>Context.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
<ul>
<li class='jac'><a href="org/apache/juneau/serializer/Serializer.Builder.html" title="class in org.apache.juneau.serializer"><code>Serializer.Builder</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/json/JsonSerializer.Builder.html" title="class in org.apache.juneau.json"><code>JsonSerializer.Builder</code></a>
</ul>
</ul>
</ul>
</ul>
Builder objects are used for building up and creating <c>Context</c> objects.
<li>
The <code>org.apache.juneau.PropertyStore</code> class has been completely rewritten.
It is now a read-only configuration store build using the <code>org.apache.juneau.PropertyStoreBuilder</code>
class.
<br>The previous <c>PropertyStore</c> class was overly-complicated with many read/write
locks to ensure thread-safety.
<br>The new design shifts to a builder-based model with read-only <c>PropertyStore</c> objects
that can be used as hash keys.
</ul>
<li>
Improvements to the HTTP-Part APIs.
<br>The existing <c>PartSerializer</c>/<c>PartParser</c> classes
have been replaced with the following all located in the new <c>org.apache.juneau.httppart</c> package:
<ul class='doctree'>
<li class='jp'><a href="org/apache/juneau/httppart/package-summary.html"><code>org.apache.juneau.httppart</code></a>
<ul>
<li class='jc'><a href="org/apache/juneau/httppart/HttpPartType.html" title="enum in org.apache.juneau.httppart"><code>HttpPartType</code></a>
<li class='jic'><a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a>
<ul>
<li class='jc'><dc>UonPartSerializer</dc>
<li class='jc'><dc>SimpleUonPartSerializer</dc>
<li class='jc'><a href="org/apache/juneau/httppart/SimplePartSerializer.html" title="class in org.apache.juneau.httppart"><code>SimplePartSerializer</code></a>
</ul>
<li class='jic'><a href="org/apache/juneau/httppart/HttpPartParser.html" title="interface in org.apache.juneau.httppart"><code>HttpPartParser</code></a>
<ul>
<li class='jc'><dc>UonPartParser</dc>
<li class='jc'><dc>SimplePartParser</dc>
</ul>
</ul>
</ul>
Code for marshalling of parts have been removed from the URL-Encoding serializers and parsers.
<li>
<c>Context.Builder.property(String,Object)</c> renamed to <dc>Builder.set(String,Object)</dc>.
<li>
<c>ResourceFinder</c> class has been replaced with the following:
<ul>
<li><dc>org.apache.juneau.utils.ClasspathResourceFinder</dc>
<li><dc>org.apache.juneau.utils.ClasspathResourceFinderSimple</dc>
<li><dc>org.apache.juneau.utils.ClasspathResourceFinderBasic</dc>
<li><dc>org.apache.juneau.utils.ClasspathResourceFinderRecursive</dc>
<li><dc>org.apache.juneau.utils.ClasspathResourceManager</dc>
</ul>
<li>
New methods on <a href="org/apache/juneau/serializer/SerializerSession.html" title="class in org.apache.juneau.serializer"><code>SerializerSession</code></a>:
<ul>
<li><a href="org/apache/juneau/serializer/SerializerSession.html#getListener--"><code>getListener()</code></a>
<li><a href="org/apache/juneau/serializer/SerializerSession.html#getListener-java.lang.Class-"><code>getListener(Class)</code></a>
</ul>
<li>
New methods on <a href="org/apache/juneau/parser/ParserSession.html" title="class in org.apache.juneau.parser"><code>ParserSession</code></a>:
<ul>
<li><a href="org/apache/juneau/parser/ParserSession.html#getListener--"><code>getListener()</code></a>
<li><a href="org/apache/juneau/parser/ParserSession.html#getListener-java.lang.Class-"><code>getListener(Class)</code></a>
</ul>
<li>
New <dc>Parser.PARSER_unbuffered</dc> setting allows you to disable internal
buffering on the JSON and UON parsers so that they can be used to read continous streams of objects.
<li>
New <dc>JsonParser.JSON_validateEnd</dc> and <dc>UonParser.UON_validateEnd</dc>
settings allow you to control whether we validate that there is no garbage at the end of the parsed input.
<li>
New <dc>Parser.PARSER_autoCloseStreams</dc> setting allows input streams and
readers passed into parsers to be automatically closed after parsing.
<li>
Syntax changed on unswap method on <dc>org.apache.juneau.transform.Surrogate</dc> classes.
<br>It's now a regular method instead of a static method.
<li>
<a href="org/apache/juneau/annotation/Swap.html" title="annotation in org.apache.juneau.annotation"><code>@Swap</code></a> annotation can now be used with
<dc>org.apache.juneau.transform.Surrogate</dc> classes.
<li>
New support for <dc>POJO Builders</dc>.
</ul>
<h5 class='topic w800'>juneau-svl</h5>
<ul class='spaced-list'>
<li>
New variables:
<ul>
<li><a href="org/apache/juneau/svl/vars/CoalesceVar.html" title="class in org.apache.juneau.svl.vars"><code>CoalesceVar</code></a>
<li><a href="org/apache/juneau/svl/vars/PatternMatchVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternMatchVar</code></a>
<li><a href="org/apache/juneau/svl/vars/NotEmptyVar.html" title="class in org.apache.juneau.svl.vars"><code>NotEmptyVar</code></a>
<li><a href="org/apache/juneau/svl/vars/UpperCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>UpperCaseVar</code></a>
<li><a href="org/apache/juneau/svl/vars/LowerCaseVar.html" title="class in org.apache.juneau.svl.vars"><code>LowerCaseVar</code></a>
</ul>
<li>
Variables moved from <l>juneau-microservice</l>:
<ul>
<li><a href="org/apache/juneau/svl/vars/ArgsVar.html" title="class in org.apache.juneau.svl.vars"><code>ArgsVar</code></a>
<li><a href="org/apache/juneau/svl/vars/ManifestFileVar.html" title="class in org.apache.juneau.svl.vars"><code>ManifestFileVar</code></a>
</ul>
</ul>
<h5 class='topic w800'>juneau-config</h5>
<ul class='spaced-list'>
<li>
The Config API has been completely revamped.
<br>New features include:
<ul>
<li>Support for pluggable storage.
<li>File-system watcher integration support.
<br>Changes made to file system files now automatically reflected in configurations
and interface proxies.
<li>New builder-based design.
</ul>
</ul>
<h5 class='topic w800'>juneau-dto</h5>
<ul class='spaced-list'>
<li>
Enhancements to Swagger DTO:
<ul>
<li>New methods for setting and retrieving properties via name:
<ul>
<li><a href="org/apache/juneau/dto/swagger/SwaggerElement.html#get-java.lang.String-java.lang.Class-"><code>SwaggerElement.get(String,Class)</code></a>
<li><a href="org/apache/juneau/dto/swagger/SwaggerElement.html#set-java.lang.String-java.lang.Object-"><code>SwaggerElement.set(String,Object)</code></a>
</ul>
<li>
Support for setting non-standard fields such as <js>"$ref"</js> via getter and setter
above.
<li>
Setter methods that take in beans and collections of beans can now take in
JSON strings.
</ul>
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
<c>RestServletDefault</c> renamed to <dc>org.apache.juneau.rest.BasicRestServlet</dc>.
<li>
<c>RestServletGroupDefault</c> renamed to <dc>org.apache.juneau.rest.BasicRestServletGroup</dc>.
<li>
The <js>"$R{...}"</js> variable has been split into the following:
<ul>
<li><js>"$RA{key1[,key2...]}"</js> - <a href="org/apache/juneau/rest/vars/RequestAttributeVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestAttributeVar</code></a>, first non-null value returned by <c>HttpServletRequest.getAttribute(String)</c>.
<li><js>"$RF{key1[,key2...]}"</js> - <a href="org/apache/juneau/rest/vars/RequestFormDataVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestFormDataVar</code></a>, first non-null value returned by <dc>RestRequest.getFormData(String)</dc>.
<li><js>"$RH{key1[,key2...]}"</js> - <a href="org/apache/juneau/rest/vars/RequestHeaderVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestHeaderVar</code></a>, first non-null value returned by <a href="org/apache/juneau/rest/RestRequest.html#getHeader-java.lang.String-"><code>RestRequest.getHeader(String)</code></a>.
<li><js>"$RI{key1[,key2...]}"</js> - <dc>org.apache.juneau.rest.vars.RestInfoVar</dc>, first non-null value returned by <dc>RestRequest.getInfoProvider()</dc>.
<br>The possible values are:
<ul>
<li><js>"contact"</js> - Value returned by <a href="org/apache/juneau/dto/swagger/Info.html#getContact--"><code>Info.getContact()</code></a>
<li><js>"description"</js> - Value returned by <dc>RestInfoProvider.getDescription(RestRequest)</dc>
<li><js>"externalDocs"</js> - Value returned by <a href="org/apache/juneau/dto/swagger/Swagger.html#getExternalDocs--"><code>Swagger.getExternalDocs()</code></a>
<li><js>"license"</js> - Value returned by <a href="org/apache/juneau/dto/swagger/Info.html#getLicense--"><code>Info.getLicense()</code></a>
<li><js>"methodDescription"</js> - Value returned by <dc>RestInfoProvider.getMethodDescription(Method,RestRequest)</dc>
<li><js>"methodSummary"</js> - Value returned by <dc>RestInfoProvider.getMethodSummary(Method,RestRequest)</dc>
<li><js>"siteName"</js> - Value returned by <dc>RestInfoProvider.getSiteName(RestRequest)</dc>
<li><js>"tags"</js> - Value returned by <a href="org/apache/juneau/dto/swagger/Swagger.html#getTags--"><code>Swagger.getTags()</code></a>
<li><js>"termsOfService"</js> - Value returned by <a href="org/apache/juneau/dto/swagger/Info.html#getTermsOfService--"><code>Info.getTermsOfService()</code></a>
<li><js>"title"</js> - See <dc>RestInfoProvider.getTitle(RestRequest)</dc>
<li><js>"version"</js> - See <a href="org/apache/juneau/dto/swagger/Info.html#getVersion--"><code>Info.getVersion()</code></a>
</ul>
<li><js>"$RP{key1[,key2...]}"</js> - <a href="org/apache/juneau/rest/vars/RequestPathVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestPathVar</code></a>, first non-null value returned by <dc>RestRequest.getPath(String)</dc>.
<li><js>"$RQ{key1[,key2...]}"</js> - <a href="org/apache/juneau/rest/vars/RequestQueryVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestQueryVar</code></a>, first non-null value returned by <dc>RestRequest.getQuery(String)</dc>.
<li><js>"$R{key1[,key2...]}"</js> - <a href="org/apache/juneau/rest/vars/RequestVar.html" title="class in org.apache.juneau.rest.vars"><code>RequestVar</code></a>, first non-null other request variable.
<br>The possible values are:
<ul>
<li><js>"contextPath"</js> - Value returned by <a href="org/apache/juneau/rest/RestRequest.html#getContextPath--"><code>RestRequest.getContextPath()</code></a>
<li><js>"method"</js> - Value returned by <a href="org/apache/juneau/rest/RestRequest.html#getMethod--"><code>RestRequest.getMethod()</code></a>
<li><js>"methodDescription"</js> - Value returned by <dc>RestRequest.getMethodDescription()</dc>
<li><js>"methodSummary"</js> - Value returned by <dc>RestRequest.getMethodSummary()</dc>
<li><js>"pathInfo"</js> - Value returned by <a href="org/apache/juneau/rest/RestRequest.html#getPathInfo--"><code>RestRequest.getPathInfo()</code></a>
<li><js>"requestParentURI"</js> - Value returned by <a href="org/apache/juneau/UriContext.html#getRootRelativePathInfoParent--"><code>UriContext.getRootRelativePathInfoParent()</code></a>
<li><js>"requestURI"</js> - Value returned by <a href="org/apache/juneau/rest/RestRequest.html#getRequestURI--"><code>RestRequest.getRequestURI()</code></a>
<li><js>"resourceDescription"</js> - Value returned by <dc>RestRequest.getResourceDescription()</dc>
<li><js>"resourceTitle"</js> - See <dc>RestRequest.getResourceTitle()</dc>
<li><js>"servletParentURI"</js> - Value returned by <a href="org/apache/juneau/UriContext.html#getRootRelativeServletPathParent--"><code>UriContext.getRootRelativeServletPathParent()</code></a>
<li><js>"servletPath"</js> - See <a href="org/apache/juneau/rest/RestRequest.html#getServletPath--"><code>RestRequest.getServletPath()</code></a>
<li><js>"servletURI"</js> - See <a href="org/apache/juneau/UriContext.html#getRootRelativeServletPath--"><code>UriContext.getRootRelativeServletPath()</code></a>
<li><js>"siteName"</js> - See <dc>RestRequest.getSiteName()</dc>
</ul>
</ul>
<li>
Refactored the <c>RestConfig</c> class into <a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>.
<br>Settings on <a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a> objects can now be set declaratively through the
following new properties:
<ul>
<li><dc>RestContext.REST_allowHeaderParams</dc>
<li><dc>RestContext.REST_allowBodyParam</dc>
<li><dc>REST_allowedMethodParams</dc>
<li><dc>REST_renderResponseStackTraces</dc>
<li><dc>RestContext.REST_useStackTraceHashes</dc>
<li><dc>REST_defaultCharset</dc>
<li><dc>REST_maxInput</dc>
<li><dc>RestContext.REST_paramResolvers</dc>
<li><dc>REST_converters</dc>
<li><dc>REST_guards</dc>
<li><dc>RestContext.REST_responseHandlers</dc>
<li><dc>RestContext.REST_defaultRequestHeaders</dc>
<li><dc>RestContext.REST_defaultResponseHeaders</dc>
<li><dc>REST_produces</dc>
<li><dc>REST_consumes</dc>
<li><dc>REST_clientVersionHeader</dc>
<li><dc>RestContext.REST_resourceResolver</dc>
<li><dc>RestContext.REST_logger</dc>
<li><dc>RestContext.REST_callHandler</dc>
<li><dc>RestContext.REST_infoProvider</dc>
<li><dc>REST_path</dc>
<li><dc>RestContext.REST_contextPath</dc>
<li><dc>REST_staticFiles</dc>
<li><dc>RestContext.REST_staticFileResponseHeaders</dc>
<li><dc>RestContext.REST_classpathResourceFinder</dc>
<li><dc>RestContext.REST_useClasspathResourceCaching</dc>
<li><dc>RestContext.REST_widgets</dc>
<li><dc>RestContext.REST_mimeTypes</dc>
</ul>
<li>
Support for static files has been simplified and improved.
<ul>
<li>Syntax on <dc>@RestResource(staticFiles)</dc> has been simplified, and
now allows you to specify response headers in the strings.
<li>Response headers for static files can also be configured through
<dc>RestContext.REST_staticFileResponseHeaders</dc>
<li>Static file in-memory caching now configurable through
<dc>RestContext.REST_useClasspathResourceCaching</dc>
<li>Static file retrieval can be customized through
<dc>RestContext.REST_classpathResourceFinder</dc>
</ul>
<li>
Eliminated the <c>RestMatcherReflecting</c> class.
<br>You can now simply create a <code>org.apache.juneau.rest.RestMatcher</code> that has a public constructor that
takes in the server and method arguments.
<li>
<dc>@RestResource.allowMethodParam</dc> renamed to <dc>RestResource.allowedMethodParams</dc>.
<li>
<c>@RestMethod.serializersInherit</c> and <c>@RestMethod.parsersInherit</c> replaced with
simplified <dc>@RestMethod(inherit)</dc>.
<li>
Changes to <dc>org.apache.juneau.rest.RequestFormData</dc>:
<ul>
<li><dc>addDefault(Map)</dc> takes in a
<c>Map&lt;String,Object&gt;</c> instead of <c>Map&lt;String,String&gt;</c>.
</ul>
<li>
Changes to <dc>org.apache.juneau.rest.RequestHeaders</dc>:
<ul>
<li><dc>addDefault(Map)</dc> takes in a
<c>Map&lt;String,Object&gt;</c> instead of <c>Map&lt;String,String&gt;</c>.
</ul>
<li>
Changes to <dc>org.apache.juneau.rest.RequestQuery</dc>:
<ul>
<li><dc>addDefault(Map)</dc> takes in a
<c>Map&lt;String,Object&gt;</c> instead of <c>Map&lt;String,String&gt;</c>.
</ul>
<li>
Changes to <a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>:
<ul>
<li><c>getResource(String,Locale)</c> renamed to <dc>getClasspathResource(String,Locale)</dc>
<li><c>getResourceAsString(String,Locale)</c> renamed to <dc>getClasspathResourceAsString(String,Locale)</dc>
<li><c>getResource(Class,MediaType,String,Locale)</c> renamed to <dc>getClasspathResourceAsString(Class,MediaType,String,Locale)</dc>
<li>New method <dc>getClasspathResource(Class,String,Locale)</dc>.
<li>New method <dc>getClasspathResourceAsString(Class,String,Locale)</dc>.
<li>New method <dc>getClasspathResource(Class,Class,MediaType,String,Locale)</dc>.
<li><dc>RestContext.getDefaultRequestHeaders()</dc> returns a
<c>Map&lt;String,Object&gt;</c> instead of <c>Map&lt;String,String&gt;</c>.
<li><dc>RestContext.getDefaultResponseHeaders()</dc> returns a
<c>Map&lt;String,Object&gt;</c> instead of <c>Map&lt;String,String&gt;</c>.
</ul>
<li>
Changes to <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>:
<ul>
<li><c>getSupportedMediaTypes()</c> replaced with
<dc>getConsumes()</dc> and
<dc>getProduces()</dc>.
<li><c>getReaderResource(String,boolean,MediaType)</c> renamed to
<dc>getClasspathReaderResource(String,boolean,MediaType)</dc>
<li><c>getReaderResource(String,boolean)</c> renamed to
<dc>getClasspathHttpResource(String,boolean)</dc>
<li><c>getReaderResource(String)</c> renamed to
<dc>getClasspathHttpResource(String)</dc>
</ul>
<li>
Changes to <dc>@RestResource</dc>
<ul>
<li>New <dc>mimeTypes()</dc> annotation.
</ul>
<li>
Changes to <dc>@RestMethod</dc>:
<ul>
<li>New <dc>consumes()</dc> and
<dc>produces()</dc>
for overriding the supported media types inferred from the serializers and parsers.
</ul>
<li>
<c>RestCallHandler</c> split up into <dc>org.apache.juneau.rest.RestCallHandler</dc> and
<dc>BasicRestCallHandler</dc>
<li>
<c>RestInfoProvider</c> split up into <dc>org.apache.juneau.rest.RestInfoProvider</dc> and
<dc>org.apache.juneau.rest.BasicRestInfoProvider</dc>
<li>
<c>RestLogger</c> split up into <dc>org.apache.juneau.rest.RestLogger</dc>,
<dc>org.apache.juneau.rest.BasicRestLogger</dc> and <dc>org.apache.juneau.rest.NoOpRestLogger</dc>
<li>
<c>RestResourceResolverSimple</c> renamed to <dc>org.apache.juneau.rest.BasicRestResourceResolver</dc>
<li>
Introduced the following classes that helps make the code more understandable:
<ul>
<li><dc>org.apache.juneau.rest.RestContextProperties</dc>
<li><dc>org.apache.juneau.rest.RestMethodProperties</dc>
<li><dc>org.apache.juneau.rest.RequestProperties</dc>
</ul>
<li>
Eliminated the <c>@Messages</c> and <c>@Properties</c> REST java method parameter
annotations.
<br>These aren't needed anymore since you can just pass in <c>MessageBundle</c> and
<c>RestRequestProperties</c> as unannotated parameters.
<li>
Revamped the <dc>org.apache.juneau.rest.RestInfoProvider</dc> class.
<li>
New builder classes:
<ul>
<li><dc>ReaderResourceBuilder</dc>
<li><dc>StreamResourceBuilder</dc>
</ul>
<li>
<a href="org/apache/juneau/rest/RestResponse.html#getNegotiatedOutputStream--"><code>RestResponse.getNegotiatedOutputStream()</code></a> now returns a
<dc>FinishableServletOutputStream</dc> and <a href="org/apache/juneau/rest/RestResponse.html#getNegotiatedWriter--"><code>RestResponse.getNegotiatedWriter()</code></a>
now returns a <dc>FinishablePrintWriter</dc> that allows you to finish the output
without closing the stream.
<br>The <dc>org.apache.juneau.rest.reshandlers.DefaultHandler</dc> class now calls <c>finish()</c>
instead of <c>close()</c> on the stream.
<li>
Added the following annotations to the <dc>org.apache.juneau.rest.BasicRestServlet</dc> class
(which were previously defined on the <dc>Resource</dc> class):
<p class='bcode'>
<ja>@RestResource</ja>(
htmldoc=<ja>@HtmlDoc</ja>(
navlinks={
<js>"up: request:/.."</js>,
<js>"options: servlet:/?method=OPTIONS"</js>
},
stylesheet=<js>"$C{REST/stylesheet,servlet:/styles/devops.css}"</js>
),
<jc>// Optional external configuration file.</jc>
config=<js>"$S{juneau.configFile}"</js>
)
</p>
</ul>
<h5 class='topic w800'>juneau-rest-client</h5>
<ul class='spaced-list'>
<li>
New configuration property <dc>RestClient.RESTCLIENT_query</dc> and
builder method <dc>Builder.query(String,Object)</dc>.
<li>
API changes to replace <c>PartSerializer</c> with <a href="org/apache/juneau/httppart/HttpPartSerializer.html" title="interface in org.apache.juneau.httppart"><code>HttpPartSerializer</code></a>.
<br>The default value is now <dc>SimpleUonPartSerializer</dc> which will
serialize strings as plain-text and collections/arrays as comma-delimited lists.
<br>We decided to change the default behavior in favor of practicality over purity.
<li>
New methods on <dc>org.apache.juneau.rest.client.RestCall</dc> class:
<ul>
<li><dc>getResponseHeader(String)</dc>
<li><dc>getResponseCode()</dc>
</ul>
<li>
<dc>org.apache.juneau.rest.client.RestCall</dc> and <a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a>
now implement the <c>Closeable</c> interface.
</ul>
<h5 class='topic w800'>juneau-microservice</h5>
<ul class='spaced-list'>
<li>
<c>Resource</c> and <c>ResourceGroup</c> classes removed.
<br><dc>org.apache.juneau.rest.BasicRestServlet</dc> and <dc>org.apache.juneau.rest.BasicRestServletGroup</dc> can be used instead.
<li>
<c>ResourceJena</c> and <c>ResourceJenaGroup</c> classes renamed to
<dc>BasicRestServletJena</dc> and <dc>BasicRestServletJenaGroup</dc>.
</ul>
</div>
</div><!-- END: 7.1.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#7.2.0' id='7.2.0'>7.2.0 (Sept 25, 2018)</a></h3>
<div class='topic'><!-- START: 7.2.0 -->
<div class='topic'>
<p>
7.2.0 is a major release that introduces several significant new features:
</p>
<ul class='spaced-list'>
<li>OpenAPI part serializing and parsing with full support for OpenAPI validation of input and output in the REST servlet and client APIs.
<li>Swagger UI.
<li>New HTTP-Part annotations that are applicable to both the servlet and client APIs.
<li>Serverless servlet and client unit testing.
<li>Simplified UI customization.
<li>Marshalls that combines serializers and parsers into a single API.
</ul>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
The REST client <ja>@Remoteable</ja> annotations and REST server <ja>@RemoteMethod</ja> annotations which used to be
in separate packages in the client and server projects have been combined into a single set of annotations in
the <a href="org/apache/juneau/http/annotation/package-summary.html"><code>org.apache.juneau.http.annotation</code></a> package.
<br>This fixes a long-standing problem where it was easy to mix up using client-side annotations in server-side code, and vis-versa.
<br>Additionally, much work has been done on these annotations to add support for Swagger-style validations and documentation.
<ul class='doctree'>
<li class='ja'><code>org.apache.juneau.http.annotation.Body</code>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/HasFormData.html" title="annotation in org.apache.juneau.http.annotation"><code>HasFormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/HasQuery.html" title="annotation in org.apache.juneau.http.annotation"><code>HasQuery</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>Request</code></a>
</ul>
<br>These are used with new Swagger schema/documentation annotations to produce schema-based serialization/parsing/validation
and auto-generated Swagger documentation:
<ul class='doctree'>
<li class='ja'><a href="org/apache/juneau/http/annotation/Contact.html" title="annotation in org.apache.juneau.http.annotation"><code>Contact</code></a>
<li class='ja'><dc>ExternalDocs</dc>
<li class='ja'><dc>Items</dc>
<li class='ja'><a href="org/apache/juneau/http/annotation/License.html" title="annotation in org.apache.juneau.http.annotation"><code>License</code></a>
<li class='ja'><dc>Schema</dc>
<li class='ja'><dc>SubItems</dc>
<li class='ja'><dc>org.apache.juneau.http.annotation.Tag</dc>
</ul>
<br>Additionally, the <ja>@Remoteable</ja> annotation has been split into the following two annotations:
<ul class='doctree'>
<li class='ja'><dc>org.apache.juneau.remote.RemoteInterface</dc>
- Used for remote proxy interfaces served up through
<dc>RemoteInterfaceServlet</dc> or REST <js>"PROXY"</js> methods.
<br>Defaults to <js>"POST"</js> with method signatures as paths.
<li class='ja'><dc>RemoteResource</dc>
- Used for 3rd-party REST interfaces.
<br>Defaults to <js>"GET"</js> with standardized naming conventions for paths.
</ul>
<li>
Support for multi-valued parameters as maps or beans on server-side annotations (it was previously supported on client-side):
<c><ja>@Query</ja>(<js>"*"</js>)</c>, <c><ja>@FormData</ja>(<js>"*"</js>)</c>, <c><ja>@Header</ja>(<js>"*"</js>)</c>, <c><ja>@Path</ja>(<js>"*"</js>)</c>
<li>
Support for server-side use of <ja>@Request</ja> annotation on <ja>@RestMethod</ja> annotations and new <a href="org/apache/juneau/rest/RestRequest.html#getRequest-org.apache.juneau.httppart.bean.RequestBeanMeta-"><code>RestRequest.getRequest(RequestBeanMeta)</code></a> method.
<li>
Fixed bug where <c><ja>@Bean</ja>(typeName)</c> was not being detected on non-bean POJO classes.
<li>
Fixed bug where HTML-Schema was not being rendered correctly.
<li>
Support for POJO examples:
<ul class='doctree'>
<li class='jf'><dc>BeanContext.BEAN_examples</dc>
<li class='ja'><a href="org/apache/juneau/annotation/Example.html" title="annotation in org.apache.juneau.annotation"><code>Example</code></a>
</ul>
<li>
Fixed bug where parsers could report the wrong line number when an error occurred.
<li>
A runtime exception is now thrown if you define a <dc>@BeanProperty(name)</dc> but forget to
add it to your <c><ja>@Bean</ja>(properties)</c> annotation.
<li>
<c><ja>@Html</ja>(asXml)</c> and <c><ja>@Html</ja>(asPlainText)</c> replaced with
<a href="org/apache/juneau/html/annotation/Html.html#format--"><code>@Html(format)</code></a>.
<li>
HTML serializer will now serializers beans and maps as HTML even when those objects are embedded
within an object with <c><ja>@Html</ja>(format=<jsf>XML</jsf>)</c>.
<br>The previous behavior was to serialize it as XML.
<li>
New settings for binary-based serializers and parsers:
<ul class='doctree'>
<li class='jf'><dc>OutputStreamSerializer.OSSERIALIZER_binaryFormat</dc>
<li class='jf'><dc>InputStreamParser.ISPARSER_binaryFormat</dc>
</ul>
<li>
Added support for auto-detection of fluent-style setters:
<ul class='doctree'>
<li class='jf'><dc>BeanContext.BEAN_fluentSetters</dc>
<li class='ja'><dc>Bean.fluentSetters()</dc>
</ul>
<li>
The <jsf>SERIALIZER_abridged</jsf> setting has been replaced with <dc>SERIALIZER_addRootType</dc>
<li>
The <jsf>SERIALIZER_addBeanTypeProperties</jsf> setting has been replaced with <dc>SERIALIZER_addBeanTypes</dc>
and is disabled by default.
<li>
Parse exception messages are now clearer and include code snippets of where a parse exception occurred:
<p class='bcode' style='color:red'>
org.apache.juneau.parser.ParseException: Expected '[' at beginning of JSON array.
At line 80, column 20.
While parsing into:
currentClass: List&lt;String&gt;
currentProperty: required: java.util.List, field=[null], getter=[public java.util.List org.apache.juneau.dto.swagger.SchemaInfo.getRequired()], setter=[public org.apache.juneau.dto.swagger.SchemaInfo org.apache.juneau.dto.swagger.SchemaInfo.setRequired(java.util.Collection)]
---start--
0075: "name": "body",
0076: "description": "Pet object that needs to be added to the store",
0077: "required": true,
0078: "schema": {
0079: "required": true,
0080: }
0081: }
0082: ],
0083: "responses": {
0084: "405": {
0085: "description": "Invalid input"
---end---
</p>
<li>
New property <dc>Parser.PARSER_debugOutputLines</dc> for controlling how many input lines are added to the exception message above.
<li>
New property <dc>BeanContext.BEAN_useEnumNames</dc> for controlling whether enums are serialized
using their name or the <c>toString()</c> method.
<li>
New property <dc>BeanContext.BEAN_examples</dc> for defining examples of POJOs.
<li>
New <a href="org/apache/juneau/annotation/Example.html" title="annotation in org.apache.juneau.annotation"><code>@Example</code></a> annotation for defining examples of POJOs.
<br>Used heavily in JSON-Schema support.
<li>
If a bean has both a <c>getX()</c> and <c>isX()</c> method, the <c>getX()</c> method takes precedence.
<br>The previous behavior was arbitrary.
<li>
Significant improvements to JSON-Schema serialization support.
<ul>
<li>New <dc>@JsonSchema</dc> annotation.
</ul>
<li>
Fixed <c>NullPointerException</c> when serializing beans with a dyna-property (i.e. <c><ja>@Bean</ja>(<js>"*"</js>)</c>)
which returns a <jk>null</jk> value.
<li>
New option for dyna-property (i.e. <c><ja>@Bean</ja>(<js>"*"</js>)</c>) using a method that returns a collection of extra keys.
<br>See new options #4 on <dc>BeanProperty.name()</dc>
<li>
New formats for the <a href="org/apache/juneau/html/annotation/Html.html#format--"><code>@Html(format)</code></a> annotation:
<ul class='doctree'>
<li class='jf'><dc>HtmlFormat.HTML_CDC</dc> - Format collections as comma-delimited lists.
<li class='jf'><dc>HtmlFormat.HTML_SDC</dc> - Format collections as space-delimited lists.
</ul>
<li>
Serializers now allow for q-values on the media types they handle.
<br>For example, the accept media type on <c>JsonSerializer.Simple</c> is <js>"application/json+simple,application/json;q=0.9"</js>.
<br>This means the serializer CAN handle requests for <js>"application/json"</js> if no other serializers provide a better match.
<li>
New methods for creating unmodifiable <dc>ObjectMaps</dc> and <dc>ObjectLists</dc>.
<ul class='doctree'>
<li class='jc'><dc>org.apache.juneau.ObjectMap</dc>
<ul>
<li class='jm'><dc>isUnmodifable()</dc>
<li class='jm'><dc>unmodifiable()</dc>
<li class='jm'><dc>modifiable()</dc>
</ul>
<li class='jp'><dc>org.apache.juneau.ObjectList</dc>
<ul>
<li class='jm'><dc>isUnmodifable()</dc>
<li class='jm'><dc>unmodifiable()</dc>
<li class='jm'><dc>modifiable()</dc>
</ul>
</ul>
<li>
The <c>JsonSerializer.Simple</c> class has been moved into the top-level <a href="org/apache/juneau/json/SimpleJsonSerializer.html" title="class in org.apache.juneau.json"><code>SimpleJsonSerializer</code></a> class.
<li>
RDF serializer subclasses have been moved into top-level classes:
<ul>
<li><c>RdfSerializer.Xml</c> -> <a href="org/apache/juneau/jena/RdfXmlSerializer.html" title="class in org.apache.juneau.jena"><code>RdfXmlSerializer</code></a>
<li><c>RdfSerializer.XmlAbbrev</c> -> <a href="org/apache/juneau/jena/RdfXmlAbbrevSerializer.html" title="class in org.apache.juneau.jena"><code>RdfXmlAbbrevSerializer</code></a>
<li><c>RdfSerializer.N3</c> -> <a href="org/apache/juneau/jena/N3Serializer.html" title="class in org.apache.juneau.jena"><code>N3Serializer</code></a>
<li><c>RdfSerializer.NTriple</c> -> <a href="org/apache/juneau/jena/NTripleSerializer.html" title="class in org.apache.juneau.jena"><code>NTripleSerializer</code></a>
<li><c>RdfSerializer.Turtle</c> -> <a href="org/apache/juneau/jena/TurtleSerializer.html" title="class in org.apache.juneau.jena"><code>TurtleSerializer</code></a>
<li><c>RdfParser.Xml</c> -> <a href="org/apache/juneau/jena/RdfXmlParser.html" title="class in org.apache.juneau.jena"><code>RdfXmlParser</code></a>
<li><c>RdfParser.N3</c> -> <a href="org/apache/juneau/jena/N3Parser.html" title="class in org.apache.juneau.jena"><code>N3Parser</code></a>
<li><c>RdfParser.NTriple</c> -> <a href="org/apache/juneau/jena/NTripleParser.html" title="class in org.apache.juneau.jena"><code>NTripleParser</code></a>
<li><c>RdfParser.Turtle</c> -> <a href="org/apache/juneau/jena/TurtleParser.html" title="class in org.apache.juneau.jena"><code>TurtleParser</code></a>
</ul>
<li>
New API for pairing serializers and parsers for simplified syntax:
<h5 class='figure'>Examples:</h5>
<p class='bcode'>
<jc>// Using instance.</jc>
Json json = <jk>new</jk> Json();
MyPojo myPojo = json.read(string, MyPojo.<jk>class</jk>);
String string = json.write(myPojo);
</p>
<p class='bcode'>
<jc>// Using DEFAULT instance.</jc>
MyPojo myPojo = Json.<jsf>DEFAULT</jsf>.read(string, MyPojo.<jk>class</jk>);
String string = Json.<jsf>DEFAULT</jsf>.write(myPojo);
</p>
<ul class='doctree'>
<li class='jac'><dc>org.apache.juneau.marshall.Marshall</dc>
<ul>
<li class='jac'><dc>org.apache.juneau.marshall.CharMarshall</dc>
<ul>
<li class='jc'><dc>org.apache.juneau.marshall.Html</dc>
<li class='jc'><dc>org.apache.juneau.marshall.Json</dc>
<li class='jc'><dc>org.apache.juneau.marshall.PlainText</dc>
<li class='jc'><dc>org.apache.juneau.marshall.SimpleJson</dc>
<li class='jc'><dc>org.apache.juneau.marshall.Uon</dc>
<li class='jc'><dc>org.apache.juneau.marshall.UrlEncoding</dc>
<li class='jc'><dc>org.apache.juneau.marshall.Xml</dc>
<li class='jc'><dc>org.apache.juneau.marshall.N3</dc>
<li class='jc'><dc>org.apache.juneau.marshall.NTriple</dc>
<li class='jc'><dc>org.apache.juneau.marshall.RdfXml</dc>
<li class='jc'><dc>org.apache.juneau.marshall.RdfXmlAbbrev</dc>
<li class='jc'><dc>org.apache.juneau.marshall.Turtle</dc>
</ul>
<li class='jac'><dc>org.apache.juneau.marshall.StreamMarshall</dc>
<ul>
<li class='jc'><dc>org.apache.juneau.marshall.Jso</dc>
<li class='jc'><dc>org.apache.juneau.marshall.MsgPack</dc>
</ul>
</ul>
</ul>
<li>
New/updated documentation:
<ul>
<li><a del='#juneau-marshall.JsonDetails.SimplifiedJson'>2.15.3 - Simplified JSON</a>
</ul>
</ul>
<h5 class='topic w800'>juneau-dto</h5>
<ul class='spaced-list'>
<li>
Fixed bug where Swagger <dc>)</dc> was defined as a boolean
instead of a list of strings.
<li>
Boolean attributes are now handled correctly for HTML5.
<br>For example, calling <c><jk>new</jk> Select().disabled(<jk>true</jk>)</c> will produce <c>&lt;select disabled='disabled'&gt;</c>
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
Auto-generated <dc>Swagger UI</dc>.
<li>
Simplified <dc>@RestResource(swagger)</dc>
and <dc>@RestMethod(swagger)</dc> annotations.
<li>
Fixed bug in <c>UriResolver</c> when request path info had special characters.
<li>
Fixed bug where incorrect media type was being set on responses (e.g. <c>text/html+schema</c> instead of <c>text/html</c> for schema documents).
<li>
The <c>RemoteableServlet</c> class has been moved and renamed to <dc>RemoteInterfaceServlet</dc>.
<li>
<dc>RemoteInterfaceServlet</dc> now provides a form page for invoking remote interface methods in a browser.
<li>
Newlines were being stripped from <c><ja>@HtmlDoc</ja>(script)</c> when serialized which could cause script lines to become commented out.
<li>
New <a href="org/apache/juneau/http/annotation/Response.html" title="annotation in org.apache.juneau.http.annotation"><code>@Response</code></a> annotation that can be applied to
throwables thrown from REST methods and POJOs returned by REST methods to specify non-200 status return codes and descriptions in Swagger documentation.
<li>
Swagger fields added to the following annotations:
<ul class='doctree'>
<li class='ja'><code>org.apache.juneau.http.annotation.Body</code>
<li class='ja'><a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>
<li class='ja'><a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>
</ul>
<li>
The <ja>@PathRemainder</ja> annotation has been removed entirely.
<br>Use <c><ja>@Path</ja>(<js>"/*"</js>)</c> to access the path remainder which includes all the new OpenAPI parsing support.
<li>
"Helper" classes (i.e. reusable beans that can be returned by REST methods) have been moved to the following package with some new additions:
<ul class='doctree'>
<li class='jp'><dc>org.apache.juneau.rest.helper</dc>
<ul>
<li class='jc'><dc>org.apache.juneau.rest.helper.BeanDescription</dc>
<li class='jc'><dc>org.apache.juneau.rest.helper.ChildResourceDescriptions</dc>
<li class='jc'><dc>ReaderResource</dc>
<li class='jc'><dc>ReaderResourceBuilder</dc>
<li class='jc'><dc>org.apache.juneau.rest.helper.SeeOtherRoot</dc>
<li class='jc'><dc>org.apache.juneau.rest.helper.ResourceDescription</dc>
<li class='jc'><dc>StreamResource</dc>
<li class='jc'><dc>StreamResourceBuilder</dc>
</ul>
</ul>
<li>
Predefined HTTP responses.
<ul class='doctree'>
<li class='jp'><dc>org.apache.juneau.rest.response</dc>
<ul>
<li class='jc'><dc>org.apache.juneau.rest.response.Accepted</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.AlreadyReported</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.Continue</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.Created</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.EarlyHints</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.Found</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.IMUsed</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.MovedPermanently</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.MultipleChoices</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.MultiStatus</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.NoContent</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.NonAuthoritiveInformation</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.NotModified</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.Ok</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.PartialContent</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.PermanentRedirect</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.Processing</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.ResetContent</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.SeeOther</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.SwitchingProtocols</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.TemporaryRedirect</dc>
<li class='jc'><dc>org.apache.juneau.rest.response.UseProxy</dc>
</ul>
</ul>
<li>
Predefined HTTP error throwables.
<br>When added to REST Java methods, reflected in generated Swagger documentation.
<ul class='doctree'>
<li class='jp'><dc>org.apache.juneau.rest.exception</dc>
<ul>
<li class='jc'><dc>org.apache.juneau.rest.exception.BadRequest</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.Conflict</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.ExpectationFailed</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.FailedDependency</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.Forbidden</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.Gone</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.HttpVersionNotSupported</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.InsufficientStorage</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.InternalServerError</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.LengthRequired</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.Locked</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.LoopDetected</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.MethodNotAllowed</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.MisdirectedRequest</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.NetworkAuthenticationRequired</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.NotAcceptable</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.NotExtended</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.NotFound</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.NotImplemented</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.PayloadTooLarge</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.PreconditionFailed</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.PreconditionRequired</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.RangeNotSatisfiable</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.RequestHeaderFieldsTooLarge</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.ServiceUnavailable</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.TooManyRequests</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.Unauthorized</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.UnavailableForLegalReasons</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.UnprocessableEntity</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.UnsupportedMediaType</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.UpgradeRequired</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.UriTooLong</dc>
<li class='jc'><dc>org.apache.juneau.rest.exception.VariantAlsoNegotiates</dc>
</ul>
</ul>
<li>
The <dc>@HtmlDoc(nav)</dc> and <dc>@HtmlDoc(navlinks)</dc>
can now both be used on the same annotation.
<br>The contents of <c>nav()</c> are free-form HTML that gets rendered immediately after the navigation links.
<li>
The following new parameter types can be used on REST methods:
<ul class='doctree'>
<li class='jc'><a href="org/apache/juneau/parser/ReaderParser.html" title="class in org.apache.juneau.parser"><code>ReaderParser</code></a> - The reader parser matching the request content type.
<li class='jc'><a href="org/apache/juneau/parser/InputStreamParser.html" title="class in org.apache.juneau.parser"><code>InputStreamParser</code></a> - The input stream parser matching the request content type.
</ul>
<li>
The <c>$F</c> variable can now be used as a initialization time variable.
<br>For example, the <c>AtomFeedResource</c> example pulls a bean example from a file on the classpath:
<p class='bcode'>
<ja>@RestResource</ja>(
path=<js>"/atom"</js>,
title=<js>"Sample ATOM feed resource"</js>,
properties={
<ja>@Property</ja>(name=<jsf>BEAN_examples</jsf>, value=<js>"{'org.apache.juneau.dto.atom.Feed': $F{AtomFeedResource_example.json}}"</js>)
},
...
)
</p>
<br>It should be noted that you cannot use the <c>$F</c> variable to retrieve localized versions of files (since you're not within
the scope of a client request.
<li>
The <dc>RestResource.nowrap()</dc> annotation has been changed to a string with a default value of <js>"true"</js>.
<br>Having it as a string allows us to differentiate between a set and unset value so that it can be overridden in subclasses.
<li>
The <a href="org/apache/juneau/http/annotation/Path.html#name--"><code>Path.name()</code></a> annotation parameter is now required.
<li>
New class for mock unit testing of REST resources:
<ul class='doctree'>
<li class='jc'><dc>MockRest</dc>
</ul>
<li>
<c><ja>@RestMethod</ja>(inherit)</c> annotation has been removed and replaced with the following classes:
<ul class='doctree'>
<li class='jc'><dc>org.apache.juneau.rest.Inherit</dc>
<li class='jc'><dc>org.apache.juneau.rest.None</dc>
</ul>
<br>These can be used in the following locations:
<ul class='doctree'>
<li class='ja'><dc>RestResource.serializers()</dc>
<li class='ja'><dc>RestResource.parsers()</dc>
<li class='ja'><dc>RestResource.beanFilters()</dc>
<li class='ja'><dc>RestResource.pojoSwaps()</dc>
<li class='ja'><dc>RestMethod.serializers()</dc>
<li class='ja'><dc>RestMethod.parsers()</dc>
<li class='ja'><dc>RestMethod.beanFilters()</dc>
<li class='ja'><dc>RestMethod.pojoSwaps()</dc>
</ul>
<br>One advantage is that you now have control over the precedence of serializers and parsers by where you insert the <c>Inherit</c> class.
<li>
<c>RequestPathMatch</c> class has been renamed to <dc>org.apache.juneau.rest.RequestPath</dc>.
<li>
<a href="org/apache/juneau/http/annotation/Request.html" title="annotation in org.apache.juneau.http.annotation"><code>@Request</code></a> objects can now be used as parameters in <ja>@RestMethod</ja> methods.
<br>Includes new methods on <a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>:
<ul class='doctree'>
<li class='jm'><a href="org/apache/juneau/rest/RestRequest.html#getRequest-java.lang.Class-"><code>getRequest(Class)</code></a>
<li class='jm'><a href="org/apache/juneau/rest/RestRequest.html#getRequest-org.apache.juneau.httppart.bean.RequestBeanMeta-"><code>getRequest(RequestBeanMeta)</code></a>
</ul>
<li>
New methods added to <a href="org/apache/juneau/rest/widget/MenuItemWidget.html" title="class in org.apache.juneau.rest.widget"><code>MenuItemWidget</code></a> to allow population of menu item content using Javascript and Ajax calls:
<ul class='doctree'>
<li class='jc'><a href="org/apache/juneau/rest/widget/MenuItemWidget.html" title="class in org.apache.juneau.rest.widget"><code>MenuItemWidget</code></a>
<ul>
<li class='jm'><dc>getBeforeShowScript(RestRequest)</dc>
<li class='jm'><dc>getAfterShowScript(RestRequest)</dc>
</ul>
</ul>
<li>
New methods added to <a href="org/apache/juneau/rest/widget/Widget.html" title="class in org.apache.juneau.rest.widget"><code>Widget</code></a> to allow retrieving classpath resources with embedded SVL variables:
<ul class='doctree'>
<li class='jc'><a href="org/apache/juneau/rest/widget/Widget.html" title="class in org.apache.juneau.rest.widget"><code>Widget</code></a>
<ul>
<li class='jm'><dc>loadHtmlWithVars(RestRequest,String)</dc>
<li class='jm'><dc>loadScriptWithVars(RestRequest,String)</dc>
<li class='jm'><dc>loadStyleWithVars(RestRequest,String)</dc>
</ul>
</ul>
<li>
New/updated documentation:
<br><dc>juneau-rest-server.UnitTesting</dc>
<li>
The behavior of the default values for <dc>RestMethod.name()</dc> and <dc>RestMethod.path()</dc>
have changed.
<br>If not specified, the values are inferred from the Java method name.
<br>See Also: <dc>RestMethod</dc>
<li>
<c>RedirectToServletRoot</c> class has been renamed to <dc>org.apache.juneau.rest.helper.SeeOtherRoot</dc>.
<li>
New REST context settings:
<ul class='doctree'>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>
<ul>
<li class='jf'><dc>REST_uriAuthority</dc>
<li class='jf'><dc>REST_uriContext</dc>
<li class='jf'><dc>REST_uriRelativity</dc>
<li class='jf'><dc>REST_uriResolution</dc>
</ul>
</ul>
<li>
New convenience annotations for specifying default <c>Accept</c> and <c>Content-Type</c> headers:
<ul class='doctree'>
<li class='jc'><dc>RestResource</dc>
<ul>
<li class='jf'><dc>defaultAccept</dc>
<li class='jf'><dc>defaultContentType</dc>
</ul>
<li class='jc'><dc>org.apache.juneau.rest.annotation.RestMethod</dc>
<ul>
<li class='jf'><dc>defaultAccept</dc>
<li class='jf'><dc>defaultContentType</dc>
</ul>
</ul>
</ul>
<h5 class='topic w800'>juneau-rest-client</h5>
<ul class='spaced-list'>
<li>
Remote Resource interfaces support OpenAPI annotations.
<li>
Made improvements to the builder API for defining SSL support.
<br>New methods added:
<ul class='doctree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jf'><dc>sslProtocols(String...)</dc>
<li class='jf'><dc>cipherSuites(String...)</dc>
<li class='jf'><dc>hostnameVerifier(HostnameVerifier)</dc>
<li class='jf'><dc>keyManagers(KeyManager...)</dc>
<li class='jf'><dc>)</dc>
<li class='jf'><dc>Builder.secureRandom(SecureRandom)</dc>
<li class='jf'><dc>Builder.httpClientConnectionManager(HttpClientConnectionManager)</dc>
</ul>
</ul>
<li>
Clients no longer have JSON defined as the default serializer and parser.
<br>Instead, the clients can now be used with no serializer/parser if you're working with InputStreams/Readers or
POJOs that can be converted to Strings and converted from Strings/InputStreams/Readers.
<li>
Methods added to client builder to make it easy to define the transport language:
<ul class='doctree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jf'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#json--"><code>json()</code></a>
<li class='jf'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#xml--"><code>xml()</code></a>
<li class='jf'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#html--"><code>html()</code></a>
<li class='jf'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#uon--"><code>uon()</code></a>
<li class='jf'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#urlEnc--"><code>urlEnc()</code></a>
<li class='jf'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#msgPack--"><code>msgPack()</code></a>
<li class='jf'><a href="org/apache/juneau/rest/client/RestClient.Builder.html#plainText--"><code>plainText()</code></a>
</ul>
</ul>
<li>
New method added for allowing serverless client testing against REST interfaces.
<ul class='doctree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a>
<ul>
<li class='jf'><dc>mockHttpConnection(MockHttpConnection)</dc>
</ul>
</ul>
<li>
Removed the deprecated <c>RestCall.execute()</c> method.
<br>Use <dc>RestCall.run()</dc>.
<li>
<c>RestCall.input(Object)</c> method renamed to <dc>RestCall.body(Object)</dc> to match OpenAPI terminology.
<li>
Made constructors on <c>RestClient</c> and <c>RestClient.Builder</c> protected so that they can be subclassed.
<li>
The <c>RestClient.getRemoteableProxy()</c> methods have been split into separate methods for Remote Interfaces and Remote Resources:
<ul class='doctree'>
<li class='jc'><a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a>
<ul>
<li class='jm'><dc>RestClient.getRemoteInterface(Class)</dc>
<li class='jm'><dc>RestClient.getRemoteInterface(Class,Object)</dc>
<li class='jm'><dc>RestClient.getRemoteInterface(Class,Object,Serializer,Parser)</dc>
<li class='jm'><dc>RestClient.getRemoteResource(Class)</dc>
<li class='jm'><dc>RestClient.getRemoteResource(Class,Object)</dc>
<li class='jm'><dc>RestClient.getRemoteResource(Class,Object,Serializer,Parser)</dc>
</ul>
</ul>
</ul>
<h5 class='topic w800'>juneau-rest-microservice</h5>
<ul class='spaced-list'>
<li>
The look-and-feel of an application is now controlled through the external configuration file and access to
CSS stylesheets in the working directory in a new folder called <c>files</c>:
<br><img class='bordered' style='width:170px' src='doc-files/ReleaseNotes.711.1.png'>
<br><br>
The default configuration is this:
<p class='bcode'>
<cc>#=======================================================================================================================
# REST settings
#=======================================================================================================================</cc>
<cs>[REST]</cs>
<ck>staticFiles</ck> = <cv>htdocs:files/htdocs</cv>
<cc># Stylesheet to use for HTML views.</cc>
<ck>theme</ck> = <cv>servlet:/htdocs/themes/devops.css</cv>
<ck>headerIcon</ck> = <cv>servlet:/htdocs/images/juneau.png</cv>
<ck>headerLink</ck> = <cv>http://juneau.apache.org</cv>
<ck>footerIcon</ck> = <cv>servlet:/htdocs/images/asf.png</cv>
<ck>footerLink</ck> = <cv>http://www.apache.org</cv>
<ck>icon</ck> = <cv>$C{REST/headerIcon}</cv>
<ck>header</ck> = <cv>&lt;a href='$U{$C{REST/headerLink}}'&gt;&lt;img src='$U{$C{REST/headerIcon}}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/&gt;&lt;/a&gt;</cv>
<ck>footer</ck> = <cv>&lt;a href='$U{$C{REST/footerLink}}'&gt;&lt;img style='float:right;padding-right:20px;height:32px' src='$U{$C{REST/footerIcon}}'&gt;</cv>
</p>
<br><br>
Note that static files can now be served up from the <c>files</c> directory in the working directory,
and you have access to modify the CSS theme files.
<br>The <c>SwaggerUI.css</c> file controls the look-and-feel of the Swagger UI, so you can make
modification there as well.
<br><br>
The <c>BasicRestConfig</c> interface (which defines the default settings for the <c>BasicRestServlet</c> class)
now looks like this...
<p class='bcode'>
<ja>@RestResource</ja>(
...
htmldoc=<ja>@HtmlDoc</ja>(
header={
<js>"&lt;h1&gt;$R{resourceTitle}&lt;/h1&gt;"</js>,
<js>"&lt;h2&gt;$R{methodSummary,resourceDescription}&lt;/h2&gt;"</js>,
<js>"$C{REST/header}"</js>
},
navlinks={
<js>"up: request:/.."</js>
},
stylesheet=<js>"$C{REST/theme,servlet:/htdocs/themes/devops.css}"</js>,
head={
<js>"&lt;link rel='icon' href='$U{$C{REST/icon}}'/&gt;"</js>
},
footer=<js>"$C{REST/footer}"</js>
),
<jc>// These are static files that are served up by the servlet under the specified sub-paths.
// For example, "/servletPath/htdocs/javadoc.css" resolves to the file "[servlet-package]/htdocs/javadoc.css"</jc>
staticFiles={<js>"$C{REST/staticFiles}"</js>}
)
<jk>public interface</jk> BasicRestConfig {}
</p>
<br><br>
The <c>PoweredByApache</c> widget which used to serve as a page footer has been eliminated.
<br><br>
If you're testing out changes in the theme stylesheets, you may want to set the following system property
that prevents caching of those files so that you don't need to restart the microservice each time a change is made:
<p class='bcode'>
<cc>#=======================================================================================================================
# System properties
#=======================================================================================================================</cc>
<cs>[SystemProperties]</cs>
<cc># Disable classpath resource caching.
# Useful if you're attached using a debugger and you're modifying classpath resources while running.</cc>
<ck>RestContext.useClasspathResourceCaching.b</ck> = <cv>false</cv>
</p>
<li>
Upgraded to Jetty 9.4.12.
</ul>
</div>
</div><!-- END: 7.2.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#7.2.1' id='7.2.1'>7.2.1 (Oct 23, 2018)</a></h3>
<div class='topic'><!-- START: 7.2.1 -->
<div class='topic'>
<p>
This release contains mostly bug fixes.
Code changes have been made to preserve binary backwards compatibility with 7.1.0.
</p>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
The <dc>@JsonSchema</dc> annotation has been merged with the <code>@Schema</code> annotation.
<li>
Annotations typically used on bean properties (getters/setters/public fields) can now be used on private fields.
This is inline with behavior on JPA-annotated beans.
These include: <ja>@Swap</ja>, <ja>@Html</ja>, <ja>@Xml</ja>, <jd>@BeanProperty</jd>.
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
Method-level annotations (e.g. <ja>@RestMethod</ja>) and parameter-level annotations (e.g. <ja>@Query</ja>) are now inheritable
from parent classes and interfaces.
<br>This allows you to define <dc>RestcDualPurposeInterfaces</dc>.
<li>
The <c>ReaderResource</c> and <c>StreamResource</c> classes have been moved to the <c>org.apache.juneau.http</c>
package in <c>juneau-marshall</c>. This allows them to be used as return types in remote REST interfaces.
<br>A new <dc>ResolvingReaderResource</dc> class has been added that includes the variable-resolving support since
this relies on the <c>juneau-svl</c> package.
<li>
The <c>RemoteInterfaceServlet</c> class has been renamed to <a href="org/apache/juneau/rest/remote/RrpcServlet.html" title="class in org.apache.juneau.rest.remote"><code>RrpcServlet</code></a>.
<li>
<c><ja>@RestMethod</ja>(name=<js>"PROXY"</js>)</c> has been changed to <c><ja>@RestMethod</ja>(name=<js>"RRPC"</js>)</c>.
</ul>
<h5 class='topic w800'>juneau-rest-client</h5>
<ul class='spaced-list'>
<li>
The <c>RestClient.getRemoteInterface()</c> method has been renamed to <a href="org/apache/juneau/rest/client/RestClient.html#getRrpcInterface-java.lang.Class-"><code>RestClient.getRrpcInterface(Class)</code></a>.
<li>
Fixed a bug where <c><ja>@RemoteMethod</ja>(path)</c> values containing '/' characters were erroneously being encoded.
</ul>
</div>
</div><!-- END: 7.2.1 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#7.2.2' id='7.2.2'>7.2.2 (Nov 7, 2018)</a></h3>
<div class='topic'><!-- START: 7.2.2 -->
<div class='topic'>
<p>
This release contains minor bug fixes and general improvements to the PetStore sample application.
</p>
</div>
</div><!-- END: 7.2.2 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#8.0.0' id='8.0.0'>8.0.0 (Jan 01, 2019)</a></h3>
<div class='topic'><!-- START: 8.0.0 -->
<div class='topic'>
<p>
This release cleans up deprecated APIs from the 7.2.0 release and makes significant modifications
to the Microservice APIs.
</p>
<p>
The project structures of the REST, Microservice, and Examples have been modified to fit new Spring Boot
integration support.
The structure is now as follows:
</p>
<ul>
<li><c>juneau-rest</c>
<ul>
<li><c>juneau-rest-client</c>
<li><c>juneau-rest-server</c>
<li><c>juneau-rest-server-jaxrs</c>
<li><c>juneau-rest-server-rdf</c>
<li><b><c>juneau-rest-server-springboot</c></b> - New Spring Boot integration support classes.
</ul>
<li><c>juneau-microservice</c>
<ul>
<li><b><c>juneau-microservice-core</c></b> - New. Contains base <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> class.
<li><b><c>juneau-microservice-jetty</c></b> - New. Contains new <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html" title="class in org.apache.juneau.microservice.jetty"><code>JettyMicroservice</code></a> class.
<li><b><c>juneau-my-jetty-microservice</c></b> - New. Template starter project for Jetty-based microservices.
<li><b><c>juneau-my-springboot-microservice</c></b> - New. Template starter project for Spring-Boot-based microservices.
</ul>
<li><c>juneau-examples</c>
<ul>
<li><c>juneau-core</c>
<li><b><c>juneau-microservice-rest</c></b> - Now contains only servlet example classes. No Jetty configuration.
<li><b><c>juneau-microservice-rest-jetty</c></b> - Servlet examples deployed using Jetty.
<li><b><c>juneau-microservice-rest-springboot</c></b> - Servlet examples deployed using Spring Boot.
</ul>
</ul>
<h5 class='topic w800'>juneau-svl</h5>
<ul class='spaced-list'>
<li>
New SVL variables:
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/svl/vars/SubstringVar.html" title="class in org.apache.juneau.svl.vars"><code>SubstringVar</code></a>
<li class='jc'><a href="org/apache/juneau/svl/vars/PatternExtractVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternExtractVar</code></a>
<li class='jc'><a href="org/apache/juneau/svl/vars/PatternReplaceVar.html" title="class in org.apache.juneau.svl.vars"><code>PatternReplaceVar</code></a>
<li class='jc'><a href="org/apache/juneau/svl/vars/LenVar.html" title="class in org.apache.juneau.svl.vars"><code>LenVar</code></a>
</ul>
</ul>
<h5 class='topic w800'>juneau-config</h5>
<ul class='spaced-list'>
<li>
New methods for setting a system default configuration:
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/Config.html" title="class in org.apache.juneau.config"><code>Config</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/config/Config.html#getSystemDefault--"><code>getSystemDefault()</code></a>
<li class='jm'><a href="org/apache/juneau/config/Config.html#setSystemDefault-org.apache.juneau.config.Config-"><code>setSystemDefault(Config)</code></a>
</ul>
</ul>
<li>
New classpath store.
<ul class='javatree'>
<li class='jc'><dc>org.apache.juneau.config.store.ConfigClasspathStore</dc>
</ul>
<li>
New API method:
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/config/store/ConfigStore.html" title="class in org.apache.juneau.config.store"><code>ConfigStore</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/config/store/ConfigStore.html#exists-java.lang.String-"><code>exists(String)</code></a>
</ul>
</ul>
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
New methods on <dc>org.apache.juneau.rest.RestServlet</dc>:
<ul class='javatree'>
<li class='jm'><dc>setRestResourceResolver(RestResourceResolver)</dc>
<li class='jm'><dc>getPath()</dc>
</ul>
<li>
The registered resource resolver is now used to instantiate objects of classes defined via <dc>@RestResource</dc>.
<br>This allows for any of those instance to be injectable beans.
</ul>
<h5 class='topic w800'>juneau-rest-server-springboot</h5>
<ul class='spaced-list'>
<li>
New project containing classes for making it easy to use Juneau with Spring Boot.
</ul>
<h5 class='topic w800'>juneau-microservice-core</h5>
<ul class='spaced-list'>
<li>
New project that consist of just the core <a href="org/apache/juneau/microservice/Microservice.html" title="class in org.apache.juneau.microservice"><code>Microservice</code></a> class and console support.
<li>
The Microservice API has been revamped to use a builder-based approach to creating microservices.
<br>The new API is considerably more flexible in design and allows for the configuration and external
files to be located in either the home directory or inside the jar classpath.
<li>
If the microservice cannot find a config file in the home directory with the same name as the jar and
the <js>"juneau.configFile"</js> system property is not found, it will try to find any file in the home
directory that ends with <js>".cfg"</js>.
<li>
New <a href="org/apache/juneau/microservice/MicroserviceListener.html" title="interface in org.apache.juneau.microservice"><code>MicroserviceListener</code></a> API for defining lifecycle event listeners.
<li>
New <a href="org/apache/juneau/microservice/console/ConfigCommand.html" title="class in org.apache.juneau.microservice.console"><code>ConfigCommand</code></a> class for performing config queries and updates through
the microservice console.
</ul>
<h5 class='topic w800'>juneau-microservice-jetty</h5>
<ul class='spaced-list'>
<li>
New <a href="org/apache/juneau/microservice/jetty/JettyMicroservice.html" title="class in org.apache.juneau.microservice.jetty"><code>JettyMicroservice</code></a> class replaces the previous <c>RestMicroservice</c>.
</ul>
<h5 class='topic w800'>juneau-my-jetty-microservice</h5>
<ul class='spaced-list'>
<li>
New template starter project for Jetty-based microservices.
</ul>
<h5 class='topic w800'>juneau-my-springboot-microservice</h5>
<ul class='spaced-list'>
<li>
Template starter project for Spring-Boot-based microservices.
<li>
<c>app.json</c> and <c>Procfile</c> files for deploying examples into Heroku.
<br>Includes instructions.
</ul>
</div>
</div><!-- END: 8.0.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#8.1.0' id='8.1.0'>8.1.0 (Aug 21, 2019)</a></h3>
<div class='topic'><!-- START: 8.1.0 -->
<div class='topic'>
<p>
8.1.0 introduces some significant new features including:
</p>
<ul class='spaced-list'>
<li>
<dc>Configurable Annotations</dc>
<li>
<dc>Default PojoSwaps</dc>
<li>
<dc>Config Imports</dc>
<li>
<dc>BasicRest</dc>, <dc>BasicRestGroup</dc> classes
<li>
<dc>Path variables on resource paths</dc>
<li>
<dc>Request Attributes API</dc>
<li>
<dc>Role Guards</dc>
<li>
<dc>Improved REST logging/debugging</dc>
<li>
<a href='#juneau-rest-mock'>New MockRest API</a>
</ul>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
New utility class for diffing beans:
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/utils/BeanDiff.html" title="class in org.apache.juneau.utils"><code>BeanDiff</code></a>
</ul>
<li>
New annotation for defining bean property names:
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/annotation/Name.html" title="annotation in org.apache.juneau.annotation"><code>Name</code></a>
</ul>
<li>
New serializer properties:
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/serializer/WriterSerializer.html" title="class in org.apache.juneau.serializer"><code>WriterSerializer</code></a>
<ul>
<li class='jf'><dc>WSERIALIZER_fileCharset</dc>
<li class='jf'><dc>WSERIALIZER_streamCharset</dc>
</ul>
</ul>
<li>
The following POJO methods can be used to convert a POJO to/from a Map before serialization and after parsing.
<br>It's a convenient way of defining a POJO transform.
<ul class='javatree'>
<li class='jm'><c><jk>public</jk> Map toMap()</c> - Can be any type of map with string keys and object vals.
<li class='jm'><c><jk>public</jk> ObjectMap toMap()</c>
<li class='jm'><c><jk>public</jk> Map toMap(BeanSession bs)</c> - Can be any type of map with string keys and object vals.
<li class='jm'><c><jk>public</jk> ObjectMap toMap(BeanSession bs)</c>
<li class='jm'><c><jk>public static</jk> T fromMap(Map m)</c> - Can be any type of map with string keys and object vals.
<li class='jm'><c><jk>public static</jk> T fromMap(ObjectMap m)</c>
<li class='jm'><c><jk>public static</jk> T fromMap(BeanSession bs, Map m)</c> - Can be any type of map with string keys and object vals.
<li class='jm'><c><jk>public static</jk> T fromMap(BeanSession bs, ObjectMap m)</c>
</ul>
<li>
New convenience debugging methods on Marshall API:
<ul class='javatree'>
<li class='jc'><dc>org.apache.juneau.marshall.Marshall</dc>
<ul>
<li class='jm'><dc>format(String,Object...)</dc> - <c>MessageFormat</c>-style formatter.
<li class='jm'><dc>out(String,Object...)</dc> - Prints <c>MessageFormat</c>-style messages to STDOUT.
<li class='jm'><dc>err(String,Object...)</dc> - Prints <c>MessageFormat</c>-style messages to STDERR.
</ul>
</ul>
<li>
Serializer and parser APIs now throw <c>IOExceptions</c> in addition to <c>SerializeException</c> and <c>ParseException</c> to make it
easier to determine if problems are stream based or syntax based.
<li>
New Java 8 date-time transforms:
<ul class='javatree'>
<li class='jc'><dc>org.apache.juneau.transforms.TemporalSwap</dc> - For all Java 8 temporal types (e.g. <a href="https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html?is-external=true" title="class or interface in java.time"><code>ZonedDateTime</code></a>)
<li class='jc'><dc>org.apache.juneau.transforms.TemporalDateSwap</dc> - For <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a>
<li class='jc'><dc>org.apache.juneau.transforms.TemporalCalendarSwap</dc> - For <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a>
</ul>
<li>
All serializers and parsers now have built-in default swaps for common class types:
<ul class='javatree'>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Enumeration.html?is-external=true" title="class or interface in java.util"><code>Enumeration</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html?is-external=true" title="class or interface in java.util"><code>Iterator</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Locale.html?is-external=true" title="class or interface in java.util"><code>Locale</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html?is-external=true" title="class or interface in java.util"><code>Calendar</code></a> - ISO offset date-time.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html?is-external=true" title="class or interface in java.util"><code>Date</code></a> - Local date-time
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html?is-external=true" title="class or interface in java.time"><code>Instant</code></a> - ISO instant.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html?is-external=true" title="class or interface in java.time"><code>ZonedDateTime</code></a> - ISO offset date-time.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html?is-external=true" title="class or interface in java.time"><code>LocalDate</code></a> - ISO local date.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html?is-external=true" title="class or interface in java.time"><code>LocalDateTime</code></a> - ISO local date-time.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html?is-external=true" title="class or interface in java.time"><code>LocalTime</code></a> - ISO local time.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html?is-external=true" title="class or interface in java.time"><code>OffsetDateTime</code></a> - ISO offset date-time.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/OffsetTime.html?is-external=true" title="class or interface in java.time"><code>OffsetTime</code></a> - ISO offset time.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/Year.html?is-external=true" title="class or interface in java.time"><code>Year</code></a> - ISO year.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/YearMonth.html?is-external=true" title="class or interface in java.time"><code>YearMonth</code></a> - ISO year-month.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/Temporal.html?is-external=true" title="class or interface in java.time"><code>Temporal</code></a> - ISO instant.
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html?is-external=true" title="class or interface in java.util"><code>TimeZone</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/javax/xml/datatype/XMLGregorianCalendar.html?is-external=true" title="class or interface in javax.xml.datatype"><code>XMLGregorianCalendar</code></a>
<li class='jc'><a href="https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html?is-external=true" title="class or interface in java.time"><code>ZoneId</code></a>
</ul>
</ul>
<h5 class='topic w800'>juneau-config</h5>
<ul class='spaced-list'>
<li>
Support for import statements:
<p class='bcode'>
<cc># Import values from another configuration:</cc>
<ci>&lt;ParentConfig1&gt;</ci>
<cs>[Foo]</cs>
<ck>bar</ck> = <cv>baz</cv>
</p>
<li>
The <dc>org.apache.juneau.config.store.ConfigFileStore</dc> now automatically resolves file extensions.
<br>New configuration property for specifying search paths for file extensions:
<ul class='javatree'>
<li class='jf'><dc>ConfigFileStore.FILESTORE_extensions</dc>
</ul>
<li>
Fixed a bug where instances of <code>org.apache.juneau.config.store.ConfigMemoryStore</code> ended up resolving to the same object.
<li>
Uses <js>"application.properties"</js> file as a system default if present.
<br>Useful when being used in a Spring Boot application.
<li>
New <a href="org/apache/juneau/config/Config.html#setSystemProperties--"><code>Config.setSystemProperties()</code></a> method for quickly moving configuration settings into the
system properties.
<li>
Entries in the system config are automatically set as system properties.
<br>This mean you can set any of the various serializer and parser settings (e.g. <js>"JsonSerializer.simpleMode.b"</js>)
in the default configuration area or <c>application.properties</c>.
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
New annotations that can be applied to REST classes and methods to configure serializers and parsers.
<p class='bcode'>
<jc>// Old way using generic properties.</jc>
<ja>@RestResource</ja>(
path=<js>"/atom"</js>,
title=<js>"Sample ATOM feed resource"</js>,
properties={
<ja>@Property</ja>(name=<jsf>WSERIALIZER_quoteChar</jsf>, value=<js>"'"</js>),
<ja>@Property</ja>(name=<jsf>RDF_rdfxml_tab</jsf>, value=<js>"5"</js>),
<ja>@Property</ja>(name<jsf>RDF_addRootProperty</jsf>, value=<js>"true"</js>),
<ja>@Property</ja>(name=<jsf>BEAN_examples</jsf>, value=<js>"{'org.apache.juneau.dto.atom.Feed': $F{AtomFeedResource_example.json}}"</js>)
}
...
)
<jk>public class</jk> AtomFeedResource <jk>extends</jk> BasicRestServletJena {
...
}
</p>
<p class='bcode'>
<jc>// New way using specific annotations.</jc>
<ja>@RestResource</ja>(
path=<js>"/atom"</js>,
title=<js>"Sample ATOM feed resource"</js>
...
)
<ja>@SerializerConfig</ja>(quoteChar=<js>"'"</js>)
<ja>@RdfConfig</ja>(rdfxml_tab=<js>"5"</js>, addRootProperty=<js>"true"</js>)
<ja>@BeanConfig</ja>(examples=<js>"Feed: $F{AtomFeedResource_example.json}"</js>)
<jk>public class</jk> AtomFeedResource <jk>extends</jk> BasicRestServletJena {
...
}
</p>
<p>
Config annotations are provided for all serializers and parsers:
</p>
<ul class='javatree'>
<li class='ja'><a href="org/apache/juneau/annotation/BeanConfig.html" title="annotation in org.apache.juneau.annotation"><code>BeanConfig</code></a>
<li class='ja'><a href="org/apache/juneau/csv/annotation/CsvConfig.html" title="annotation in org.apache.juneau.csv.annotation"><code>CsvConfig</code></a>
<li class='ja'><a href="org/apache/juneau/html/annotation/HtmlConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlConfig</code></a>
<li class='ja'><a href="org/apache/juneau/html/annotation/HtmlDocConfig.html" title="annotation in org.apache.juneau.html.annotation"><code>HtmlDocConfig</code></a>
<li class='ja'><dc>JsoConfig</dc>
<li class='ja'><a href="org/apache/juneau/json/annotation/JsonConfig.html" title="annotation in org.apache.juneau.json.annotation"><code>JsonConfig</code></a>
<li class='ja'><a href="org/apache/juneau/jsonschema/annotation/JsonSchemaConfig.html" title="annotation in org.apache.juneau.jsonschema.annotation"><code>JsonSchemaConfig</code></a>
<li class='ja'><a href="org/apache/juneau/msgpack/annotation/MsgPackConfig.html" title="annotation in org.apache.juneau.msgpack.annotation"><code>MsgPackConfig</code></a>
<li class='ja'><a href="org/apache/juneau/oapi/annotation/OpenApiConfig.html" title="annotation in org.apache.juneau.oapi.annotation"><code>OpenApiConfig</code></a>
<li class='ja'><a href="org/apache/juneau/parser/annotation/ParserConfig.html" title="annotation in org.apache.juneau.parser.annotation"><code>ParserConfig</code></a>
<li class='ja'><a href="org/apache/juneau/plaintext/annotation/PlainTextConfig.html" title="annotation in org.apache.juneau.plaintext.annotation"><code>PlainTextConfig</code></a>
<li class='ja'><a href="org/apache/juneau/jena/annotation/RdfConfig.html" title="annotation in org.apache.juneau.jena.annotation"><code>RdfConfig</code></a>
<li class='ja'><a href="org/apache/juneau/serializer/annotation/SerializerConfig.html" title="annotation in org.apache.juneau.serializer.annotation"><code>SerializerConfig</code></a>
<li class='ja'><a href="org/apache/juneau/soap/annotation/SoapXmlConfig.html" title="annotation in org.apache.juneau.soap.annotation"><code>SoapXmlConfig</code></a>
<li class='ja'><a href="org/apache/juneau/uon/annotation/UonConfig.html" title="annotation in org.apache.juneau.uon.annotation"><code>UonConfig</code></a>
<li class='ja'><a href="org/apache/juneau/urlencoding/annotation/UrlEncodingConfig.html" title="annotation in org.apache.juneau.urlencoding.annotation"><code>UrlEncodingConfig</code></a>
<li class='ja'><a href="org/apache/juneau/xml/annotation/XmlConfig.html" title="annotation in org.apache.juneau.xml.annotation"><code>XmlConfig</code></a>
</ul>
<li>
New support for using Servlet request attributes.
<ul class='javatree'>
<li class='jc'><dc>org.apache.juneau.rest.RequestAttributes</dc>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>
<ul>
<li class='jf'><dc>REST_attrs</dc>
</ul>
<li class='jc'><a href="org/apache/juneau/rest/RestContext.Builder.html" title="class in org.apache.juneau.rest"><code>RestContext.Builder</code></a>
<ul>
<li class='jm'><dc>attrs(String...)</dc>
<li class='jm'><dc>attr(String,Object)</dc>
</ul>
<li class='jc'><dc>org.apache.juneau.rest.RestMethodContext</dc>
<ul>
<li class='jf'><dc>RESTMETHOD_attrs</dc>
</ul>
<li class='jc'><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/RestRequest.html#getAttributes--"><code>getAttributes()</code></a>
</ul>
<li class='jc'><a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/RestResponse.html#getAttributes--"><code>getAttributes()</code></a>
<li class='jm'><dc>attr(String,Object)</dc>
</ul>
<li class='ja'><a href="org/apache/juneau/rest/annotation/Attr.html" title="annotation in org.apache.juneau.rest.annotation"><code>Attr</code></a>
<li class='ja'><dc>RestMethod.attrs()</dc>
<li class='ja'><dc>RestResource.attrs()</dc>
</ul>
<br>This deprecates the following APIs:
<ul class='javatree'>
<li class='jc'><dc>org.apache.juneau.rest.RequestProperties</dc>
<li class='jc'><dc>org.apache.juneau.rest.RestMethodProperties</dc>
<li class='jc'><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>
<ul>
<li class='jm'><dc>getProperties()</dc>
<li class='jm'><dc>prop(String,Object)</dc>
</ul>
</ul>
<li>
Added the following classes that provide the same support as the servlet classes but doesn't extend from <c>HttpServlet</c>.
<br>This fixes an issue where instances of <dc>org.apache.juneau.rest.BasicRestServlet</dc> are registered as top-level servlets even though
you don't want them to be.
<ul class='javatree'>
<li class='jac'><dc>org.apache.juneau.rest.BasicRest</dc> - Non-servlet equivalent to <dc>org.apache.juneau.rest.BasicRestServlet</dc>
<li class='jac'><dc>org.apache.juneau.rest.BasicRestGroup</dc> - Non-servlet equivalent to <dc>org.apache.juneau.rest.BasicRestServletGroup</dc>
<li class='jac'><dc>org.apache.juneau.rest.BasicRestJena</dc> - Non-servlet equivalent to <dc>org.apache.juneau.rest.BasicRestServletJena</dc>
<li class='jac'><dc>org.apache.juneau.rest.BasicRestJenaGroup</dc> - Non-servlet equivalent to <dc>org.apache.juneau.rest.BasicRestServletJenaGroup</dc>
</ul>
<li>
HTML widgets now have access to the <c>RestResponse</c> object if they need access to the output bean.
<li>
New annotations for simplified role-based guards on classes and methods:
<ul class='javatree'>
<li class='ja'><dc>RestResource</dc>
<ul>
<li class='jm'><dc>roleGuard()</dc>
<li class='jm'><dc>rolesDeclared()</dc>
</ul>
<li class='ja'><dc>org.apache.juneau.rest.annotation.RestMethod</dc>
<ul>
<li class='jm'><dc>roleGuard()</dc>
<li class='jm'><dc>rolesDeclared()</dc>
</ul>
</ul>
<li>
New annotations for fine-tuned handling of http-methods/http-headers as query parameters and others:
<ul class='javatree'>
<li class='ja'><dc>RestResource</dc>
<ul>
<li class='jm'><dc>allowedHeaderParams()</dc>
<li class='jm'><dc>allowedMethodHeaders()</dc>
<li class='jm'><dc>allowedMethodParams()</dc>
</ul>
</ul>
<li>
The <dc>@RestResource(path)</dc> annotation can now use variables:
<p class='bcode'>
<ja>@RestResource</ja>(
path=<js>"/myResource/{foo}/{bar}"</js>
)
<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet {...}
</p>
<li>
New methods:
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/rest/RestRequest.html" title="class in org.apache.juneau.rest"><code>RestRequest</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/RestRequest.html#getCharset--"><code>getCharset()</code></a>
</ul>
<li class='jc'><a href="org/apache/juneau/rest/RestResponse.html" title="class in org.apache.juneau.rest"><code>RestResponse</code></a>
<ul>
<li class='jm'><a href="org/apache/juneau/rest/RestResponse.html#getCharset--"><code>getCharset()</code></a>
</ul>
</ul>
<li>
New interface method for catching arbitrary thrown objects and converting them to other throwables.
<ul class='javatree'>
<li class='jc'><dc>org.apache.juneau.rest.RestCallHandler</dc>
<ul>
<li class='jm'><dc>convertThrowable(Throwable)</dc>
</ul>
<li class='jc'><dc>BasicRestCallHandler</dc>
<ul>
<li class='jm'><dc>convertThrowable(Throwable)</dc>
</ul>
</ul>
<li>
Support for fine-tuned logging of HTTP requests and responses.
<p class='bcode'>
<ja>@RestResource</ja>(
debug=<js>"per-request"</js>,
logging=<ja>@Logging</ja>(
level=<js>"info"</js>,
rules={
<ja>@LoggingRule</ja>(codes<js>"400-499"</js>, level=<js>"warning"</js>, req=<js>"short"</js>, res=<js>"short"</js>)
<ja>@LoggingRule</ja>(codes<js>"500-"</js>, level=<js>"severe"</js>, req=<js>"long"</js>, res=<js>"long"</js>)
}
)
)
<jk>public class</jk> MyRest {
<ja>@RestMethod</ja>(
method=<js>"POST"</js>,
path=<js>"foo"</js>
logging=<ja>@Logging</ja>(
level=<js>"info"</js>,
rules={
<ja>@LoggingRule</ja>(exceptions<js>"NotFound*"</js>, level=<js>"info"</js>)
<ja>@LoggingRule</ja>(codes<js>"200"</js>, disabled=<js>"true"</js>)
}
)
)
<jk>public</jk> String myMethod() <jk>throws</jk> Exception {...}
</p>
See <dc>RestLoggingAndDebugging</dc> for details.
<li>
Fixed a bug where the HTTP response was returning 405 (method not found) but should really be 404 (not found)
when no path patterns match on any of the Java methods.
</ul>
<h5 class='topic w800'>juneau-rest-client</h5>
<ul class='spaced-list'>
<li>
PATCH support added.
</ul>
</div>
</div><!-- END: 8.1.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#8.1.1' id='8.1.1'>8.1.1 (Sept 20, 2019)</a></h3>
<div class='topic'><!-- START: 8.1.1 -->
<div class='topic'>
<p>
Juneau 8.1.1 is a minor release but introduces some new features/modifications.
</p>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
Support for serializing/parsing <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html?is-external=true" title="class or interface in java.util"><code>Optional</code></a> objects and bean properties.
<li>
Fixed a bug in the parsers where the generic subtype of a complex bean property type involving both collections and arrays
was not being found. (e.g. <c>List&lt;Long&gt;[]</c>)
<li>
New packages of HTTP response/exceptions beans from <c>juneau-rest-server</c> bundle and REST proxy annotations from <c>juneau-rest-client</c>
so that they can be used when building REST proxy interfaces while only pulling in the marshall bundle.
<ul>
<li class='jp'><a href="org/apache/juneau/http/response/package-summary.html"><code>org.apache.juneau.http.response</code></a>
<li class='jp'><dc>org.apache.juneau.http.exception</dc>
<li class='jp'><a href="org/apache/juneau/http/remote/package-summary.html"><code>org.apache.juneau.http.remote</code></a>
</ul>
These replace the <c>org.apache.juneau.rest.response</c>, <c>org.apache.juneau.rest.exception</c>, and <c>org.apache.juneau.rest.client.remote</c> packages.
<li>
Defaulting SVL variables now won't ignore additional parameters.
<br><js>"$S{Foo,bar,baz}"</js> used to default to <js>"bar"</js> but now will default to <js>"bar,baz"</js>.
<li>
Ranking support has been added to all <ja>@XConfig</ja> annotations.
This allows you to override the normal precedence of application of config annotations on class and method hierarchies.
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
Support for <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html?is-external=true" title="class or interface in java.util"><code>Optional</code></a> on method parameters annotated with <a href="org/apache/juneau/http/annotation/Header.html" title="annotation in org.apache.juneau.http.annotation"><code>Header</code></a>, <a href="org/apache/juneau/http/annotation/FormData.html" title="annotation in org.apache.juneau.http.annotation"><code>FormData</code></a>,
<a href="org/apache/juneau/http/annotation/Query.html" title="annotation in org.apache.juneau.http.annotation"><code>Query</code></a>, <a href="org/apache/juneau/http/annotation/Path.html" title="annotation in org.apache.juneau.http.annotation"><code>Path</code></a>.
<li>
Fixed issue where <dc>RestMethod.debug()</dc> annotation wasn't resulting
in the HTTP request being logged.
<li>
<dc>org.apache.juneau.rest.RestException</dc> has been deprecated and replaced by <dc>org.apache.juneau.http.exception.HttpException</dc>.
<li>
Resolved issue where parameterized types on <ja>@RestMethod</ja>-annotated method parameters of Spring beans.
This is due to Spring relying on CGLIB for runtime-recompilation of beans that results in loss of parameterized-type
information.
<br>In the following example, the <c>beans</c> parameter would resolve as an unparameterized <c>List</c>
which would typically result in getting a <c>List&lt;ObjectMap&gt;<c> and subsequent <c>ClassCastExceptions</c>.
<p class='bcode'>
<ja>@RestMethod</ja>
<jk>public void</jk> doFoo(<ja>@Body</ja> List&lt;MyBean&gt; beans) {...}
</p>
The fix involves resolving the original bean class for resolving parameterized type while leaving
method invocation on the proxy method so as not to bypass Spring features.
<li>
New methods on <dc>org.apache.juneau.rest.BasicRest</dc> to provide feature-parity with <dc>org.apache.juneau.rest.RestServlet</dc>:
<ul class='javatree'>
<li class='jc'><dc>org.apache.juneau.rest.BasicRest</dc>
<ul class='javatreec'>
<li class='jm'><dc>getContext()</dc>
<li class='jm'><dc>getRequest()</dc>
<li class='jm'><dc>getResponse()</dc>
<li class='jm'><dc>log(String)</dc>
<li class='jm'><dc>log(String,Throwable)</dc>
<li class='jm'><dc>log(Level,String,Object[])</dc>
<li class='jm'><dc>BasicRest.logObjects(Level,String,Object[])</dc>
<li class='jm'><dc>log(Level,Throwable,String,Object[])</dc>
</ul>
</li>
</ul>
<li>
The <dc>@RestResource(staticFiles)</dc> annotation now supports absolute path locations and multiple mappings:
<p class='bcode'>
<jc>// Resolves static files in root package "htdocs" or working directory "htdocs", and then relative package "htdocs".</jc>
<ja>@RestResource</ja>(staticFiles=<js>"htdocs:/htdocsfolder,htdocs:htdocs.package"</js>)
</p>
<li>
Fixed a bug in <dc>@RestResource(staticFiles)</dc> where the order of lookup between parent and child resources
was wrong.
</ul>
<h5 class='topic w800'>juneau-rest-client</h5>
<ul class='spaced-list'>
<li>
Removed the dependency on the <c>juneau-rest-server</c> module.
Allows the client API to be used without pulling in all the javax.servlet and server dependencies.
</ul>
<h5 class='topic w800'>juneau-examples</h5>
<ul class='spaced-list'>
<li>
The PetStore application has been moved to a separate Git repository.
<ul>
<li><a class='doclink' href='https://github.com/apache/juneau-petstore'>GitHub Repo</a>
<li><a class='doclink' href='http://juneau.apache.org/index.html#petstore.html'>Documentation</a>
</ul>
</ul>
</div>
</div><!-- END: 8.1.1 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#8.1.2' id='8.1.2'>8.1.2 (Dec 01, 2019)</a></h3>
<div class='topic'><!-- START: 8.1.2 -->
<div class='topic'>
<p>
Juneau 8.1.2 is a moderate release.
</p>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
Support for read-only and write-only properties.
<ul>
<li class='ja'><dc>Bean.bpro()</dc>
<li class='ja'><dc>Bean.bpwo()</dc>
<li class='ja'><a href="org/apache/juneau/annotation/Beanp.html#ro--"><code>Beanp.ro()</code></a>
<li class='ja'><a href="org/apache/juneau/annotation/Beanp.html#wo--"><code>Beanp.wo()</code></a>
<li class='jf'><dc>BEAN_bpro</dc>
<li class='jf'><dc>BEAN_bpwo</dc>
<li class='jm'><dc>Builder.bpro(Map)</dc>
<li class='jm'><dc>Builder.bpwo(Map)</dc>
</ul>
<li>
New convenience methods:
<ul>
<li class='jm'><dc>ObjectMap.parse(CharSequence)</dc>
<li class='jm'><dc>ObjectList.parse(CharSequence)</dc>
</ul>
<li>
<dc>org.apache.juneau.marshall.CharMarshall</dc> and <code>org.apache.juneau.marshall.StreamMarshall</code> now have public constructors.
<li>
<a href="org/apache/juneau/annotation/Beanp.html" title="annotation in org.apache.juneau.annotation"><code>@Beanp</code></a> replaces <dc>@BeanProperty</dc>.
<li>
<a href="org/apache/juneau/annotation/Beanc.html" title="annotation in org.apache.juneau.annotation"><code>@Beanc</code></a> replaces <dc>@BeanConstructor</dc>.
<li>
<a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>@Remote</code></a> replaces <dc>@RemoteResource</dc>.
<li>
Shortened names for <a href="org/apache/juneau/annotation/Bean.html#dictionary--"><code>@Bean(dictionary)</code></a> and <a href="org/apache/juneau/BeanContext.Builder.html#beanDictionary-java.lang.Class...-"><code>BeanContext.Builder.beanDictionary(Class...)</code></a>.
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
<a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a> replaces <dc>@RestResource</dc> with shorter syntax.
<li>
New method <dc>RestResponse.setHeaderSafe(String,String)</dc> to strip invalid characters from header values.
<li>
Fixed issues related to invalid characters being set on HTTP header values.
</ul>
<h5 class='topic w800'>juneau-rest-client</h5>
<ul class='spaced-list'>
<li>
<a href="org/apache/juneau/rest/client/RestClient.html" title="class in org.apache.juneau.rest.client"><code>RestClient</code></a> is now extendible. The constructor has been made public and simplified to:
<dc>Builder)</dc>.
<li>
Duplicate methods between <a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a> and <code>HttpClientBuilder</code>
have been made deprecated on the former. This eliminates the need to try to keep the two builder classes in
sync.
</ul>
</div>
</div><!-- END: 8.1.2 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#8.1.3' id='8.1.3'>8.1.3 (Jan 20, 2020)</a></h3>
<div class='topic'><!-- START: 8.1.3 -->
<div class='topic'>
<p>
Juneau 8.1.3 is a moderate release.
</p>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
Dynamically applied annotations: <dc>DynamicallyAppliedAnnotations</dc>
<li>
Better representation of nulls for XML and HTML content properties.
<br>Old: <js>"&lt;myBean&gt;&lt;null&gt;&lt;/myBean&gt;"</js>
<br>New: <js>"&lt;myBean nil='true'&gt;&lt;/myBean&gt;"</js>
<li>
Configurable properties such as <dc>Context.CONTEXT_debug</dc> can now be set globally by either
system properties or environment variables.
<br>For <jsf>CONTEXT_debug</jsf> you can use either the system
property <js>"Context.debug"</js> or environment variables <js>"CONTEXT_DEBUG"</js>.
<li>
Fixed an initialization time race condition that can cause initial parse errors when concurrently parsing into
array types like so:
<p class='bcode'>
JsonParser.<jsf>DEFAULT</jsf>.parse(input, MyBean[].<jk>class</jk>);
</p>
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
Fixed bug in <dc>BasicRestCallHandler</dc> where if you have the following REST methods...
<p class='bcode'>
<ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo"</js>)
<ja>@RestMethod</ja>(name=<js>"*"</js>, path=<js>"/bar"</js>)
</p>
...and you tried to make a GET request to /bar, you'd erroneously get a 404 error instead of matching the 2nd method.
<li>
Fixed an issue involving using Juneau REST with Spring Security. When Spring Security cannot authenticate a
request, it sets the URL on the request to <js>"/error"</js> with a 401 status. When Juneau then processes
this request, it cannot find that mapping and changes the status to 404 which messes with HTTP clients.
<br>Solution was to add a default no-op error method to the <dc>org.apache.juneau.rest.BasicRestConfig</dc> (and implementers):
<p class='bcode'>
<ja>@RestMethod</ja>(name=<js>"*"</js>, path=<js>"/error"</js>)
<jk>public void</jk> error() {}
</p>
<li>
Fixed a bug where <c><ja>@RestResource</ja>(debug=<js>"true"</js>)</c> wouldn't log requests if a
<ja>@RestMethod</ja>-annotated method was not matched.
<li>
Renamed the following annotations:
<ul>
<li><ja>@Rest(attrs)</ja> --> <dc>@Rest(reqAttrs)</dc>
<li><ja>@Rest(defaultRequestHeaders)</ja> --> <dc>@Rest(reqHeaders)</dc>
<li><ja>@Rest(defaultResponseHeaders)</ja> --> <dc>@Rest(resHeaders)</dc>
<li><ja>@RestMethod(attrs)</ja> --> <dc>@RestMethod(reqAttrs)</dc>
<li><ja>@RestMethod(defaultRequestHeaders)</ja> --> <dc>@RestMethod(reqHeaders)</dc>
</ul>
<li>
New auto-generated REST method execution statistics: <dc>RestExecutionStatistics</dc>
</ul>
<h5 class='topic w800'>juneau-rest-client</h5>
<ul class='spaced-list'>
<li>
Several convenience methods defined in <a href="org/apache/juneau/rest/client/RestClient.Builder.html" title="class in org.apache.juneau.rest.client"><code>RestClient.Builder</code></a> that were deprecated in 8.1.2 have been
undeprecated in this release due to user feedback.
</ul>
<h5 class='topic w800'>juneau-doc</h5>
<ul class='spaced-list'>
<li>
New auto-generated glossary of all configurable properties: <dc>GlossaryConfigurableProperties</dc>
</ul>
</div>
</div><!-- END: 8.1.3 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#8.2.0' id='8.2.0'>8.2.0 (Oct 14, 2020)</a></h3>
<div class='topic'><!-- START: 8.2.0 -->
<div class='topic'>
<p>
Juneau 8.2.0 is a major release.
The most significant change is the addition of an entirely new <dc>org.apache.juneau.rest.client2.RestClient</dc> API build from scratch
with near 100% unit test coverage.
The new API is located in the <c>org.apache.juneau.rest.client2</c> package and will replace the old API in 9.0.
</p>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
<a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a> and <a href="org/apache/juneau/annotation/BeanIgnore.html" title="annotation in org.apache.juneau.annotation"><code>@BeanIgnore</code></a> annotations can alternately occur in parent class hierarchy.
The first one found dictates whether a class is ignored as a bean or not.
<li>
Applying the <a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a> annotation on a class will now force non-public classes to be interpreted as beans.
For example, applying <a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a> to a <jk>private</jk> class will force it to be treated as a bean.
<br>
Also, if a public bean constructor cannot be found, the default constructor will be used
regardless of it's visibility if the <a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a> annotation is on the class.
<li>
The <ja>@Beanc</ja> annotation can now be recognized and used on non-public constructors.
<li>
Annotations are now aggregated across the entire class hierarchy instead of simply being overridden.
<br>The following is an example.
<p class='bcode'>
<jc>// Parent class with properties a,b,c</jc>
<ja>@Bean</ja>(bpi=<js>"a,b,c"</js>)
<jk>public class</jk> MyClass {
<jk>public int</jk> a, b, c, d;
}
<jc>// New behavior: Child class with properties a,c because @Beans are aggregated.</jc>
<jc>// Old behavior: Child class with properties a,c,d because @Bean is overridden.</jc>
<ja>@Bean</ja>(bpx=<js>"b"</js>)
<jk>public class</jk> MyClass {
<jk>public int</jk> a, b, c, d;
}
</p>
<li>
Include/exclude/read-only/write-only properties defined on the bean context now override those defined on
annotations of the class itself. For example, the following methods override the <a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>@Bean</code></a>
annotations on classes:
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/BeanContext.Builder.html" title="class in org.apache.juneau"><code>BeanContext.Builder</code></a>
<ul class='javatreec'>
<li class='jm'><dc>bpi(Class,String)</dc>
<li class='jm'><dc>bpi(String,String)</dc>
<li class='jm'><dc>bpx(Class,String)</dc>
<li class='jm'><dc>bpx(String,String)</dc>
<li class='jm'><dc>bpro(Class,String)</dc>
<li class='jm'><dc>bpro(String,String)</dc>
<li class='jm'><dc>bpwo(Class,String</dc>
<li class='jm'><dc>bpwo(String,String</dc>
</ul>
</li>
</ul>
<li>
Config annotations now override class-level annotations.
<br>For example, only the 'a' and 'b' properties get serialized on the bean below:
<p class='bcode'>
<jc>// Parent class with properties a,b,c</jc>
<ja>@Bean</ja>(bpi=<js>"a,b,c"</js>)
<jk>public class</jk> MyClass {
<jk>public int</jk> a, b, c, d;
}
<ja>@RestMethod</ja>
<ja>@BeanConfig</ja>(beanApply={<ja>@Bean</ja>(on=<js>"MyClass"</js>,bpi=<js>"a,b"</js>)}
<jk>public</jk> MyClass getMyClass() {...}
</p>
<li>
The following concrete annotation implementation classes are now provided that can be used with the <a href="org/apache/juneau/BeanContext.Builder.html#annotations-java.lang.annotation.Annotation...-"><code>BeanContext.Builder.annotations(Annotation...)</code></a> method:
<ul class='javatree'>
<li class='jc'><a href="org/apache/juneau/annotation/BeanAnnotation.html" title="class in org.apache.juneau.annotation"><code>BeanAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/annotation/Bean.html" title="annotation in org.apache.juneau.annotation"><code>Bean</code></a>
<li class='jc'><a href="org/apache/juneau/annotation/BeancAnnotation.html" title="class in org.apache.juneau.annotation"><code>BeancAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/annotation/Beanc.html" title="annotation in org.apache.juneau.annotation"><code>Beanc</code></a>
<li class='jc'><a href="org/apache/juneau/annotation/BeanIgnoreAnnotation.html" title="class in org.apache.juneau.annotation"><code>BeanIgnoreAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/annotation/BeanIgnore.html" title="annotation in org.apache.juneau.annotation"><code>BeanIgnore</code></a>
<li class='jc'><a href="org/apache/juneau/annotation/BeanpAnnotation.html" title="class in org.apache.juneau.annotation"><code>BeanpAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/annotation/Beanp.html" title="annotation in org.apache.juneau.annotation"><code>Beanp</code></a>
<li class='jc'><a href="org/apache/juneau/annotation/ExampleAnnotation.html" title="class in org.apache.juneau.annotation"><code>ExampleAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/annotation/Example.html" title="annotation in org.apache.juneau.annotation"><code>Example</code></a>
<li class='jc'><a href="org/apache/juneau/annotation/NamePropertyAnnotation.html" title="class in org.apache.juneau.annotation"><code>NamePropertyAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/annotation/NameProperty.html" title="annotation in org.apache.juneau.annotation"><code>NameProperty</code></a>
<li class='jc'><a href="org/apache/juneau/annotation/ParentPropertyAnnotation.html" title="class in org.apache.juneau.annotation"><code>ParentPropertyAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/annotation/ParentProperty.html" title="annotation in org.apache.juneau.annotation"><code>ParentProperty</code></a>
<li class='jc'><a href="org/apache/juneau/annotation/SwapAnnotation.html" title="class in org.apache.juneau.annotation"><code>SwapAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/annotation/Swap.html" title="annotation in org.apache.juneau.annotation"><code>Swap</code></a>
<li class='jc'><a href="org/apache/juneau/annotation/UriAnnotation.html" title="class in org.apache.juneau.annotation"><code>UriAnnotation</code></a> <jk>implements</jk> <dc>org.apache.juneau.annotation.URI</dc>
<li class='jc'><a href="org/apache/juneau/csv/annotation/CsvAnnotation.html" title="class in org.apache.juneau.csv.annotation"><code>CsvAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/csv/annotation/Csv.html" title="annotation in org.apache.juneau.csv.annotation"><code>Csv</code></a>
<li class='jc'><a href="org/apache/juneau/html/annotation/HtmlAnnotation.html" title="class in org.apache.juneau.html.annotation"><code>HtmlAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/html/annotation/Html.html" title="annotation in org.apache.juneau.html.annotation"><code>Html</code></a>
<li class='jc'><dc>org.apache.juneau.jso.annotation.JsoAnnotation</dc> <jk>implements</jk> <dc>org.apache.juneau.jso.annotation.Jso</dc>
<li class='jc'><a href="org/apache/juneau/json/annotation/JsonAnnotation.html" title="class in org.apache.juneau.json.annotation"><code>JsonAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/json/annotation/Json.html" title="annotation in org.apache.juneau.json.annotation"><code>Json</code></a>
<li class='jc'><code>org.apache.juneau.jsonschema.annotation.SchemaAnnotation</code> <jk>implements</jk> <code>org.apache.juneau.jsonschema.annotation.Schema</code>
<li class='jc'><a href="org/apache/juneau/msgpack/annotation/MsgPackAnnotation.html" title="class in org.apache.juneau.msgpack.annotation"><code>MsgPackAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/msgpack/annotation/MsgPack.html" title="annotation in org.apache.juneau.msgpack.annotation"><code>MsgPack</code></a>
<li class='jc'><a href="org/apache/juneau/oapi/annotation/OpenApiAnnotation.html" title="class in org.apache.juneau.oapi.annotation"><code>OpenApiAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/oapi/annotation/OpenApi.html" title="annotation in org.apache.juneau.oapi.annotation"><code>OpenApi</code></a>
<li class='jc'><a href="org/apache/juneau/plaintext/annotation/PlainTextAnnotation.html" title="class in org.apache.juneau.plaintext.annotation"><code>PlainTextAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/plaintext/annotation/PlainText.html" title="annotation in org.apache.juneau.plaintext.annotation"><code>PlainText</code></a>
<li class='jc'><a href="org/apache/juneau/soap/annotation/SoapXmlAnnotation.html" title="class in org.apache.juneau.soap.annotation"><code>SoapXmlAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/soap/annotation/SoapXml.html" title="annotation in org.apache.juneau.soap.annotation"><code>SoapXml</code></a>
<li class='jc'><a href="org/apache/juneau/uon/annotation/UonAnnotation.html" title="class in org.apache.juneau.uon.annotation"><code>UonAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/uon/annotation/Uon.html" title="annotation in org.apache.juneau.uon.annotation"><code>Uon</code></a>
<li class='jc'><a href="org/apache/juneau/urlencoding/annotation/UrlEncodingAnnotation.html" title="class in org.apache.juneau.urlencoding.annotation"><code>UrlEncodingAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/urlencoding/annotation/UrlEncoding.html" title="annotation in org.apache.juneau.urlencoding.annotation"><code>UrlEncoding</code></a>
<li class='jc'><a href="org/apache/juneau/xml/annotation/XmlAnnotation.html" title="class in org.apache.juneau.xml.annotation"><code>XmlAnnotation</code></a> <jk>implements</jk> <a href="org/apache/juneau/xml/annotation/Xml.html" title="annotation in org.apache.juneau.xml.annotation"><code>Xml</code></a>
</ul>
<br>Example:
<p class='bcode'>
<ja>@Bean</ja>(bpi=<js>"street,city"</js>) <jc>// Will be overridden</jc>
<jk>public class</jk> AddressBean {...}
<ja>Bean</ja> ba = <jk>new</jk> BeanAnnotation(<js>"AddressBean"</js>).bpi(<js>"street,city,state"</js>);
WriterSerializer ws = JsonSerializer.<jsm>create</jsm>().annotations(ba).build();
String json = ws.toString(addressBean); <jc>// Will print street,city,state</jc>
</p>
<li>
Bean maps now have the concept of "hidden" properties (properties that aren't serialized but otherwise accessible).
<br>For example, the <a href="org/apache/juneau/html/annotation/Html.html#link--"><code>Html.link()</code></a> can now reference hidden properties:
<p class='bcode'>
<ja>@Bean</ja>(bpi=<js>"a"</js>) <jc>// Will be overridden</jc>
<jk>public class</jk> MyBean {
<ja>@Html</ja>(link=<js>"servlet:/{b}"</js>)
<jk>public</jk> String <jf>a</jf>;
<jk>public</jk> String <jf>b</jf>; <jc>// Not serialized but referenced in link on a.</jc>
}
</p>
<br>
The general rule for the <a href="org/apache/juneau/BeanMap.html" title="class in org.apache.juneau"><code>BeanMap</code></a> class is that <c>get()</c>,<c>put()</c>, and <c>containsKey()</c>
will work against hidden properties but <c>keySet()</c> and <c>entrySet()</c> will skip them.
<li>
Several bug fixes in the <a href="org/apache/juneau/html/HtmlSerializer.html" title="class in org.apache.juneau.html"><code>HtmlSerializer</code></a> and <a href="org/apache/juneau/html/HtmlParser.html" title="class in org.apache.juneau.html"><code>HtmlParser</code></a> classes around the handling of
collections and arrays of beans with <c><ja>@Bean</ja>(typeName)</c> annotations.
<li>
New swaps auto-added to all serializers/parsers:
<ul>
<li class='jc'><dc>org.apache.juneau.transforms.MatchResultSwap</dc>
<li class='jc'><dc>org.apache.juneau.transforms.StackTraceElementSwap</dc>
</ul>
<li>
<a href="org/apache/juneau/html/annotation/Html.html#noTableHeaders--"><code>Html.noTableHeaders()</code></a> now can be applied to collections of beans.
<li>
New <a href="org/apache/juneau/html/annotation/HtmlDocConfig.html#asideFloat--"><code>HtmlDocConfig.asideFloat()</code></a> setting so that you can position the contents of the aside section on the page.
<li>
Various minor fixes surrounding HTML serialization.
<ul>
<li>Collections of beans that were supposed to be serialized as tables were being serialized as lists.
<li>Collections of beans with <c><ja>@Bean</ja>(bpi)</c> were not being serialized in the correct column order.
</ul>
<li>
Fixed a bug where a copy constructor can erroneously be recognized as a builder constructor if the class also
has a static <c>create</c> method. Net effect was that the copy constructor would needlessly be called during parsing.
<li>
New <a href="org/apache/juneau/collections/package-summary.html"><code>org.apache.juneau.collections</code></a> package containing various convenience fluent-style collection classes:
<ul>
<li class='jc'><dc>org.apache.juneau.collections.AList</dc>
<li class='jc'><dc>org.apache.juneau.collections.ASet</dc>
<li class='jc'><dc>org.apache.juneau.collections.ASortedSet</dc>
<li class='jc'><dc>org.apache.juneau.collections.AMap</dc>
<li class='jc'><dc>org.apache.juneau.collections.ASortedMap</dc>
<li class='jc'><dc>org.apache.juneau.collections.OMap</dc>
<li class='jc'><dc>org.apache.juneau.collections.OList</dc>
</ul>
<li>
<dc>org.apache.juneau.ObjectMap</dc> is being deprecated and replaced with <dc>org.apache.juneau.collections.OMap</dc>.
<li>
<dc>org.apache.juneau.ObjectList</dc> is being deprecated and replaced with <dc>org.apache.juneau.collections.OList</dc>.
<li>
All classes in the <a href="org/apache/juneau/http/response/package-summary.html"><code>org.apache.juneau.http.response</code></a> and <dc>org.apache.juneau.http.exception</dc> now have <c>header(String,Object)</c>
methods for adding response headers.
<p class='bcode'>
<jc>// Method that performs a BASIC Auth handshake.</jc>
<ja>@RestMethod</ja>
<jk>public</jk> Ok checkBasicAuth(<ja>@Header</ja>(<js>"Authorization"</js>) String auth) <jk>throws</jk> Unauthorized {
<jk>if</jk> (auth == <jk>null</jk>)
<jk>throw new</jk> Unauthorized().header(<js>"WWW-Authenticate"</js>, <js>"BASIC realm=\"foo\""</js>);
<jk>return</jk> Ok.<jsf>OK</jsf>;
}
</p>
<li>
New annotations for multi-part support:
<ul>
<li class='jm'><dc>Header.multi()</dc>
<li class='jm'><dc>Query.multi()</dc>
<li class='jm'><dc>FormData.multi()</dc>
</ul>
<li>
<dc>BeanTraverseContext.BEANTRAVERSE_ignoreRecursions</dc> setting no longer requires <dc>BeanTraverseContext.BEANTRAVERSE_detectRecursions</dc>
to be enabled.
<li>
Fixed bug in JSON/UON/URL-Encoding serializers where indentation was not correct of first line when <dc>BeanTraverseContext.BEANTRAVERSE_initialDepth</dc>
used.
<li>
Fixed bug in JSON/UON/URL-Encoding serializers where properties past the max depth were being serialized as null instead
of being treated as null and not being serialized at all.
<li>
Fixed bug in HTML serializer where tables of maps were not sorted if <jsf>SERIALIZER_sortMaps</jsf> was specified.
<li>
<jsf>SERIALIZER_trimNullProperties</jsf> has been replaced with <dc>SERIALIZER_keepNullProperties</dc>.
<li>
Improvements to OpenAPI serializer and parser:
<ul>
<li>Collection format can now be specified on OBJECTs to allow key/value pairs to be delimited with the same support as ARRAYs.
<li>New <dc>OAPI_format</dc> and <dc>OAPI_collectionFormat</dc> properties.
</ul>
<li>
Convenience methods added to <a href="org/apache/juneau/httppart/HttpPartSchema.html" title="class in org.apache.juneau.httppart"><code>HttpPartSchema</code></a> and related classes to simplify schema definitions:
<p class='bcode'>
<jk>import static</jk> org.apache.juneau.httppart.HttpPartSchema.*;
<jc>// Old</jc>
HttpPartSchema s = <jsm>schema</jsm>(<js>"object"</js>)
.property(<js>"f01"</js>, <jsm>schema</jsm>(<js>"array"</js>).collectionFormat(<js>"pipes"</js>).items(<jsm>schema</jsm>(<js>"string"</js>)))
.property(<js>"f02"</js>, <jsm>schema</jsm>(<js>"array"</js>).collectionFormat(<js>"pipes"</js>).items(<jsm>schema</jsm>(<js>"string"</js>, <js>"byte"</js>)))
.property(<js>"f03"</js>, <jsm>schema</jsm>(<js>"array"</js>).collectionFormat(<js>"pipes"</js>).items(<jsm>schema</jsm>(<js>"string"</js>, <js>"date-time"</js>)))
.build();
<jc>// New</jc>
HttpPartSchema s = <jsm>tObject</jsm>()
.p(<js>"f01"</js>, <jsm>tArray</jsm>(<jsm>tString()</jsm>))
.p(<js>"f02"</js>, <jsm>tArray</jsm>(<jsm>tByte()</jsm>))
.p(<js>"f03"</js>, <jsm>tArray</jsm>(<jsm>tDateTime()</jsm>))
.build();
</p>
<li>
Fixes where the bean method/constructor visibility wasn't being used when finding swap methods and constructors.
<li>
HTML-Schema support is being deprecated due to low-use and difficulty in maintaining. It will be removed in 9.0.
<li>
<c>JuneauLogger</c> class is being deprecated. Improvements in logging in Java 8 make it obsolete.
<li>
Bean filters can now be specified programmatically through a builder API.
<p class='bcode'>
<jc>// Create a JSON serializer that only includes specified fields on a specific class.</jc>
WriterSerializer s = JsonSerializer
.<jsm>create</jsm>()
.beanFilters(BeanFilter.<jsm>create</jsm>(MyBean.<jk>class</jk>).bpi(<js>"foo,bar,baz"</js>).build())
.build();
</p>
<li>
<c>BeanContext.REST_pojoSwaps</c> replaced with <dc>BeanContext.BEAN_swaps</dc> (and builder methods as well).
<li>
New Bean Property Interceptor API for intercepting calls to bean getters/setters.
<ul>
<li class='jac'><dc>org.apache.juneau.transform.BeanInterceptor</dc>
<li class='ja'><a href="org/apache/juneau/annotation/Bean.html#interceptor--"><code>Bean(interceptor)</code></a>
<li class='jm'><a href="org/apache/juneau/BeanContext.Builder.html#beanInterceptor-java.lang.Class-java.lang.Class-"><code>BeanContext.Builder.beanInterceptor(Class,Class)</code></a>
</ul>
<li>
Fluent setters that follow the <c>withX</c> convention are now automatically detected by all parsers.
<p class='bcode'>
<jc>// A bean with a fluent setter.</jc>
<jk>public class</jk> MyBean {
<jk>public</jk> MyBean withFoo(String <jv>foo</jv>) {
<jk>this</jk>.<jf>foo</jf> = <jv>foo</jv>;
<jk>return this</jk>;
}
}
</p>
Note you could previously use the <ja>@BeanProperty</ja> annotation to identify these setters.
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
New <dc>REST_context</dc>/<dc>@Rest(context)</dc> setting to allow you to extend the <a href="org/apache/juneau/rest/RestContext.html" title="class in org.apache.juneau.rest"><code>RestContext</code></a>
class.
<li>
<a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>Rest</code></a>-annotated classes can now implement the following interfaces directly instead of having
to define secondary classes and hook them up through annotations:
<ul>
<li class='jic'><dc>org.apache.juneau.rest.RestCallHandler</dc> - Normally defined through <dc>@Rest.callHandler()</dc>.
<li class='jic'><dc>org.apache.juneau.rest.RestInfoProvider</dc> - Normally defined through <dc>@Rest.infoProvider()</dc>.
<li class='jic'><dc>org.apache.juneau.rest.RestCallLogger</dc> - Normally defined through <dc>@Rest.callLogger()</dc>.
<li class='jic'><dc>org.apache.juneau.utils.ClasspathResourceFinder</dc> - Normally defined through <dc>@Rest.classpathResourceFinder()</dc>.
</ul>
<br>The methods added for <dc>org.apache.juneau.rest.RestInfoProvider</dc> are:
<ul>
<li class='jac'><dc>org.apache.juneau.rest.RestServlet</dc>
<ul>
<li class='jm'><dc>getSwagger(RestRequest)</dc>
<li class='jm'><dc>getSiteName(RestRequest)</dc>
<li class='jm'><dc>getTitle(RestRequest)</dc>
<li class='jm'><dc>getDescription(RestRequest)</dc>
<li class='jm'><dc>getMethodSummary(Method,RestRequest)</dc>
<li class='jm'><dc>getMethodDescription(Method,RestRequest)</dc>
</ul>
<li class='jac'><dc>BasicRest</dc>
<ul>
<li class='jm'><dc>getSwagger(RestRequest)</dc>
<li class='jm'><dc>getSiteName(RestRequest)</dc>
<li class='jm'><dc>getTitle(RestRequest)</dc>
<li class='jm'><dc>getDescription(RestRequest)</dc>
<li class='jm'><dc>getMethodSummary(Method,RestRequest)</dc>
<li class='jm'><dc>getMethodDescription(Method,RestRequest)</dc>
</ul>
</ul>
<br>The methods added for <dc>org.apache.juneau.rest.RestCallLogger</dc> are:
<ul>
<li class='jac'><dc>org.apache.juneau.rest.RestServlet</dc>
<ul>
<li class='jm'><dc>log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse)</dc>
</ul>
<li class='jac'><dc>org.apache.juneau.rest.BasicRest</dc>
<ul>
<li class='jm'><dc>log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse)</dc>
</ul>
</ul>
<br>The methods added for <dc>org.apache.juneau.utils.ClasspathResourceFinder</dc> are:
<ul>
<li class='jac'><dc>org.apache.juneau.rest.RestServlet</dc>
<ul>
<li class='jm'><dc>findResource(Class,String,Locale)</dc>
</ul>
<li class='jac'><dc>org.apache.juneau.rest.BasicRest</dc>
<ul>
<li class='jm'><dc>findResource(Class,String,Locale)</dc>
</ul>
</ul>
<br>The methods added for <dc>org.apache.juneau.rest.RestResourceResolver</dc> are:
<ul>
<li class='jac'><dc>org.apache.juneau.rest.RestServlet</dc>
<ul>
<li class='jm'><dc>resolve(Object,Class&lt;T&gt;,RestContext.Builder,Object...)</dc>
</ul>
<li class='jac'><dc>org.apache.juneau.rest.BasicRest</dc>
<ul>
<li class='jm'><dc>resolve(Object,Class&lt;T&gt;,RestContext.Builder,Object...)</dc>
</ul>
</ul>
<li>
Added the following convenience hook methods on the <dc>org.apache.juneau.rest.RestServlet</dc> and <dc>org.apache.juneau.rest.BasicRest</dc> classes:
<ul>
<li class='jac'><dc>org.apache.juneau.rest.RestServlet</dc>
<ul>
<li class='jm'><dc>onInit(RestContext.Builder)</dc>
<li class='jm'><dc>onPostInit(RestContext)</dc>
<li class='jm'><dc>onPostInitChildFirst(RestContext)</dc>
<li class='jm'><dc>onDestroy(RestContext)</dc>
<li class='jm'><dc>onStartCall(HttpServletRequest,HttpServletResponse)</dc>
<li class='jm'><dc>onPreCall(RestRequest,RestResponse)</dc>
<li class='jm'><dc>onPostCall(RestRequest,RestResponse)</dc>
<li class='jm'><dc>onEndCall(HttpServletRequest,HttpServletResponse)</dc>
</ul>
<li class='jac'><dc>org.apache.juneau.rest.BasicRest</dc>
<ul>
<li class='jm'><dc>onInit(RestContext.Builder)</dc>
<li class='jm'><dc>onPostInit(RestContext)</dc>
<li class='jm'><dc>onPostInitChildFirst(RestContext)</dc>
<li class='jm'><dc>onDestroy(RestContext)</dc>
<li class='jm'><dc>onStartCall(HttpServletRequest,HttpServletResponse)</dc>
<li class='jm'><dc>onPreCall(RestRequest,RestResponse)</dc>
<li class='jm'><dc>onPostCall(RestRequest,RestResponse)</dc>
<li class='jm'><dc>onEndCall(HttpServletRequest,HttpServletResponse)</dc>
</ul>
</ul>
<li>
New <a href="org/apache/juneau/rest/annotation/Rest.html#debugOn--"><code>@Rest(debugOn)</code></a> annotation for turning on debug mode using class/method identifiers:
<h5 class='figure'>Example:</h5>
<p class='bcode'>
<jc>// Turn on debug per-request on the class and always on the doX() method</jc>.
<ja>@Rest</ja>(
debugOn=<js>"MyResource=per-request,Mysource.doX=true"</js> <jc>// Typically defined via system or env property</jc>.
)
<jk>public class</jk> MyResource {
<ja>@RestMethod</ja>
<jk>public void</jk> String doX() {
...
}
</p>
<li>
<dc>org.apache.juneau.rest.BasicRestConfig</dc> has been broken up into <dc>BasicRestConfig</dc> and <dc>org.apache.juneau.rest.BasicRestMethods</dc> so that
you're not forced to implement methods such as <c>getOptions()</c> and <c>getStats()</c> if you're implementing the interface
to configure your REST class.
<li>
Any of the following classes can now be instantiated with <c><jk>public static</jk> <jsm>create</jsm>()</c> methods:
<ul>
<li class='jc'><dc>org.apache.juneau.rest.RestCallHandler</dc>
<li class='jc'><dc>org.apache.juneau.rest.RestCallLogger</dc>
<li class='jc'><dc>org.apache.juneau.rest.RestInfoProvider</dc>
<li class='jc'><dc>org.apache.juneau.utils.ClasspathResourceFinder</dc>
<li class='jc'><dc>org.apache.juneau.rest.RestResourceResolver</dc>
<li class='jc'><dc>org.apache.juneau.rest.RestGuard</dc>
<li class='jc'><code>org.apache.juneau.rest.ResponseHandler</code>
</ul>
<li>
New <dc>@Path(required)</dc> annotation support.
<br>A path can be marked as not-required when the path variable is resolved by a parent resource like so:
<p class='bcode'>
<ja>@Rest</ja>(path=<js>"/parent/{p1}"</js>,children=Child.<jk>class</jk>)
<jk>public class</jk> Parent {
...
}
<ja>@Rest</ja>(path="/child")
<jk>public class</jk> Child {
<ja>@RestMethod</ja>(path="/")
<jk>public</jk> String doGet(<ja>@Path</ja>(name=<js>"p1"</js>,required=<jk>false</jk>) String p1) {
<jc>// p1 will be null when accessed via "/child"</jc>
<jc>// p1 will be non-null when accessed via "/parent/p1/child".</jc>
}
...
}
</p>
<br>This allows the child resource to be mapped to multiple parents that may resolve various different path variables.
<li>
New <dc>@RestMethod(paths)</dc> annotation that allows you to map multiple
paths to the same Java method.
<br>Example:
<p class='bcode'>
<ja>@RestMethod</ja>(
name=<jsf>GET</jsf>,
paths={<js>"/"</js>,<js>"/{foo}"</js>}
)
<jk>public</jk> String doGet(<ja>@Path</ja>(name=<js>"foo"</js>,required=<jk>false</jk>) String foo) {...}
</p>
<li>
The <dc>@RestMethod</dc> annotation is now implied on all unannotated methods of a <a href="org/apache/juneau/rest/annotation/Rest.html" title="annotation in org.apache.juneau.rest.annotation"><code>@Rest</code></a>-annotated
interface.
<p class='bcode'>
<ja>@Rest
<jk>public interface</jk> MyRest {
String getFoo(); <jc>// @RestMethod(name=GET,path="/foo") is implied.</jc>
}
</p>
<li>
Improved <dc>REST_messages</dc> support (mostly bug fixes).
</ul>
<h5 class='topic w800'>juneau-rest-server-springboot</h5>
<ul class='spaced-list'>
<li>
<dc>org.apache.juneau.rest.springboot.JuneauRestInitializer</dc> now provides a no-arg constructor so that it can be used in
the <c><ja>@ConfigurationContext</ja>(initializers=JuneauRestInitializer.<jk>class</jk>)</c> when unit testing
using <ja>@SpringBootTest</ja>.
<li>
New <dc>ResourceDescription.ResourceDescription(String,String,String)</dc> constructor and <dc>ResourceDescriptions.append(String,String,String)</dc> method.
<li>
New <dc>org.apache.juneau.rest.helper.Hyperlink</dc> class.
</ul>
<h5 class='topic w800'>juneau-rest-client</h5>
<ul class='spaced-list'>
<li>
Completely revamped RestClient API.
<ul>
<li>All APIs now extend from HttpClient interfaces.
<li>Better integration with HttpClient.
<li>New fluent-style methods with many new convenience methods.
<li>Updated <a class='doclink' href='#juneau-rest-client'>documentation</a>.
</ul>
<li>
<ja>@RemoteMethod</ja>-annotated methods can now return <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html?is-external=true" title="class or interface in java.util.concurrent"><code>Futures</code></a> and
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html?is-external=true" title="class or interface in java.util.concurrent"><code>CompletableFutures</code></a> for concurrent processing of requests.
<br>Example:
<p class='bcode'>
<ja>@Remote</ja>
<jk>public interface</jk> MyInterface {
<jk>public</jk> Future&lt;String&gt; doGet();
}
MyInterface i = client.getRemote(MyInterface.<jk>class</jk>, <js>"http://localhost:12345/myInterface"</js>);
Future&lt;String&gt; f = i.doGet();
<jc>// Do other stuff.</jc>
String result = f.get();
</p>
<li>Additions to <a href="org/apache/juneau/http/remote/Remote.html" title="annotation in org.apache.juneau.http.remote"><code>Remote</code></a> annotation:
<ul>
<li><a href="org/apache/juneau/http/remote/Remote.html#version--"><code>version</code></a> - Adds a client version header to all requests.
<li><a href="org/apache/juneau/http/remote/Remote.html#headers--"><code>headers</code></a> - Adds a set of headers to all requests.
<li><dc>headerSupplier</dc> - Adds a dynamic supplier of headers to all requests.
</ul>
</ul>
<h5 class='topic w800'>juneau-rest-mock</h5>
<ul class='spaced-list'>
<li>
The <c>MockRest</c> and <c>MockRemote</c> classes have been remove entirely and all existing functions
have been moved into the improved <dc>org.apache.juneau.rest.mock2.MockRestClient</dc> class. All REST test mocking can be
done through this single class.
</ul>
</div>
</div><!-- END: 8.2.0 -->
<!-- ==================================================================================================== -->
<h3 class='topic' onclick='toggle(this)'><a href='#9.0.0' id='9.0.0'>9.0.0 (TBD)</a></h3>
<div class='topic'><!-- START: 9.0.0 -->
<div class='topic'>
<p>
Juneau 9.0.0 is a major release. Deprecated APIs that have been accumulating over time have been removed.
The underlying code has undergone significant refactoring to ease maintainability and improve overall performance.
</p>
<h5 class='topic w800'>General changes</h5>
<ul class='spaced-list'>
<li>
Configuration properties have been removed entirely. They have been replaced with a standard builder-based
architecture. In addition to making the code more maintainable, it also improves performance when
creating new serializers/parsers/rest clients (and others).
</ul>
<h5 class='topic w800'>juneau-marshall</h5>
<ul class='spaced-list'>
<li>
Eliminated the various <c><ja>@XConfig</ja>(applyX={...})</c> annotations and replaced them with the ability
to apply targeted annotations directly to configuration classes and methods (such as REST classes/methods).
<p class='bcode'>
<ja>@Rest</ja>(...)
<ja>@Bean</ja>(on=<js>"MyBean1,MyBean2"</js>,sort=<jk>true</jk>)
<ja>@UrlEncoding</ja>(onClass=MyList.<jk>class</jk>,expandedParams=<jk>true</jk>)
<jk>public class</jk> MyRestClass {
<ja>@RestOp</ja>(...)
<ja>@Bean</ja>(on=<js>"MyBean1,MyBean2"</js>,sort=<jk>false</jk>)
<ja>@UrlEncoding</ja>(onClass=MyList.<jk>class</jk>,expandedParams=<jk>false</jk>)
<jk>public</jk> Object myRestMethod() { ... }
}
</p>
<li>
New shortened form <a href="org/apache/juneau/http/remote/RemoteOp.html#value--"><code>RemoteOp.value()</code></a> for specifying http method name and path.
<p class='bcode'>
<jc>// Normal form</jc>
<ja>@RemoteOp</ja>(method=<jsf>PUT</jsf>, path=<js>"/foo"</js>)
<jc>// Shortened form</jc>
<ja>@RemoteOp</ja>(<js>"PUT /foo"</js>)
</p>
<li>
New annotations: <a href="org/apache/juneau/http/remote/RemoteGet.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteGet</code></a>/<a href="org/apache/juneau/http/remote/RemotePut.html" title="annotation in org.apache.juneau.http.remote"><code>RemotePut</code></a>/<a href="org/apache/juneau/http/remote/RemotePost.html" title="annotation in org.apache.juneau.http.remote"><code>RemotePost</code></a>/<a href="org/apache/juneau/http/remote/RemoteDelete.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteDelete</code></a>
<li>
Significant refactoring of the classes in the <a href="org/apache/juneau/http/package-summary.html"><code>org.apache.juneau.http</code></a> package and subpackages. Attempts were made to make classes as natural
extensions to the Apache HttpComponents APIs. Significant new functionality here.
<li>
New <a href="org/apache/juneau/annotation/Marshalled.html" title="annotation in org.apache.juneau.annotation"><code>@Marshalled</code></a> annotation for non-bean classes.
<li>
New <a href="org/apache/juneau/annotation/Bean.html#example--"><code>@Bean(example)</code></a> annotation.
<li>
New <a href="org/apache/juneau/annotation/BeanConfig.html#ignoreUnknownEnumValues--"><code>@BeanConfig(ignoreUnknownEnumValues)</code></a> annotation and support for ignoring
unknown enum values during parsing.
<li>
Java Serialized Object marshalling support has been removed entirely due to security risks with usage (better safe than sorry).
</ul>
<h5 class='topic w800'>juneau-rest-server</h5>
<ul class='spaced-list'>
<li>
Significant refactoring done to allow for many extensible aspects of the API to be performed through injected beans
in Spring. These include logging, debugging, REST method arg types, static files, file finders, swagger creators, thrown stores, response
processors, serializers/parsers, JSON schema generators, statistics gathering stores, and default request attributes/headers and response
headers.
<li>
Defining REST resources with predefined marshalling support is now much simpler. You now extend from a basic REST servlet/object
class and then include an interface with predefined common annotations.
<p class='bcode'>
<jc>// A root resource that supports JSON/HTML marshalling.</jc>
<jk>public class</jk> MyRootResources <jk>extends</jk> BasicRestServletGroup <jk>implements</jk> BasicJsonHtmlConfig { ... }
<jc>// A child resource that supports all available marshalling.</jc>
<jk>public class</jk> MyChildResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig { ... }
</p>
REST servlets/objects are in the <a href="org/apache/juneau/rest/servlet/package-summary.html"><code>org.apache.juneau.rest.servlet</code></a> package and REST configs are in the <a href="org/apache/juneau/rest/config/package-summary.html"><code>org.apache.juneau.rest.config</code></a> package.
<li>
<ja>@RestMethod</ja> annotation has been replaced with
<a href="org/apache/juneau/http/remote/RemoteGet.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteGet</code></a> / <a href="org/apache/juneau/http/remote/RemotePut.html" title="annotation in org.apache.juneau.http.remote"><code>RemotePut</code></a> / <a href="org/apache/juneau/http/remote/RemotePost.html" title="annotation in org.apache.juneau.http.remote"><code>RemotePost</code></a> / <a href="org/apache/juneau/http/remote/RemoteDelete.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteDelete</code></a>
/ <a href="org/apache/juneau/http/remote/RemoteOp.html" title="annotation in org.apache.juneau.http.remote"><code>RemoteOp</code></a>
<li>
New shortened form <a href="org/apache/juneau/rest/annotation/RestOp.html#value--"><code>RestOp.value()</code></a> for specifying http method name and path.
<p class='bcode'>
<jc>// Normal form</jc>
<ja>@RestOp</ja>(method=<jsf>PUT</jsf>, path=<js>"/{propertyName}"</js>)
<jc>// Shortened form</jc>
<ja>@RestOp</ja>(<js>"PUT /{propertyName}"</js>)
</p>
</ul>
<h5 class='topic w800'>juneau-dto</h5>
<ul class='spaced-list'>
<li>
Addition of OpenAPI 3.0 (<a href="org/apache/juneau/dto/openapi3/package-summary.html"><code>org.apache.juneau.dto.openapi3</code></a> package).
</ul>
<h5 class='topic w800'>juneau-rest-server-springboot</h5>
<ul class='spaced-list'>
<li>
The requirement for using <c>JuneauRestInitializer</c> during App initialization to use bean injection has been eliminated.
Instead, root resources should simply extend from <a href="org/apache/juneau/rest/springboot/BasicSpringRestServlet.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServlet</code></a> and <a href="org/apache/juneau/rest/springboot/BasicSpringRestServletGroup.html" title="class in org.apache.juneau.rest.springboot"><code>BasicSpringRestServletGroup</code></a>.
These will automatically hook into the Spring Boot framework for resolution of REST children and various extension beans added
to the REST API framework.
</ul>
<h5 class='topic w800'>juneau-rest-client</h5>
<ul class='spaced-list'>
<li>
While the general usage pattern stays the same, the REST client code has undergone significant rewriting. It is now more inline
as an extension of the Apache HttpClient library. Much new functionality such as support for fluent assertions has been added.
</ul>
<h5 class='topic w800'>juneau-rest-mock</h5>
<ul class='spaced-list'>
<li>
Entirely rewritten. Changes too many to list.
</ul>
</div>
</div><!-- END: 9.0.0 -->
</div></div>
</div>
<!-- ======= START OF BOTTOM NAVBAR ====== -->
<div class="bottomNav"><a name="navbar.bottom">
<!-- -->
</a>
<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
<a name="navbar.bottom.firstrow">
<!-- -->
</a>
<ul class="navList" title="Navigation">
<li class="navBarCell1Rev">Overview</li>
<li>Package</li>
<li>Class</li>
<li><a href="overview-tree.html">Tree</a></li>
<li><a href="deprecated-list.html">Deprecated</a></li>
<li><a href="index-all.html">Index</a></li>
<li><a href="help-doc.html">Help</a></li>
</ul>
</div>
<div class="subNav">
<ul class="navList">
<li>Prev</li>
<li>Next</li>
</ul>
<ul class="navList">
<li><a href="index.html?overview-summary.html" target="_top">Frames</a></li>
<li><a href="overview-summary.html" target="_top">No&nbsp;Frames</a></li>
</ul>
<ul class="navList" id="allclasses_navbar_bottom">
<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
</ul>
<div>
<script type="text/javascript"><!--
allClassesLink = document.getElementById("allclasses_navbar_bottom");
if(window==top) {
allClassesLink.style.display = "block";
}
else {
allClassesLink.style.display = "none";
}
//-->
</script>
</div>
<a name="skip.navbar.bottom">
<!-- -->
</a></div>
<!-- ======== END OF BOTTOM NAVBAR ======= -->
<p class="legalCopy"><small>Copyright &#169; 2016&#x2013;2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All rights reserved.</small></p>
</body>
</html>