You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2018/09/12 19:55:33 UTC

[juneau] branch master updated: Javadocs and Swagger UI tweaks.

This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 2e478e4  Javadocs and Swagger UI tweaks.
2e478e4 is described below

commit 2e478e4df0ae14a963f7d705e0229e28bf93118d
Author: JamesBognar <ja...@apache.org>
AuthorDate: Wed Sep 12 15:55:05 2018 -0400

    Javadocs and Swagger UI tweaks.
---
 .../apache/juneau/dto/swagger/SwaggerElement.java  |  16 ++
 .../apache/juneau/dto/swagger/ui/SwaggerUI.java    |  71 ++++--
 .../src/main/java/org/apache/juneau/ObjectMap.java |  25 +++
 .../org/apache/juneau/http/annotation/Query.java   |   2 +-
 juneau-doc/docs.txt                                |   1 +
 .../juneau-rest-server.Swagger.Models.3.png        | Bin 0 -> 59691 bytes
 .../juneau-rest-server.Swagger.Operations.2.png    | Bin 213265 -> 82846 bytes
 juneau-doc/src/main/javadoc/overview.html          | 243 +++++++++++++++++++--
 .../07.juneau-rest-server/27.Swagger/03.Tags.html  |   1 -
 .../27.Swagger/04.Operations.html                  |  45 +++-
 .../27.Swagger/05.Parameters.html                  |  85 ++++++-
 .../27.Swagger/07.Responses.html                   |   1 +
 .../27.Swagger/09.Models.html                      |  91 +++++++-
 .../{07.Responses.html => 10.Stylesheet.html}      |  12 +-
 .../juneau-rest-server.Swagger.Models.3.png        | Bin 0 -> 59691 bytes
 .../juneau-rest-server.Swagger.Operations.2.png    | Bin 213265 -> 82846 bytes
 .../org/apache/juneau/rest/SwaggerGenerator.java   |  81 ++++---
 .../apache/juneau/rest/converters/Queryable.java   |  23 +-
 .../juneau/rest/annotation/PathAnnotationTest.java |  14 +-
 19 files changed, 613 insertions(+), 98 deletions(-)

diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
index f930749..19ee0eb 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/SwaggerElement.java
@@ -16,6 +16,7 @@ import static org.apache.juneau.internal.BeanPropertyUtils.*;
 
 import java.util.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.utils.*;
@@ -158,6 +159,21 @@ public abstract class SwaggerElement {
 		return s;
 	}
 
+	/**
+	 * Returns a copy of this swagger element as a modifiable map.
+	 *
+	 * <p>
+	 * Each call produces a new map.
+	 *
+	 * @return A map containing all the values in this swagger element.
+	 */
+	public ObjectMap asMap() {
+		ObjectMap m = new ObjectMap();
+		for (String s : keySet())
+			m.put(s, get(s, Object.class));
+		return m;
+	}
+
 	@Override /* Object */
 	public String toString() {
 		return JsonSerializer.DEFAULT.toString(this);
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
index e2901f1..f39a423 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
@@ -245,7 +245,7 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
 
 				Td parameterValue = td(
 					div(pi.getDescription())._class("description"),
-					examples(s, pi.getSchema(), pi.getExamples())
+					examples(s, pi)
 				)._class("parameter-value");
 
 				parameters.child(tr(parameterKey, parameterValue));
@@ -267,7 +267,7 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
 
 				Td codeValue = td(
 					div(ri.getDescription())._class("description"),
-					examples(s, ri.getSchema(), ri.getExamples()),
+					examples(s, ri),
 					headers(s, ri)
 				)._class("response-value");
 
@@ -304,28 +304,61 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
 		return headers;
 	}
 
