http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/JsonSerializerWriter.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/JsonSerializerWriter.java
 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/JsonSerializerWriter.java
new file mode 100755
index 0000000..4fa6458
--- /dev/null
+++ 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/JsonSerializerWriter.java
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014, 2015. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.core.json;
+
+import java.io.*;
+
+import com.ibm.juno.core.serializer.*;
+import com.ibm.juno.core.utils.*;
+
+/**
+ * Specialized writer for serializing JSON.
+ * <p>
+ *     <b>Note:  This class is not intended for external use.</b>
+ *
+ * @author James Bognar ([email protected])
+ */
+public final class JsonSerializerWriter extends SerializerWriter {
+
+       private final boolean laxMode, escapeSolidus;
+
+       // Characters that trigger special handling of serializing attribute 
values.
+       private static final AsciiSet
+               encodedChars = new AsciiSet("\n\t\b\f\r'\"\\"),
+               encodedChars2 = new AsciiSet("\n\t\b\f\r'\"\\/");
+
+       private static final KeywordSet reservedWords = new KeywordSet(
+               
"arguments","break","case","catch","class","const","continue","debugger","default","delete",
+               
"do","else","enum","eval","export","extends","false","finally","for","function","if",
+               
"implements","import","in","instanceof","interface","let","new","null","package",
+               
"private","protected","public","return","static","super","switch","this","throw",
+               
"true","try","typeof","var","void","while","with","undefined","yield"
+       );
+
+
+       // Characters that represent attribute name characters that don't 
trigger quoting.
+       // These are actually more strict than the actual Javascript 
specification, but
+       // can be narrowed in the future if necessary.
+       // For example, we quote attributes that start with $ even though we 
don't need to.
+       private static final AsciiSet validAttrChars = new 
AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
+       private static final AsciiSet validFirstAttrChars = new 
AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_");
+
+       private final AsciiSet ec;
+
+       /**
+        * Constructor.
+        * @param out The writer being wrapped.
+        * @param useIndentation If <jk>true</jk>, tabs will be used in output.
+        * @param useWhitespace If <jk>true</jk>, whitespace will be used in 
output.
+        * @param escapeSolidus If <jk>true</jk>, forward slashes should be 
escaped in the output.
+        * @param quoteChar The quote character to use (i.e. <js>'\''</js> or 
<js>'"'</js>)
+        * @param laxMode If <jk>true</jk>, JSON attributes will only be quoted 
when necessary.
+        * @param relativeUriBase The base (e.g. 
<js>https://localhost:9443/contextPath";</js>) for relative URIs (e.g. 
<js>"my/path"</js>).
+        * @param absolutePathUriBase The base (e.g. 
<js>https://localhost:9443";</js>) for relative URIs with absolute paths (e.g. 
<js>"/contextPath/my/path"</js>).
+        */
+       protected JsonSerializerWriter(Writer out, boolean useIndentation, 
boolean useWhitespace, boolean escapeSolidus, char quoteChar, boolean laxMode, 
String relativeUriBase, String absolutePathUriBase) {
+               super(out, useIndentation, useWhitespace, quoteChar, 
relativeUriBase, absolutePathUriBase);
+               this.laxMode = laxMode;
+               this.escapeSolidus = escapeSolidus;
+               this.ec = escapeSolidus ? encodedChars2 : encodedChars;
+       }
+
+       /**
+        * Serializes the specified object as a JSON string value.
+        * @param o The object being serialized.
+        * @return This object (for method chaining).
+        * @throws IOException Should never happen.
+        */
+       public JsonSerializerWriter stringValue(Object o) throws IOException {
+                /*
+                 * Fixes up a Java string so that it can be used as a JSON 
string.<br>
+                 * Does the following:<br>
+                 * <ul>
+                 *  <li> Replaces {@code \r?\n} with {@code \\n}<br>
+                 *  <li> Replaces {@code \t} with {@code \\t}<br>
+                 *  <li> Replaces {@code '} with {@code \\'}<br>
+                 *  <li> Replaces {@code "} with {@code \\"}<br>
+                 * </ul>
+                 */
+               if (o == null)
+                       return this;
+               String s = o.toString();
+               boolean doConvert = false;
+               for (int i = 0; i < s.length() && ! doConvert; i++) {
+                       char c = s.charAt(i);
+                       doConvert |= ec.contains(c);
+               }
+               q();
+               if (! doConvert) {
+                       out.append(s);
+               } else {
+                       for (int i = 0; i < s.length(); i++) {
+                               char c = s.charAt(i);
+                               if (ec.contains(c)) {
+                                       if (c == '\n')
+                                               out.append('\\').append('n');
+                                       else if (c == '\t')
+                                               out.append('\\').append('t');
+                                       else if (c == '\b')
+                                               out.append('\\').append('b');
+                                       else if (c == '\f')
+                                               out.append('\\').append('f');
+                                       else if (c == quoteChar)
+                                               
out.append('\\').append(quoteChar);
+                                       else if (c == '\\')
+                                               out.append('\\').append('\\');
+                                       else if (c == '/' && escapeSolidus)
+                                               out.append('\\').append('/');
+                                       else if (c != '\r')
+                                               out.append(c);
+                               } else {
+                                       out.append(c);
+                               }
+                       }
+               }
+               q();
+               return this;
+       }
+
+       /**
+        * Serializes the specified object as a JSON attribute name.
+        * @param o The object being serialized.
+        * @return This object (for method chaining).
+        * @throws IOException Should never happen.
+        */
+       public JsonSerializerWriter attr(Object o) throws IOException {
+               /*
+                * Converts a Java string to an acceptable JSON attribute name. 
If
+                * useStrictJson is false, then quotes will only be used if the 
attribute
+                * name consists of only alphanumeric characters.
+                */
+               boolean doConvert = ! laxMode;          // Always convert when 
not in lax mode.
+
+               String s = null;
+
+               // If the attribute is null, it must always be printed as null 
without quotes.
+               // Technically, this isn't part of the JSON spec, but it does 
allow for null key values.
+               if (o == null) {
+                       s = "null";
+                       doConvert = false;
+
+               } else {
+                       s = o.toString();
+
+                       // Look for characters that would require the attribute 
to be quoted.
+                       // All possible numbers should be caught here.
+                       if (! doConvert) {
+                               for (int i = 0; i < s.length() && ! doConvert; 
i++) {
+                                       char c = s.charAt(i);
+                                       doConvert |= ! (i == 0 ? 
validFirstAttrChars.contains(c) : validAttrChars.contains(c));
+                               }
+                       }
+
+                       // Reserved words and blanks must be quoted.
+                       if (! doConvert) {
+                               if (s.isEmpty() || reservedWords.contains(s))
+                                       doConvert = true;
+                       }
+               }
+
+               // If no conversion necessary, just print the attribute as-is.
+               if (doConvert)
+                       stringValue(s);
+               else
+                       out.append(s);
+
+               return this;
+       }
+
+       
//--------------------------------------------------------------------------------
+       // Overridden methods
+       
//--------------------------------------------------------------------------------
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter cr(int depth) throws IOException {
+               super.cr(depth);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter appendln(int indent, String text) throws 
IOException {
+               super.appendln(indent, text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter appendln(String text) throws IOException {
+               super.appendln(text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter append(int indent, String text) throws 
IOException {
+               super.append(indent, text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter append(int indent, char c) throws 
IOException {
+               super.append(indent, c);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter s() throws IOException {
+               super.s();
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter q() throws IOException {
+               super.q();
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter i(int indent) throws IOException {
+               super.i(indent);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter nl() throws IOException {
+               super.nl();
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter append(Object text) throws IOException {
+               super.append(text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter append(String text) throws IOException {
+               super.append(text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter appendIf(boolean b, String text) throws 
IOException {
+               super.appendIf(b, text);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter appendIf(boolean b, char c) throws 
IOException {
+               super.appendIf(b, c);
+               return this;
+       }
+
+       @Override /* SerializerWriter */
+       public JsonSerializerWriter append(char c) throws IOException {
+               super.append(c);
+               return this;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/Json.class
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/Json.class
 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/Json.class
new file mode 100755
index 0000000..b375a8d
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/Json.class
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/Json.java
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/Json.java 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/Json.java
new file mode 100755
index 0000000..d4b0f0a
--- /dev/null
+++ 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/Json.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Licensed Materials - Property of IBM
+ * (c) Copyright IBM Corporation 2014. All Rights Reserved.
+ *
+ *  The source code for this program is not published or otherwise
+ *  divested of its trade secrets, irrespective of what has been
+ *  deposited with the U.S. Copyright Office.
+ 
*******************************************************************************/
+package com.ibm.juno.core.json.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation for specifying various JSON options for the JSON serializers and 
parsers.
+ * <p>
+ *     Can be applied to Java types.
+ * <p>
+ *     Can be used for the following:
+ * <ul>
+ *     <li>Wrap bean instances inside wrapper object (e.g. 
<code>{'wrapperAttr':bean}</code>).
+ * </ul>
+ *
+ * @author James Bognar ([email protected])
+ */
+@Documented
+@Target({TYPE})
+@Retention(RUNTIME)
+@Inherited
+public @interface Json {
+
+       /**
+        * Wraps beans in a JSON object with the specified attribute name.
+        * <p>
+        *      Applies only to {@link ElementType#TYPE}.
+        * <p>
+        *      This annotation can be applied to beans as well as other 
objects serialized to other types (e.g. strings).
+        *
+        * <dl>
+        *      <dt>Example:</dt>
+        *      <dd>
+        * <p class='bcode'>
+        *      <ja>@Json</ja>(wrapperAttr=<js>"myWrapper"</js>)
+        *      <jk>public class</jk> MyBean {
+        *              <jk>public int</jk> f1 = 123;
+        *      }
+        * </p>
+        * <p>
+        *      Without the <ja>@Xml</ja> annotations, serializing this bean as 
JSON would have produced the following...
+        * </p>
+        * <p class='bcode'>
+        *      {
+        *              f1: 123
+        *      }
+        * </p>
+        * <p>
+        *      With the annotations, serializing this bean as XML produces the 
following...
+        * </p>
+        * <p class='bcode'>
+        *      {
+        *              myWrapper: {
+        *                      f1: 123
+        *              }
+        *      }
+        * </p>
+        *      </dd>
+        * </dl>
+        */
+       String wrapperAttr() default "";
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/package.html
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/package.html
 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/package.html
new file mode 100755
index 0000000..3d37d51
--- /dev/null
+++ 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/annotation/package.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<!--
+    Licensed Materials - Property of IBM
+    (c) Copyright IBM Corporation 2014. All Rights Reserved.
+   
+    Note to U.S. Government Users Restricted Rights:  
+    Use, duplication or disclosure restricted by GSA ADP Schedule 
+    Contract with IBM Corp. 
+ -->
+<html>
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <style type="text/css">
+               /* For viewing in Page Designer */
+               @IMPORT url("../../../../../../../javadoc.css");
+
+               /* For viewing in REST interface */
+               @IMPORT url("../htdocs/javadoc.css");
+               body { 
+                       margin: 20px; 
+               }       
+       </style>
+       <script>
+               /* Replace all @code and @link tags. */ 
+               window.onload = function() {
+                       document.body.innerHTML = 
document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
+                       document.body.innerHTML = 
document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, 
'<code>$3</code>');
+               }
+       </script>
+</head>
+<body>
+<p>JSON annotations</p>
+</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_HTML.png
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_HTML.png
 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_HTML.png
new file mode 100755
index 0000000..b4a3576
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_HTML.png
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSON.png
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSON.png
 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSON.png
new file mode 100755
index 0000000..13b5c22
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSON.png
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSONSchema.png
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSONSchema.png
 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSONSchema.png
new file mode 100755
index 0000000..bf1cdc6
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSONSchema.png
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSONSimple.png
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSONSimple.png
 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSONSimple.png
new file mode 100755
index 0000000..935e8a9
Binary files /dev/null and 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/doc-files/Example_JSONSimple.png
 differ

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/7e4f63e6/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/package.html
----------------------------------------------------------------------
diff --git 
a/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/package.html 
b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/package.html
new file mode 100755
index 0000000..d9a78ec
--- /dev/null
+++ b/com.ibm.team.juno.releng/bin/core/com/ibm/juno/core/json/package.html
@@ -0,0 +1,1460 @@
+<!DOCTYPE HTML>
+<!--
+    Licensed Materials - Property of IBM
+    (c) Copyright IBM Corporation 2014. All Rights Reserved.
+   
+    Note to U.S. Government Users Restricted Rights:  
+    Use, duplication or disclosure restricted by GSA ADP Schedule 
+    Contract with IBM Corp. 
+ -->
+<html>
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <style type="text/css">
+               /* For viewing in Page Designer */
+               @IMPORT url("../../../../../../javadoc.css");
+
+               /* For viewing in REST interface */
+               @IMPORT url("../htdocs/javadoc.css");
+               body { 
+                       margin: 20px; 
+               }       
+       </style>
+       <script>
+               /* Replace all @code and @link tags. */ 
+               window.onload = function() {
+                       document.body.innerHTML = 
document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>');
+                       document.body.innerHTML = 
document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, 
'<code>$3</code>');
+               }
+       </script>
+</head>
+<body>
+<p>JSON serialization and parsing support</p>
+<script>
+       function toggle(x) {
+               var div = x.nextSibling;
+               while (div != null && div.nodeType != 1)
+                       div = div.nextSibling;
+               if (div != null) {
+                       var d = div.style.display;
+                       if (d == 'block' || d == '') {
+                               div.style.display = 'none';
+                               x.className += " closed";
+                       } else {
+                               div.style.display = 'block';
+                               x.className = 
x.className.replace(/(?:^|\s)closed(?!\S)/g , '' );
+                       }
+               }
+       }
+</script>
+
+<a id='TOC'></a><h5 class='toc'>Table of Contents</h5>
+<ol class='toc'>
+       <li><p><a class='doclink' href='#Overview'>JSON support 
overview</a></p> 
+       <ol>
+               <li><p><a class='doclink' 
href='#OverviewExample'>Example</a></p>
+       </ol>
+       <li><p><a class='doclink' href='#JsonSerializer'>JsonSerializer 
class</a></p> 
+       <ol>
+               <li><p><a class='doclink' href='#BeanAnnotations'>@Bean and 
@BeanProperty annotations</a></p>
+               <li><p><a class='doclink' 
href='#Collections'>Collections</a></p>
+               <li><p><a class='doclink' href='#JsonSchemaSupport'>JSON-Schema 
support</a></p>
+               <li><p><a class='doclink' href='#Recursion'> Non-tree models 
and recursion detection</a></p>
+               <li><p><a class='doclink' 
href='#SerializerConfigurableProperties'>Configurable properties</a></p>
+               <li><p><a class='doclink' href='#SerializerOtherNotes'>Other 
notes</a></p>
+       </ol>
+       <li><p><a class='doclink' href='#JsonParser'>JsonParser class</a></p> 
+       <ol>
+               <li><p><a class='doclink' href='#GenericParsing'>Parsing into 
generic POJO models</a></p>
+               <li><p><a class='doclink' 
href='#ParserConfigurableProperties'>Configurable properties</a></p>
+               <li><p><a class='doclink' href='#ParserOtherNotes'>Other 
notes</a></p>
+       </ol>
+       <li><p><a class='doclink' href='#RestApiSupport'>REST API 
support</a></p> 
+       <ol>
+               <li><p><a class='doclink' href='#RestServerSupport'>REST server 
support</a></p>
+               <ol>
+               <li><p><a class='doclink' href='#RestServletDefault'>Using 
RestServletDefault</a></p>
+               <li><p><a class='doclink' href='#RestServlet'>Using RestServlet 
with annotations</a></p>
+               <li><p><a class='doclink' href='#DefaultProvider'>Using JAX-RS 
DefaultProvider</a></p>
+               <li><p><a class='doclink' href='#BaseProvider'>Using JAX-RS 
BaseProvider with annotations</a></p>
+               </ol>
+               <li><p><a class='doclink' href='#RestClientSupport'>REST client 
support</a></p>
+       </ol>   
+</ol>
+
+<!-- 
========================================================================================================
 -->
+<a id="Overview"></a>
+<h2 class='topic' onclick='toggle(this)'>1 -JSON support overview</h2>
+<div class='topic'>
+       <p>
+               Juno supports converting arbitrary POJOs to and from JSON using 
ultra-efficient serializers and parsers.<br>
+               The JSON serializer converts POJOs directly to JSON without the 
need for intermediate DOM objects using a highly-efficient state machine.<br>
+               Likewise, the JSON parser creates POJOs directly from JSON 
without the need for intermediate DOM objects. 
+       </p>
+       <p>
+               Juno can serialize and parse instances of any of the following 
POJO types:
+       </p>
+       <ul>
+               <li>Java primitives and primitive objects (e.g. 
<code>String</code>, <code>Integer</code>, <code>Boolean</code>, 
<code>Float</code>).
+               <li>Java Collections Framework objects (e.g. 
<code>HashSet</code>, <code>TreeMap</code>) containing anything on this list.
+               <li>Multi-dimensional arrays of any type on this list.
+               <li>Java Beans with properties of any type on this list.
+               <li>Classes with standard transformations to and from 
<code>Strings</code> (e.g. classes containing <code>toString()</code>, 
<code>fromString()</code>, <code>valueOf()</code>, 
<code>constructor(String)</code>).
+               <li>Non-serializable classes and properties with associated 
<code>PojoFilters</code> that convert them to serializable forms.
+       </ul>
+       <p>
+               Refer to <a href='../package-summary.html#PojoCategories' 
class='doclink'>POJO Categories</a> for a complete definition of supported 
POJOs.
+       </p>
+       <h6 class='topic'>Prerequisites</h6>
+       <p>
+               The Juno JSON serialization and parsing support does not 
require any external prerequisites.  
+               It only requires Java 1.6 or above.
+       </p>
+
+       <!-- 
========================================================================================================
 -->
+       <a id="OverviewExample"></a>
+       <h3 class='topic' onclick='toggle(this)'>1.1 - JSON support overview - 
example</h3>
+       <div class='topic'>
+               <p>
+                       The example shown here is from the Address Book 
resource located in the <code>com.ibm.juno.sample.war</code> application.<br>
+                       The POJO model consists of a <code>List</code> of 
<code>Person</code> beans, with each <code>Person</code> containing
+                               zero or more <code>Address</code> beans.
+               </p>
+               <p>
+                       When you point a browser at 
<code>/sample/addressBook</code>, the POJO is rendered as HTML:
+               </p>
+               <img class='bordered' src="doc-files/Example_HTML.png">
+               <p>
+                       By appending 
<code>?Accept=<i>mediaType</i>&plainText=true</code> to the URL, you can view 
the data in the various supported JSON formats:
+               </p>
+               
+               <h6 class='figure'>Normal JSON</h6>
+               <img class='bordered' src="doc-files/Example_JSON.png">
+               
+               <h6 class='figure'>Simple JSON</h6>
+               <img class='bordered' src="doc-files/Example_JSONSimple.png">
+
+               <p>
+                       In addition to serializing POJOs to JSON, Juno includes 
support for serializing POJO metamodels to JSON Schema.
+               </p>
+               
+               <h6 class='figure'>JSON Schema</h6>
+               <img class='bordered' src="doc-files/Example_JSONSchema.png">
+               
+               <p>
+                       The JSON data type produced depends on the Java object 
type being serialized.
+               </p>
+               <ul>
+                       <li>Primitives and primitive objects are converted to 
JSON primitives.<br>
+                       <li>Beans and Maps are converted to JSON objects.<br>
+                       <li>Collections and arrays are converted to JSON 
arrays.<br>
+                       <li>Anything else is converted to JSON strings.
+               </ul>
+                       
+               <h6 class='figure'>Examples</h6>
+                       <table class='styled'>
+                       <tr>
+                               <th>POJO type</th>
+                               <th>Example</th>
+                               <th>Serialized form</th>
+                       </tr>
+                       <tr>
+                               <td>String</td>
+                               
<td><code>serializer.serialize(<js>"foobar"</js>);</code></td>
+                               <td><code><js>'foobar'</js></code>
+                       </tr>
+                       <tr>
+                               <td>Number</td>
+                               <td><code>serializer.serialize(123);</code></td>
+                               <td><code><jk>123</jk></code>
+                       </tr>
+                       <tr>
+                               <td>Boolean</td>
+                               
<td><code>serializer.serialize(<jk>true</jk>);</code></td>
+                               <td><code><jk>true</jk></code>
+                       </tr>
+                       <tr>
+                               <td>Null</td>
+                               
<td><code>serializer.serialize(<jk>null</jk>);</code></td>
+                               <td><code><jk>null</jk></code>
+                       </tr>
+                       <tr>
+                               <td>Beans with properties of any type on this 
list</td>
+                               <td><code>serializer.serialize(<jk>new</jk> 
MyBean());</code></td>
+                               
<td><code>{p1:<js>'val1'</js>,p2:<jk>true</jk>}</code>
+                       </tr>
+                       <tr>
+                               <td>Maps with values of any type on this 
list</td>
+                               <td><code>serializer.serialize(<jk>new</jk> 
TreeMap());</code></td>
+                               
<td><code>{key1:<js>'val1'</js>,key2:<jk>true</jk>}</code>
+                       </tr>
+                       <tr>
+                               <td>Collections and arrays of any type on this 
list</td>
+                               <td><code>serializer.serialize(<jk>new</jk> 
Object[]{1,<js>"foo"</js>,<jk>true</jk>});</code></td>
+                               <td><code>[1,'foo',true]</code>
+                       </tr>
+               </table>
+               <p>
+                       In addition, filters can be used to convert 
non-serializable POJOs into serializable forms, such as converting 
+                               <code>Calendar</code> object to ISO8601 
strings, or <code><jk>byte</jk>[]</code> arrays to Base-64 encoded strings.<br>
+                       These filters can be associated at various levels:
+               </p>
+               <ul>
+                       <li>On serializer and parser instances to handle all 
objects of the class type globally.
+                       <li>On classes through the <code><ja>@Bean</ja></code> 
annotation.
+                       <li>On bean properties through the 
<code><ja>@BeanProperty</ja></code> annotations.
+               </ul>
+               <p>
+                       For more information about filters, refer to {@link 
com.ibm.juno.core.filter}.
+               </p>
+       </div>
+</div>
+
+<!-- 
========================================================================================================
 -->
+<a id="JsonSerializer"></a>
+<h2 class='topic' onclick='toggle(this)'>2 - JsonSerializer class</h2>
+<div class='topic'>
+       <p>
+               {@link com.ibm.juno.core.json.JsonSerializer} is the class used 
to convert POJOs to JSON.<br>
+               {@link com.ibm.juno.core.json.JsonSchemaSerializer} is the 
class used to generate JSON-Schema from POJOs.<br>
+       </p>    
+       <p>
+               The JSON serializer includes several configurable settings.<br>
+               Static reusable instances of Json serializers are provided with 
commonly-used settings:
+       </p>
+       <ul>
+               <li>{@link com.ibm.juno.core.json.JsonSerializer#DEFAULT} - All 
default settings
+               <li>{@link com.ibm.juno.core.json.JsonSerializer#DEFAULT_LAX} - 
Single quotes, only quote attributes when necessary.
+               <li>{@link 
com.ibm.juno.core.json.JsonSerializer#DEFAULT_LAX_READABLE} - Readable output.
+       </ul>
+       <h6 class='topic'>Notes about examples</h6>
+       <p>
+               The examples shown in this document will use single-quote, 
readable settings.<br>
+               For brevity, the examples will use public fields instead of 
getters/setters to reduce the size of the examples.<br>
+               In the real world, you'll typically want to use standard bean 
getters and setters.
+       </p>
+       <p>
+               To start off simple, we'll begin with the following simplified 
bean and build upon it.
+       </p>
+       <p class='bcode'>
+       <jk>public class</jk> Person {
+               <jc>// Bean properties</jc>
+               <jk>public int</jk> <jf>id</jf>;
+               <jk>public</jk> String <jf>name</jf>;
+
+               <jc>// Bean constructor (needed by parser)</jc>
+               <jk>public</jk> Person() {}
+
+               <jc>// Normal constructor</jc>
+               <jk>public</jk> Person(<jk>int</jk> id, String name) {
+                       <jk>this</jk>.<jf>id</jf> = id;
+                       <jk>this</jk>.<jf>name</jf> = name;
+               }
+       }
+       </p>
+       <p>
+               The following code shows how to convert this to simple JSON:
+       </p>
+       <p class='bcode'>
+       <jc>// Use serializer with readable output, simple mode.</jc>
+       JsonSerializer s = JsonSerializer.<jsf>DEFAULT_LAX_READABLE</jsf>;
+
+       <jc>// Create our bean.</jc>
+       Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>);
+
+       <jc>// Serialize the bean to JSON.</jc>
+       String json = s.serialize(p);
+       </p>
+       <p>
+               We could have also created a new serializer with the same 
settings using the following code:
+       </p>
+       <p class='bcode'>
+       JsonSerializer s = <jk>new</jk> JsonSerializer()
+               
.setProperty(SerializerProperties.<jsf>SERIALIZER_useIndentation</jsf>, 
<jk>true</jk>)
+               
.setProperty(JsonSerializerProperties.<jsf>JSON_useWhitespace</jsf>, 
<jk>true</jk>)
+               
.setProperty(JsonSerializerProperties.<jsf>JSON_simpleMode</jsf>, <jk>true</jk>)
+               
.setProperty(SerializerProperties.<jsf>SERIALIZER_quoteChar</jsf>, 
<js>'\''</js>);
+       </p>
+       
+       <p>
+               The code above produces the following output:
+       </p>
+       <p class='bcode'>
+       {
+               id: <jk>1</jk>, 
+               name: <js>'John Smith'</js>
+       }
+       </p>
+       
+
+       <!-- 
========================================================================================================
 -->
+       <a id="BeanAnnotations"></a>
+       <h3 class='topic' onclick='toggle(this)'>2.1 - @Bean and @BeanProperty 
annotations</h3>
+       <div class='topic'>
+               <p>
+                       The {@link com.ibm.juno.core.annotation.Bean @Bean} and 
{@link com.ibm.juno.core.annotation.BeanProperty @BeanProperty} annotations
+                               are used to customize the behavior of beans 
across the entire framework.<br>
+                       They have various uses:
+               </p>
+               <ul>
+                       <li>Hiding bean properties.
+                       <li>Specifying the ordering of bean properties.
+                       <li>Overriding the names of bean properties.
+                       <li>Associating filters at both the class and property 
level (to convert non-serializable POJOs to serializable forms).
+               </ul>
+               <p>
+                       For example, we now add a <code>birthDate</code> 
property, and associate a filter with it to transform
+                               it to an ISO8601 date-time string in GMT 
time.<br>
+                       We'll also add a couple of <code>URI</code> 
properties.<br>
+                       By default, <code>Calendars</code> are treated as beans 
by the framework, which is usually not how you want them serialized.<br>
+                       Using filters, we can convert them to standardized 
string forms.
+               </p>
+               <p class='bcode'>       
+       <jk>public class</jk> Person {
+               <jc>// Bean properties</jc>
+               <jk>public int</jk> <jf>id</jf>;
+               <jk>public</jk> String <jf>name</jf>;
+               <jk>public</jk> URI <jf>uri</jf>;
+               <jk>public</jk> URI <jf>addressBookUri</jf>;
+
+               
<ja>@BeanProperty</ja>(filter=CalendarFilter.ISO8601DTZ.<jk>class</jk>) 
<jk>public</jk> Calendar <jf>birthDate</jf>;
+
+
+               <jc>// Bean constructor (needed by parser)</jc>
+               <jk>public</jk> Person() {}
+
+               <jc>// Normal constructor</jc>
+               <jk>public</jk> Person(<jk>int</jk> id, String name, String 
uri, String addressBookUri, String birthDate) <jk>throws</jk> Exception {
+                       <jk>this</jk>.<jf>id</jf> = id;
+                       <jk>this</jk>.<jf>name</jf> = name;
+                       <jk>this</jk>.<jf>uri</jf> = <jk>new</jk> URI(uri);
+                       <jk>this</jk>.<jf>addressBookUri</jf> = <jk>new</jk> 
URI(addressBookUri);
+                       <jk>this</jk>.<jf>birthDate</jf> = <jk>new</jk> 
GregorianCalendar();
+                       
<jk>this</jk>.<jf>birthDate</jf>.setTime(DateFormat.<jsm>getDateInstance</jsm>(DateFormat.<jsf>MEDIUM</jsf>).parse(birthDate));
+               }
+       }
+               </p>
+               <p>
+                       Next, we alter our code to pass in the birthdate:
+               </p>
+               <p class='bcode'>
+       <jc>// Create our bean.</jc>
+       Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, 
<js>"http://sample/addressBook/person/1";</js>, 
<js>"http://sample/addressBook";</js>, <js>"Aug 12, 1946"</js>);
+               </p>
+               <p>
+                       Now when we rerun the sample code, we'll get the 
following:
+               </p>
+               <p class='bcode'>
+       {
+               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>
+       }
+               </p>
+               <p>
+                       Another useful feature is the {@link 
com.ibm.juno.core.annotation.Bean#propertyNamer()} annotation that allows you 
to plug in your own
+                               logic for determining bean property names.<br>
+                       The {@link com.ibm.juno.core.PropertyNamerDashedLC} is 
an example of an alternate property namer.
+                       It converts bean property names to lowercase-dashed 
format.
+               </p>
+               <h6 class='figure'>Example</h6>
+               <p class='bcode'>       
+       <ja>@Bean</ja>(propertyNamer=PropertyNamerDashedLC.<jk>class</jk>)
+       <jk>public class</jk> Person {
+               ...
+               </p>
+               <h6 class='figure'>Results</h6>
+               <p class='bcode'>
+       {
+               id: <jk>1</jk>, 
+               name: <js>'John Smith'</js>, 
+               uri: <js>'http://sample/addressBook/person/1'</js>, 
+               <js>'address-book-uri'</js>: 
<js>'http://sample/addressBook'</js>, 
+               <js>'birth-date'</js>: <js>'1946-08-12T00:00:00Z'</js>
+       }
+               </p>
+       </div>
+       
+               
+       <!-- 
========================================================================================================
 -->
+       <a id="Collections"></a>
+       <h3 class='topic' onclick='toggle(this)'>2.2 - Collections</h3>
+       <div class='topic'>
+               <p>
+                       In our example, let's add a list-of-beans property to 
our sample class:
+               </p>
+               <p class='bcode'>
+       <jk>public class</jk> Person {
+               
+               <jc>// Bean properties</jc>
+               <jk>public</jk> LinkedList&lt;Address&gt; <jf>addresses</jf> = 
<jk>new</jk> LinkedList&lt;Address&gt;();
+               ...
+       }
+               </p>
+               <p>
+                       The <code>Address</code> class has the following 
properties defined:
+               </p>
+               <p class='bcode'>
+       <jk>public class</jk> Address {
+
+               <jc>// Bean properties</jc>
+               <jk>public</jk> URI <jf>uri</jf>;
+               <jk>public</jk> URI <jf>personUri</jf>;
+               <jk>public int</jk> <jf>id</jf>;
+               <jk>public</jk> String <jf>street</jf>, <jf>city</jf>, 
<jf>state</jf>;
+               <jk>public int</jk> <jf>zip</jf>;
+               <jk>public boolean</jk> <jf>isCurrent</jf>;
+       }
+               </p>
+               <p>
+                       Next, add some quick-and-dirty code to add an address 
to our person bean:
+               </p>
+               <p class='bcode'>
+       <jc>// Use serializer with readable output, simple mode.</jc>
+       JsonSerializer s = JsonSerializer.<jsf>DEFAULT_LAX_READABLE</jsf>;
+
+       <jc>// Create our bean.</jc>
+       Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, 
<js>"http://sample/addressBook/person/1";</js>, 
<js>"http://sample/addressBook";</js>, <js>"Aug 12, 1946"</js>);
+       Address a = <jk>new</jk> Address();
+       a.<jf>uri</jf> = <jk>new</jk> 
URI(<js>"http://sample/addressBook/address/1";</js>);
+       a.<jf>personUri</jf> = <jk>new</jk> 
URI(<js>"http://sample/addressBook/person/1";</js>);
+       a.<jf>id</jf> = 1;
+       a.<jf>street</jf> = <js>"100 Main Street"</js>;
+       a.<jf>city</jf> = <js>"Anywhereville"</js>;
+       a.<jf>state</jf> = <js>"NY"</js>;
+       a.<jf>zip</jf> = 12345;
+       a.<jf>isCurrent</jf> = <jk>true</jk>;
+       p.<jf>addresses</jf>.add(a);    
+               </p>
+               <p>
+                       Now when we run the sample code, we get the following:
+               </p>
+               <p class='bcode'>
+       {
+               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>
+       </div>
+       
+
+       <!-- 
========================================================================================================
 -->
+       <a id="JsonSchemaSupport"></a>
+       <h3 class='topic' onclick='toggle(this)'>2.3 - JSON-Schema support</h3>
+       <div class='topic'>
+               <p>
+                       Juno provides the {@link 
com.ibm.juno.core.json.JsonSchemaSerializer} class for generating JSON-Schema 
documents
+                               that describe the output generated by the 
{@link com.ibm.juno.core.json.JsonSerializer} class.<br>
+                       This class shares the same properties as 
<code>JsonSerializer</code>.<br>
+                       For convenience the {@link 
com.ibm.juno.core.json.JsonSerializer#getSchemaSerializer()} method 
+                               has been added for creating instances of schema 
serializers from the regular serializer instance.
+               </p>
+               <p>
+                       <i>Note:</i> As of this writing, JSON-Schema has not 
been standardized, so the output generated by the schema
+                               serializer may be subject to future 
modifications.
+               </p>
+               <p>
+                       Lets start with the classes from the previous examples:
+               </p>
+               <p class='bcode'>
+       <jk>public class</jk> Person {
+               <jc>// Bean properties</jc>
+               <jk>public int</jk> <jf>id</jf>;
+               <jk>public</jk> String <jf>name</jf>;
+               <jk>public</jk> URI <jf>uri</jf>;
+               <jk>public</jk> URI <jf>addressBookUri</jf>;
+               
<ja>@BeanProperty</ja>(filter=CalendarFilter.ISO8601DTZ.<jk>class</jk>) 
<jk>public</jk> Calendar <jf>birthDate</jf>;
+               <jk>public</jk> LinkedList&lt;Address&gt; <jf>addresses</jf> = 
<jk>new</jk> LinkedList&lt;Address&gt;();
+
+               <jc>// Bean constructor (needed by parser)</jc>
+               <jk>public</jk> Person() {}
+
+               <jc>// Normal constructor</jc>
+               <jk>public</jk> Person(<jk>int</jk> id, String name, String 
uri, String addressBookUri, String birthDate) <jk>throws</jk> Exception {
+                       <jk>this</jk>.<jf>id</jf> = id;
+                       <jk>this</jk>.<jf>name</jf> = name;
+                       <jk>this</jk>.<jf>uri</jf> = <jk>new</jk> URI(uri);
+                       <jk>this</jk>.<jf>addressBookUri</jf> = <jk>new</jk> 
URI(addressBookUri);
+                       <jk>this</jk>.<jf>birthDate</jf> = <jk>new</jk> 
GregorianCalendar();
+                       
<jk>this</jk>.<jf>birthDate</jf>.setTime(DateFormat.getDateInstance(DateFormat.<jsf>MEDIUM</jsf>).parse(birthDate));
+               }
+       }
+
+       <jk>public class</jk> Address {
+               <jc>// Bean properties</jc>
+               <jk>public</jk> URI <jf>uri</jf>;
+               <jk>public</jk> URI <jf>personUri</jf>;
+               <jk>public int</jk> <jf>id</jf>;
+               <jk>public</jk> String <jf>street</jf>, <jf>city</jf>, 
<jf>state</jf>;
+               <jk>public int</jk> <jf>zip</jf>;
+               <jk>public boolean</jk> <jf>isCurrent</jf>;
+       }
+               </p>
+               <p>
+                       The code for creating our POJO model and generating 
JSON-Schema is shown below:
+               </p>
+               <p class='bcode'>
+       <jc>// Get the schema serializer for one of the default JSON 
serializers.</jc>
+       JsonSchemaSerializer s = 
JsonSerializer.<jsf>DEFAULT_LAX_READABLE</jsf>.getSchemaSerializer();
+
+       <jc>// Create our bean.</jc>
+       Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, 
<js>"http://sample/addressBook/person/1";</js>, 
<js>"http://sample/addressBook";</js>, <js>"Aug 12, 1946"</js>);
+       Address a = <jk>new</jk> Address();
+       a.<jf>uri</jf> = <jk>new</jk> 
URI(<js>"http://sample/addressBook/address/1";</js>);
+       a.<jf>personUri</jf> = <jk>new</jk> 
URI(<js>"http://sample/addressBook/person/1";</js>);
+       a.<jf>id</jf> = 1;
+       a.<jf>street</jf> = <js>"100 Main Street"</js>;
+       a.<jf>city</jf> = <js>"Anywhereville"</js>;
+       a.<jf>state</jf> = <js>"NY"</js>;
+       a.<jf>zip</jf> = 12345;
+       a.<jf>isCurrent</jf> = <jk>true</jk>;
+       p.<jf>addresses</jf>.add(a);
+
+       <jc>// Get the JSON Schema corresponding to the JSON generated 
above.</jc>
+       String jsonSchema = s.serialize(p);
+               </p>
+               <h6 class='figure'>Results</h6>
+               <p class='bcode'>
+       {
+               type: <js>'object'</js>, 
+               description: <js>'com.ibm.juno.sample.Person'</js>, 
+               properties: {
+                       id: {
+                               type: <js>'number'</js>, 
+                               description: <js>'int'</js>
+                       }, 
+                       name: {
+                               type: <js>'string'</js>, 
+                               description: <js>'java.lang.String'</js>
+                       }, 
+                       uri: {
+                               type: <js>'any'</js>, 
+                               description: <js>'java.net.URI'</js>
+                       }, 
+                       addressBookUri: {
+                               type: <js>'any'</js>, 
+                               description: <js>'java.net.URI'</js>
+                       }, 
+                       birthDate: {
+                               type: <js>'any'</js>, 
+                               description: <js>'java.util.Calendar'</js>
+                       }, 
+                       addresses: {
+                               type: <js>'array'</js>, 
+                               description: 
<js>'java.util.LinkedList&lt;com.ibm.juno.sample.Address&gt;'</js>, 
+                               items: {
+                                       type: <js>'object'</js>, 
+                                       description: 
<js>'com.ibm.juno.sample.Address'</js>, 
+                                       properties: {
+                                               uri: {
+                                                       type: <js>'any'</js>, 
+                                                       description: 
<js>'java.net.URI'</js>
+                                               }, 
+                                               personUri: {
+                                                       type: <js>'any'</js>, 
+                                                       description: 
<js>'java.net.URI'</js>
+                                               }, 
+                                               id: {
+                                                       type: 
<js>'number'</js>, 
+                                                       description: 
<js>'int'</js>
+                                               }, 
+                                               street: {
+                                                       type: 
<js>'string'</js>, 
+                                                       description: 
<js>'java.lang.String'</js>
+                                               }, 
+                                               city: {
+                                                       type: 
<js>'string'</js>, 
+                                                       description: 
<js>'java.lang.String'</js>
+                                               }, 
+                                               state: {
+                                                       type: 
<js>'string'</js>, 
+                                                       description: 
<js>'java.lang.String'</js>
+                                               }, 
+                                               zip: {
+                                                       type: 
<js>'number'</js>, 
+                                                       description: 
<js>'int'</js>
+                                               }, 
+                                               isCurrent: {
+                                                       type: 
<js>'boolean'</js>, 
+                                                       description: 
<js>'boolean'</js>
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+               </p>
+       </div>
+
+
+       <!-- 
========================================================================================================
 -->
+       <a id="Recursion"></a>
+       <h3 class='topic' onclick='toggle(this)'>2.4 - Non-tree models and 
recursion detection</h3>
+       <div class='topic'>
+               <p>
+                       The JSON serializer is designed to be used against POJO 
tree structures. <br> 
+                       It expects that there not be loops in the POJO model 
(e.g. children with references to parents, etc...).<br>
+                       If you try to serialize models with loops, you will 
usually cause a <code>StackOverflowError</code> to 
+                               be thrown (if {@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_maxDepth} is not 
reached first).
+               </p>
+               <p>
+                       If you still want to use the JSON serializer on such 
models, Juno provides the 
+                               {@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_detectRecursions} 
setting.<br>
+                       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='bcode'>
+       <jk>public class</jk> A {
+               <jk>public</jk> B b;
+       }
+       
+       <jk>public class</jk> B {
+               <jk>public</jk> C c;
+       }
+       
+       <jk>public class</jk> C {
+               <jk>public</jk> A a;
+       }
+               </p>
+               <p>
+                       Now we create a model with a loop and serialize the 
results.
+               </p>
+               <p class='bcode'>
+       <jc>// Clone an existing serializer and set property for detecting 
recursions.</jc>
+       JsonSerializer s = 
JsonSerializer.<jsf>DEFAULT_LAX_READABLE</jsf>.clone().setProperty(SerializerProperties.<jsf>SERIALIZER_detectRecursions</jsf>,
 <jk>true</jk>);
+
+       <jc>// Create a recursive loop.</jc>
+       A a = <jk>new</jk> A();
+       a.<jf>b</jf> = <jk>new</jk> B();
+       a.<jf>b</jf>.<jf>c</jf> = <jk>new</jk> C();
+       a.<jf>b</jf>.<jf>c</jf>.<jf>a</jf> = a;
+       
+       <jc>// Serialize to JSON.</jc>
+       String json = s.serialize(a);
+               </p>
+               <p>
+                       What we end up with is the following, which does not 
serialize the contents of the <code>c</code> field:
+               </p>
+               <p class='bcode'>
+       {
+               b: {
+                       c: {
+                       }
+               }
+       }
+               </p>
+               <p>
+                       Without recursion detection enabled, this would cause a 
stack-overflow error.
+               </p>
+               <p>
+                       Recursion detection introduces a performance penalty of 
around 20%.<br>
+                       For this reason the setting is disabled by default.
+               </p>
+       </div>
+
+
+       <!-- 
========================================================================================================
 -->
+       <a id="SerializerConfigurableProperties"></a>
+       <h3 class='topic' onclick='toggle(this)'>2.5 - Configurable 
properties</h3>
+       <div class='topic'>
+               <p>
+                       The full list of configurable settings applicable to 
the <code>JsonSerializer</code> class is shown below:
+               </p>
+               <table class='styled' style='border-collapse: collapse;'>
+                       <tr><th>Property</th><th>Short Description</th></tr>
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.json.JsonSerializerProperties#JSON_simpleMode}</td>
+                               <td>Simple JSON mode</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.json.JsonSerializerProperties#JSON_useWhitespace}</td>
+                               <td>Use whitespace in output</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_maxDepth}</td>
+                               <td>Maximum serialization depth</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_detectRecursions}</td>
+                               <td>Automatically detect POJO recursions</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_useIndentation}</td>
+                               <td>Use indentation in output</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_quoteChar}</td>
+                               <td>Quote character</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_trimNullProperties}</td>
+                               <td>Trim null bean property values from 
output</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_trimEmptyLists}</td>
+                               <td>Trim empty lists and arrays from output</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_trimEmptyMaps}</td>
+                               <td>Trim empty maps from output</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_relativeUriBase}</td>
+                               <td>URI context root for relative URIs</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.serializer.SerializerProperties#SERIALIZER_absolutePathUriBase}</td>
+                               <td>URI authority for absolute path relative 
URIs</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_beansRequireDefaultConstructor}</td>
+                               <td>Beans require no-arg constructors</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_beansRequireSerializable}</td>
+                               <td>Beans require <code>Serializable</code> 
interface</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_beansRequireSettersForGetters}</td>
+                               <td>Beans require setters for getters</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_beansRequireSomeProperties}</td>
+                               <td>Beans require some properties</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_beanConstructorVisibility}</td>
+                               <td>Look for bean constructors with the 
specified minimum visibility</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_beanClassVisibility}</td>
+                               <td>Look for bean classes with the specified 
minimum visibility</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_beanFieldVisibility}</td>
+                               <td>Look for bean fields with the specified 
minimum visibility</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_methodVisibility}</td>
+                               <td>Look for bean methods with the specified 
minimum visibility</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_useJavaBeanIntrospector}</td>
+                               <td>Use Java bean Introspector for determining 
bean properties</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_useInterfaceProxies}</td>
+                               <td>Use interface proxies</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_ignoreUnknownBeanProperties}</td>
+                               <td>Ignore unknown properties</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_ignoreUnknownNullBeanProperties}</td>
+                               <td>Ignore unknown properties with null 
values</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_ignorePropertiesWithoutSetters}</td>
+                               <td>Ignore properties without setters</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_ignoreInvocationExceptionsOnGetters}</td>
+                               <td>Ignore invocation errors when calling 
getters</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_ignoreInvocationExceptionsOnSetters}</td>
+                               <td>Ignore invocation errors when calling 
setters</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_addNotBeanPackages}</td>
+                               <td>Add to the list of packages whose classes 
should not be considered beans</td>
+                       </tr>   
+                       <tr>
+                               <td>{@link 
com.ibm.juno.core.BeanContextProperties#BEAN_removeNotBeanPackages}</td>
+                               <td>Remove from the list of packages whose 
classes should not be considered beans</td>
+                       </tr>   
+               </table>        
+       </div>          
+
+
+       <!-- 
========================================================================================================
 -->
+       <a id="SerializerOtherNotes"></a>
+       <h3 class='topic' onclick='toggle(this)'>2.6 - Other notes</h3>
+       <div class='topic'>
+               <ul>
+                       <li>Like all other Juno serializers, the JSON 
serializer is thread safe and maintains an internal cache of bean classes 
encountered.<br>
+                               For performance reasons, it's recommended that 
serializers be reused whenever possible instead of always creating new 
instances.
+               </ul>
+       </div>
+</div>
+
+
+<!-- 
========================================================================================================
 -->
+<a id="JsonParser"></a>
+<h2 class='topic' onclick='toggle(this)'>3 - JsonParser class</h2>
+<div class='topic'>
+       <p>
+               The {@link com.ibm.juno.core.json.JsonParser} class is the 
class used to parse JSON back into POJOs.
+       </p>    
+       <p>
+               The JSON parser supports ALL valid JSON, including:
+       </p>
+       <ul>
+               <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>   
+       <p>
+               A static reusable instance of <code>JsonParser</code> is also 
provided for convenience:
+       </p>
+       <ul>
+               <li>{@link com.ibm.juno.core.json.JsonParser#DEFAULT}
+       </ul>
+       <p>
+               Let's build upon the previous example and parse the generated 
JSON back into the original bean.<br>
+               We start with the JSON that was generated.
+       </p>
+       <p class='bcode'>
+       <jc>// Use serializer with readable output, simple mode.</jc>
+       JsonSerializer s = JsonSerializer.<jsf>DEFAULT_LAX_READABLE</jsf>;
+
+       <jc>// Create our bean.</jc>
+       Person p = <jk>new</jk> Person(1, <js>"John Smith"</js>, 
<js>"http://sample/addressBook/person/1";</js>, 
<js>"http://sample/addressBook";</js>, <js>"Aug 12, 1946"</js>);
+       Address a = <jk>new</jk> Address();
+       a.<jf>uri</jf> = <jk>new</jk> 
URI(<js>"http://sample/addressBook/address/1";</js>);
+       a.<jf>personUri</jf> = <jk>new</jk> 
URI(<js>"http://sample/addressBook/person/1";</js>);
+       a.<jf>id</jf> = 1;
+       a.<jf>street</jf> = <js>"100 Main Street"</js>;
+       a.<jf>city</jf> = <js>"Anywhereville"</js>;
+       a.<jf>state</jf> = <js>"NY"</js>;
+       a.<jf>zip</jf> = 12345;
+       a.<jf>isCurrent</jf> = <jk>true</jk>;
+       p.<jf>addresses</jf>.add(a);    
+
+       <jc>// Serialize the bean to JSON.</jc>
+       String json = s.serialize(p);
+       </p>
+       <p>
+               This code produced the following:
+       </p>
+       <p class='bcode'>
+       {
+               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>
+               The code to convert this back into a bean is:
+       </p>
+       <p class='bcode'>
+       <jc>// Parse it back into a bean using the reusable JSON parser.</jc>
+       Person p = JsonParser.<jsf>DEFAULT</jsf>.parse(json, 
Person.<jk>class</jk>);
+
+       <jc>// Render it back as JSON.</jc>
+       json = JsonSerializer.<jsf>DEFAULT_LAX_READABLE</jsf>.serialize(p);
+       </p>
+       <p>
+               We print it back out to JSON to show that all the data has been 
preserved:
+       </p>
+       <p class='bcode'>
+       {
+               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>
+       
+
+       <!-- 
========================================================================================================
 -->
+       <a id="GenericParsing"></a>
+       <h3 class='topic' onclick='toggle(this)'>3.1 - Parsing into generic 
POJO models</h3>
+       <div class='topic'>
+               <p>
+                       The JSON parser is not limited to parsing back into the 
original bean classes.<br>  
+                       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 
<code>Maps</code>, <code>Collections</code>, and primitive
+                               objects.
+               </p>
+               <p>
+                       You can parse into any <code>Map</code> type (e.g. 
<code>HashMap</code>, <code>TreeMap</code>), but
+                               using {@link com.ibm.juno.core.ObjectMap} is 
recommended since it has many convenience methods
+                               for converting values to various types.<br> 
+                       The same is true when parsing collections.  You can use 
any Collection (e.g. <code>HashSet</code>, <code>LinkedList</code>)
+                               or array (e.g. <code>Object[]</code>, 
<code>String[]</code>, <code>String[][]</code>), but using 
+                               {@link com.ibm.juno.core.ObjectList} is 
recommended.
+               </p>
+               <p>
+                       When the map or list type is not specified, or is the 
abstract <code>Map</code>, <code>Collection</code>, or <code>List</code> types, 
+                               the parser will use <code>ObjectMap</code> and 
<code>ObjectList</code> by default.
+               </p>
+               <p>
+                       Starting back with our original JSON:
+               </p>
+               <p class='bcode'>
+       {
+               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 <code>ObjectMap</code>:
+               </p>
+               <p class='bcode'>       
+       <jc>// Parse JSON into a generic POJO model.</jc>
+       ObjectMap m = JsonParser.<jsf>DEFAULT</jsf>.parse(json, 
ObjectMap.<jk>class</jk>);
+
+       <jc>// Convert it back to JSON.</jc>
+       String json = 
JsonSerializer.<jsf>DEFAULT_LAX_READABLE</jsf>.serialize(m);
+               </p>
+               <p>
+                       What we end up with is the exact same output.<br>
+                       Even the numbers and booleans are preserved because 
they are parsed into <code>Number</code> and <code>Boolean</code> objects
+                               when parsing into generic models.
+               </p>
+               <p class='bcode'>
+       {
+               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 <code>ObjectMap</code>
+                               and <code>ObjectList</code> classes to retrieve 
values:
+               </p>
+               <p class='bcode'>
+       <jc>// Parse JSON into a generic POJO model.</jc>
+       ObjectMap m = JsonParser.<jsf>DEFAULT</jsf>.parse(json, 
ObjectMap.<jk>class</jk>);
+
+       <jc>// Get some simple values.</jc>
+       String name = m.getString(<js>"name"</js>);
+       <jk>int</jk> id = m.getInt(<js>"id"</js>);
+
+       <jc>// Get a value convertable from a String.</jc>
+       URI uri = m.get(URI.<jk>class</jk>, <js>"uri"</js>);
+
+       <jc>// Get a value using a filter.</jc>
+       CalendarFilter filter = <jk>new</jk> CalendarFilter.ISO8601DTZ();
+       Calendar birthDate = m.get(filter, <js>"birthDate"</js>);
+
+       <jc>// Get the addresses.</jc>
+       ObjectList addresses = m.getObjectList(<js>"addresses"</js>);
+
+       <jc>// Get the first address and convert it to a bean.</jc>
+       Address address = addresses.get(Address.<jk>class</jk>, 0);
+               </p>
+
+               <p>
+                       As a general rule, parsing into beans is often more 
efficient than parsing into generic models.<br>
+                       And working with beans is often less error prone than 
working with generic models.
+               </p>            
+       </div>
+
+
+       <!-- 
========================================================================================================
 -->
+       <a id="ParserConfigurableProperties"></a>
+       <h3 class='topic' onclick='toggle(this)'>3.2 - Configurable 
properties</h3>
+       <div class='topic'>
+               <p>
+                       The <code>JsonParser</code> class does not currently 
have any configurable properties.
+               </p>
+       </div>          
+
+
+       <!-- 
========================================================================================================
 -->
+       <a id="ParserOtherNotes"></a>
+       <h3 class='topic' onclick='toggle(this)'>3.3 - Other notes</h3>
+       <div class='topic'>
+               <ul>
+                       <li>Like all other Juno parsers, the JSON parser is 
thread safe and maintains an internal cache of bean classes encountered.<br>
+                               For performance reasons, it's recommended that 
parser be reused whenever possible instead of always creating new instances.
+               </ul>
+       </div>
+       
+</div>
+
+
+<!-- 
========================================================================================================
 -->
+<a id="RestApiSupport"></a>
+<h2 class='topic' onclick='toggle(this)'>4 - REST API support</h2>
+<div class='topic'>
+       <p>
+               Juno provides fully-integrated support for JSON 
serialization/parsing in the REST server and client APIs.<br>
+               The next two sections describe these in detail.
+       </p>
+
+       <!-- 
========================================================================================================
 -->
+       <a id="RestServerSupport"></a>
+       <h3 class='topic' onclick='toggle(this)'>4.1 - REST server support</h3>
+       <div class='topic'>
+               <p>
+                       There are four general ways of defining REST interfaces 
with support for JSON.
+                       Two using the built-in Juno Server API, and two using 
the JAX-RS integration component.
+               </p>
+               <ul>
+                       <li>Create a servlet that subclasses from {@link 
com.ibm.juno.server.RestServletDefault}.<br>
+                                       This includes JSON 
serialization/parsing support by default, in addition to several other media 
types.<br><br>
+                       <li>Create a servlet that subclasses from {@link 
com.ibm.juno.server.RestServlet} and specify the
+                                       a JSON serializer and/or parser using 
the {@link com.ibm.juno.server.annotation.RestResource#serializers()} and
+                                       {@link 
com.ibm.juno.server.annotation.RestResource#parsers()} on the entire servlet 
class, or 
+                                       the {@link 
com.ibm.juno.server.annotation.RestMethod#serializers()} and {@link 
com.ibm.juno.server.annotation.RestMethod#parsers()}
+                                       annotations on individual methods 
within the class.<br><br>
+                       <li>Register {@link 
com.ibm.juno.server.jaxrs.DefaultProvider} with JAX-RS.<br>
+                                       This includes JSON 
serialization/parsing support by default, in addition to several other media 
types.<br><br>
+                       <li>Create and register a subclass of {@link 
com.ibm.juno.server.jaxrs.BaseProvider} and specify the serializers and parsers 
to use on JAX-RS resources.
+               </ul>
+               <p>
+                       In general, the Juno REST server API is much more 
configurable and easier to use than JAX-RS, but beware that the author may be 
slightly biased in this statement.
+               </p>
+
+               <!-- 
========================================================================================================
 -->
+               <a id="RestServletDefault"></a>
+               <h4 class='topic' onclick='toggle(this)'>4.1.1 - Using 
RestServletDefault</h4>
+               <div class='topic'>
+                       <p>
+                               The quickest way to implement a REST resource 
with JSON support is to create a subclass of {@link 
com.ibm.juno.server.RestServletDefault}.<br>
+                               This class provides support for JSON, XML, 
HTML, URL-Encoding, and others.
+                       </p>
+                       <p>
+                               The <code>AddressBookResource</code> example 
shown in the first chapter uses the <code>RestServletJenaDefault</code> class
+                                       which is a subclass of 
<code>RestServletDefault</code> with additional support for RDF languages.<br>
+                               The start of the class definition is shown 
below:
+                       </p>
+                       <p class='bcode'>
+       <jc>// Proof-of-concept resource that shows off the capabilities of 
working with POJO resources.
+       // Consists of an in-memory address book repository.</jc>
+       <ja>@RestResource</ja>(
+               messages=<js>"nls/AddressBookResource"</js>,
+               properties={
+                       
<ja>@Property</ja>(name=SerializerProperties.<jsf>SERIALIZER_quoteChar</jsf>, 
value=<js>"'"</js>),
+                       
<ja>@Property</ja>(name=HtmlSerializerProperties.<jsf>HTML_uriAnchorText</jsf>, 
value=<jsf>TO_STRING</jsf>),
+                       
<ja>@Property</ja>(name=HtmlDocSerializerProperties.<jsf>HTMLDOC_title</jsf>, 
value=<js>"$L{title}"</js>),
+                       
<ja>@Property</ja>(name=HtmlDocSerializerProperties.<jsf>HTMLDOC_description</jsf>,
 value=<js>"$L{description}"</js>),
+                       
<ja>@Property</ja>(name=HtmlDocSerializerProperties.<jsf>HTMLDOC_links</jsf>, 
value=<js>"{options:'?method=OPTIONS',doc:'doc'}"</js>)
+               },
+               encoders=GzipEncoder.<jk>class</jk>
+       )
+       <jk>public class</jk> AddressBookResource <jk>extends</jk> 
RestServletJenaDefault {
+                       </p>
+                       <p>
+                               Notice how serializer and parser properties can 
be specified using the <code>@RestResource.properties()</code> annotation.<br>
+                               The <jsf>SERIALIZER_quoteChar</jsf> is a 
property common to all serializers, including the JSON serializer.
+                               The remaining properties are specific to the 
HTML serializer.
+                       </p>
+                       <p>
+                               The <code>$L{...}</code> variable represent 
localized strings pulled from the resource bundle identified by the 
<code>messages</code> annotation.
+                               These variables are replaced at runtime based 
on the HTTP request locale.
+                               Several built-in runtime variable types are 
defined, and the API can be extended to include user-defined variables.
+                               See {@link 
com.ibm.juno.server.RestServlet#getVarResolver()} for more information.
+                       </p>
+                       <p>
+                               This document won't go into all the details of 
the Juno <code>RestServlet</code> class.<br>
+                               Refer to the {@link com.ibm.juno.server} 
documentation for more information on the REST servlet class in general.
+                       </p>
+                       <p>
+                               The rest of the code in the resource class 
consists of REST methods that simply accept and return POJOs.<br>
+                               The framework takes care of all content 
negotiation, serialization/parsing, and error handling.<br>
+                               Below are 3 of those methods to give you a 
general idea of the concept:
+                       </p>
+                       <p class='bcode'>
+       <jc>// GET person request handler</jc>
+       <ja>@RestMethod</ja>(name=<js>"GET"</js>, 
path=<js>"/people/{id}/*"</js>, rc={200,404})
+       <jk>public</jk> Person getPerson(RestRequest req, <ja>@Attr</ja> 
<jk>int</jk> id) throws Exception {
+               
properties.put(HtmlDocSerializerProperties.<jsf>HTMLDOC_title</jsf>, 
req.getPathInfo());
+               <jk>return</jk> findPerson(id);
+       }
+       
+       <jc>// POST person handler</jc>
+       <ja>@RestMethod</ja>(name=<js>"POST"</js>, path=<js>"/people"</js>, 
guards=AdminGuard.<jk>class</jk>, rc={307,404})
+       <jk>public void</jk> createPerson(RestResponse res, <ja>@Content</ja> 
CreatePerson cp) <jk>throws</jk> Exception {
+               Person p = addressBook.createPerson(cp);
+               res.sendRedirect(p.<jf>uri</jf>);
+       }
+
+       <jc>// DELETE person handler</jc>
+       <ja>@RestMethod</ja>(name=<js>"DELETE"</js>, 
path=<js>"/people/{id}"</js>, guards=AdminGuard.<jk>class</jk>, rc={200,404})
+       <jk>public</jk> String deletePerson(RestResponse res, <ja>@Attr</ja> 
<jk>int</jk> id) <jk>throws</jk> Exception {
+               Person p = findPerson(id);
+               addressBook.remove(p);
+               <jk>return</jk> <js>"DELETE successful"</js>;                   
+       }       
+                       </p>
+                       <p>
+                               The resource class can be registered with the 
web application like any other servlet, or can be 
+                                       defined as a child of another resource 
through the {@link com.ibm.juno.server.annotation.RestResource#children()} 
annotation.
+               </div>
+
+               <!-- 
========================================================================================================
 -->
+               <a id="RestServlet"></a>
+               <h4 class='topic' onclick='toggle(this)'>4.1.2 - Using 
RestServlet with annotations</h4>
+               <div class='topic'>
+                       <p>
+                               For fine-tuned control of media types, the 
{@link com.ibm.juno.server.RestServlet} class 
+                                       can be subclassed directly.<br>
+                               The serializers/parsers can be specified 
through annotations at the class and/or method levels.
+                       </p>
+                       <p>
+                               An equivalent <code>AddressBookResource</code> 
class could be defined to only support JSON using
+                                       the following definition:
+                       </p>
+                       <p class='bcode'>
+       <ja>@RestResource</ja>(
+               serializers={JsonSerializer.<jk>class</jk>},
+               parsers={JsonParser.<jk>class</jk>},
+               properties={
+                       
<ja>@Property</ja>(name=SerializerProperties.<jsf>SERIALIZER_quoteChar</jsf>, 
value=<js>"'"</js>)
+               }
+       )
+       <jk>public class</jk> AddressBookResource <jk>extends</jk> RestServlet {
+                       </p>
+                       <p>
+                               Likewise, serializers and parsers can be 
specified/augmented/overridden at the method level like so:
+                       </p>
+                       <p class='bcode'>
+       <jc>// GET person request handler</jc>
+       <ja>@RestMethod</ja>(name=<js>"GET"</js>, 
path=<js>"/people/{id}/*"</js>, rc={200,404},
+               serializers={JsonSerializer.<jk>class</jk>},
+               parsers={JsonParser.<jk>class</jk>},
+               properties={
+                       
<ja>@Property</ja>(name=SerializerProperties.<jsf>SERIALIZER_quoteChar</jsf>, 
value=<js>"'"</js>)
+               }
+       )
+       <jk>public</jk> Person getPerson(RestRequest req, <ja>@Attr</ja> 
<jk>int</jk> id) throws Exception {
+               
properties.put(HtmlDocSerializerProperties.<jsf>HTMLDOC_title</jsf>, 
req.getPathInfo());
+               <jk>return</jk> findPerson(id);
+       }
+                       </p>
+                       <p>
+                               The {@link 
com.ibm.juno.server.annotation.RestMethod#serializersInherit()} and 
+                                       {@link 
com.ibm.juno.server.annotation.RestMethod#parsersInherit()} control how various 
artifacts
+                                       are inherited from the parent class.<br>
+                               Refer to {@link com.ibm.juno.server} for 
additional information on using these annotations.
+                       </p>
+               </div>
+
+               <!-- 
========================================================================================================
 -->
+               <a id="DefaultProvider"></a>
+               <h4 class='topic' onclick='toggle(this)'>4.1.3 - Using JAX-RS 
DefaultProvider</h4>
+               <div class='topic'>
+                       <p>
+                               JSON media type support in JAX-RS can be 
achieved by using the {@link com.ibm.juno.server.jaxrs.DefaultProvider} 
class.<br>
+                               It implements the JAX-RS 
<code>MessageBodyReader</code> and <code>MessageBodyWriter</code> interfaces 
for all Juno supported media types.
+                       </p>
+                       <p>
+                               The <code>DefaultProvider</code> class 
definition is shown below:
+                       </p>
+                       <p class='bcode'>
+       <ja>@Provider</ja>
+       <ja>@Produces</ja>({
+               <js>"application/json"</js>, <js>"text/json"</js>,              
   <jc>// JsonSerializer</jc>
+               <js>"application/json+simple"</js>,<js>"text/json+simple"</js>, 
   <jc>// JsonSerializer.Simple</jc>
+               <js>"application/json+schema"</js>,<js>"text/json+schema"</js>, 
   <jc>// JsonSchemaSerializer</jc>
+               <js>"text/xml"</js>,                                      
<jc>// XmlDocSerializer</jc>
+               <js>"text/xml+simple"</js>,                               
<jc>// XmlDocSerializer.Simple</jc>
+               <js>"text/xml+schema"</js>,                               
<jc>// XmlSchemaDocSerializer</jc>
+               <js>"text/html"</js>,                                     
<jc>// HtmlDocSerializer</jc>
+               <js>"application/x-www-form-urlencoded"</js>,             
<jc>// UrlEncodingSerializer</jc>
+               <js>"text/xml+soap"</js>,                                 
<jc>// SoapXmlSerializer</jc>
+               <js>"application/x-java-serialized-object"</js>           
<jc>// JavaSerializedObjectSerializer</jc>
+       })
+       <ja>@Consumes</ja>({
+               <js>"application/json"</js>, <js>"text/json"</js>,              
   <jc>// JsonParser</jc>
+               <js>"text/xml"</js>,                                      
<jc>// XmlParser</jc>
+               <js>"text/html"</js>,                                     
<jc>// HtmlParser</jc>
+               <js>"application/x-www-form-urlencoded"</js>,             
<jc>// UrlEncodingParser</jc>
+               <js>"application/x-java-serialized-object"</js>           
<jc>// JavaSerializedObjectParser</jc>
+       })
+       <ja>@JunoProvider</ja>(
+               serializers={
+                       JsonSerializer.<jk>class</jk>,
+                       JsonSerializer.Simple.<jk>class</jk>,
+                       JsonSchemaSerializer.<jk>class</jk>,
+                       XmlDocSerializer.<jk>class</jk>,
+                       XmlDocSerializer.Simple.<jk>class</jk>,
+                       XmlSchemaDocSerializer.<jk>class</jk>,
+                       HtmlDocSerializer.<jk>class</jk>,
+                       UrlEncodingSerializer.<jk>class</jk>,
+                       SoapXmlSerializer.<jk>class</jk>,
+                       JavaSerializedObjectSerializer.<jk>class</jk>
+               },
+               parsers={
+                       JsonParser.<jk>class</jk>,
+                       XmlParser.<jk>class</jk>,
+                       HtmlParser.<jk>class</jk>,
+                       UrlEncodingParser.<jk>class</jk>,
+                       JavaSerializedObjectParser.<jk>class</jk>,
+               }
+       )
+       <jk>public final class</jk> DefaultProvider <jk>extends</jk> 
BaseProvider {}
+                       </p>
+                       <p>
+                               That's the entire class.  It consists of only 
annotations to hook up media types to Juno serializers and parsers.
+                               The <ja>@Provider</ja>, <ja>@Produces</ja>, and 
<ja>@Consumes</ja> annotations are standard JAX-RS annotations, and the 
<ja>@JunoProvider</ja> annotation is from Juno.
+                       </p>
+                       <p>
+                               To enable the provider, you need to make the 
JAX-RS environment aware of it.
+                               In Wink, this is accomplished by adding an 
entry to a config file.
+                       </p>
+                       <p class='bcode'>
+       <xt>&lt;web-app</xt> <xa>version</xa>=<xs>"2.3"</xs><xt>&gt;</xt>
+               <xt>&lt;servlet&gt;</xt>
+                       
<xt>&lt;servlet-name&gt;</xt>WinkService<xt>&lt;/servlet-name&gt;</xt>
+                       
<xt>&lt;servlet-class&gt;</xt>org.apache.wink.server.internal.servlet.RestServlet<xt>&lt;/servlet-class&gt;</xt>
+                       <xt>&lt;init-param&gt;</xt>
+                               
<xt>&lt;param-name&gt;</xt>applicationConfigLocation<xt>&lt;/param-name&gt;</xt>
+                               
<xt>&lt;param-value&gt;</xt>/WEB-INF/wink.cfg<xt>&lt;/param-value&gt;</xt>
+                       <xt>&lt;/init-param&gt;</xt>
+               <xt>&lt;/servlet&gt;</xt>
+                       </p>
+                       <p>
+                               Simply include a reference to the provider in 
the configuration file.
+                       <p class='bcode'>
+       com.ibm.juno.server.jaxrs.DefaultProvider
+                       </p>
+                       <p>
+                               Properties can be specified on providers 
through the {@link com.ibm.juno.server.jaxrs.JunoProvider#properties()} 
annotation.<br>
+                               Properties can also be specified at the method 
level by using the {@link com.ibm.juno.server.annotation.RestMethod#properties} 
annotation, like so:
+                       </p>
+                       <p class='bcode'>
+       <ja>@GET</ja>
+       <ja>@Produces</ja>(<js>"*/*"</js>)
+       <ja>@RestMethod</ja>( <jc>/* Override some properties */</jc>
+               properties={
+                       
<ja>@Property</ja>(name=SerializerProperties.<jsf>SERIALIZER_quoteChar</jsf>, 
value=<js>"'"</js>)
+               }
+       )
+       <jk>public</jk> Message getMessage() {
+               <jk>return</jk> message;
+       }
+                       </p>
+                       <h6 class='topic'>Limitations</h6>
+                       <p>
+                               In general, the Juno REST API is considerably 
more flexible than the JAX-RS API, since you can specify and override
+                                       serializers, parsers, properties, 
filters, converters, guards, etc... at both the class and method levels.<br>
+                               Therefore, the JAX-RS API has the following 
limitations that the Juno Server API does not:
+                       </p>
+                       <ul>
+                               <li>The ability to specify different media type 
providers at the class and method levels.<br> 
+                                       For example, you may want to use 
<code>JsonSerializer</code> with one set of properties on 
+                                               one class, and another instance 
with different properties on another class.<br>
+                                       There is currently no way to define 
this at the class level.<br>
+                                       You can override properties at the 
method level, but this can be cumbersome since it would have to be
+                                               done for all methods in the 
resource.<br><br>
+                               <li>The Juno Server API allows you to 
manipulate properties programatically through the {@link 
com.ibm.juno.server.RestResponse#setProperty(String,Object)}
+                                       method, and through the {@link 
com.ibm.juno.server.annotation.Properties} annotation.<br>
+                                       There is no equivalent in JAX-RS.
+                       </ul>
+               </div>
+
+               <!-- 
========================================================================================================
 -->
+               <a id="BaseProvider"></a>
+               <h4 class='topic' onclick='toggle(this)'>4.1.4 - Using JAX-RS 
BaseProvider with annotations</h4>
+               <div class='topic'>
+                       <p>
+                               To provide support for only JSON media types, 
you can define your own provider class, like so:
+                       </p>
+                       <p class='bcode'>
+       <ja>@Provider</ja>
+       <ja>@Produces</ja>({
+               <js>"application/json"</js>, <js>"text/json"</js>,              
   <jc>// JsonSerializer</jc>
+               <js>"application/json+simple"</js>,<js>"text/json+simple"</js>, 
   <jc>// JsonSerializer.Simple</jc>
+               <js>"application/json+schema"</js>,<js>"text/json+schema"</js>  
   <jc>// JsonSchemaSerializer</jc>
+       })
+       <ja>@Consumes</ja>({
+               <js>"application/json"</js>, <js>"text/json"</js>               
   <jc>// JsonParser</jc>
+       })
+       <ja>@JunoProvider</ja>(
+               serializers={
+                       JsonSerializer.<jk>class</jk>,
+                       JsonSerializer.Simple.<jk>class</jk>,
+                       JsonSchemaSerializer.<jk>class</jk>,
+               },
+               parsers={
+                       JsonParser.<jk>class</jk>,
+               }
+               properties={
+                       
<ja>@Property</ja>(name=SerializerProperties.<jsf>SERIALIZER_quoteChar</jsf>, 
value=<js>"'"</js>)
+               }
+       )
+       <jk>public final class</jk> MyRdfProvider <jk>extends</jk> BaseProvider 
{}
+                       </p>
+                       <p>
+                               Then register it with Wink the same way as 
<code>DefaultProvider</code>.
+                       </p>
+               </div>
+
+       </div>
+
+       <!-- 
========================================================================================================
 -->
+       <a id="RestClientSupport"></a>
+       <h3 class='topic' onclick='toggle(this)'>4.2 - REST client support</h3>
+       <div class='topic'>
+               <p>
+                       The {@link com.ibm.juno.client.RestClient} class 
provides an easy-to-use REST client interface with 
+                               pluggable media type handling using any of the 
Juno serializers and parsers.<br>
+                       Defining a client to support JSON media types on HTTP 
requests and responses can be done in one line of code:
+               </p>
+               <p class='bcode'>
+       <jc>// Create a client to handle JSON requests and responses.</jc>
+       RestClient client = <jk>new</jk> 
RestClient(JsonSerializer.<jk>class</jk>, JsonParser.<jk>class</jk>);
+               </p>
+               <p>
+                       The client handles all content negotiation based on the 
registered serializers and parsers.
+               </p>
+               <p>
+                       The following code is pulled from the main method of 
the <code>ClientTest</code> class in the sample web application, and
+                               is run against the 
<code>AddressBookResource</code> class running within the sample app.<br>
+                       It shows how the client can be used to interact with 
the REST API while completely hiding the negotiated content type and working 
with nothing more than beans.
+               </p>
+               <h6 class='figure'>Example</h6>
+               <p class='bcode'>
+       String root = <js>"http://localhost:9080/sample/addressBook";</js>;
+       
+       <jc>// Get the current contents of the address book</jc>
+       AddressBook ab = 
client.doGet(root).getResponse(AddressBook.<jk>class</jk>);
+       System.<jsm>out</jsm>.println(<js>"Number of entries = "</js> + 
ab.size());
+       
+       <jc>// Delete the existing entries</jc>
+       <jk>for</jk> (Person p : ab) {
+               String r = 
client.doDelete(p.<jf>uri</jf>).getResponse(String.<jk>class</jk>);
+               System.<jsm>out</jsm>.println(<js>"Deleted person "</js> + 
p.<jf>name</jf> + <js>", response = "</js> + r);
+       }
+       
+       <jc>// Make sure they're gone</jc>
+       ab = client.doGet(root).getResponse(AddressBook.<jk>class</jk>);
+       System.<jsm>out</jsm>.println(<js>"Number of entries = "</js> + 
ab.size());
+       
+       <jc>// Add 1st person again</jc>
+       CreatePerson cp = <jk>new</jk> CreatePerson(
+               <js>"Barack Obama"</js>, 
+               <jsm>toCalendar</jsm>(<js>"Aug 4, 1961"</js>),
+               <jk>new</jk> CreateAddress(<js>"1600 Pennsylvania Ave"</js>, 
<js>"Washington"</js>, <js>"DC"</js>, 20500, <jk>true</jk>),
+               <jk>new</jk> CreateAddress(<js>"5046 S Greenwood Ave"</js>, 
<js>"Chicago"</js>, <js>"IL"</js>, 60615, <jk>false</jk>)
+       ); 
+       Person p = client.doPost(root + <js>"/people"</js>, 
cp).getResponse(Person.<jk>class</jk>);
+       System.<jsm>out</jsm>.println(<js>"Created person "</js> + 
p.<jf>name</jf> + <js>", uri = "</js> + p.<jf>uri</jf>);
+       
+       <jc>// Add 2nd person again, but add addresses separately</jc>
+       cp = <jk>new</jk> CreatePerson(
+               <js>"George Walker Bush"</js>, 
+               toCalendar(<js>"Jul 6, 1946"</js>)
+       );
+       p = client.doPost(root + <js>"/people"</js>, 
cp).getResponse(Person.<jk>class</jk>);
+       System.<jsm>out</jsm>.println(<js>"Created person "</js> + 
p.<jf>name</jf> + <js>", uri = "</js> + p.<jf>uri</jf>);
+       
+       <jc>// Add addresses to 2nd person</jc>
+       CreateAddress ca = <jk>new</jk> CreateAddress(<js>"43 Prairie Chapel 
Rd"</js>, <js>"Crawford"</js>, <js>"TX"</js>, 76638, <jk>true</jk>);
+       Address a = client.doPost(p.<jf>uri</jf> + <js>"/addresses"</js>, 
ca).getResponse(Address.<jk>class</jk>);
+       System.<jsm>out</jsm>.println(<js>"Created address "</js> + 
a.<jf>uri</jf>);
+                               
+       ca = <jk>new</jk> CreateAddress(<js>"1600 Pennsylvania Ave"</js>, 
<js>"Washington"</js>, <js>"DC"</js>, 20500, <jk>false</jk>);
+       a = client.doPost(p.<jf>uri</jf> + "/addresses"</js>, 
ca).getResponse(Address.<jk>class</jk>);
+       System.<jsm>out</jsm>.println(<js>"Created address "</js> + 
a.<jf>uri</jf>);
+       
+       <jc>// Find 1st person, and change name</jc>
+       Person[] pp = client.doGet(root + 
<js>"?q={name:\"'Barack+Obama'\"}"</js>).getResponse(Person[].<jk>class</jk>);
+       String r = client.doPut(pp[0].<jf>uri</jf> + <js>"/name"</js>, 
<js>"Barack Hussein Obama"</js>).getResponse(String.<jk>class</jk>);
+       System.<jsm>out</jsm>.println(<js>"Changed name, response = "</js> + r);
+       p = client.doGet(pp[0].<jf>uri</jf>).getResponse(Person.<jk>class</jk>);
+       System.<jsm>out</jsm>.println(<js>"New name = "</js> + p.<jf>name</jf>);
+               </p>
+               <h6 class='figure'>Results</h6>
+               <p class='bcode'>
+       Number of entries = 2
+       Deleted person Barack Obama, response = DELETE successful
+       Deleted person George Walker Bush, response = DELETE successful
+       Number of entries = 0
+       Created person Barack Obama, uri = 
http://localhost:9080/sample/addressBook/people/3
+       Created person George Walker Bush, uri = 
http://localhost:9080/sample/addressBook/people/4
+       Created address http://localhost:9080/sample/addressBook/addresses/7
+       Created address http://localhost:9080/sample/addressBook/addresses/8
+       Changed name, response = PUT successful
+       New name = Barack Hussein Obama
+               </p>
+       </div>
+</div>
+<p align="center"><i><b>*** fín ***</b></i></p>
+
+</body>
+</html>
\ No newline at end of file

Reply via email to