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/04/16 21:08:59 UTC

[juneau] branch master updated: Improvements to PetStore.

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 a7b6e65  Improvements to PetStore.
a7b6e65 is described below

commit a7b6e65aed32cb738bed9868b120fa88624f8736
Author: JamesBognar <ja...@apache.org>
AuthorDate: Mon Apr 16 17:08:50 2018 -0400

    Improvements to PetStore.
---
 .../java/org/apache/juneau/PropertyStoreTest.java  |   2 +-
 .../juneau/a/rttests/RoundTripBeanMapsTest.java    |   2 +-
 .../main/java/org/apache/juneau/BeanContext.java   |  30 +++--
 .../main/java/org/apache/juneau/utils/AList.java   |  12 +-
 .../main/java/org/apache/juneau/utils/ASet.java    |  10 ++
 .../java/org/apache/juneau/utils/IdGenerator.java  |   7 +
 .../java/org/apache/juneau/utils/IdGenerators.java |  14 +-
 juneau-doc/src/main/javadoc/overview.html          |   3 +
 juneau-examples/juneau-examples-rest/examples.cfg  |   5 +
 .../juneau/examples/rest/RequestEchoResource.java  |   3 +-
 .../examples/rest/SystemPropertiesResource.java    |   5 +-
 .../petstore/{Tag.java => AddPetMenuItem.java}     |  70 ++++++----
 .../rest/petstore/{Tag.java => CreatePet.java}     |  55 +++++---
 .../{PetStatus.java => InvalidSpecies.java}        |  18 ++-
 .../juneau/examples/rest/petstore/Order.java       |   5 +-
 .../juneau/examples/rest/petstore/OrderStatus.java |  17 +++
 .../apache/juneau/examples/rest/petstore/Pet.java  |  29 +++--
 .../juneau/examples/rest/petstore/PetStatus.java   |  19 ++-
 .../juneau/examples/rest/petstore/PetStore.java    | 143 ++++++++++++++++-----
 .../examples/rest/petstore/PetStoreResource.java   | 102 ++++++++++-----
 .../rest/petstore/{Category.java => Species.java}  |  28 +++-
 .../apache/juneau/examples/rest/petstore/Tag.java  |  15 +++
 .../apache/juneau/examples/rest/petstore/User.java |  23 +---
 .../petstore/{Category.java => UserStatus.java}    |  43 +++----
 .../juneau/examples/rest/petstore/Orders.json}     |  11 +-
 .../juneau/examples/rest/petstore/Pets.json}       |  17 ++-
 .../juneau/examples/rest/petstore/Species.json}    |  14 +-
 .../juneau/examples/rest/petstore/Tags.json}       |  15 ++-
 .../juneau/examples/rest/petstore/Users.json}      |  11 +-
 .../juneau/examples/rest/petstore/htdocs/bird.png  | Bin 0 -> 1925 bytes
 .../juneau/examples/rest/petstore/htdocs/cat.png   | Bin 0 -> 1878 bytes
 .../juneau/examples/rest/petstore/htdocs/dog.png   | Bin 0 -> 1980 bytes
 .../juneau/examples/rest/petstore/htdocs/fish.png  | Bin 0 -> 2198 bytes
 .../juneau/examples/rest/petstore/htdocs/mouse.png | Bin 0 -> 1551 bytes
 .../examples/rest/petstore/htdocs/rabbit.png       | Bin 0 -> 1603 bytes
 .../juneau/examples/rest/petstore/htdocs/snake.png | Bin 0 -> 1824 bytes
 .../microservice/resources/DirectoryResource.java  |   3 +-
 .../microservice/resources/LogsResource.java       |   3 +-
 .../apache/juneau/rest/test/HtmlDocResource.java   |   3 +-
 .../juneau/rest/test/ThirdPartyProxyTest.java      |   4 +-
 .../org/apache/juneau/rest/BasicRestConfig.java    |   3 +-
 .../org/apache/juneau/rest/HtmlDocBuilder.java     |   4 +-
 .../org/apache/juneau/rest/annotation/HtmlDoc.java |   2 +-
 43 files changed, 523 insertions(+), 227 deletions(-)

diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PropertyStoreTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PropertyStoreTest.java
index 3c4c5c7..c261d45 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PropertyStoreTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/PropertyStoreTest.java
@@ -641,7 +641,7 @@ public class PropertyStoreTest {
 		testError(b, "A.f1.lc/add", "java.lang.Integer", "Cannot add value 'java.lang.Integer' (String) to property 'f1.lc' (List<Class>).  Value 'java.lang.Integer' (String) cannot be converted to a Class.");
 
 		b.clear();
-		b.set("A.f1.lc/add", new AList<Class<?>>().appendAll(Integer.class, String.class));  
+		b.set("A.f1.lc/add", AList.<Class<?>>create(Integer.class, String.class));  
 		b.set("A.f1.lc/add", new AList<Class<?>>().appendAll(Map.class));
 		b.addTo("A.f1.lc", new AList<Class<?>>().appendAll(List.class));
 		assertObjectEquals("{A:{'f1.lc':['java.util.List','java.util.Map','java.lang.Integer','java.lang.String']}}", b.build());
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
index 8b07deb..50eb915 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
@@ -93,7 +93,7 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
 	//====================================================================================================
 	@Test
 	public void testImplListClasses() throws Exception {
-		List<IBean> l = new AList<IBean>().append(new CBean());
+		List<IBean> l = AList.<IBean>create(new CBean());
 
 		l.get(0).setF1("bar");
 		l = roundTrip(l, List.class, IBean.class);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
index 147425c..f8cd254 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -1468,8 +1468,8 @@ public class BeanContext extends Context {
 	 * 
 	 * <h5 class='section'>Property:</h5>
 	 * <ul>
-	 * 	<li><b>Name:</b>  <js>"BeanContext.pojoSwaps.lc"</js>
-	 * 	<li><b>Data type:</b>  <code>List&lt;Class&gt;</code>
+	 * 	<li><b>Name:</b>  <js>"BeanContext.pojoSwaps.lo"</js>
+	 * 	<li><b>Data type:</b>  <code>List&lt;Object&gt;</code>
 	 * 	<li><b>Default:</b>  empty list
 	 * 	<li><b>Session-overridable:</b>  <jk>false</jk>
 	 * 	<li><b>Annotations:</b> 
@@ -1503,6 +1503,7 @@ public class BeanContext extends Context {
 	 * Values can consist of any of the following types:
 	 * <ul>
 	 * 	<li>Any subclass of {@link PojoSwap}.
+	 * 	<li>Any instance of {@link PojoSwap}.
 	 * 	<li>Any surrogate class.  A shortcut for defining a {@link SurrogateSwap}.
 	 * 	<li>Any array or collection of the objects above.
 	 * </ul>
@@ -1565,17 +1566,17 @@ public class BeanContext extends Context {
 	 * 	<li class='link'><a class="doclink" href="../../../overview-summary.html#juneau-marshall.SurrogateClasses">Overview &gt; juneau-marshall &gt; Surrogate Classes</a>
 	 * </ul>
 	 */
-	public static final String BEAN_pojoSwaps = PREFIX + "pojoSwaps.lc";
+	public static final String BEAN_pojoSwaps = PREFIX + "pojoSwaps.lo";
 
 	/**
 	 * Configuration property:  Add to POJO swap classes.
 	 */
-	public static final String BEAN_pojoSwaps_add = PREFIX + "pojoSwaps.lc/add";
+	public static final String BEAN_pojoSwaps_add = PREFIX + "pojoSwaps.lo/add";
 
 	/**
 	 * Configuration property:  Remove from POJO swap classes.
 	 */
-	public static final String BEAN_pojoSwaps_remove = PREFIX + "pojoSwaps.lc/remove";
+	public static final String BEAN_pojoSwaps_remove = PREFIX + "pojoSwaps.lo/remove";
 
 	/**
 	 * Configuration property:  Bean property namer.
@@ -2000,13 +2001,18 @@ public class BeanContext extends Context {
 		beanFilters = lbf.toArray(new BeanFilter[0]);
 
 		LinkedList<PojoSwap<?,?>> lpf = new LinkedList<>();
-		for (Class<?> c : getClassListProperty(BEAN_pojoSwaps)) {
-			if (isParentClass(PojoSwap.class, c))
-				lpf.add(newInstance(PojoSwap.class, c));
-			else if (isParentClass(Surrogate.class, c))
-				lpf.addAll(SurrogateSwap.findPojoSwaps(c));
-			else
-				throw new FormattedRuntimeException("Invalid class {0} specified in BeanContext.pojoSwaps property.  Must be a subclass of PojoSwap or Surrogate.", c);
+		for (Object o : getListProperty(BEAN_pojoSwaps, Object.class)) {
+			if (o instanceof Class) {
+				Class<?> c = (Class<?>)o;
+				if (isParentClass(PojoSwap.class, c))
+					lpf.add(newInstance(PojoSwap.class, c));
+				else if (isParentClass(Surrogate.class, c))
+					lpf.addAll(SurrogateSwap.findPojoSwaps(c));
+				else
+					throw new FormattedRuntimeException("Invalid class {0} specified in BeanContext.pojoSwaps property.  Must be a subclass of PojoSwap or Surrogate.", c);
+			} else if (o instanceof PojoSwap) {
+				lpf.add((PojoSwap)o);
+			}
 		}
 		pojoSwaps = lpf.toArray(new PojoSwap[lpf.size()]);
 		
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AList.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AList.java
index 45aa3fc..b391bf5 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AList.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AList.java
@@ -28,7 +28,17 @@ import java.util.*;
  */
 @SuppressWarnings({"serial","unchecked"})
 public final class AList<T> extends LinkedList<T> {
-
+	
+	/**
+	 * Convenience method for creating a list of objects.
+	 * 
+	 * @param t The initial values.
+	 * @return A new list.
+	 */
+	public static <T> AList<T> create(T...t) {
+		return new AList<T>().appendAll(t);
+	}
+	
 	/**
 	 * Adds an entry to this list.
 	 * 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ASet.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ASet.java
index f606573..36ed4e6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ASet.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ASet.java
@@ -30,6 +30,16 @@ import java.util.*;
 public final class ASet<T> extends LinkedHashSet<T> {
 
 	/**
+	 * Convenience method for creating a list of objects.
+	 * 
+	 * @param t The initial values.
+	 * @return A new list.
+	 */
+	public static <T> ASet<T> create(T...t) {
+		return new ASet<T>().appendAll(t);
+	}
+
+	/**
 	 * Adds an entry to this set.
 	 * 
 	 * @param t The entry to add to this set.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdGenerator.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdGenerator.java
index d654d51..4a755d2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdGenerator.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdGenerator.java
@@ -25,4 +25,11 @@ public interface IdGenerator<K> {
 	 * @return The next available ID.
 	 */
 	K next();
+	
+	/**
+	 * Sets a lower bound for this generator.
+	 * 
+	 * @param k The lower bound.
+	 */
+	void lb(K k);
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdGenerators.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdGenerators.java
index 67417fd..15db513 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdGenerators.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/IdGenerators.java
@@ -30,9 +30,14 @@ public class IdGenerators {
 			private final AtomicInteger i = new AtomicInteger(initValue);
 			
 			@Override /* IdGenerator */
-			public Integer next() {
+			public synchronized Integer next() {
 				return i.getAndIncrement();
 			}
+
+			@Override
+			public synchronized void lb(Integer k) {
+				i.set(Math.max(k + 1, i.get()));
+			}
 		};
 	}
 
@@ -56,9 +61,14 @@ public class IdGenerators {
 			private final AtomicLong l = new AtomicLong(initValue);
 			
 			@Override /* IdGenerator */
-			public Long next() {
+			public synchronized Long next() {
 				return l.getAndIncrement();
 			}
+
+			@Override
+			public synchronized void lb(Long k) {
+				l.set(Math.max(k + 1, l.get()));
+			}
 		};
 	}
 
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index edd958a..8b37669 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -21380,6 +21380,9 @@
 				</p>
 				<br>It should be noted that you cannot use the <code>$F</code> variable to retrieve localized versions of files (since you're not within
 				the scope of a client request.
+			<li>
+				The {@link org.apache.juneau.rest.annotation.RestResource#nowrap()} annotation has been changed to a string with a default value of <js>"true"</js>.
+				<br>Having it as a string allows us to differentiate between a set and unset value so that it can be overridden in subclasses.
 		</ul>
 	
 		<ul class='spaced-list'>
diff --git a/juneau-examples/juneau-examples-rest/examples.cfg b/juneau-examples/juneau-examples-rest/examples.cfg
index 23d9f06..e592f7b 100755
--- a/juneau-examples/juneau-examples-rest/examples.cfg
+++ b/juneau-examples/juneau-examples-rest/examples.cfg
@@ -196,3 +196,8 @@ gitHub = https://github.com/apache/juneau/blob/master/juneau-examples/juneau-exa
 [TempDirResource]
 dir = $S{java.io.tmpdir}
 
+#=======================================================================================================================
+# PetStoreResource properties
+#=======================================================================================================================
+[PetStore]
+headerImage = <a href='http://swagger.io'><img src='$U{servlet:/htdocs/cat.png}' style='position:absolute;top:5;right:5;background-color:transparent;height:30px'/></a>
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
index d325cbf..800fa13 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
@@ -48,7 +48,8 @@ import org.apache.juneau.transforms.*;
 			"	<p>Also shows how to specify serializer properties, filters, and swaps at the servlet level to control how POJOs are serialized.</p>",
 			"	<p>Also provides an example of how to use the Traversable and Queryable APIs.</p>",
 			"</div>"
-		}
+		},
+		nowrap="false"
 	),
 	properties={
 		@Property(name=SERIALIZER_maxDepth, value="5"),
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
index 591d042..369057b 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/SystemPropertiesResource.java
@@ -67,7 +67,10 @@ import org.apache.juneau.rest.widget.*;
 		style={
 			"aside {display:table-caption} ",
 			"aside p {margin: 0px 20px;}"
-		}
+		},
+		
+		// Allow text wrapping in cells.
+		nowrap="false"
 	),
 		
 	// Properties that get applied to all serializers and parsers.
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/AddPetMenuItem.java
similarity index 52%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/AddPetMenuItem.java
index 8c580b1..a493027 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/AddPetMenuItem.java
@@ -12,35 +12,55 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest.petstore;
 
-import org.apache.juneau.annotation.*;
+import static org.apache.juneau.dto.html5.HtmlBuilder.*;
+import static org.apache.juneau.http.HttpMethodName.*;
 
-@Bean(typeName="Tag", fluentSetters=true)
-public class Tag {
-	private long id;
-	private String name;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.widget.*;
 
-	public long getId() {
-		return id;
-	}
-
-	public Tag id(long id) {
-		this.id = id;
-		return this;
-	}
+/**
+ * Menu item for adding a Pet.
+ */
+public class AddPetMenuItem extends MenuItemWidget {
 
-	public String getName() {
-		return name;
+	@Override /* MenuItemWidget */
+	public String getLabel(RestRequest req) throws Exception {
+		return "add";
 	}
 
-	public Tag name(String name) {
-		this.name = name;
-		return this;
-	}
-	
-	@Example
-	public static Tag example() {
-		return new Tag()
-			.id(123)
-			.name("MyTag");
+	@Override /* Widget */
+	public Object getContent(RestRequest req) throws Exception {
+		return div(
+			form().id("form").action("servlet:/").method(POST).children(
+				table(
+					tr(
+						th("Name:"),
+						td(input().name("name").type("text")),
+						td(new Tooltip("(?)", "The name of the pet.", br(), "e.g. 'Fluffy'")) 
+					),
+					tr(
+						th("Species:"),
+						td(
+							select().name("kind").children(
+								option("CAT"), option("DOG"), option("BIRD"), option("FISH"), option("MOUSE"), option("RABBIT"), option("SNAKE")
+							)
+						),
+						td(new Tooltip("(?)", "The kind of animal.")) 
+					),
+					tr(
+						th("Price:"),
+						td(input().name("price").type("number").placeholder("1.0").step("0.01").min(1).max(100)),
+						td(new Tooltip("(?)", "The price to charge for this pet.")) 
+					),
+					tr(
+						td().colspan(2).style("text-align:right").children(
+							button("reset", "Reset"),
+							button("button","Cancel").onclick("window.location.href='/'"),
+							button("submit", "Submit")
+						)
+					)
+				).style("white-space:nowrap")
+			)
+		);
 	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/CreatePet.java
similarity index 66%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/CreatePet.java
index 8c580b1..2e91036 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/CreatePet.java
@@ -12,35 +12,52 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest.petstore;
 
+import java.util.*;
+
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.utils.*;
 
-@Bean(typeName="Tag", fluentSetters=true)
-public class Tag {
-	private long id;
-	private String name;
+/**
+ * Bean for creating {@link Pet} objects.
+ */
+public class CreatePet {
 
-	public long getId() {
-		return id;
+	private final String name;
+	private final float price;
+	private final String species;
+	private final List<String> tags;
+	private final PetStatus status;
+	
+	@BeanConstructor(properties="name,price,species,tags,status")
+	public CreatePet(String name, float price, String species, List<String> tags, PetStatus status) {
+		this.name = name;
+		this.price = price;
+		this.species = species;
+		this.tags = tags;
+		this.status = status;
 	}
-
-	public Tag id(long id) {
-		this.id = id;
-		return this;
+	
+	public static CreatePet example() {
+		return new CreatePet("Doggie", 9.99f, "doc", AList.create("friendly","cute"), PetStatus.AVAILABLE);
 	}
 
 	public String getName() {
 		return name;
 	}
 
-	public Tag name(String name) {
-		this.name = name;
-		return this;
+	public float getPrice() {
+		return price;
 	}
-	
-	@Example
-	public static Tag example() {
-		return new Tag()
-			.id(123)
-			.name("MyTag");
+
+	public String getSpecies() {
+		return species;
+	}
+
+	public List<String> getTags() {
+		return tags;
+	}
+
+	public PetStatus getStatus() {
+		return status;
 	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
similarity index 80%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
index 2d2826e..d856988 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/InvalidSpecies.java
@@ -12,6 +12,20 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest.petstore;
 
-public enum PetStatus {
-	AVAILABLE, PENDING, SOLD;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.exception.*;
+
+/**
+ * Exception thrown when an invalid species is looked up.
+ */
+@SuppressWarnings("serial")
+@ResponseInfo(description="Invalid species provided")
+public class InvalidSpecies extends BadRequest {
+
+	/**
+	 * Constructor.
+	 */
+	public InvalidSpecies() {
+		super("Invalid species provided.");
+	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
index 1ecaf39..43139e0 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Order.java
@@ -13,8 +13,9 @@
 package org.apache.juneau.examples.rest.petstore;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.html.annotation.*;
 
-@Bean(fluentSetters=true)
+@Bean(fluentSetters=true, properties="id,petId,quantity,shipDate,status")
 @Example("{id:123,petId:456,quantity:100,shipDate:'2012-12-21',status:'APPROVED'}")
 public class Order {
 	private long id, petId;
@@ -26,11 +27,13 @@ public class Order {
 		return id;
 	}
 	
+	@Html(link="servlet:/store/order/{id}") 
 	public Order id(long id) {
 		this.id = id;
 		return this;
 	}
 	
+	@Html(link="servlet:/pet/{id}")
 	public long getPetId() {
 		return petId;
 	}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
index f8084ab..1da4834 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
@@ -12,6 +12,23 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest.petstore;
 
+import org.apache.juneau.html.*;
+import org.apache.juneau.html.annotation.*;
+import org.apache.juneau.serializer.*;
+
+@Html(render=OrderStatus.OrderStatusRender.class)
 public enum OrderStatus {
 	PLACED, APPROVED, DELIVERED;
+	
+	public static class OrderStatusRender extends HtmlRender<OrderStatus> {
+		@Override /* HtmlRender */
+		public String getStyle(SerializerSession session, OrderStatus value) {
+			switch(value) {
+				case PLACED:  return "background-color:#5cb85c;text-align:center;vertical-align:middle;"; 
+				case APPROVED:  return "background-color:#f0ad4e;text-align:center;vertical-align:middle;"; 
+				case DELIVERED:  return "background-color:#777;text-align:center;vertical-align:middle;"; 
+				default:  return "background-color:#888;text-align:center;vertical-align:middle;"; 
+			}
+		}
+	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Pet.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Pet.java
index 4817903..240a2a7 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Pet.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Pet.java
@@ -15,15 +15,17 @@ package org.apache.juneau.examples.rest.petstore;
 import java.util.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.html.annotation.*;
 import org.apache.juneau.xml.annotation.*;
 
 /**
- * 
+ * Pet bean.
  */
-@Bean(typeName="Pet", fluentSetters=true)
+@Bean(typeName="Pet", fluentSetters=true, properties="id,species,name,photoUrls,tags,price,status")
 public class Pet {
 	private long id;
-	private Category category;
+	private float price;
+	private Species species;
 	private String name;
 	private List<String> photoUrls;
 	private List<Tag> tags;
@@ -34,12 +36,13 @@ public class Pet {
 	public static Pet example() {
 		return new Pet()
 			.id(123)
-			.category(Category.example())
+			.species(Species.example())
 			.name("Doggie")
 			.tags(Tag.example())
 			.status(PetStatus.AVAILABLE);
 	}
 
+	@Html(link="servlet:/pet/{id}")
 	public long getId() {
 		return id;
 	}
@@ -49,12 +52,12 @@ public class Pet {
 		return this;
 	}
 	
-	public Category getCategory() {
-		return category;
+	public Species getSpecies() {
+		return species;
 	}
 	
-	public Pet category(Category category) {
-		this.category = category;
+	public Pet species(Species species) {
+		this.species = species;
 		return this;
 	}
 	
@@ -115,4 +118,14 @@ public class Pet {
 					return true;
 		return false;
 	}
+	
+	@BeanProperty(format="$%.2f")  // Renders price in dollars.
+	public float getPrice() {
+		return price;
+	}
+	
+	public Pet price(float price) {
+		this.price = price;
+		return this;
+	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java
index 2d2826e..212f927 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStatus.java
@@ -12,6 +12,23 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest.petstore;
 
+import org.apache.juneau.html.*;
+import org.apache.juneau.html.annotation.*;
+import org.apache.juneau.serializer.*;
+
+@Html(render=PetStatus.PetStatusRender.class)
 public enum PetStatus {
-	AVAILABLE, PENDING, SOLD;
+	AVAILABLE, PENDING, SOLD, UNKNOWN;
+	
+	public static class PetStatusRender extends HtmlRender<PetStatus> {
+		@Override /* HtmlRender */
+		public String getStyle(SerializerSession session, PetStatus value) {
+			switch(value) {
+				case AVAILABLE:  return "background-color:#5cb85c;text-align:center;vertical-align:middle;"; 
+				case PENDING:  return "background-color:#f0ad4e;text-align:center;vertical-align:middle;"; 
+				case SOLD:  return "background-color:#888;text-align:center;vertical-align:middle;"; 
+				default:  return "background-color:#777;text-align:center;vertical-align:middle;"; 
+			}
+		}
+	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java
index 958bca9..c7bae5f 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStore.java
@@ -12,8 +12,13 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest.petstore;
 
+import java.io.*;
 import java.util.*;
+import java.util.concurrent.*;
 
+import org.apache.juneau.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.transform.*;
 import org.apache.juneau.utils.*;
 
 /**
@@ -21,13 +26,42 @@ import org.apache.juneau.utils.*;
  */
 public class PetStore {
 
-	// Our databases.
-	private IdMap<Long,Pet> petDb = IdMap.createLongMap(Pet.class);
-	private IdMap<Long,Category> categoryDb = IdMap.createLongMap(Category.class);
-	private IdMap<Long,Order> orderDb = IdMap.createLongMap(Order.class);
-	private IdMap<Long,Tag> tagDb = IdMap.createLongMap(Tag.class);
-	private IdMap<Long,User> userDb = IdMap.createLongMap(User.class);
+	// Our "databases".
+	IdMap<Long,Pet> petDb = IdMap.createLongMap(Pet.class);
+	IdMap<Long,Species> speciesDb = IdMap.createLongMap(Species.class);
+	IdMap<Long,Order> orderDb = IdMap.createLongMap(Order.class);
+	IdMap<Long,Tag> tagDb = IdMap.createLongMap(Tag.class);
+	ConcurrentHashMap<String,User> userDb = new ConcurrentHashMap<>();
 
+	public PetStore init() throws Exception {
+		
+		// Load our databases from local JSON files.
+		
+		JsonParser parser = JsonParser.create().build();
+		
+		// Note that these must be loaded in the specified order to prevent IdNotFound exceptions.
+		for (Species s : parser.parse(getStream("Species.json"), Species[].class)) 
+			add(s);
+		for (Tag t : parser.parse(getStream("Tags.json"), Tag[].class)) 
+			add(t);
+		
+		parser = parser.builder().pojoSwaps(new CategorySwap(), new TagSwap()).build();
+		for (Pet p : parser.parse(getStream("Pets.json"), Pet[].class)) 
+			add(p);
+		
+		parser = parser.builder().pojoSwaps(new PetSwap()).build();
+		for (Order o : parser.parse(getStream("Orders.json"), Order[].class)) 
+			add(o);
+
+		for (User u : parser.parse(getStream("Users.json"), User[].class)) 
+			add(u);
+		
+		return this;
+	}
+	
+	private InputStream getStream(String fileName) {
+		return getClass().getResourceAsStream(fileName);
+	}
 	
 	public Pet getPet(long id) throws IdNotFound {
 		Pet value = petDb.get(id);
@@ -36,13 +70,20 @@ public class PetStore {
 		return value;
 	}
 	
-	public Category getCategory(long id) throws IdNotFound {
-		Category value = categoryDb.get(id);
+	public Species getSpecies(long id) throws IdNotFound {
+		Species value = speciesDb.get(id);
 		if (value == null)
 			throw new IdNotFound(id, Pet.class);
 		return value;
 	}
 	
+	public Species getSpecies(String name) throws IdNotFound {
+		for (Species value : speciesDb.values())
+			if (value.getName().equals(name))
+				return value;
+		throw new InvalidSpecies();
+	}
+
 	public Order getOrder(long id) throws IdNotFound {
 		Order value = orderDb.get(id);
 		if (value == null)
@@ -64,13 +105,6 @@ public class PetStore {
 		throw new InvalidTag();
 	}
 
-	public User getUser(long id) throws IdNotFound {
-		User value =  userDb.get(id);
-		if (value == null)
-			throw new IdNotFound(id, Pet.class);
-		return value;
-	}
-	
 	public User getUser(String username) throws InvalidUsername, IdNotFound  {
 		assertValidUsername(username);
 		for (User user : userDb.values())
@@ -90,8 +124,8 @@ public class PetStore {
 		return petDb.values();
 	}
 
-	public Collection<Category> getCategories() {
-		return categoryDb.values();
+	public Collection<Species> getCategories() {
+		return speciesDb.values();
 	}
 
 	public Collection<Order> getOrders() {
@@ -115,12 +149,12 @@ public class PetStore {
 		return value;
 	}
 
-	public Category add(Category value) throws IdConflict {
+	public Species add(Species value) throws IdConflict {
 		if (value.getId() == 0)
-			value.id(categoryDb.nextId());
-		Category old = categoryDb.putIfAbsent(value.getId(), value);
+			value.id(speciesDb.nextId());
+		Species old = speciesDb.putIfAbsent(value.getId(), value);
 		if (old != null)
-			throw new IdConflict(value.getId(), Category.class);
+			throw new IdConflict(value.getId(), Species.class);
 		return value;
 	}
 	
@@ -144,11 +178,9 @@ public class PetStore {
 	
 	public User add(User value) throws IdConflict, InvalidUsername {
 		assertValidUsername(value.getUsername());
-		if (value.getId() == 0)
-			value.id(userDb.nextId());
-		User old = userDb.putIfAbsent(value.getId(), value);
+		User old = userDb.putIfAbsent(value.getUsername(), value);
 		if (old != null)
-			throw new IdConflict(value.getId(), User.class);
+			throw new IdConflict(value.getUsername(), User.class);
 		return value;
 	}
 	
@@ -159,10 +191,10 @@ public class PetStore {
 		return value;
 	}
 
-	public Category update(Category value) throws IdNotFound {
-		Category old = categoryDb.replace(value.getId(), value);
+	public Species update(Species value) throws IdNotFound {
+		Species old = speciesDb.replace(value.getId(), value);
 		if (old == null)
-			throw new IdNotFound(value.getId(), Category.class);
+			throw new IdNotFound(value.getId(), Species.class);
 		return value;
 	}
 	
@@ -183,9 +215,9 @@ public class PetStore {
 	
 	public User update(User value) throws IdNotFound, InvalidUsername {
 		assertValidUsername(value.getUsername());
-		User old = userDb.replace(value.getId(), value);
+		User old = userDb.replace(value.getUsername(), value);
 		if (old == null)
-			throw new IdNotFound(value.getId(), User.class);
+			throw new IdNotFound(value.getUsername(), User.class);
 		return value;
 	}
 
@@ -194,7 +226,7 @@ public class PetStore {
 	}
 
 	public void removeCategory(long id) throws IdNotFound {
-		categoryDb.remove(getCategory(id).getId());
+		speciesDb.remove(getSpecies(id).getId());
 	}
 	
 	public void removeOrder(long id) throws IdNotFound {
@@ -205,8 +237,8 @@ public class PetStore {
 		tagDb.remove(getTag(id).getId());
 	}
 	
-	public void removeUser(long id) throws IdNotFound {
-		userDb.remove(getUser(id).getId());
+	public void removeUser(String username) throws IdNotFound {
+		userDb.remove(getUser(username).getUsername());
 	}
 
 	private void assertValidUsername(String username) throws InvalidUsername {
@@ -238,8 +270,51 @@ public class PetStore {
 	}
 
 	public Map<PetStatus,Integer> getInventory() {
-		// TODO
 		Map<PetStatus,Integer> m = new LinkedHashMap<>();
+		for (Pet p : petDb.values()) {
+			PetStatus ps = p.getStatus();
+			if (! m.containsKey(ps))
+				m.put(ps, 1);
+			else
+				m.put(ps, m.get(ps) + 1);
+		}
 		return m;
 	}
+	
+	//-----------------------------------------------------------------------------------------------------------------
+	// Helper beans
+	//-----------------------------------------------------------------------------------------------------------------
+	
+	public class CategorySwap extends PojoSwap<Species,String> {
+		@Override
+		public String swap(BeanSession bs, Species o) throws Exception {
+			return o.getName();
+		}
+		@Override
+		public Species unswap(BeanSession bs, String o, ClassMeta<?> hint) throws Exception {
+			return getSpecies(o);
+		}
+	}
+	
+	public class TagSwap extends PojoSwap<Tag,String> {
+		@Override
+		public String swap(BeanSession bs, Tag o) throws Exception {
+			return o.getName();
+		}
+		@Override
+		public Tag unswap(BeanSession bs, String o, ClassMeta<?> hint) throws Exception {
+			return getTag(o);
+		}
+	}
+
+	public class PetSwap extends PojoSwap<Pet,Long> {
+		@Override
+		public Long swap(BeanSession bs, Pet o) throws Exception {
+			return o.getId();
+		}
+		@Override
+		public Pet unswap(BeanSession bs, Long o, ClassMeta<?> hint) throws Exception {
+			return petDb.get(o);
+		}
+	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
index 2e7b5da..1e130fe 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/PetStoreResource.java
@@ -13,6 +13,7 @@
 package org.apache.juneau.examples.rest.petstore;
 
 import static org.apache.juneau.dto.swagger.ui.SwaggerUI.*;
+import static org.apache.juneau.rest.annotation.HookEvent.*;
 import static org.apache.juneau.rest.helper.Ok.*;
 
 import java.util.*;
@@ -38,7 +39,7 @@ import org.apache.juneau.rest.converters.*;
 	htmldoc=@HtmlDoc(
 		widgets={
 			ContentTypeMenuItem.class,
-			ThemeMenuItem.class
+			ThemeMenuItem.class,
 		},
 		navlinks={
 			"up: request:/..",
@@ -46,19 +47,33 @@ import org.apache.juneau.rest.converters.*;
 			"$W{ContentTypeMenuItem}",
 			"$W{ThemeMenuItem}",
 			"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/petstore/$R{servletClassSimple}.java"
+		},
+		head={
+			"<link rel='icon' href='$U{servlet:/htdocs/cat.png}'/>"  // Add a cat icon to the page.
+		},
+		header={
+			"<h1>$R{resourceTitle}</h1>",
+			"<h2>$R{methodSummary}</h2>",
+			"$C{PetStore/headerImage}"
 		}
 	),
 	properties= {
 		// Resolve recursive references when showing schema info in the swagger.
 		@Property(name=SWAGGERUI_resolveRefsMaxDepth, value="99")
 	},
-	swagger="$F{PetStoreResource.json}"
+	swagger="$F{PetStoreResource.json}",
+	staticFiles={"htdocs:htdocs"}
 )
 public class PetStoreResource extends BasicRestServletJena {
 	private static final long serialVersionUID = 1L;
 	
-	private final PetStore db = new PetStore();
+	private PetStore store;
 	
+	@RestHook(INIT) 
+	public void initDatabase(RestContextBuilder builder) throws Exception {
+		store = new PetStore().init();
+	}
+
 	@RestMethod(
 		name="GET", 
 		path="/",
@@ -67,7 +82,7 @@ public class PetStoreResource extends BasicRestServletJena {
 	public ResourceDescription[] getTopPage() {
 		return new ResourceDescription[] {
 			new ResourceDescription("pet", "All pets in the store"), 
-			new ResourceDescription("store", "Petstore orders"), 
+			new ResourceDescription("store", "Orders and inventory"), 
 			new ResourceDescription("user", "Petstore users")
 		};
 	}
@@ -86,10 +101,23 @@ public class PetStoreResource extends BasicRestServletJena {
 				 Queryable.SWAGGER_PARAMS,
 			"]"
 		},
+		bpx="Pet: tags",
+		htmldoc=@HtmlDoc(
+			widgets={
+				QueryMenuItem.class,
+				AddPetMenuItem.class
+			},
+
+			navlinks={
+				"INHERIT",                // Inherit links from class.
+				"[2]:$W{QueryMenuItem}",  // Insert QUERY link in position 2.
+				"[3]:$W{AddPetMenuItem}"  // Insert ADD link in position 3.
+			}
+		),
 		converters={Queryable.class}
 	)
 	public Collection<Pet> getPets() throws NotAcceptable {
-		return db.getPets();
+		return store.getPets();
 	}
 	
 	@RestMethod(
@@ -106,7 +134,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Path(description="ID of pet to return", example="123") long petId
 		) throws IdNotFound, NotAcceptable {
 		
-		return db.getPet(petId);
+		return store.getPet(petId);
 	}
 	
 	@RestMethod(
@@ -122,7 +150,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Body(description="Pet object that needs to be added to the store") Pet pet
 		) throws IdConflict, NotAcceptable, UnsupportedMediaType {
 		
-		db.add(pet);
+		store.add(pet);
 		return OK;
 	}
 	
@@ -139,7 +167,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Body(description="Pet object that needs to be added to the store") Pet pet
 		) throws IdNotFound, NotAcceptable, UnsupportedMediaType {
 		
-		db.update(pet);
+		store.update(pet);
 		return OK;
 	}
 
@@ -163,7 +191,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			PetStatus[] status
 		) throws NotAcceptable {
 		
-		return db.getPetsByStatus(status);
+		return store.getPetsByStatus(status);
 	}
 	
 	@RestMethod(
@@ -187,7 +215,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			String[] tags
 		) throws InvalidTag, NotAcceptable {
 		
-		return db.getPetsByTags(tags);
+		return store.getPetsByTags(tags);
 	}
 
 	@RestMethod(
@@ -205,10 +233,10 @@ public class PetStoreResource extends BasicRestServletJena {
 			@FormData(name="status", description="Updated status of the pet", example="'AVAILABLE'") PetStatus status
 		) throws IdNotFound, NotAcceptable, UnsupportedMediaType {
 		
-		Pet pet = db.getPet(petId);
+		Pet pet = store.getPet(petId);
 		pet.name(name);
 		pet.status(status);
-		db.update(pet);
+		store.update(pet);
 		return OK;
 	}
 
@@ -226,7 +254,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Path(description="Pet id to delete", example="123") long petId
 		) throws IdNotFound, NotAcceptable {
 		
-		db.removePet(petId);
+		store.removePet(petId);
 		return OK;
 	}
 
@@ -253,33 +281,45 @@ public class PetStoreResource extends BasicRestServletJena {
 	//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
 	@RestMethod(
-		name="GET",
+		name="GET", 
 		path="/store",
+		summary="Navigation page"
+	) 
+	public ResourceDescription[] getTopStorePage() {
+		return new ResourceDescription[] {
+			new ResourceDescription("store/order", "Petstore orders"), 
+			new ResourceDescription("store/inventory", "Petstore inventory")
+		};
+	}
+
+	@RestMethod(
+		name="GET",
+		path="/store/order",
 		summary="Petstore orders",
 		swagger={
 			"tags:['store']"
 		}
 	) 
 	public Collection<Order> getOrders() throws NotAcceptable {
-		return db.getOrders();
+		return store.getOrders();
 	}
 
 	@RestMethod(
 		name="GET", 
 		path="/store/order/{orderId}",
 		summary="Find purchase order by ID",
-		description="For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions",
+		description="Returns a purchase order by ID.",
 		swagger={
 			"tags:[ 'store' ]",
 		}
 	)
 	public Order getOrder(
-			@Path(description="ID of order to fetch", maximum="10", minimum="1", example="5") long orderId
+			@Path(description="ID of order to fetch", maximum="1000", minimum="101", example="123") long orderId
 		) throws InvalidId, IdNotFound, NotAcceptable {
 		
-		if (orderId < 0 || orderId > 10)
+		if (orderId < 101 || orderId > 1000)
 			throw new InvalidId();
-		return db.getOrder(orderId);
+		return store.getOrder(orderId);
 	}
 	
 	@RestMethod(
@@ -294,7 +334,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Body(description="Order placed for purchasing the pet", example="{petId:456,quantity:100}") Order order
 		) throws IdConflict, NotAcceptable, UnsupportedMediaType {
 		
-		return db.add(order);
+		return store.add(order);
 	}
 
 	@RestMethod(
@@ -312,7 +352,7 @@ public class PetStoreResource extends BasicRestServletJena {
 		
 		if (orderId < 0)
 			throw new InvalidId();
-		db.removeOrder(orderId);
+		store.removeOrder(orderId);
 		return OK;
 	}
 
@@ -330,7 +370,7 @@ public class PetStoreResource extends BasicRestServletJena {
 		}
 	)
 	public Map<PetStatus,Integer> getStoreInventory() throws NotAcceptable {
-		return db.getInventory();
+		return store.getInventory();
 	}
 
 	//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -341,12 +381,13 @@ public class PetStoreResource extends BasicRestServletJena {
 		name="GET",
 		path="/user",
 		summary="Petstore users",
+		bpx="User: email,password,phone",
 		swagger={
 			"tags:['user']"
 		}
 	)
 	public Collection<User> getUsers() throws NotAcceptable {
-		return db.getUsers();
+		return store.getUsers();
 	}
 
 	@RestMethod(
@@ -361,7 +402,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Path(description="The name that needs to be fetched. Use user1 for testing.") String username
 		) throws InvalidUsername, IdNotFound, NotAcceptable {
 		
-		return db.getUser(username);
+		return store.getUser(username);
 	}
 	
 	@RestMethod(
@@ -377,7 +418,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Body(description="Created user object") User user
 		) throws InvalidUsername, IdConflict, NotAcceptable, UnsupportedMediaType {
 		
-		db.add(user);
+		store.add(user);
 		return OK;
 	}
 
@@ -394,7 +435,7 @@ public class PetStoreResource extends BasicRestServletJena {
 		) throws InvalidUsername, IdConflict, NotAcceptable, UnsupportedMediaType {
 		
 		for (User user : users)
-			db.add(user);
+			store.add(user);
 		return OK;
 	}
 
@@ -412,9 +453,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Body(description="Updated user object") User user
 		) throws InvalidUsername, IdNotFound, NotAcceptable, UnsupportedMediaType {
 		
-		User oldUser = db.getUser(username);
-		user.id(oldUser.getId());
-		db.update(user);
+		store.update(user);
 		return OK;
 	}
 
@@ -431,8 +470,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			@Path(description="The name that needs to be deleted") String username
 		) throws InvalidUsername, IdNotFound, NotAcceptable {
 		
-		User oldUser = db.getUser(username);
-		db.removeUser(oldUser.getId());
+		store.removeUser(username);
 		return OK;
 	}
 	
@@ -459,7 +497,7 @@ public class PetStoreResource extends BasicRestServletJena {
 			RestResponse res
 		) throws InvalidLogin, NotAcceptable {
 		
-		if (! db.isValid(username, password))
+		if (! store.isValid(username, password))
 			throw new InvalidLogin();
 		
 		Date d = new Date(System.currentTimeMillis() + 30 * 60 * 1000);
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Category.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Species.java
similarity index 71%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Category.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Species.java
index 4041d6b..09b5a4c 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Category.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Species.java
@@ -13,9 +13,14 @@
 package org.apache.juneau.examples.rest.petstore;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.dto.html5.Img;
+import org.apache.juneau.html.*;
+import org.apache.juneau.html.annotation.*;
+import org.apache.juneau.serializer.*;
 
-@Bean(typeName="Category", fluentSetters=true)
-public class Category {
+@Bean(typeName="Species", fluentSetters=true)
+@Html(render=Species.SpeciesRender.class)
+public class Species {
 	private long id;
 	private String name;
 	
@@ -23,7 +28,7 @@ public class Category {
 		return id;
 	}
 	
-	public Category id(long id) {
+	public Species id(long id) {
 		this.id = id;
 		return this;
 	}
@@ -32,15 +37,26 @@ public class Category {
 		return name;
 	}
 	
-	public Category name(String name) {
+	public Species name(String name) {
 		this.name = name;
 		return this;
 	}
 	
 	@Example
-	public static Category example() {
-		return new Category()
+	public static Species example() {
+		return new Species()
 			.id(123)
 			.name("Dog");
 	}
+
+	public static class SpeciesRender extends HtmlRender<Species> {
+		@Override
+		public Object getContent(SerializerSession session, Species value) {
+			return new Img().src("servlet:/htdocs/"+value.getName().toLowerCase()+".png");
+		}
+		@Override
+		public String getStyle(SerializerSession session, Species value) {
+			return "background-color:#FDF2E9";
+		}
+	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
index 8c580b1..649c38c 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Tag.java
@@ -12,9 +12,13 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest.petstore;
 
+import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.transform.*;
 
 @Bean(typeName="Tag", fluentSetters=true)
+@Swap(Tag.TagNameOnly.class)
 public class Tag {
 	private long id;
 	private String name;
@@ -43,4 +47,15 @@ public class Tag {
 			.id(123)
 			.name("MyTag");
 	}
+	
+	public static class TagNameOnly extends PojoSwap<Tag,String> {
+		@Override
+		public String swap(BeanSession bs, Tag o) throws Exception {
+			return o.getName();
+		}
+		@Override
+		public MediaType[] forMediaTypes() {
+			return new MediaType[] { MediaType.HTML };
+		}
+	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/User.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/User.java
index 9722010..3170f55 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/User.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/User.java
@@ -13,12 +13,12 @@
 package org.apache.juneau.examples.rest.petstore;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.html.annotation.*;
 
-@Bean(typeName="User", fluentSetters=true)
+@Bean(typeName="User", fluentSetters=true, properties="username,firstName,lastName,email,password,phone,userStatus")
 public class User {
-	private long id;
 	private String username, firstName, lastName, email, password, phone;
-	private int userStatus;
+	private UserStatus userStatus;
 	
 	// This shows an example provided as a static field.
 	@Example
@@ -27,19 +27,10 @@ public class User {
 		.firstName("Billy")
 		.lastName("Bob")
 		.email("billy@apache.org")
-		.id(123)
-		.userStatus(1)
+		.userStatus(UserStatus.ACTIVE)
 		.phone("111-222-3333");
 	
-	public long getId() {
-		return id;
-	}
-
-	public User id(long id) {
-		this.id = id;
-		return this;
-	}
-
+	@Html(link="servlet:/user/{username}")
 	public String getUsername() {
 		return username;
 	}
@@ -94,11 +85,11 @@ public class User {
 		return this;
 	}
 
-	public int getUserStatus() {
+	public UserStatus getUserStatus() {
 		return userStatus;
 	}
 
-	public User userStatus(int userStatus) {
+	public User userStatus(UserStatus userStatus) {
 		this.userStatus = userStatus;
 		return this;
 	}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Category.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/UserStatus.java
similarity index 71%
rename from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Category.java
rename to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/UserStatus.java
index 4041d6b..7141065 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/Category.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/UserStatus.java
@@ -12,35 +12,22 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.examples.rest.petstore;
 
-import org.apache.juneau.annotation.*;
+import org.apache.juneau.html.*;
+import org.apache.juneau.html.annotation.*;
+import org.apache.juneau.serializer.*;
 
-@Bean(typeName="Category", fluentSetters=true)
-public class Category {
-	private long id;
-	private String name;
+@Html(render=UserStatus.UserStatusRender.class)
+public enum UserStatus {
+	ACTIVE, INACTIVE;
 	
-	public long getId() {
-		return id;
-	}
-	
-	public Category id(long id) {
-		this.id = id;
-		return this;
-	}
-	
-	public String getName() {
-		return name;
-	}
-	
-	public Category name(String name) {
-		this.name = name;
-		return this;
-	}
-	
-	@Example
-	public static Category example() {
-		return new Category()
-			.id(123)
-			.name("Dog");
+	public static class UserStatusRender extends HtmlRender<UserStatus> {
+		@Override /* HtmlRender */
+		public String getStyle(SerializerSession session, UserStatus value) {
+			switch(value) {
+				case ACTIVE:  return "background-color:#5cb85c;text-align:center;vertical-align:middle;"; 
+				case INACTIVE:  return "background-color:#888;text-align:center;vertical-align:middle;"; 
+				default:  return ""; 
+			}
+		}
 	}
 }
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Orders.json
similarity index 83%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
copy to juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Orders.json
index f8084ab..15e5ab0 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Orders.json
@@ -2,7 +2,7 @@
 // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
 // * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
 // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              * 
+// * with the License.  You may obtain a copy of the License at                                                              *
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,8 +10,9 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.examples.rest.petstore;
 
-public enum OrderStatus {
-	PLACED, APPROVED, DELIVERED;
-}
+[
+	{id:101,petId:101,quantity:1,shipDate:'2018-01-01',status:'PLACED'},
+	{id:102,petId:102,quantity:5,shipDate:'2018-01-01',status:'APPROVED'},
+	{id:103,petId:103,quantity:10,shipDate:'2018-01-01',status:'DELIVERED'}
+]
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Pets.json
similarity index 64%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
copy to juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Pets.json
index f8084ab..9976a4a 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Pets.json
@@ -2,7 +2,7 @@
 // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
 // * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
 // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              * 
+// * with the License.  You may obtain a copy of the License at                                                              *
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,8 +10,15 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.examples.rest.petstore;
 
-public enum OrderStatus {
-	PLACED, APPROVED, DELIVERED;
-}
+[
+	{id:101, species:'cat', name:'Mr. Frisky', price:39.99, tags:['friendly'], status:'AVAILABLE'},
+	{id:102, species:'dog', name:'Kibbles', price:99.99, tags:['loyal'], status:'AVAILABLE'},
+	{id:103, species:'rabbit', name:'Hoppy', price:49.99, tags:['friendly','smells nice'], status:'AVAILABLE'},
+	{id:104, species:'rabbit', name:'Hoppy 2', price:49.99, status:'AVAILABLE'},
+	{id:105, species:'rabbit', name:'Hoppy 3', price:49.99, status:'AVAILABLE'},
+	{id:106, species:'rabbit', name:'Hoppy 4', price:49.99, status:'AVAILABLE'},
+	{id:107, species:'fish', name:'Gorton', price:1.99, status:'PENDING'},
+	{id:108, species:'mouse', name:'Hackwrench', price:4.99, status:'SOLD'},
+	{id:109, species:'snake', name:'Just Snake', price:9.99, status:'SOLD'}
+]
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Species.json
similarity index 87%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
copy to juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Species.json
index f8084ab..fc5ecbf 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Species.json
@@ -2,7 +2,7 @@
 // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
 // * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
 // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              * 
+// * with the License.  You may obtain a copy of the License at                                                              *
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,8 +10,12 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.examples.rest.petstore;
 
-public enum OrderStatus {
-	PLACED, APPROVED, DELIVERED;
-}
+[
+	{id:101, name:'cat'},
+	{id:102, name:'dog'},
+	{id:103, name:'rabbit'},
+	{id:104, name:'fish'},
+	{id:105, name:'mouse'},
+	{id:106, name:'snake'}
+]
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Tags.json
similarity index 84%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
copy to juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Tags.json
index f8084ab..1a1caef 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Tags.json
@@ -2,7 +2,7 @@
 // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
 // * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
 // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              * 
+// * with the License.  You may obtain a copy of the License at                                                              *
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,8 +10,13 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.examples.rest.petstore;
 
-public enum OrderStatus {
-	PLACED, APPROVED, DELIVERED;
-}
+[
+	{id:101, name:'friendly'},
+	{id:102, name:'special'},
+	{id:103, name:'intelligent'},
+	{id:104, name:'mean'},
+	{id:105, name:'easy to care for'},
+	{id:106, name:'smells nice'},
+	{id:107, name:'loyal'}
+]
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Users.json
similarity index 73%
copy from juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
copy to juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Users.json
index f8084ab..5e340c1 100644
--- a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/petstore/OrderStatus.java
+++ b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/Users.json
@@ -2,7 +2,7 @@
 // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
 // * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
 // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              * 
+// * with the License.  You may obtain a copy of the License at                                                              *
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,8 +10,9 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.examples.rest.petstore;
 
-public enum OrderStatus {
-	PLACED, APPROVED, DELIVERED;
-}
+[
+	{username:'mariewatson',firstName:'Marie',lastName:'Watson',email:'marie.watson@fakemail.com',password:'123456',phone:'444-555-7777',userStatus:'ACTIVE'},
+	{username:'danielvaughn',firstName:'Daniel',lastName:'Vaughn',email:'daniel.vaughn@test.com',password:'123456',phone:'666-777-3333',userStatus:'ACTIVE'},
+	{username:'brendafuller',firstName:'Brenda',lastName:'Fuller',email:'brenda.fuller@example.com',password:'123456',phone:'777-888-3333',userStatus:'INACTIVE'}
+]
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/bird.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/bird.png
new file mode 100644
index 0000000..636ecf8
Binary files /dev/null and b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/bird.png differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/cat.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/cat.png
new file mode 100644
index 0000000..917abc6
Binary files /dev/null and b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/cat.png differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/dog.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/dog.png
new file mode 100644
index 0000000..e100eb2
Binary files /dev/null and b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/dog.png differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/fish.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/fish.png
new file mode 100644
index 0000000..ca76a46
Binary files /dev/null and b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/fish.png differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/mouse.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/mouse.png
new file mode 100644
index 0000000..5308006
Binary files /dev/null and b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/mouse.png differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/rabbit.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/rabbit.png
new file mode 100644
index 0000000..f013470
Binary files /dev/null and b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/rabbit.png differ
diff --git a/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/snake.png b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/snake.png
new file mode 100644
index 0000000..7f17660
Binary files /dev/null and b/juneau-examples/juneau-examples-rest/src/main/resources/org/apache/juneau/examples/rest/petstore/htdocs/snake.png differ
diff --git a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
index 2e10ed3..732b108 100755
--- a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
+++ b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/DirectoryResource.java
@@ -122,8 +122,7 @@ public class DirectoryResource extends BasicRestServlet {
 		summary="View information on file or directory",
 		description="Returns information about the specified file or directory.",
 		htmldoc=@HtmlDoc(
-			nav={"<h5>Folder:  $RA{fullPath}</h5>"},
-			nowrap=true
+			nav={"<h5>Folder:  $RA{fullPath}</h5>"}
 		)
 	)
 	public FileResource getFile(RestRequest req, @PathRemainder String path) throws NotFound, Exception {
diff --git a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
index 66751d0..eb6a6b7 100755
--- a/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
+++ b/juneau-microservice/juneau-microservice-server/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
@@ -114,8 +114,7 @@ public class LogsResource extends BasicRestServlet {
 		summary="View information on file or directory",
 		description="Returns information about the specified file or directory.",
 		htmldoc=@HtmlDoc(
-			nav={"<h5>Folder:  $RA{fullPath}</h5>"},
-			nowrap=true
+			nav={"<h5>Folder:  $RA{fullPath}</h5>"}
 		)
 	)
 	public FileResource getFile(RestRequest req, @PathRemainder String path) throws NotFound, Exception {
diff --git a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/HtmlDocResource.java b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/HtmlDocResource.java
index e836a57..7cc9eeb 100644
--- a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/HtmlDocResource.java
+++ b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/HtmlDocResource.java
@@ -28,7 +28,8 @@ import org.apache.juneau.rest.annotation.*;
 		nav={"nav1a","nav1b"},
 		script={"script1a","script1b"},
 		style={"style1a","style1b"},
-		stylesheet="stylesheet1"
+		stylesheet="stylesheet1",
+		nowrap="false"
 	),
 	children={
 		HtmlDocResource.HtmlDocResource2.class
diff --git a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java
index ce50720..f6de1e9 100644
--- a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java
+++ b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java
@@ -130,7 +130,7 @@ public class ThirdPartyProxyTest extends RestTestcase {
 			new int[][][]{{{1,2},null},null},
 			new Integer[][][]{{{1,null},null},null},
 			new String[][][]{{{"foo",null},null},null},
-			new AList<Integer>().append(1).append(null),
+			AList.<Integer>create(1,null),
 			new AList<List<List<Integer>>>()
 				.append(
 					new AList<List<Integer>>()
@@ -1295,7 +1295,7 @@ public class ThirdPartyProxyTest extends RestTestcase {
 
 	@Test
 	public void ef08_setEnum1d3dListMap() {
-		proxy.setEnum1d3dListMap(new AMap<TestEnum,List<TestEnum[][][]>>().append(TestEnum.ONE, new AList<TestEnum[][][]>().append(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null)));
+		proxy.setEnum1d3dListMap(new AMap<TestEnum,List<TestEnum[][][]>>().append(TestEnum.ONE, AList.<TestEnum[][][]>create(new TestEnum[][][]{{{TestEnum.TWO,null},null},null}).append(null)));
 	}
 
 	//--------------------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
index 0828de5..502ef1b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestConfig.java
@@ -77,7 +77,8 @@ import org.apache.juneau.xmlschema.*;
 		head={
 			"<link rel='icon' href='$U{$C{REST/favicon}}'/>"
 		},
-		footer="$C{REST/footer}"
+		footer="$C{REST/footer}",
+		nowrap="true"
 	),
 	
 	// Optional external configuration file.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocBuilder.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocBuilder.java
index 27818fc..258e258 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocBuilder.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/HtmlDocBuilder.java
@@ -71,8 +71,8 @@ public class HtmlDocBuilder {
 			stylesheet((Object[])hd.stylesheet());
 		if (! hd.noResultsMessage().isEmpty())
 			noResultsMessage(hd.noResultsMessage());
-		if (hd.nowrap())
-			nowrap(true);
+		if (! hd.nowrap().isEmpty())
+			nowrap(Boolean.valueOf(hd.nowrap()));
 		if (hd.template() != HtmlDocTemplate.class)
 			template(hd.template());
 	}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
index 1fe9bb7..20acff5 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HtmlDoc.java
@@ -396,7 +396,7 @@ public @interface HtmlDoc {
 	 * 	<li class='jm'>{@link HtmlDocBuilder#nowrap(boolean)}
 	 * </ul>
 	 */
-	boolean nowrap() default false;
+	String nowrap() default "";
 
 	/**
 	 * Sets the HTML script section contents.

-- 
To stop receiving notification emails like this one, please contact
jamesbognar@apache.org.