-	private Div examples(Session s, SchemaInfo si, Map<String,?> examples) {
-		if (si == null && examples == null)
-			return null;
+	private Div examples(Session s, ParameterInfo pi) {
+		boolean isBody = "body".equals(pi.getIn());
+
+		ObjectMap m = new ObjectMap();
+		if (isBody) {
+			SchemaInfo si = pi.getSchema();
+			if (si != null)
+				m.put("model", si.copy().resolveRefs(s.swagger, new ArrayDeque<String>(), s.resolveRefsMaxDepth));
+		} else {
+			ObjectMap om = pi
+				.copy()
+				.resolveRefs(s.swagger, new ArrayDeque<String>(), s.resolveRefsMaxDepth)
+				.asMap()
+				.keepAll("format","pattern","collectionFormat","maximum","minimum","multipleOf","maxLength","minLength","maxItems","minItems","allowEmptyValue","exclusiveMaximum","exclusiveMinimum","uniqueItems","items","default","enum");
+			m.put("model", om.isEmpty() ? i("none") : om);
+		}
 
-		int count = (si == null ? 0 : 1) + (examples == null ? 0 : examples.entrySet().size());
-		Select select = (Select)select().onchange("selectExample(this)")._class("example-select");
-		if (count < 2)
-			select.disabled(true);
-		Div div = div(select)._class("examples");
+		Map<String,?> examples = pi.getExamples();
+		if (examples != null)
+			for (Map.Entry<String,?> e : examples.entrySet())
+				m.put(e.getKey(), e.getValue());
+
+		return examplesDiv(m);
+	}
+
+	private Div examples(Session s, ResponseInfo ri) {
+		SchemaInfo si = ri.getSchema();
 
+		ObjectMap m = new ObjectMap();
 		if (si != null) {
-			select.child(option("model","model"));
-			div.child(div(si.copy().resolveRefs(s.swagger, new ArrayDeque<String>(), s.resolveRefsMaxDepth))._class("model active").attr("data-name", "model"));
+			si = si.copy().resolveRefs(s.swagger, new ArrayDeque<String>(), s.resolveRefsMaxDepth);
+			m.put("model", si);
 		}
 
-		if (examples != null) {
-			for (Map.Entry<String,?> e : examples.entrySet()) {
-				String name = e.getKey();
-				String value = e.getValue().toString();
-				select.child(option(name, name));
-				div.child(div(value.replaceAll("\\n", "\n"))._class("example" + (si == null ? " active" : "")).attr("data-name", name));
-			}
+		Map<String,?> examples = ri.getExamples();
+		if (examples != null)
+			for (Map.Entry<String,?> e : examples.entrySet())
+				m.put(e.getKey(), e.getValue());
+
+		return examplesDiv(m);
+	}
+
+	private Div examplesDiv(ObjectMap m) {
+		if (m.isEmpty())
+			return null;
+
+		Select select = (Select)select().disabled(m.size() < 2).onchange("selectExample(this)")._class("example-select");
+		Div div = div(select)._class("examples");
+
+		select.child(option("model","model"));
+		div.child(div(m.remove("model"))._class("model active").attr("data-name", "model"));
+
+		for (Map.Entry<String,Object> e : m.entrySet()) {
+			select.child(option(e.getKey(), e.getKey()));
+			div.child(div(e.getValue().toString().replaceAll("\\n", "\n"))._class("example").attr("data-name", e.getKey()));
 		}
 
 		return div;
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ObjectMap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ObjectMap.java
index 8e579b0..8c18aa1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ObjectMap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ObjectMap.java
@@ -1291,6 +1291,31 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 			remove(k);
 	}
 
+	/**
+	 * The opposite of {@link #removeAll(String...)}.
+	 *
+	 * <p>
+	 * Discards all keys from this map that aren't in the specified list.
+	 *
+	 * @param keys The keys to keep.
+	 * @return This map.
+	 */
+	public ObjectMap keepAll(String...keys) {
+		for (Iterator<String> i = keySet().iterator(); i.hasNext();) {
+			boolean remove = true;
+			String key = i.next();
+			for (String k : keys) {
+				if (k.equals(key)) {
+					remove = false;
+					break;
+				}
+			}
+			if (remove)
+				i.remove();
+		}
+		return this;
+	}
+
 	@Override /* Map */
 	public boolean containsKey(Object key) {
 		if (super.containsKey(key))
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java
index c18ed48..43f2802 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/annotation/Query.java
@@ -871,7 +871,7 @@ public @interface Query {
 	 * 		name=<js>"status"</js>,
 	 * 		type=<js>"array"</js>,
 	 * 		collectionFormat=<js>"csv"</js>,
-	 * 		example=<js>"AVALIABLE,PENDING"</js>
+	 * 		example=<js>"AVAILABLE,PENDING"</js>
 	 * 	)
 	 * 	PetStatus[] status
 	 * </p>
diff --git a/juneau-doc/docs.txt b/juneau-doc/docs.txt
index 902fd39..d7a2a5d 100644
--- a/juneau-doc/docs.txt
+++ b/juneau-doc/docs.txt
@@ -322,6 +322,7 @@ juneau-rest-server.Swagger.ParameterExamples = #juneau-rest-server.Swagger.Param
 juneau-rest-server.Swagger.Parameters = #juneau-rest-server.Swagger.Parameters, Overview > juneau-rest-server > Swagger > Parameters
 juneau-rest-server.Swagger.ResponseExamples = #juneau-rest-server.Swagger.ResponseExamples, Overview > juneau-rest-server > Swagger > Response Examples
 juneau-rest-server.Swagger.Responses = #juneau-rest-server.Swagger.Responses, Overview > juneau-rest-server > Swagger > Responses
+juneau-rest-server.Swagger.Stylesheet = #juneau-rest-server.Swagger.Stylesheet, Overview > juneau-rest-server > Swagger > SwaggerUI.css
 juneau-rest-server.Swagger.Tags = #juneau-rest-server.Swagger.Tags, Overview > juneau-rest-server > Swagger > Tags
 juneau-rest-server.Transforms = #juneau-rest-server.Transforms, Overview > juneau-rest-server > Transforms
 juneau-rest-server.URIs = #juneau-rest-server.URIs, Overview > juneau-rest-server > URIs
diff --git a/juneau-doc/src/main/javadoc/doc-files/juneau-rest-server.Swagger.Models.3.png b/juneau-doc/src/main/javadoc/doc-files/juneau-rest-server.Swagger.Models.3.png
new file mode 100644
index 0000000..01df721
Binary files /dev/null and b/juneau-doc/src/main/javadoc/doc-files/juneau-rest-server.Swagger.Models.3.png differ
diff --git a/juneau-doc/src/main/javadoc/doc-files/juneau-rest-server.Swagger.Operations.2.png b/juneau-doc/src/main/javadoc/doc-files/juneau-rest-server.Swagger.Operations.2.png
index 014b981..9cbc361 100644
Binary files a/juneau-doc/src/main/javadoc/doc-files/juneau-rest-server.Swagger.Operations.2.png and b/juneau-doc/src/main/javadoc/doc-files/juneau-rest-server.Swagger.Operations.2.png differ
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 1416d72..9d1c805 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -338,12 +338,13 @@
 			<li><p class='new'><a class='doclink' href='#juneau-rest-server.Swagger.BasicRestServlet'>BasicRestServlet</a></p>
 			<li><p class='new'><a class='doclink' href='#juneau-rest-server.Swagger.BasicSwaggerInfo'>Basic Swagger Info</a></p>
 			<li><p class='new'><a class='doclink' href='#juneau-rest-server.Swagger.Tags'>Tags</a></p>
-			<li><p class='todo'><a class='doclink' href='#juneau-rest-server.Swagger.Operations'>Operations</a></p>
+			<li><p class='new'><a class='doclink' href='#juneau-rest-server.Swagger.Operations'>Operations</a></p>
 			<li><p class='todo'><a class='doclink' href='#juneau-rest-server.Swagger.Parameters'>Parameters</a></p>
 			<li><p class='todo'><a class='doclink' href='#juneau-rest-server.Swagger.ParameterExamples'>Parameter Examples</a></p>
 			<li><p class='todo'><a class='doclink' href='#juneau-rest-server.Swagger.Responses'>Responses</a></p>
 			<li><p class='todo'><a class='doclink' href='#juneau-rest-server.Swagger.ResponseExamples'>Response Examples</a></p>
-			<li><p class='todo'><a class='doclink' href='#juneau-rest-server.Swagger.Models'>Models</a></p>
+			<li><p class='new'><a class='doclink' href='#juneau-rest-server.Swagger.Models'>Models</a></p>
+			<li><p class='new'><a class='doclink' href='#juneau-rest-server.Swagger.Stylesheet'>SwaggerUI.css</a></p>
 		</ol>
 		<li><p class=''><a class='doclink' href='#juneau-rest-server.HtmlDocAnnotation'>@HtmlDoc</a></p>
 		<ol>
@@ -18725,7 +18726,6 @@
 			}
 		}
 	],
-
 </p>
 <p>
 	The annotation-only approach is shown here:
@@ -18791,15 +18791,47 @@
 
 <!-- ==================================================================================================== -->
 
-<h4 class='topic todo' onclick='toggle(this)'><a href='#juneau-rest-server.Swagger.Operations' id='juneau-rest-server.Swagger.Operations'>7.27.4 - Operations</a></h4>
+<h4 class='topic new' onclick='toggle(this)'><a href='#juneau-rest-server.Swagger.Operations' id='juneau-rest-server.Swagger.Operations'>7.27.4 - Operations</a></h4>
 <div class='topic'><!-- START: 7.27.4 - juneau-rest-server.Swagger.Operations -->
 <p>
-	TODO
+	<ja>@RestMethod</ja>-annotated methods automatically get rendered as Swagger operations:
+</p>
+<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.1.png'>
+<p>
+	The following shows the annotations defined on the <code>GET /pet</code> operation:
+</p>
+<h5 class='figure'>PetStoreResource.getPets()</h5>
+<p class='bpcode w800'>
+	<ja>@RestMethod</ja>(
+		name=<jsf>GET</jsf>,
+		path=<js>"/pet"</js>,
+		summary=<js>"All pets in the store"</js>,
+		swagger=<ja>@MethodSwagger</ja>(
+			tags=<js>"pet"</js>,
+			...
+		),
+		...
+	)
+	<jk>public</jk> Collection&lt;Pet&gt; getPets() <jk>throws</jk> NotAcceptable {
+		<jk>return</jk> <jsf>store</jsf>.getPets();
+	}
+</p> 
+<p>
+	Methods marked as deprecated will show up as deprecated in the Swagger UI:	
+</p>
+<h5 class='figure'>PetStoreResource.findPetsByTag()</h5>
+<p class='bpcode w800'>	
+	<ja>@RestMethod</ja>(
+		name=<jsf>GET</jsf>,
+		path=<js>"/pet/findByTags"</js>,
+		summary=<js>"Finds Pets by tags"</js>,
+		...
+	)
+	<ja>@Deprecated</ja>
+	<jk>public</jk> Collection&lt;Pet&gt; findPetsByTags(...) {
+		...
+	}
 </p>
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.1.png'> 
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.2.png'> 
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.3.png'> 
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.4.png'>
 </div><!-- END: 7.27.4 - juneau-rest-server.Swagger.Operations -->
 
 <!-- ==================================================================================================== -->
@@ -18807,7 +18839,90 @@
 <h4 class='topic todo' onclick='toggle(this)'><a href='#juneau-rest-server.Swagger.Parameters' id='juneau-rest-server.Swagger.Parameters'>7.27.5 - Parameters</a></h4>
 <div class='topic'><!-- START: 7.27.5 - juneau-rest-server.Swagger.Parameters -->
 <p>
-	TODO
+	Expanding operations shows you a list of parameters:
+</p>
+<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.2.png'> 
+<p>
+	The <code>parameters</code> annotation is a free-form Simple JSON field that allows you to add arbitrary
+	parameter information to your resource.
+	In this case, we pull from a common field defined in the {@link org.apache.juneau.rest.converters.Queryable} converter class:
+</p>
+<p class='bpcode w800'>
+	<jk>public class</jk> Queryable <jk>implements</jk> RestConverter {
+	
+		<jk>public static final</jk> String <jsf>SWAGGER_PARAMS</jsf>=<js>""</js>
+			+ <js>"{"</js>
+				+ <js>"in:'query',"</js>
+				+ <js>"name:'s',"</js>
+				+ <js>"description:'"</js>
+					+ <js>"Search.\n"</js>
+					+ <js>"Key/value pairs representing column names and search tokens.\n"</js>
+					+ <js>"\\'*\\' and \\'?\\' can be used as meta-characters in string fields.\n"</js>
+					+ <js>"\\'>\\', \\'>=\\', \\'<\\', and \\'<=\\' can be used as limits on numeric and date fields.\n"</js>
+					+ <js>"Date fields can be matched with partial dates (e.g. \\'2018\\' to match any date in the year 2018)."</js>
+				+ <js>"',"</js>
+				+ <js>"type:'array',"</js>
+				+ <js>"collectionFormat:'csv',"</js>
+				+ <js>"x-examples:{example:'?s=Bill*,birthDate>2000'}"</js>
+			+ <js>"},"</js>
+			+ <js>"{"</js>
+				+ <js>"in:'query',"</js>
+				+ <js>"name:'v',"</js>
+				+ <js>"description:'"</js>
+					+ <js>"View.\n"</js>
+					+ <js>"Column names to display."</js>
+				+ <js>"',"</js>
+				+ <js>"type:'array',"</js>
+				+ <js>"collectionFormat:'csv',"</js>
+				+ <js>"x-examples:{example:'?v=name,birthDate'}"</js>
+			+ <js>"},"</js>
+			...
+		;
+	}
+</p>
+<p>
+	Note that this information could have also been defined in the Swagger JSON for the resource as well.
+</p>
+<p>
+	The Swagger can also be defined via annotations on parameters directly, as shown below:
+</p>
+<p class='bpcode w800'>
+	<ja>@RestMethod</ja>(
+		...
+	)
+	<jk>public</jk> Collection&lt;Pet&gt; getPets(
+			<ja>@Query</ja>(
+				name=<js>"s"</js>,
+				description={
+					<js>"Search."</js>,
+					<js>"Key/value pairs representing column names and search tokens."</js>,
+					<js>"'*' and '?' can be used as meta-characters in string fields."</js>,
+					<js>"'>', '>=', '<', and '<=' can be used as limits on numeric and date fields."</js>,
+					<js>"Date fields can be matched with partial dates (e.g. '2018' to match any date in the year 2018)."</js>
+				},
+				type=<js>"array"</js>,
+				collectionFormat=<js>"csv"</js>,
+				example=<js>"Bill*,birthDate>2000"</js>
+			) 
+			String[] s,
+			<ja>@Query</ja>(
+				name=<js>"v"</js>,
+				description={
+					<js>"View."</js>,
+					<js>"Column names to display."</js>
+				},
+				type=<js>"array"</js>,
+				collectionFormat=<js>"csv"</js>,
+				example=<js>"name,birthDate"</js>
+			) 
+			String[] v
+		) <jk>throws</jk> NotAcceptable {
+		...
+	}
+</p>
+<p>
+	<b>Note:</b>  The <code>type</code> and <code>collectionFormat</code> values above are optional and auto-detected based on the
+	parameter class type if omitted.
 </p>
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Parameters.1.png'> 
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Parameters.2.png'> 
@@ -18831,6 +18946,7 @@
 <p>
 	TODO
 </p>
+<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.3.png'> 
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Responses.1.png'> 
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Responses.2.png'> 
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Responses.3.png'>
@@ -18847,14 +18963,115 @@
 
 <!-- ==================================================================================================== -->
 
-<h4 class='topic todo' onclick='toggle(this)'><a href='#juneau-rest-server.Swagger.Models' id='juneau-rest-server.Swagger.Models'>7.27.9 - Models</a></h4>
+<h4 class='topic new' onclick='toggle(this)'><a href='#juneau-rest-server.Swagger.Models' id='juneau-rest-server.Swagger.Models'>7.27.9 - Models</a></h4>
 <div class='topic'><!-- START: 7.27.9 - juneau-rest-server.Swagger.Models -->
 <p>
-	TODO
+	The {@link org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_useBeanDefs} setting can be used to reduce the size of your
+	generated Swagger JSON files by creating model definitions for beans and referencing those definitions through <code>$ref</code> attributes.
+</p>
+<p>
+	By default, this flag is enabled when extending from {@link org.apache.juneau.rest.BasicRestServlet}:
+</p>
+<p class='bpcode w800'>
+	<jk>public abstract class</jk> BasicRestServlet <jk>extends</jk> RestServlet <jk>implements</jk> BasicRestConfig {
+		
+		<ja>@RestMethod</ja>(name=<jsf>OPTIONS</jsf>, path=<js>"/*"</js>,
+			...
+			flags={
+				<jc>// Use $ref references for bean definitions to reduce duplication in Swagger.</jc>
+				<jsf>JSONSCHEMA_useBeanDefs</jsf>
+			}
+		)
+		<jk>public</jk> Swagger getOptions(RestRequest req) {...}
+</p>
+<p>
+	In the Swagger UI, this causes bean definitions to show up in the Models section at the bottom of the page:
 </p>
+<h5 class='figure'>Models section</h5>
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Models.1.png'> 
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Models.2.png'>
+<h5 class='figure'>Models section with Order bean expanded</h5>
+<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Models.2.png'> 
+<p>
+	In the generated Swagger JSON, embedded schema information for beans will be replaced with references such as the one shown below for the <code>Order</code> bean:
+</p>
+<p class='bpcode w800'>
+	{
+		<jok>"swagger"</jok>: <jov>"2.0"</jov>,
+		<jok>"paths"</jok>: {
+			<jok>"/store/order"</jok>: {
+				<jok>"get"</jok>: {
+					<jok>"operationId"</jok>: <jov>"getOrders"</jov>,
+					<jok>"summary"</jok>: <jov>"Petstore orders"</jov>,
+					<jok>"responses"</jok>: {
+						<jok>"200"</jok>: {
+							<jok>"description"</jok>: <jov>"OK"</jov>,
+							<jok>"schema"</jok>: {
+								<jok>"description"</jok>: <jov>"java.util.Collection&lt;org.apache.juneau.examples.rest.petstore.Order&gt;"</jov>,
+								<jok>"type"</jok>: <jov>"array"</jov>,
+								<jok>"items"</jok>: {
+									<jok>"$ref"</jok>: <jov>"#/definitions/Order"</jov>
+								}
+							},
+							...
+						...
+					...
+				...
+			...
+		},
+		<jok>"definitions"</jok>: {
+			<jok>"Order"</jok>: {
+				<jok>"type"</jok>: <jov>"object"</jov>,
+				<jok>"properties"</jok>: {
+					<jok>"id"</jok>: {
+						<jok>"type"</jok>: <jov>"integer"</jov>,
+						<jok>"format"</jok>: <jov>"int64"</jov>
+					},
+					<jok>"petId": {
+						<jok>"type"</jok>: <jov>"integer"</jov>,
+						<jok>"format"</jok>: <jov>"int64"</jov>
+					},
+					<jok>"shipDate"</jok>: {
+						<jok>"type"</jok>: <jov>"string"</jov>
+					},
+					<jok>"status"</jok>: {
+						<jok>"type"</jok>: <jov>"string"</jov>,
+						<jok>"enum"</jok>: [
+							<jov>"PLACED"</jov>,
+							<jov>"APPROVED"</jov>,
+							<jov>"DELIVERED"</jov>
+						]
+					}
+				},
+				<jok>"description"</jok>: <jov>"org.apache.juneau.examples.rest.petstore.Order"</jov>,
+				<jok>"example"</jok>: {
+					<jok>"id"</jok>: <jov>123</jov>,
+					<jok>"petId"</jok>: <jov>456</jov>,
+					<jok>"shipDate"</jok>: <jov>"2012-12-21"</jov>,
+					<jok>"status"</jok>: <jov>"APPROVED"</jov>
+				}
+			},
+		...
+	}
+</p>
+<p>
+	Note that this does not affect how the information is rendered for that bean in the Swagger UI:
+</p>
+<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Models.3.png'>
 </div><!-- END: 7.27.9 - juneau-rest-server.Swagger.Models -->
+
+<!-- ==================================================================================================== -->
+
+<h4 class='topic new' onclick='toggle(this)'><a href='#juneau-rest-server.Swagger.Stylesheet' id='juneau-rest-server.Swagger.Stylesheet'>7.27.10 - SwaggerUI.css</a></h4>
+<div class='topic'><!-- START: 7.27.10 - juneau-rest-server.Swagger.Stylesheet -->
+<p>
+	The look-and-feel of the Swagger UI is controlled via a single CSS file:  <code>SwaggerUI.css</code>.
+</p>
+<p>
+	In the microservice template, this file is located in the <code>files/htdocs/styles</code> directory.
+	It's a simple straightforward file consisting of less than 350 lines.
+	<br>This file can be modified to change the look-and-feel of your Swagger UI.
+</p>
+</div><!-- END: 7.27.10 - juneau-rest-server.Swagger.Stylesheet -->
 </div><!-- END: 7.27 - juneau-rest-server.Swagger -->
 
 <!-- ==================================================================================================== -->
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/03.Tags.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/03.Tags.html
index bd26f86..4c6566d 100644
--- a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/03.Tags.html
+++ b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/03.Tags.html
@@ -49,7 +49,6 @@
 			}
 		}
 	],
-
 </p>
 <p>
 	The annotation-only approach is shown here:
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/04.Operations.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/04.Operations.html
index 4c6f97b..aabe7f1 100644
--- a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/04.Operations.html
+++ b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/04.Operations.html
@@ -13,12 +13,45 @@
  ***************************************************************************************************************************/
  -->
 
-{todo} Operations
+{new} Operations
 
 <p>
-	TODO
+	<ja>@RestMethod</ja>-annotated methods automatically get rendered as Swagger operations:
 </p>
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.1.png'> 
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.2.png'> 
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.3.png'> 
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.4.png'> 
+<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.1.png'>
+<p>
+	The following shows the annotations defined on the <code>GET /pet</code> operation:
+</p>
+<h5 class='figure'>PetStoreResource.getPets()</h5>
+<p class='bpcode w800'>
+	<ja>@RestMethod</ja>(
+		name=<jsf>GET</jsf>,
+		path=<js>"/pet"</js>,
+		summary=<js>"All pets in the store"</js>,
+		swagger=<ja>@MethodSwagger</ja>(
+			tags=<js>"pet"</js>,
+			...
+		),
+		...
+	)
+	<jk>public</jk> Collection&lt;Pet&gt; getPets() <jk>throws</jk> NotAcceptable {
+		<jk>return</jk> <jsf>store</jsf>.getPets();
+	}
+</p> 
+<p>
+	Methods marked as deprecated will show up as deprecated in the Swagger UI:	
+</p>
+<h5 class='figure'>PetStoreResource.findPetsByTag()</h5>
+<p class='bpcode w800'>	
+	<ja>@RestMethod</ja>(
+		name=<jsf>GET</jsf>,
+		path=<js>"/pet/findByTags"</js>,
+		summary=<js>"Finds Pets by tags"</js>,
+		...
+	)
+	<ja>@Deprecated</ja>
+	<jk>public</jk> Collection&lt;Pet&gt; findPetsByTags(...) {
+		...
+	}
+</p>
+
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/05.Parameters.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/05.Parameters.html
index 61f7c3c..5987b72 100644
--- a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/05.Parameters.html
+++ b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/05.Parameters.html
@@ -16,7 +16,90 @@
 {todo} Parameters
 
 <p>
-	TODO
+	Expanding operations shows you a list of parameters:
+</p>
+<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.2.png'> 
+<p>
+	The <code>parameters</code> annotation is a free-form Simple JSON field that allows you to add arbitrary
+	parameter information to your resource.
+	In this case, we pull from a common field defined in the {@link oajr.converters.Queryable} converter class:
+</p>
+<p class='bpcode w800'>
+	<jk>public class</jk> Queryable <jk>implements</jk> RestConverter {
+	
+		<jk>public static final</jk> String <jsf>SWAGGER_PARAMS</jsf>=<js>""</js>
+			+ <js>"{"</js>
+				+ <js>"in:'query',"</js>
+				+ <js>"name:'s',"</js>
+				+ <js>"description:'"</js>
+					+ <js>"Search.\n"</js>
+					+ <js>"Key/value pairs representing column names and search tokens.\n"</js>
+					+ <js>"\\'*\\' and \\'?\\' can be used as meta-characters in string fields.\n"</js>
+					+ <js>"\\'>\\', \\'>=\\', \\'<\\', and \\'<=\\' can be used as limits on numeric and date fields.\n"</js>
+					+ <js>"Date fields can be matched with partial dates (e.g. \\'2018\\' to match any date in the year 2018)."</js>
+				+ <js>"',"</js>
+				+ <js>"type:'array',"</js>
+				+ <js>"collectionFormat:'csv',"</js>
+				+ <js>"x-examples:{example:'?s=Bill*,birthDate>2000'}"</js>
+			+ <js>"},"</js>
+			+ <js>"{"</js>
+				+ <js>"in:'query',"</js>
+				+ <js>"name:'v',"</js>
+				+ <js>"description:'"</js>
+					+ <js>"View.\n"</js>
+					+ <js>"Column names to display."</js>
+				+ <js>"',"</js>
+				+ <js>"type:'array',"</js>
+				+ <js>"collectionFormat:'csv',"</js>
+				+ <js>"x-examples:{example:'?v=name,birthDate'}"</js>
+			+ <js>"},"</js>
+			...
+		;
+	}
+</p>
+<p>
+	Note that this information could have also been defined in the Swagger JSON for the resource as well.
+</p>
+<p>
+	The Swagger can also be defined via annotations on parameters directly, as shown below:
+</p>
+<p class='bpcode w800'>
+	<ja>@RestMethod</ja>(
+		...
+	)
+	<jk>public</jk> Collection&lt;Pet&gt; getPets(
+			<ja>@Query</ja>(
+				name=<js>"s"</js>,
+				description={
+					<js>"Search."</js>,
+					<js>"Key/value pairs representing column names and search tokens."</js>,
+					<js>"'*' and '?' can be used as meta-characters in string fields."</js>,
+					<js>"'>', '>=', '<', and '<=' can be used as limits on numeric and date fields."</js>,
+					<js>"Date fields can be matched with partial dates (e.g. '2018' to match any date in the year 2018)."</js>
+				},
+				type=<js>"array"</js>,
+				collectionFormat=<js>"csv"</js>,
+				example=<js>"Bill*,birthDate>2000"</js>
+			) 
+			String[] s,
+			<ja>@Query</ja>(
+				name=<js>"v"</js>,
+				description={
+					<js>"View."</js>,
+					<js>"Column names to display."</js>
+				},
+				type=<js>"array"</js>,
+				collectionFormat=<js>"csv"</js>,
+				example=<js>"name,birthDate"</js>
+			) 
+			String[] v
+		) <jk>throws</jk> NotAcceptable {
+		...
+	}
+</p>
+<p>
+	<b>Note:</b>  The <code>type</code> and <code>collectionFormat</code> values above are optional and auto-detected based on the
+	parameter class type if omitted.
 </p>
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Parameters.1.png'> 
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Parameters.2.png'> 
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/07.Responses.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/07.Responses.html
index b1a144b..50c9db2 100644
--- a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/07.Responses.html
+++ b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/07.Responses.html
@@ -18,6 +18,7 @@
 <p>
 	TODO
 </p>
+<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Operations.3.png'> 
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Responses.1.png'> 
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Responses.2.png'> 
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Responses.3.png'> 
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/09.Models.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/09.Models.html
index 245d08e..64e5eb1 100644
--- a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/09.Models.html
+++ b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/09.Models.html
@@ -13,10 +13,97 @@
  ***************************************************************************************************************************/
  -->
 
-{todo} Models
+{new} Models
 
 <p>
-	TODO
+	The {@link oaj.jsonschema.JsonSchemaGenerator#JSONSCHEMA_useBeanDefs} setting can be used to reduce the size of your
+	generated Swagger JSON files by creating model definitions for beans and referencing those definitions through <code>$ref</code> attributes.
 </p>
+<p>
+	By default, this flag is enabled when extending from {@link oajr.BasicRestServlet}:
+</p>
+<p class='bpcode w800'>
+	<jk>public abstract class</jk> BasicRestServlet <jk>extends</jk> RestServlet <jk>implements</jk> BasicRestConfig {
+		
+		<ja>@RestMethod</ja>(name=<jsf>OPTIONS</jsf>, path=<js>"/*"</js>,
+			...
+			flags={
+				<jc>// Use $ref references for bean definitions to reduce duplication in Swagger.</jc>
+				<jsf>JSONSCHEMA_useBeanDefs</jsf>
+			}
+		)
+		<jk>public</jk> Swagger getOptions(RestRequest req) {...}
+</p>
+<p>
+	In the Swagger UI, this causes bean definitions to show up in the Models section at the bottom of the page:
+</p>
+<h5 class='figure'>Models section</h5>
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Models.1.png'> 
+<h5 class='figure'>Models section with Order bean expanded</h5>
 <img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Models.2.png'> 
+<p>
+	In the generated Swagger JSON, embedded schema information for beans will be replaced with references such as the one shown below for the <code>Order</code> bean:
+</p>
+<p class='bpcode w800'>
+	{
+		<jok>"swagger"</jok>: <jov>"2.0"</jov>,
+		<jok>"paths"</jok>: {
+			<jok>"/store/order"</jok>: {
+				<jok>"get"</jok>: {
+					<jok>"operationId"</jok>: <jov>"getOrders"</jov>,
+					<jok>"summary"</jok>: <jov>"Petstore orders"</jov>,
+					<jok>"responses"</jok>: {
+						<jok>"200"</jok>: {
+							<jok>"description"</jok>: <jov>"OK"</jov>,
+							<jok>"schema"</jok>: {
+								<jok>"description"</jok>: <jov>"java.util.Collection&lt;org.apache.juneau.examples.rest.petstore.Order&gt;"</jov>,
+								<jok>"type"</jok>: <jov>"array"</jov>,
+								<jok>"items"</jok>: {
+									<jok>"$ref"</jok>: <jov>"#/definitions/Order"</jov>
+								}
+							},
+							...
+						...
+					...
+				...
+			...
+		},
+		<jok>"definitions"</jok>: {
+			<jok>"Order"</jok>: {
+				<jok>"type"</jok>: <jov>"object"</jov>,
+				<jok>"properties"</jok>: {
+					<jok>"id"</jok>: {
+						<jok>"type"</jok>: <jov>"integer"</jov>,
+						<jok>"format"</jok>: <jov>"int64"</jov>
+					},
+					<jok>"petId": {
+						<jok>"type"</jok>: <jov>"integer"</jov>,
+						<jok>"format"</jok>: <jov>"int64"</jov>
+					},
+					<jok>"shipDate"</jok>: {
+						<jok>"type"</jok>: <jov>"string"</jov>
+					},
+					<jok>"status"</jok>: {
+						<jok>"type"</jok>: <jov>"string"</jov>,
+						<jok>"enum"</jok>: [
+							<jov>"PLACED"</jov>,
+							<jov>"APPROVED"</jov>,
+							<jov>"DELIVERED"</jov>
+						]
+					}
+				},
+				<jok>"description"</jok>: <jov>"org.apache.juneau.examples.rest.petstore.Order"</jov>,
+				<jok>"example"</jok>: {
+					<jok>"id"</jok>: <jov>123</jov>,
+					<jok>"petId"</jok>: <jov>456</jov>,
+					<jok>"shipDate"</jok>: <jov>"2012-12-21"</jov>,
+					<jok>"status"</jok>: <jov>"APPROVED"</jov>
+				}
+			},
+		...
+	}
+</p>
+<p>
+	Note that this does not affect how the information is rendered for that bean in the Swagger UI:
+</p>
+<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Models.3.png'> 
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/07.Responses.html b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/10.Stylesheet.html
similarity index 73%
copy from juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/07.Responses.html
copy to juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/10.Stylesheet.html
index b1a144b..931d102 100644
--- a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/07.Responses.html
+++ b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/10.Stylesheet.html
@@ -13,11 +13,13 @@
  ***************************************************************************************************************************/
  -->
 
-{todo} Responses
+{new} SwaggerUI.css
 
 <p>
-	TODO
+	The look-and-feel of the Swagger UI is controlled via a single CSS file:  <code>SwaggerUI.css</code>.
+</p>
+<p>
+	In the microservice template, this file is located in the <code>files/htdocs/styles</code> directory.
+	It's a simple straightforward file consisting of less than 350 lines.
+	<br>This file can be modified to change the look-and-feel of your Swagger UI.
 </p>
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Responses.1.png'> 
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Responses.2.png'> 
-<img class='bordered' style='width:900px' src='doc-files/juneau-rest-server.Swagger.Responses.3.png'> 
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/doc-files/juneau-rest-server.Swagger.Models.3.png b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/doc-files/juneau-rest-server.Swagger.Models.3.png
new file mode 100644
index 0000000..01df721
Binary files /dev/null and b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/doc-files/juneau-rest-server.Swagger.Models.3.png differ
diff --git a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/doc-files/juneau-rest-server.Swagger.Operations.2.png b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/doc-files/juneau-rest-server.Swagger.Operations.2.png
index 014b981..9cbc361 100644
Binary files a/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/doc-files/juneau-rest-server.Swagger.Operations.2.png and b/juneau-doc/src/main/resources/Topics/07.juneau-rest-server/27.Swagger/doc-files/juneau-rest-server.Swagger.Operations.2.png differ
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
index 74c38d3..e6d20d5 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
@@ -29,7 +29,6 @@ import org.apache.juneau.http.annotation.Contact;
 import org.apache.juneau.http.annotation.Items;
 import org.apache.juneau.http.annotation.License;
 import org.apache.juneau.http.annotation.Tag;
-import org.apache.juneau.httppart.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
@@ -360,7 +359,10 @@ final class SwaggerGenerator {
 					if ((in == BODY || in == PATH) && ! param.containsKeyNotEmpty("required"))
 						param.put("required", true);
 
-					addXExamples(sm, param, in.toString(), mp.getType());
+					if (in == BODY)
+						addBodyExamples(sm, param, false, mp.getType());
+					else
+						addParamExample(sm, param, in, mp.getType());
 				}
 			}
 
@@ -396,7 +398,7 @@ final class SwaggerGenerator {
 				ObjectMap om = responses.getObjectMap("200", true);
 				if (! om.containsKey("schema"))
 					om.appendSkipEmpty("schema", getSchema(om.getObjectMap("schema", true), m.getGenericReturnType()));
-				addXExamples(sm, om, "ok", m.getGenericReturnType());
+				addBodyExamples(sm, om, true, m.getGenericReturnType());
 			}
 
 			// Finally, look for @ResponseHeader parameters defined on method.
@@ -719,7 +721,7 @@ final class SwaggerGenerator {
 		return om;
 	}
 
-	private void addXExamples(RestJavaMethod sm, ObjectMap piri, String in, Type type) throws Exception {
+	private void addBodyExamples(RestJavaMethod sm, ObjectMap piri, boolean response, Type type) throws Exception {
 
 		String sex = piri.getString("x-example");
 
@@ -732,8 +734,6 @@ final class SwaggerGenerator {
 		if (isEmpty(sex))
 			return;
 
-		boolean isOk = "ok".equals(in), isBody = "body".equals(in);
-
 		Object example = null;
 		if (isJson(sex)) {
 			example = JsonParser.DEFAULT.parse(sex, type);
@@ -744,47 +744,62 @@ final class SwaggerGenerator {
 			}
 		}
 
-		String examplesKey = isOk ? "examples" : "x-examples";  // Parameters don't have an examples attribute.
+		String examplesKey = response ? "examples" : "x-examples";  // Parameters don't have an examples attribute.
 
 		ObjectMap examples = piri.getObjectMap(examplesKey);
 		if (examples == null)
 			examples = new ObjectMap();
 
-		if (isOk || isBody) {
-			List<MediaType> mediaTypes = isOk ? sm.getSerializers().getSupportedMediaTypes() : sm.getParsers().getSupportedMediaTypes();
-
-			for (MediaType mt : mediaTypes) {
-				if (mt != MediaType.HTML) {
-					Serializer s2 = sm.getSerializers().getSerializer(mt);
-					if (s2 != null) {
-						SerializerSessionArgs args = new SerializerSessionArgs(null, req.getJavaMethod(), req.getLocale(), null, mt, null, req.isDebug() ? true : null, req.getUriContext(), true);
-						try {
-							String eVal = s2.createSession(args).serializeToString(example);
-							examples.put(s2.getPrimaryMediaType().toString(), eVal);
-						} catch (Exception e) {
-							System.err.println("Could not serialize to media type ["+mt+"]: " + e.getLocalizedMessage());  // NOT DEBUG
-						}
+		List<MediaType> mediaTypes = response ? sm.getSerializers().getSupportedMediaTypes() : sm.getParsers().getSupportedMediaTypes();
+
+		for (MediaType mt : mediaTypes) {
+			if (mt != MediaType.HTML) {
+				Serializer s2 = sm.getSerializers().getSerializer(mt);
+				if (s2 != null) {
+					SerializerSessionArgs args = new SerializerSessionArgs(null, req.getJavaMethod(), req.getLocale(), null, mt, null, req.isDebug() ? true : null, req.getUriContext(), true);
+					try {
+						String eVal = s2.createSession(args).serializeToString(example);
+						examples.put(s2.getPrimaryMediaType().toString(), eVal);
+					} catch (Exception e) {
+						System.err.println("Could not serialize to media type ["+mt+"]: " + e.getLocalizedMessage());  // NOT DEBUG
 					}
 				}
 			}
-		} else {
-			String paramName = piri.getString("name");
-			String s = sm.partSerializer.createPartSession(req.getSerializerSessionArgs()).serialize(HttpPartType.valueOf(in.toUpperCase()), null, example);
-			if ("query".equals(in))
-				s = "?" + urlEncodeLax(paramName) + "=" + urlEncodeLax(s);
-			else if ("formData".equals(in))
-				s = paramName + "=" + s;
-			else if ("header".equals(in))
-				s = paramName + ": " + s;
-			else if ("path".equals(in))
-				s = sm.getPathPattern().replace("{"+paramName+"}", urlEncodeLax(s));
- 			examples.put("example", s);
 		}
 
 		if (! examples.isEmpty())
 			piri.put(examplesKey, examples);
 	}
 
+	private void addParamExample(RestJavaMethod sm, ObjectMap piri, RestParamType in, Type type) throws Exception {
+
+		String s = piri.getString("x-example");
+
+		if (isEmpty(s))
+			return;
+
+		ObjectMap examples = piri.getObjectMap("x-examples");
+		if (examples == null)
+			examples = new ObjectMap();
+
+		String paramName = piri.getString("name");
+
+		if (in == QUERY)
+			s = "?" + urlEncodeLax(paramName) + "=" + urlEncodeLax(s);
+		else if (in == FORM_DATA)
+			s = paramName + "=" + s;
+		else if (in == HEADER)
+			s = paramName + ": " + s;
+		else if (in == PATH)
+			s = sm.getPathPattern().replace("{"+paramName+"}", urlEncodeLax(s));
+
+		examples.put("example", s);
+
+		if (! examples.isEmpty())
+			piri.put("x-examples", examples);
+	}
+
+
 	private ObjectMap resolveRef(ObjectMap m) {
 		if (m == null)
 			return null;
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Queryable.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Queryable.java
index b3cbfae..d8d7e63 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Queryable.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/converters/Queryable.java
@@ -85,7 +85,8 @@ public final class Queryable implements RestConverter {
 				+ "\\'>\\', \\'>=\\', \\'<\\', and \\'<=\\' can be used as limits on numeric and date fields.\n"
 				+ "Date fields can be matched with partial dates (e.g. \\'2018\\' to match any date in the year 2018)."
 			+ "',"
-			+ "schema:{type:'array',collectionFormat:'csv'},"
+			+ "type:'array',"
+			+ "collectionFormat:'csv',"
 			+ "x-examples:{example:'?s=Bill*,birthDate>2000'}"
 		+ "},"
 		+ "{"
@@ -94,8 +95,9 @@ public final class Queryable implements RestConverter {
 			+ "description:'"
 				+ "View.\n"
 				+ "Column names to display."
-			+"',"
-			+ "schema:{type:'array',collectionFormat:'csv'},"
+			+ "',"
+			+ "type:'array',"
+			+ "collectionFormat:'csv',"
 			+ "x-examples:{example:'?v=name,birthDate'}"
 		+ "},"
 		+ "{"
@@ -107,7 +109,8 @@ public final class Queryable implements RestConverter {
 				+ "Column names can be suffixed with \\'+\\' or \\'-\\' to indicate ascending or descending order.\n"
 				+ "The default is ascending order."
 			+ "',"
-			+ "schema:{type:'array',collectionFormat:'csv'},"
+			+ "type:'array',"
+			+ "collectionFormat:'csv',"
 			+ "x-examples:{example:'?o=name,birthDate-'}"
 		+ "},"
 		+ "{"
@@ -117,7 +120,7 @@ public final class Queryable implements RestConverter {
 				+ "Case-insensitive.\n"
 				+ "Flag for case-insensitive matching on the search parameters."
 			+ "',"
-			+ "schema:{type:'boolean'},"
+			+ "type:'boolean',"
 			+ "x-examples:{example:'?i=true'}"
 		+ "},"
 		+ "{"
@@ -127,10 +130,10 @@ public final class Queryable implements RestConverter {
 				+ "Position.\n"
 				+ "Only return rows starting at the specified index position (zero-indexed).\n"
 				+ "Default is 0"
-			+"',"
-			+ "schema:{type:'integer'},"
+			+ "',"
+			+ "type:'integer',"
 			+ "x-examples:{example:'?p=100'}"
-			+ "},"
+		+ "},"
 		+ "{"
 			+ "in:'query',"
 			+ "name:'l',"
@@ -138,8 +141,8 @@ public final class Queryable implements RestConverter {
 				+ "Limit.\n"
 				+ "Only return the specified number of rows.\n"
 				+ "Default is 0 (meaning return all rows)."
-			+"',"
-			+ "schema:{type:'integer'},"
+			+ "',"
+			+ "type:'integer',"
 			+ "x-examples:{example:'?l=100'}"
 		+ "}"
 	;
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/PathAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/PathAnnotationTest.java
index b4d3439..8da6f13 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/PathAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/PathAnnotationTest.java
@@ -296,7 +296,7 @@ public class PathAnnotationTest {
 			description={"a","b"},
 			type="string",
 			_enum="a,b",
-			example="'a'"
+			example="a"
 		)
 		public static class SA01 {
 			public SA01(String x) {}
@@ -338,7 +338,7 @@ public class PathAnnotationTest {
 			description={"a","b"},
 			type="string",
 			_enum="a,b",
-			example="'a'"
+			example="a"
 		)
 		public static class SA03 {
 			public SA03(String x) {}
@@ -381,8 +381,8 @@ public class PathAnnotationTest {
 		assertEquals("a\nb", x.getDescription());
 		assertEquals("string", x.getType());
 		assertObjectEquals("['a','b']", x.getEnum());
-		assertEquals("'a'", x.getExample());
-		assertObjectEquals("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'\\'a\\'','x-examples':{example:'/basic/sa01'}}", x);
+		assertEquals("a", x.getExample());
+		assertObjectEquals("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/basic/a'}}", x);
 	}
 	@Test
 	public void sa02_Path_onPojo_api() throws Exception {
@@ -392,7 +392,7 @@ public class PathAnnotationTest {
 		assertEquals("string", x.getType());
 		assertObjectEquals("['a','b']", x.getEnum());
 		assertEquals("a", x.getExample());
-		assertObjectEquals("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/api/sa02'}}", x);
+		assertObjectEquals("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/api/a'}}", x);
 	}
 	@Test
 	public void sa03_Path_onPojo_mixed() throws Exception {
@@ -401,8 +401,8 @@ public class PathAnnotationTest {
 		assertEquals("a\nb", x.getDescription());
 		assertEquals("string", x.getType());
 		assertObjectEquals("['a','b']", x.getEnum());
-		assertEquals("'a'", x.getExample());
-		assertObjectEquals("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'\\'a\\'','x-examples':{example:'/mixed/sa03'}}", x);
+		assertEquals("a", x.getExample());
+		assertObjectEquals("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/mixed/a'}}", x);
 	}
 	@Test
 	public void sa04_Path_onPojo_value() throws Exception {