Rest server tests.
diff --git a/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/html/annotation/HtmlDocConfig_Test.java b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/html/annotation/HtmlDocConfig_Test.java
new file mode 100644
index 0000000..d611825
--- /dev/null
+++ b/juneau-core/juneau-core-utest/src/test/java/org/apache/juneau/html/annotation/HtmlDocConfig_Test.java
@@ -0,0 +1,681 @@
+package org.apache.juneau.html.annotation;
+
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+//***************************************************************************************************************************
+//* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+//* distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+//* to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+//* with the License.  You may obtain a copy of the License at                                                              *
+//*                                                                                                                         *
+//*  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+//*                                                                                                                         *
+//* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+//* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+//* specific language governing permissions and limitations under the License.                                              *
+//***************************************************************************************************************************
+
+@FixMethodOrder(NAME_ASCENDING)
+@SuppressWarnings({"serial"})
+public class HtmlDocConfig_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @HtmlDocConfig(aside)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	@HtmlDocConfig(aside={"a01a","a01b","INHERIT"})
+	public static class A1 extends BasicRestServlet {
+		@RestMethod
+		public Object a01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(aside={"a02a","a02b"})
+		public Object a02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(aside={"INHERIT","a03a","a03b"})
+		public Object a03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(aside={"a04a","INHERIT","a04b"})
+		public Object a04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(aside={"a05a","a05b","INHERIT"})
+		public Object a05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void a01_aside() throws Exception {
+		RestClient a1 = client(A1.class);
+		a1.get("/a01").accept("text/html").run().assertBody().contains("<aside>a01a a01b</aside>");
+		a1.get("/a02").accept("text/html").run().assertBody().contains("<aside>a02a a02b</aside>");
+		a1.get("/a03").accept("text/html").run().assertBody().contains("<aside>a01a a01b a03a a03b</aside>");
+		a1.get("/a04").accept("text/html").run().assertBody().contains("<aside>a04a a01a a01b a04b</aside>");
+		a1.get("/a05").accept("text/html").run().assertBody().contains("<aside>a05a a05b a01a a01b</aside>");
+	}
+
+	@Rest
+	@HtmlDocConfig(aside={"INHERIT","b01a","b01b"})
+	public static class A2 extends A1 {
+		@RestMethod
+		public Object b01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(aside={"b02a","b02b"})
+		public Object b02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(aside={"INHERIT","b03a","b03b"})
+		public Object b03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(aside={"b04a","INHERIT","b04b"})
+		public Object b04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(aside={"b05a","b05b","INHERIT"})
+		public Object b05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void a02_aside_inherited() throws Exception {
+		RestClient a2 = client(A2.class);
+		a2.get("/b01").accept("text/html").run().assertBody().contains("<aside>a01a a01b b01a b01b</aside>");
+		a2.get("/b02").accept("text/html").run().assertBody().contains("<aside>b02a b02b</aside>");
+		a2.get("/b03").accept("text/html").run().assertBody().contains("<aside>a01a a01b b01a b01b b03a b03b</aside>");
+		a2.get("/b04").accept("text/html").run().assertBody().contains("<aside>b04a a01a a01b b01a b01b b04b</aside>");
+		a2.get("/b05").accept("text/html").run().assertBody().contains("<aside>b05a b05b a01a a01b b01a b01b</aside>");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @HtmlDocConfig(footer)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	@HtmlDocConfig(footer={"a01a","a01b"})
+	public static class B1 extends BasicRestServlet {
+		@RestMethod
+		public Object a01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(footer={"a02a","a02b"})
+		public Object a02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(footer={"INHERIT","a03a","a03b"})
+		public Object a03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(footer={"a04a","INHERIT","a04b"})
+		public Object a04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(footer={"a05a","a05b","INHERIT"})
+		public Object a05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void b01_footer() throws Exception {
+		RestClient b1 = client(B1.class);
+		b1.get("/a01").accept("text/html").run().assertBody().contains("<footer>a01a a01b</footer>");
+		b1.get("/a02").accept("text/html").run().assertBody().contains("<footer>a02a a02b</footer>");
+		b1.get("/a03").accept("text/html").run().assertBody().contains("<footer>a01a a01b a03a a03b</footer>");
+		b1.get("/a04").accept("text/html").run().assertBody().contains("<footer>a04a a01a a01b a04b</footer>");
+		b1.get("/a05").accept("text/html").run().assertBody().contains("<footer>a05a a05b a01a a01b</footer>");
+	}
+
+	@Rest
+	@HtmlDocConfig(footer={"b01a","INHERIT","b01b"})
+	public static class B2 extends B1 {
+		@RestMethod
+		public Object b01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(footer={"b02a","b02b"})
+		public Object b02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(footer={"INHERIT","b03a","b03b"})
+		public Object b03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(footer={"b04a","INHERIT","b04b"})
+		public Object b04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(footer={"b05a","b05b","INHERIT"})
+		public Object b05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void b02_footer_inherited() throws Exception {
+		RestClient b2 = client(B2.class);
+		b2.get("/b01").accept("text/html").run().assertBody().contains("<footer>b01a a01a a01b b01b</footer>");
+		b2.get("/b02").accept("text/html").run().assertBody().contains("<footer>b02a b02b</footer>");
+		b2.get("/b03").accept("text/html").run().assertBody().contains("<footer>b01a a01a a01b b01b b03a b03b</footer>");
+		b2.get("/b04").accept("text/html").run().assertBody().contains("<footer>b04a b01a a01a a01b b01b b04b</footer>");
+		b2.get("/b05").accept("text/html").run().assertBody().contains("<footer>b05a b05b b01a a01a a01b b01b</footer>");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @HtmlDocConfig(header)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	@HtmlDocConfig(header={"a01a","a01b"})
+	public static class C1 extends BasicRestServlet {
+		@RestMethod
+		public Object a01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(header={"a02a","a02b"})
+		public Object a02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(header={"INHERIT","a03a","a03b"})
+		public Object a03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(header={"a04a","INHERIT","a04b"})
+		public Object a04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(header={"a05a","a05b","INHERIT"})
+		public Object a05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void c01_header() throws Exception {
+		RestClient c1 = client(C1.class);
+		c1.get("/a01").accept("text/html").run().assertBody().contains("<header>a01a a01b</header>");
+		c1.get("/a02").accept("text/html").run().assertBody().contains("<header>a02a a02b</header>");
+		c1.get("/a03").accept("text/html").run().assertBody().contains("<header>a01a a01b a03a a03b</header>");
+		c1.get("/a04").accept("text/html").run().assertBody().contains("<header>a04a a01a a01b a04b</header>");
+		c1.get("/a05").accept("text/html").run().assertBody().contains("<header>a05a a05b a01a a01b</header>");
+	}
+
+	@Rest
+	@HtmlDocConfig(header={"b01a","b01b","INHERIT"})
+	public static class C2 extends C1 {
+		@RestMethod
+		public Object b01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(header={"b02a","b02b"})
+		public Object b02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(header={"INHERIT","b03a","b03b"})
+		public Object b03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(header={"b04a","INHERIT","b04b"})
+		public Object b04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(header={"b05a","b05b","INHERIT"})
+		public Object b05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void c02_header_inherited() throws Exception {
+		RestClient c2 = client(C2.class);
+		c2.get("/b01").accept("text/html").run().assertBody().contains("<header>b01a b01b a01a a01b</header>");
+		c2.get("/b02").accept("text/html").run().assertBody().contains("<header>b02a b02b</header>");
+		c2.get("/b03").accept("text/html").run().assertBody().contains("<header>b01a b01b a01a a01b b03a b03b</header>");
+		c2.get("/b04").accept("text/html").run().assertBody().contains("<header>b04a b01a b01b a01a a01b b04b</header>");
+		c2.get("/b05").accept("text/html").run().assertBody().contains("<header>b05a b05b b01a b01b a01a a01b</header>");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @HtmlDocConfig(navlinks)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	@HtmlDocConfig(navlinks={"a01a","a01b"})
+	public static class D1 extends BasicRestServlet {
+		@RestMethod
+		public Object a01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"a02a","a02b"})
+		public Object a02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"INHERIT","a03a","a03b"})
+		public Object a03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"a04a","INHERIT","a04b"})
+		public Object a04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"a05a","a05b","INHERIT"})
+		public Object a05() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"INHERIT","[0]:a06a","[3]:a06b"})
+		public Object a06() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"[1]:a07a","[2]:a07b","INHERIT"})
+		public Object a07() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"[1]:a08a","[0]:a08b"})
+		public Object a08() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"INHERIT","foo[0]:a09a","bar[3]:a09b"})
+		public Object a09() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"foo[1]:a10a","bar[2]:a10b","INHERIT"})
+		public Object a10() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"foo[1]:a11a","bar[0]:a11b"})
+		public Object a11() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void d01_navlinks() throws Exception {
+		RestClient d1 = client(D1.class);
+		d1.get("/a01").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li></ol></nav>");
+		d1.get("/a02").accept("text/html").run().assertBody().contains("<nav><ol><li>a02a</li><li>a02b</li></ol></nav>");
+		d1.get("/a03").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li><li>a03a</li><li>a03b</li></ol></nav>");
+		d1.get("/a04").accept("text/html").run().assertBody().contains("<nav><ol><li>a04a</li><li>a01a</li><li>a01b</li><li>a04b</li></ol></nav>");
+		d1.get("/a05").accept("text/html").run().assertBody().contains("<nav><ol><li>a05a</li><li>a05b</li><li>a01a</li><li>a01b</li></ol></nav>");
+		d1.get("/a06").accept("text/html").run().assertBody().contains("<nav><ol><li>a06a</li><li>a01a</li><li>a01b</li><li>a06b</li></ol></nav>");
+		d1.get("/a07").accept("text/html").run().assertBody().contains("<nav><ol><li>a07a</li><li>a07b</li><li>a01a</li><li>a01b</li></ol></nav>");
+		d1.get("/a08").accept("text/html").run().assertBody().contains("<nav><ol><li>a08b</li><li>a08a</li></ol></nav>");
+		d1.get("/a09").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/a09a\">foo</a></li><li>a01a</li><li>a01b</li><li><a href=\"/a09b\">bar</a></li></ol></nav>");
+		d1.get("/a10").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/a10a\">foo</a></li><li><a href=\"/a10b\">bar</a></li><li>a01a</li><li>a01b</li></ol></nav>");
+		d1.get("/a11").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/a11b\">bar</a></li><li><a href=\"/a11a\">foo</a></li></ol></nav>");
+	}
+
+	@Rest
+	@HtmlDocConfig(navlinks={"INHERIT","b01a","b01b"})
+	public static class D2 extends D1 {
+		@RestMethod
+		public Object b01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"b02a","b02b"})
+		public Object b02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"INHERIT","b03a","b03b"})
+		public Object b03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"b04a","INHERIT","b04b"})
+		public Object b04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"b05a","b05b","INHERIT"})
+		public Object b05() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"INHERIT","[0]:b06a","[3]:b06b"})
+		public Object b06() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"[1]:b07a","[2]:b07b","INHERIT"})
+		public Object b07() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"[1]:b08a","[0]:b08b"})
+		public Object b08() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"INHERIT","foo[0]:b09a","bar[3]:b09b"})
+		public Object b09() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"foo[1]:b10a","bar[2]:b10b","INHERIT"})
+		public Object b10() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(navlinks={"foo[1]:b11a","bar[0]:b11b"})
+		public Object b11() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void d02_navlinks_inherited() throws Exception {
+		RestClient d2 = client(D2.class);
+		d2.get("/b01").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
+		d2.get("/b02").accept("text/html").run().assertBody().contains("<nav><ol><li>b02a</li><li>b02b</li></ol></nav>");
+		d2.get("/b03").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li><li>b03a</li><li>b03b</li></ol></nav>");
+		d2.get("/b04").accept("text/html").run().assertBody().contains("<nav><ol><li>b04a</li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li><li>b04b</li></ol></nav>");
+		d2.get("/b05").accept("text/html").run().assertBody().contains("<nav><ol><li>b05a</li><li>b05b</li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
+		d2.get("/b06").accept("text/html").run().assertBody().contains("<nav><ol><li>b06a</li><li>a01a</li><li>a01b</li><li>b06b</li><li>b01a</li><li>b01b</li></ol></nav>");
+		d2.get("/b07").accept("text/html").run().assertBody().contains("<nav><ol><li>b07a</li><li>b07b</li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
+		d2.get("/b08").accept("text/html").run().assertBody().contains("<nav><ol><li>b08b</li><li>b08a</li></ol></nav>");
+		d2.get("/b09").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/b09a\">foo</a></li><li>a01a</li><li>a01b</li><li><a href=\"/b09b\">bar</a></li><li>b01a</li><li>b01b</li></ol></nav>");
+		d2.get("/b10").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/b10a\">foo</a></li><li><a href=\"/b10b\">bar</a></li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
+		d2.get("/b11").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/b11b\">bar</a></li><li><a href=\"/b11a\">foo</a></li></ol></nav>");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @HtmlDocConfig(nav)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	@HtmlDocConfig(navlinks={"NONE"},nav={"a01a","a01b"})
+	public static class E1 extends BasicRestServlet {
+		@RestMethod
+		public Object a01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(nav={"a02a","a02b"})
+		public Object a02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(nav={"INHERIT","a03a","a03b"})
+		public Object a03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(nav={"a04a","INHERIT","a04b"})
+		public Object a04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(nav={"a05a","a05b","INHERIT"})
+		public Object a05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void e01_nav() throws Exception {
+		RestClient e1 = client(E1.class);
+		e1.get("/a01").accept("text/html").run().assertBody().contains("<nav>a01a a01b</nav>");
+		e1.get("/a02").accept("text/html").run().assertBody().contains("<nav>a02a a02b</nav>");
+		e1.get("/a03").accept("text/html").run().assertBody().contains("<nav>a01a a01b a03a a03b</nav>");
+		e1.get("/a04").accept("text/html").run().assertBody().contains("<nav>a04a a01a a01b a04b</nav>");
+		e1.get("/a05").accept("text/html").run().assertBody().contains("<nav>a05a a05b a01a a01b</nav>");
+	}
+
+	@Rest
+	@HtmlDocConfig(nav={"INHERIT","b01a","b01b"})
+	public static class E2 extends E1 {
+		@RestMethod
+		public Object b01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(nav={"b02a","b02b"})
+		public Object b02() {
+			return "OK";
+		}
+		@RestMethod(path="/b03")
+		@HtmlDocConfig(nav={"INHERIT","b03a","b03b"})
+		public Object b03() {
+			return "OK";
+		}
+		@RestMethod(path="/b04")
+		@HtmlDocConfig(nav={"b04a","INHERIT","b04b"})
+		public Object b04() {
+			return "OK";
+		}
+		@RestMethod(path="/b05")
+		@HtmlDocConfig(nav={"b05a","b05b","INHERIT"})
+		public Object b05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void e02_nav_inherited() throws Exception {
+		RestClient e2 = client(E2.class);
+		e2.get("/b01").accept("text/html").run().assertBody().contains("<nav>a01a a01b b01a b01b</nav>");
+		e2.get("/b02").accept("text/html").run().assertBody().contains("<nav>b02a b02b</nav>");
+		e2.get("/b03").accept("text/html").run().assertBody().contains("<nav>a01a a01b b01a b01b b03a b03b</nav>");
+		e2.get("/b04").accept("text/html").run().assertBody().contains("<nav>b04a a01a a01b b01a b01b b04b</nav>");
+		e2.get("/b05").accept("text/html").run().assertBody().contains("<nav>b05a b05b a01a a01b b01a b01b</nav>");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @HtmlDocConfig(script)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	@HtmlDocConfig(script={"a01a","a01b"})
+	public static class F1 extends BasicRestServlet {
+		@RestMethod
+		public Object a01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(script={"a02a","a02b"})
+		public Object a02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(script={"INHERIT","a03a","a03b"})
+		public Object a03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(script={"a04a","INHERIT","a04b"})
+		public Object a04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(script={"a05a","a05b","INHERIT"})
+		public Object a05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void f01_script() throws Exception {
+		RestClient f1 = client(F1.class);
+		f1.get("/a01").accept("text/html").run().assertBody().contains("<script>a01a\n a01b\n</script>");
+		f1.get("/a02").accept("text/html").run().assertBody().contains("<script>a02a\n a02b\n</script>");
+		f1.get("/a03").accept("text/html").run().assertBody().contains("<script>a01a\n a01b\n a03a\n a03b\n</script>");
+		f1.get("/a04").accept("text/html").run().assertBody().contains("<script>a04a\n a01a\n a01b\n a04b\n</script>");
+		f1.get("/a05").accept("text/html").run().assertBody().contains("<script>a05a\n a05b\n a01a\n a01b\n</script>");
+	}
+
+	@Rest
+	@HtmlDocConfig(script={"b01a","b01b"})
+	public static class F2 extends F1 {
+		@RestMethod
+		public Object b01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(script={"b02a","b02b"})
+		public Object b02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(script={"INHERIT","b03a","b03b"})
+		public Object b03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(script={"b04a","INHERIT","b04b"})
+		public Object b04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(script={"b05a","b05b","INHERIT"})
+		public Object b05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void f02_script_inherited() throws Exception {
+		RestClient f2 = client(F2.class);
+		f2.get("/b01").accept("text/html").run().assertBody().contains("<script>b01a\n b01b\n</script>");
+		f2.get("/b02").accept("text/html").run().assertBody().contains("<script>b02a\n b02b\n</script>");
+		f2.get("/b03").accept("text/html").run().assertBody().contains("<script>b01a\n b01b\n b03a\n b03b\n</script>");
+		f2.get("/b04").accept("text/html").run().assertBody().contains("<script>b04a\n b01a\n b01b\n b04b\n</script>");
+		f2.get("/b05").accept("text/html").run().assertBody().contains("<script>b05a\n b05b\n b01a\n b01b\n</script>");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @HtmlDocConfig(style)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	@HtmlDocConfig(style={"a01a","a01b"},stylesheet="a01s",nowrap="false")
+	public static class G1 extends BasicRestServlet {
+		@RestMethod
+		public Object a01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(style={"a02a","a02b"},stylesheet="a02s")
+		public Object a02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(style={"INHERIT","a03a","a03b"})
+		public Object a03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(style={"a04a","INHERIT","a04b"})
+		public Object a04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(style={"a05a","a05b","INHERIT"})
+		public Object a05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void g01_style() throws Exception {
+		RestClient g1 = client(G1.class);
+		g1.get("/a01").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a01a a01b</style>");
+		g1.get("/a02").accept("text/html").run().assertBody().contains("<style>@import \"/a02s\"; a02a a02b</style>");
+		g1.get("/a03").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a01a a01b a03a a03b</style>");
+		g1.get("/a04").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a04a a01a a01b a04b</style>");
+		g1.get("/a05").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a05a a05b a01a a01b</style>");
+	}
+
+	@Rest
+	@HtmlDocConfig(style={"b01a","b01b"},stylesheet="b01s")
+	public static class G2 extends G1 {
+		@RestMethod
+		public Object b01() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(style={"b02a","b02b"},stylesheet="b02s")
+		public Object b02() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(style={"INHERIT","b03a","b03b"})
+		public Object b03() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(style={"b04a","INHERIT","b04b"})
+		public Object b04() {
+			return "OK";
+		}
+		@RestMethod
+		@HtmlDocConfig(style={"b05a","b05b","INHERIT"})
+		public Object b05() {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void g02_style_inherited() throws Exception {
+		RestClient g2 = client(G2.class);
+		g2.get("/b01").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b01a b01b</style>");
+		g2.get("/b02").accept("text/html").run().assertBody().contains("<style>@import \"/b02s\"; b02a b02b</style>");
+		g2.get("/b03").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b01a b01b b03a b03b</style>");
+		g2.get("/b04").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b04a b01a b01b b04b</style>");
+		g2.get("/b05").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b05a b05b b01a b01b</style>");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Helper methods.
+	//------------------------------------------------------------------------------------------------------------------
+
+	private RestClient client(Class<?> c) {
+		return MockRestClient.build(c);
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicResponsesTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicResponsesTest.java
deleted file mode 100644
index eff109e..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicResponsesTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import static org.apache.juneau.rest.testutils.TestUtils.*;
-
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.http.response.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class BasicResponsesTest {
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic sanity tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class A {
-		@RestMethod public Accepted accepted() { return new Accepted(); }
-		@RestMethod public AlreadyReported alreadyReported() { return new AlreadyReported(); }
-		@RestMethod(path="/continue") public Continue _continue() { return new Continue(); }
-		@RestMethod public Created created() { return new Created(); }
-		@RestMethod public EarlyHints earlyHints() { return new EarlyHints(); }
-		@RestMethod public Found found() { return new Found(); }
-		@RestMethod public IMUsed imUsed() { return new IMUsed(); }
-		@RestMethod public MovedPermanently movedPermanently() { return new MovedPermanently(); }
-		@RestMethod public MultipleChoices multipleChoices() { return new MultipleChoices(); }
-		@RestMethod public MultiStatus multiStatus() { return new MultiStatus(); }
-		@RestMethod public NoContent noContent() { return new NoContent(); }
-		@RestMethod public NonAuthoritiveInformation nonAuthoritiveInformation() { return new NonAuthoritiveInformation(); }
-		@RestMethod public NotModified notModified() { return new NotModified(); }
-		@RestMethod public Ok ok() { return new Ok(); }
-		@RestMethod public PartialContent partialContent() { return new PartialContent(); }
-		@RestMethod public PermanentRedirect permanentRedirect() { return new PermanentRedirect(); }
-		@RestMethod public Processing processing() { return new Processing(); }
-		@RestMethod public ResetContent resetContent() { return new ResetContent(); }
-		@RestMethod public SeeOther seeOther() { return new SeeOther(); }
-		@RestMethod public SwitchingProtocols switchingProtocols() { return new SwitchingProtocols(); }
-		@RestMethod public TemporaryRedirect temporaryRedirect() { return new TemporaryRedirect(); }
-		@RestMethod public UseProxy useProxy() { return new UseProxy(); }
-	}
-
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Test Swagger
-	//-----------------------------------------------------------------------------------------------------------------
-
-	static Swagger e = getSwagger(A.class);
-
-	@Test
-	public void e01_accepted() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/accepted").get("get").getResponse(Accepted.CODE);
-		assertEquals(Accepted.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e02_alreadyReported() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/alreadyReported").get("get").getResponse(AlreadyReported.CODE);
-		assertEquals(AlreadyReported.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e03_continue() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/continue").get("get").getResponse(Continue.CODE);
-		assertEquals(Continue.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e04_created() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/created").get("get").getResponse(Created.CODE);
-		assertEquals(Created.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e05_earlyHints() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/earlyHints").get("get").getResponse(EarlyHints.CODE);
-		assertEquals(EarlyHints.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e06_found() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/found").get("get").getResponse(Found.CODE);
-		assertEquals(Found.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e07_imUsed() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/imUsed").get("get").getResponse(IMUsed.CODE);
-		assertEquals(IMUsed.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e08_movedPermanently() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/movedPermanently").get("get").getResponse(MovedPermanently.CODE);
-		assertEquals(MovedPermanently.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e09_multipleChoices() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/multipleChoices").get("get").getResponse(MultipleChoices.CODE);
-		assertEquals(MultipleChoices.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e10_multiStatus() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/multiStatus").get("get").getResponse(MultiStatus.CODE);
-		assertEquals(MultiStatus.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e11_noContent() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/noContent").get("get").getResponse(NoContent.CODE);
-		assertEquals(NoContent.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e12_nonAuthoritiveInformation() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/nonAuthoritiveInformation").get("get").getResponse(NonAuthoritiveInformation.CODE);
-		assertEquals(NonAuthoritiveInformation.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e13_notModified() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/notModified").get("get").getResponse(NotModified.CODE);
-		assertEquals(NotModified.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e14_ok() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/ok").get("get").getResponse(Ok.CODE);
-		assertEquals(Ok.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e15_partialContent() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/partialContent").get("get").getResponse(PartialContent.CODE);
-		assertEquals(PartialContent.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e16_permanentRedirect() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/permanentRedirect").get("get").getResponse(PermanentRedirect.CODE);
-		assertEquals(PermanentRedirect.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e17_processing() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/processing").get("get").getResponse(Processing.CODE);
-		assertEquals(Processing.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e18_resetContent() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/resetContent").get("get").getResponse(ResetContent.CODE);
-		assertEquals(ResetContent.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e19_seeOther() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/seeOther").get("get").getResponse(SeeOther.CODE);
-		assertEquals(SeeOther.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e20_switchingProtocols() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/switchingProtocols").get("get").getResponse(SwitchingProtocols.CODE);
-		assertEquals(SwitchingProtocols.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e21_temporaryRedirect() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/temporaryRedirect").get("get").getResponse(TemporaryRedirect.CODE);
-		assertEquals(TemporaryRedirect.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void e22_useProxy() throws Exception {
-		ResponseInfo ri = e.getPaths().get("/useProxy").get("get").getResponse(UseProxy.CODE);
-		assertEquals(UseProxy.MESSAGE, ri.getDescription());
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicRestCallLoggerTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicRestCallLogger_Test.java
similarity index 98%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicRestCallLoggerTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicRestCallLogger_Test.java
index 567c75b..1b6e389 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicRestCallLoggerTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicRestCallLogger_Test.java
@@ -26,84 +26,13 @@
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class BasicRestCallLoggerTest {
+public class BasicRestCallLogger_Test {
 
-	static class TestLogger extends Logger {
-		Level level;
-		String msg;
-		Throwable t;
-
-		protected TestLogger() {
-			super(null, null);
-		}
-
-		@Override
-		public void log(Level level, String msg, Throwable t) {
-			this.level = level;
-			this.msg = msg;
-			this.t = t;
-		}
-
-		public void check(Level level, String msg, boolean hasThrowable) {
-			boolean isNot = (msg != null && msg.length() > 0 && msg.charAt(0) == '!');
-			if (isNot)
-				msg = msg.substring(1);
-			if (msg != null && msg.indexOf('*') != -1) {
-				Pattern p = StringUtils.getMatchPattern(msg, Pattern.DOTALL);
-				boolean eq = p.matcher(this.msg).matches();
-				if (isNot ? eq : ! eq)
-					fail("Message text didn't match [2].\nExpected=["+msg+"]\nActual=["+this.msg+"]");
-			} else {
-				boolean eq = StringUtils.isEquals(this.msg, msg);
-				if (isNot ? eq : ! eq)
-					fail("Message text didn't match [1].\nExpected=["+msg+"]\nActual=["+this.msg+"]");
-			}
-
-			assertEquals("Message level didn't match.", level, this.level);
-			if (hasThrowable && t == null)
-				fail("Throwable not present");
-			if (t != null && ! hasThrowable)
-				fail("Throwable present.");
-		}
-	}
-
-	private RestCallLoggerConfig.Builder config() {
-		return RestCallLoggerConfig.create();
-	}
-
-	private RestCallLoggerConfig wrapped(RestCallLoggerConfig config) {
-		return RestCallLoggerConfig.create().parent(config).build();
-	}
-
-	private BasicRestCallLogger logger(Logger l, StackTraceDatabase std) {
-		return new BasicRestCallLogger(l, std);
-	}
-
-	private BasicRestCallLogger logger(Logger l) {
-		return new BasicRestCallLogger(l, new StackTraceDatabase());
-	}
-
-	private RestCallLoggerRule.Builder rule() {
-		return RestCallLoggerRule.create();
-	}
-
-	private MockServletRequest req() {
-		return MockServletRequest.create();
-	}
-
-	private MockServletResponse res() {
-		return MockServletResponse.create();
-	}
-
-	private MockServletResponse res(int status) {
-		return MockServletResponse.create().status(status);
-	}
 
 	//------------------------------------------------------------------------------------------------------------------
 	// No logging
 	//------------------------------------------------------------------------------------------------------------------
 
-
 	@Test
 	public void a01a_noRules() {
 		RestCallLoggerConfig lc = config().build();
@@ -883,4 +812,79 @@
 		tc.check(INFO, "!*---Response Body UTF-8---\nfoo\n*", false);
 		tc.check(INFO, "!*---Response Body Hex---\n66 6F 6F\n*", false);
 	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Helper methods
+	//------------------------------------------------------------------------------------------------------------------
+
+	static class TestLogger extends Logger {
+		Level level;
+		String msg;
+		Throwable t;
+
+		protected TestLogger() {
+			super(null, null);
+		}
+
+		@Override
+		public void log(Level level, String msg, Throwable t) {
+			this.level = level;
+			this.msg = msg;
+			this.t = t;
+		}
+
+		public void check(Level level, String msg, boolean hasThrowable) {
+			boolean isNot = (msg != null && msg.length() > 0 && msg.charAt(0) == '!');
+			if (isNot)
+				msg = msg.substring(1);
+			if (msg != null && msg.indexOf('*') != -1) {
+				Pattern p = StringUtils.getMatchPattern(msg, Pattern.DOTALL);
+				boolean eq = p.matcher(this.msg).matches();
+				if (isNot ? eq : ! eq)
+					fail("Message text didn't match [2].\nExpected=["+msg+"]\nActual=["+this.msg+"]");
+			} else {
+				boolean eq = StringUtils.isEquals(this.msg, msg);
+				if (isNot ? eq : ! eq)
+					fail("Message text didn't match [1].\nExpected=["+msg+"]\nActual=["+this.msg+"]");
+			}
+
+			assertEquals("Message level didn't match.", level, this.level);
+			if (hasThrowable && t == null)
+				fail("Throwable not present");
+			if (t != null && ! hasThrowable)
+				fail("Throwable present.");
+		}
+	}
+
+	private RestCallLoggerConfig.Builder config() {
+		return RestCallLoggerConfig.create();
+	}
+
+	private RestCallLoggerConfig wrapped(RestCallLoggerConfig config) {
+		return RestCallLoggerConfig.create().parent(config).build();
+	}
+
+	private BasicRestCallLogger logger(Logger l, StackTraceDatabase std) {
+		return new BasicRestCallLogger(l, std);
+	}
+
+	private BasicRestCallLogger logger(Logger l) {
+		return new BasicRestCallLogger(l, new StackTraceDatabase());
+	}
+
+	private RestCallLoggerRule.Builder rule() {
+		return RestCallLoggerRule.create();
+	}
+
+	private MockServletRequest req() {
+		return MockServletRequest.create();
+	}
+
+	private MockServletResponse res() {
+		return MockServletResponse.create();
+	}
+
+	private MockServletResponse res(int status) {
+		return MockServletResponse.create().status(status);
+	}
 }
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
deleted file mode 100644
index 8f441dc..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
+++ /dev/null
@@ -1,2350 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import static org.junit.Assert.*;
-import static org.junit.Assert.assertEquals;
-import static org.junit.runners.MethodSorters.*;
-import static org.apache.juneau.assertions.Assertions.*;
-import static org.apache.juneau.http.HttpMethod.*;
-import java.io.*;
-import java.util.*;
-
-import org.apache.juneau.json.*;
-import org.apache.juneau.jsonschema.annotation.ExternalDocs;
-import org.apache.juneau.jsonschema.annotation.Schema;
-import org.apache.juneau.xml.*;
-import org.apache.juneau.*;
-import org.apache.juneau.annotation.*;
-import org.apache.juneau.cp.*;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.http.annotation.Body;
-import org.apache.juneau.http.annotation.Contact;
-import org.apache.juneau.http.annotation.License;
-import org.apache.juneau.http.annotation.Query;
-import org.apache.juneau.http.annotation.Response;
-import org.apache.juneau.http.annotation.Tag;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class BasicRestInfoProviderTest {
-
-	//=================================================================================================================
-	// Setup
-	//=================================================================================================================
-
-	private Swagger getSwaggerWithFile(Object resource) throws Exception {
-		RestContext rc = RestContext.create(resource).classpathResourceFinder(TestClasspathResourceFinder.class).build();
-		RestRequest req = rc.createRequest(new RestCall(rc, new MockServletRequest(), null));
-		RestInfoProvider ip = rc.getInfoProvider();
-		return ip.getSwagger(req);
-	}
-
-	private static Swagger getSwagger(Object resource) throws Exception {
-		RestContext rc = RestContext.create(resource).build();
-		RestRequest req = rc.createRequest(new RestCall(rc, new MockServletRequest(), null));
-		RestInfoProvider ip = rc.getInfoProvider();
-		return ip.getSwagger(req);
-	}
-
-	public static class TestClasspathResourceFinder extends BasicResourceFinder {
-		@Override
-		public InputStream findResource(Class<?> baseClass, String name, Locale locale) throws IOException {
-			if (name.endsWith(".json"))
-				return BasicRestInfoProvider.class.getResourceAsStream("BasicRestInfoProviderTest_swagger.json");
-			return super.findResource(baseClass, name, locale);
-		}
-	}
-
-	//=================================================================================================================
-	// /<root>
-	//=================================================================================================================
-
-	@Rest
-	public static class A01 {}
-
-	@Test
-	public void a01_swagger_default() throws Exception {
-		Swagger x = getSwagger(new A01());
-		assertEquals("2.0", x.getSwagger());
-		assertEquals(null, x.getHost());
-		assertEquals(null, x.getBasePath());
-		assertEquals(null, x.getSchemes());
-	}
-	@Test
-	public void a01_swagger_default_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new A01());
-		assertEquals("0.0", x.getSwagger());
-		assertEquals("s-host", x.getHost());
-		assertEquals("s-basePath", x.getBasePath());
-		assertObject(x.getSchemes()).json().is("['s-scheme']");
-	}
-
-
-	@Rest(swagger=@ResourceSwagger("{swagger:'3.0',host:'a-host',basePath:'a-basePath',schemes:['a-scheme']}"))
-	public static class A02 {}
-
-	@Test
-	public void a02_swagger_ResourceSwagger_value() throws Exception {
-		Swagger x = getSwagger(new A02());
-		assertEquals("3.0", x.getSwagger());
-		assertEquals("a-host", x.getHost());
-		assertEquals("a-basePath", x.getBasePath());
-		assertObject(x.getSchemes()).json().is("['a-scheme']");
-	}
-	@Test
-	public void a02_swagger_ResourceSwagger_value_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new A02());
-		assertEquals("3.0", x.getSwagger());
-		assertEquals("a-host", x.getHost());
-		assertEquals("a-basePath", x.getBasePath());
-		assertObject(x.getSchemes()).json().is("['a-scheme']");
-	}
-
-	//=================================================================================================================
-	// /info
-	//=================================================================================================================
-
-	@Rest(
-		title="a-title",
-		description="a-description"
-	)
-	public static class B01 {}
-
-	@Test
-	public void b01a_info_Rest() throws Exception {
-		Info x = getSwagger(new B01()).getInfo();
-		assertEquals("a-title", x.getTitle());
-		assertEquals("a-description", x.getDescription());
-		assertEquals(null, x.getVersion());
-		assertEquals(null, x.getTermsOfService());
-		assertEquals(null, x.getContact());
-		assertEquals(null, x.getLicense());
-	}
-	@Test
-	public void b01b_info_Rest_withFile() throws Exception {
-		Info x = getSwaggerWithFile(new B01()).getInfo();
-		assertEquals("s-title", x.getTitle());
-		assertEquals("s-description", x.getDescription());
-		assertEquals("0.0.0", x.getVersion());
-		assertEquals("s-termsOfService", x.getTermsOfService());
-		assertObject(x.getContact()).json().is("{name:'s-name',url:'s-url',email:'s-email'}");
-		assertObject(x.getLicense()).json().is("{name:'s-name',url:'s-url'}");
-	}
-
-	@Rest(
-		messages="BasicRestInfoProviderTest",
-		title="$L{foo}",
-		description="$L{foo}"
-	)
-	public static class B02 {}
-
-	@Test
-	public void b02a_info_Rest_localized() throws Exception {
-		Info x = getSwagger(new B02()).getInfo();
-		assertEquals("l-foo", x.getTitle());
-		assertEquals("l-foo", x.getDescription());
-	}
-	@Test
-	public void b02b_info_Rest_localized_withFile() throws Exception {
-		Info x = getSwaggerWithFile(new B02()).getInfo();
-		assertEquals("s-title", x.getTitle());
-		assertEquals("s-description", x.getDescription());
-	}
-
-	@Rest(
-		title="a-title",
-		description="a-description",
-		swagger=@ResourceSwagger(
-			{
-				"info:{",
-					"title:'b-title',",
-					"description:'b-description',",
-					"version:'2.0.0',",
-					"termsOfService:'a-termsOfService',",
-					"contact:{name:'a-name',url:'a-url',email:'a-email'},",
-					"license:{name:'a-name',url:'a-url'}",
-				"}"
-			}
-		)
-	)
-	public static class B03 {}
-
-	@Test
-	public void b03a_info_ResourceSwagger_value() throws Exception {
-		Info x = getSwagger(new B03()).getInfo();
-		assertEquals("b-title", x.getTitle());
-		assertEquals("b-description", x.getDescription());
-		assertEquals("2.0.0", x.getVersion());
-		assertEquals("a-termsOfService", x.getTermsOfService());
-		assertObject(x.getContact()).json().is("{name:'a-name',url:'a-url',email:'a-email'}");
-		assertObject(x.getLicense()).json().is("{name:'a-name',url:'a-url'}");
-	}
-	@Test
-	public void b03b_info_ResourceSwagger_value_withFile() throws Exception {
-		Info x = getSwaggerWithFile(new B03()).getInfo();
-		assertEquals("b-title", x.getTitle());
-		assertEquals("b-description", x.getDescription());
-		assertEquals("2.0.0", x.getVersion());
-		assertEquals("a-termsOfService", x.getTermsOfService());
-		assertObject(x.getContact()).json().is("{name:'a-name',url:'a-url',email:'a-email'}");
-		assertObject(x.getLicense()).json().is("{name:'a-name',url:'a-url'}");
-	}
-
-	@Rest(
-		messages="BasicRestInfoProviderTest",
-		title="a-title",
-		description="a-description",
-		swagger=@ResourceSwagger("{info:{title:'$L{bar}',description:'$L{bar}'}}")
-	)
-	public static class B04 {}
-
-	@Test
-	public void b04_info_ResourceSwagger_value_localised() throws Exception {
-		assertEquals("l-bar", getSwagger(new B04()).getInfo().getTitle());
-		assertEquals("l-bar", getSwaggerWithFile(new B04()).getInfo().getTitle());
-		assertEquals("l-bar", getSwagger(new B04()).getInfo().getDescription());
-		assertEquals("l-bar", getSwaggerWithFile(new B04()).getInfo().getDescription());
-	}
-
-	@Rest(
-		title="a-title",
-		description="a-description",
-		swagger=@ResourceSwagger(
-			value= {
-				"info:{",
-					"title:'b-title',",
-					"description:'b-description',",
-					"version:'2.0.0',",
-					"termsOfService:'a-termsOfService',",
-					"contact:{name:'a-name',url:'a-url',email:'a-email'},",
-					"license:{name:'a-name',url:'a-url'}",
-				"}"
-			},
-			title="c-title",
-			description="c-description",
-			version="3.0.0",
-			termsOfService="b-termsOfService",
-			contact=@Contact(name="b-name",url="b-url",email="b-email"),
-			license=@License(name="b-name",url="b-url")
-		)
-	)
-	public static class B05 {}
-
-	@Test
-	public void b05a_info_ResourceSwagger_title() throws Exception {
-		Info x = getSwagger(new B05()).getInfo();
-		assertEquals("c-title", x.getTitle());
-		assertEquals("c-description", x.getDescription());
-		assertEquals("3.0.0", x.getVersion());
-		assertEquals("b-termsOfService", x.getTermsOfService());
-		assertObject(x.getContact()).json().is("{name:'b-name',url:'b-url',email:'b-email'}");
-		assertObject(x.getLicense()).json().is("{name:'b-name',url:'b-url'}");
-	}
-	@Test
-	public void b05b_info_ResourceSwagger_title_withFile() throws Exception {
-		Info x = getSwaggerWithFile(new B05()).getInfo();
-		assertEquals("c-title", x.getTitle());
-		assertEquals("c-description", x.getDescription());
-		assertEquals("3.0.0", x.getVersion());
-		assertEquals("b-termsOfService", x.getTermsOfService());
-		assertObject(x.getContact()).json().is("{name:'b-name',url:'b-url',email:'b-email'}");
-		assertObject(x.getLicense()).json().is("{name:'b-name',url:'b-url'}");
-	}
-
-	@Rest(
-		title="a-title",
-		description="a-description",
-		swagger=@ResourceSwagger(
-			value= {
-				"info:{",
-					"title:'b-title',",
-					"description:'b-description',",
-					"version:'2.0.0',",
-					"termsOfService:'a-termsOfService',",
-					"contact:{name:'a-name',url:'a-url',email:'a-email'},",
-					"license:{name:'a-name',url:'a-url'}",
-				"}"
-			},
-			title="$L{baz}",
-			description="$L{baz}",
-			version="$L{foo}",
-			termsOfService="$L{foo}",
-			contact=@Contact("{name:'$L{foo}',url:'$L{bar}',email:'$L{baz}'}"),
-			license=@License("{name:'$L{foo}',url:'$L{bar}'}")
-		),
-		messages="BasicRestInfoProviderTest"
-	)
-	public static class B06 {}
-
-	@Test
-	public void b06a_info_ResourceSwagger_title_localized() throws Exception {
-		Info x = getSwagger(new B06()).getInfo();
-		assertEquals("l-baz", x.getTitle());
-		assertEquals("l-baz", x.getDescription());
-		assertEquals("l-foo", x.getVersion());
-		assertEquals("l-foo", x.getTermsOfService());
-		assertObject(x.getContact()).json().is("{name:'l-foo',url:'l-bar',email:'l-baz'}");
-		assertObject(x.getLicense()).json().is("{name:'l-foo',url:'l-bar'}");
-	}
-	@Test
-	public void b06b_info_ResourceSwagger_title_localized_withFile() throws Exception {
-		Info x = getSwaggerWithFile(new B06()).getInfo();
-		assertEquals("l-baz", x.getTitle());
-		assertEquals("l-baz", x.getDescription());
-		assertEquals("l-foo", x.getVersion());
-		assertEquals("l-foo", x.getTermsOfService());
-		assertObject(x.getContact()).json().is("{name:'l-foo',url:'l-bar',email:'l-baz'}");
-		assertObject(x.getLicense()).json().is("{name:'l-foo',url:'l-bar'}");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			title="c-title",
-			description="c-description"
-		)
-	)
-	public static class B07 {}
-
-	@Test
-	public void b07a_title_ResourceSwagger_title_only() throws Exception {
-		Info x = getSwagger(new B07()).getInfo();
-		assertEquals("c-title", x.getTitle());
-		assertEquals("c-description", x.getDescription());
-	}
-	@Test
-	public void b07b_title_ResourceSwagger_title_only_withFile() throws Exception {
-		Info x = getSwaggerWithFile(new B07()).getInfo();
-		assertEquals("c-title", x.getTitle());
-		assertEquals("c-description", x.getDescription());
-	}
-
-	//=================================================================================================================
-	// /tags
-	//=================================================================================================================
-
-	@Rest
-	public static class C01 {}
-
-	@Test
-	public void c01a_tags_default() throws Exception {
-		Swagger x = getSwagger(new C01());
-		assertEquals(null, x.getTags());
-	}
-	@Test
-	public void c01b_tags_default_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C01());
-		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}}]");
-	}
-
-	// Tags in @ResourceSwagger(value) should override file.
-	@Rest(
-		swagger=@ResourceSwagger(
-			"{tags:[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]}"
-		)
-	)
-	public static class C02 {}
-
-	@Test
-	public void c02a_tags_ResourceSwagger_value() throws Exception {
-		Swagger x = getSwagger(new C02());
-		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]");
-	}
-	@Test
-	public void c02b_tags_ResourceSwagger_value_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C02());
-		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]");
-	}
-
-	// Tags in both @ResourceSwagger(value) and @ResourceSwagger(tags) should accumulate.
-	@Rest(
-		swagger=@ResourceSwagger(
-			value="{tags:[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]}",
-			tags=@Tag(name="b-name",description="b-description",externalDocs=@ExternalDocs(description="b-description",url="b-url"))
-		)
-	)
-	public static class C03 {}
-
-	@Test
-	public void c03a_tags_ResourceSwagger_tags() throws Exception {
-		Swagger x = getSwagger(new C03());
-		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
-	}
-	@Test
-	public void c03b_tags_ResourceSwagger_tags_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C03());
-		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
-	}
-
-	// Same as above but without [] outer characters.
-	@Rest(
-		swagger=@ResourceSwagger(
-			value="{tags:[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]}",
-			tags=@Tag(name="b-name",value=" { description:'b-description', externalDocs: { description:'b-description', url:'b-url' } } ")
-		)
-	)
-	public static class C04 {}
-
-	@Test
-	public void c04a_tags_ResourceSwagger_tags() throws Exception {
-		Swagger x = getSwagger(new C04());
-		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
-	}
-	@Test
-	public void c04b_tags_ResourceSwagger_tags_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C04());
-		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
-	}
-
-	// Tags in both Swagger.json and @ResourceSwagger(tags) should accumulate.
-	@Rest(
-		swagger=@ResourceSwagger(
-			tags=@Tag(name="b-name",description="b-description",externalDocs=@ExternalDocs(description="b-description",url="b-url"))
-		)
-	)
-	public static class C05 {}
-
-	@Test
-	public void c05a_tags_ResourceSwagger_tags_only() throws Exception {
-		Swagger x = getSwagger(new C05());
-		assertObject(x.getTags()).json().is("[{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
-	}
-	@Test
-	public void c05b_tags_ResourceSwagger_tags_only_witFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C05());
-		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
-	}
-
-	// Dup tag names should be overwritten
-	@Rest(
-		swagger=@ResourceSwagger(
-			tags={
-				@Tag(name="s-name",description="b-description",externalDocs=@ExternalDocs(description="b-description",url="b-url")),
-				@Tag(name="s-name",value="{description:'c-description',externalDocs:{description:'c-description',url:'c-url'}}")
-			}
-		)
-	)
-	public static class C06 {}
-
-	@Test
-	public void c06a_tags_ResourceSwagger_tags_dups() throws Exception {
-		Swagger x = getSwagger(new C06());
-		assertObject(x.getTags()).json().is("[{name:'s-name',description:'c-description',externalDocs:{description:'c-description',url:'c-url'}}]");
-	}
-	@Test
-	public void c06b_tags_ResourceSwagger_tags_dups_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C06());
-		assertObject(x.getTags()).json().is("[{name:'s-name',description:'c-description',externalDocs:{description:'c-description',url:'c-url'}}]");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			value="{tags:[{name:'$L{foo}',description:'$L{foo}',externalDocs:{description:'$L{foo}',url:'$L{foo}'}}]}",
-			tags=@Tag(name="$L{foo}",description="$L{foo}",externalDocs=@ExternalDocs(description="$L{foo}",url="$L{foo}"))
-		),
-		messages="BasicRestInfoProviderTest"
-	)
-	public static class C07 {}
-
-	@Test
-	public void c07a_tags_ResourceSwagger_tags_localised() throws Exception {
-		Swagger x = getSwagger(new C07());
-		assertObject(x.getTags()).json().is("[{name:'l-foo',description:'l-foo',externalDocs:{description:'l-foo',url:'l-foo'}}]");
-	}
-	@Test
-	public void c07b_tags_ResourceSwagger_tags_localised_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C07());
-		assertObject(x.getTags()).json().is("[{name:'l-foo',description:'l-foo',externalDocs:{description:'l-foo',url:'l-foo'}}]");
-	}
-
-	// Auto-detect tags defined on methods.
-	@Rest
-	public static class C08 {
-		@RestMethod(swagger=@MethodSwagger(tags="foo"))
-		public void doFoo() {}
-	}
-
-	@Test
-	public void c08a_tags_ResourceSwagger_tags_loose() throws Exception {
-		Swagger x = getSwagger(new C08());
-		assertObject(x.getTags()).json().is("[{name:'foo'}]");
-	}
-	@Test
-	public void c08b_tags_ResourceSwagger_tags_loose_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C08());
-		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'foo'}]");
-	}
-
-	// Comma-delimited list
-	@Rest
-	public static class C09 {
-		@RestMethod(swagger=@MethodSwagger(tags=" foo, bar "))
-		public void doFoo() {}
-	}
-
-	@Test
-	public void c09a_tags_ResourceSwagger_tags_loose_cdl() throws Exception {
-		Swagger x = getSwagger(new C09());
-		assertObject(x.getTags()).json().is("[{name:'foo'},{name:'bar'}]");
-	}
-	@Test
-	public void c09b_tags_ResourceSwagger_tags_loose_cdl_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C09());
-		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'foo'},{name:'bar'}]");
-	}
-
-	// OList
-	@Rest
-	public static class C10 {
-		@RestMethod(swagger=@MethodSwagger(tags="['foo', 'bar']"))
-		public void doFoo() {}
-	}
-
-	@Test
-	public void c10a_tags_ResourceSwagger_tags_loose_olist() throws Exception {
-		Swagger x = getSwagger(new C10());
-		assertObject(x.getTags()).json().is("[{name:'foo'},{name:'bar'}]");
-	}
-	@Test
-	public void c10b_tags_ResourceSwagger_tags_loose_olist_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C10());
-		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'foo'},{name:'bar'}]");
-	}
-
-	// OList localized
-	@Rest(messages="BasicRestInfoProviderTest")
-	public static class C11 {
-		@RestMethod(swagger=@MethodSwagger(tags="['$L{foo}', '$L{bar}']"))
-		public void doFoo() {}
-	}
-
-	@Test
-	public void c11a_tags_ResourceSwagger_tags_loose_olist_localized() throws Exception {
-		Swagger x = getSwagger(new C11());
-		assertObject(x.getTags()).json().is("[{name:'l-foo'},{name:'l-bar'}]");
-	}
-	@Test
-	public void c11b_tags_ResourceSwagger_tags_loose_olist_localized_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C11());
-		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'l-foo'},{name:'l-bar'}]");
-	}
-
-	// Comma-delimited list localized
-	@Rest(messages="BasicRestInfoProviderTest")
-	public static class C12 {
-		@RestMethod(swagger=@MethodSwagger(tags=" $L{foo}, $L{bar} "))
-		public void doFoo() {}
-	}
-
-	@Test
-	public void c12a_tags_ResourceSwagger_tags_loose_cdl_localized() throws Exception {
-		Swagger x = getSwagger(new C12());
-		assertObject(x.getTags()).json().is("[{name:'l-foo'},{name:'l-bar'}]");
-	}
-	@Test
-	public void c12b_tags_ResourceSwagger_tags_loose_cdl_localized_withFile() throws Exception {
-		Swagger x = getSwaggerWithFile(new C12());
-		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'l-foo'},{name:'l-bar'}]");
-	}
-
-	//=================================================================================================================
-	// /externalDocs
-	//=================================================================================================================
-
-	@Rest
-	public static class D01 {}
-
-	@Test
-	public void d01a_externalDocs_default() throws Exception {
-		ExternalDocumentation x = getSwagger(new D01()).getExternalDocs();
-		assertEquals(null, x);
-	}
-	@Test
-	public void d01b_externalDocs_default_withFile() throws Exception {
-		ExternalDocumentation x = getSwaggerWithFile(new D01()).getExternalDocs();
-		assertObject(x).json().is("{description:'s-description',url:'s-url'}");
-	}
-
-
-	@Rest(
-		swagger=@ResourceSwagger("{externalDocs:{description:'a-description',url:'a-url'}}")
-	)
-	public static class D02 {}
-
-	@Test
-	public void d02a_externalDocs_ResourceSwagger_value() throws Exception {
-		ExternalDocumentation x = getSwagger(new D02()).getExternalDocs();
-		assertObject(x).json().is("{description:'a-description',url:'a-url'}");
-	}
-	@Test
-	public void d02b_externalDocs_ResourceSwagger_value_withFile() throws Exception {
-		ExternalDocumentation x = getSwaggerWithFile(new D02()).getExternalDocs();
-		assertObject(x).json().is("{description:'a-description',url:'a-url'}");
-	}
-
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			value="{externalDocs:{description:'a-description',url:'a-url'}}",
-			externalDocs=@ExternalDocs(description="b-description",url="b-url")
-		)
-	)
-	public static class D03 {}
-
-	@Test
-	public void d03a_externalDocs_ResourceSwagger_externalDocs() throws Exception {
-		ExternalDocumentation x = getSwagger(new D03()).getExternalDocs();
-		assertObject(x).json().is("{description:'b-description',url:'b-url'}");
-	}
-	@Test
-	public void d03b_externalDocs_ResourceSwagger_externalDocs_withFile() throws Exception {
-		ExternalDocumentation x = getSwaggerWithFile(new D03()).getExternalDocs();
-		assertObject(x).json().is("{description:'b-description',url:'b-url'}");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			value="{info:{externalDocs:{description:'a-description',url:'a-url'}}}",
-			externalDocs=@ExternalDocs(" description:'b-description', url:'b-url' ")
-			)
-	)
-	public static class D04 {}
-
-	@Test
-	public void d04a_externalDocs_ResourceSwagger_externalDocs() throws Exception {
-		ExternalDocumentation x = getSwagger(new D04()).getExternalDocs();
-		assertObject(x).json().is("{description:'b-description',url:'b-url'}");
-	}
-	@Test
-	public void d04b_externalDocs_ResourceSwagger_externalDocs_withFile() throws Exception {
-		ExternalDocumentation x = getSwaggerWithFile(new D04()).getExternalDocs();
-		assertObject(x).json().is("{description:'b-description',url:'b-url'}");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			value="{externalDocs:{description:'a-description',url:'a-url'}}",
-			externalDocs=@ExternalDocs("{description:'$L{foo}',url:'$L{bar}'}")
-		),
-		messages="BasicRestInfoProviderTest"
-	)
-	public static class D05 {}
-
-	@Test
-	public void d05a_externalDocs_ResourceSwagger_externalDocs_localised() throws Exception {
-		ExternalDocumentation x = getSwagger(new D05()).getExternalDocs();
-		assertObject(x).json().is("{description:'l-foo',url:'l-bar'}");
-	}
-	@Test
-	public void d05b_externalDocs_ResourceSwagger_externalDocs_localised_withFile() throws Exception {
-		ExternalDocumentation x = getSwaggerWithFile(new D05()).getExternalDocs();
-		assertObject(x).json().is("{description:'l-foo',url:'l-bar'}");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>
-	//=================================================================================================================
-
-	@Rest
-	public static class E01 {
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void e01a_operation_summary_default() throws Exception {
-		Operation x = getSwagger(new E01()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("doFoo", x.getOperationId());
-		assertEquals(null, x.getSummary());
-		assertEquals(null, x.getDescription());
-		assertEquals(null, x.getDeprecated());
-		assertEquals(null, x.getSchemes());
-	}
-	@Test
-	public void e01b_operation_summary_default_withFile() throws Exception {
-		Operation x = getSwaggerWithFile(new E01()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("s-operationId", x.getOperationId());
-		assertEquals("s-summary", x.getSummary());
-		assertEquals("s-description", x.getDescription());
-		assertObject(x.getDeprecated()).json().is("true");
-		assertObject(x.getSchemes()).json().is("['s-scheme']");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
-		)
-	)
-	public static class E02 {
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void e02a_operation_summary_swaggerOnClass() throws Exception {
-		Operation x = getSwagger(new E02()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("a-operationId", x.getOperationId());
-		assertEquals("a-summary", x.getSummary());
-		assertEquals("a-description", x.getDescription());
-		assertObject(x.getDeprecated()).json().is("false");
-		assertObject(x.getSchemes()).json().is("['a-scheme']");
-	}
-	@Test
-	public void e02b_operation_summary_swaggerOnClass_withFile() throws Exception {
-		Operation x = getSwaggerWithFile(new E02()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("a-operationId", x.getOperationId());
-		assertEquals("a-summary", x.getSummary());
-		assertEquals("a-description", x.getDescription());
-		assertObject(x.getDeprecated()).json().is("false");
-		assertObject(x.getSchemes()).json().is("['a-scheme']");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
-		)
-	)
-	public static class E03 {
-		@RestMethod(name=GET,path="/path/{foo}",
-			swagger=@MethodSwagger("operationId:'b-operationId',summary:'b-summary',description:'b-description',deprecated:false,schemes:['b-scheme']")
-		)
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void e03a_operation_summary_swaggerOnMethod() throws Exception {
-		Operation x = getSwagger(new E03()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("b-operationId", x.getOperationId());
-		assertEquals("b-summary", x.getSummary());
-		assertEquals("b-description", x.getDescription());
-		assertObject(x.getDeprecated()).json().is("false");
-		assertObject(x.getSchemes()).json().is("['b-scheme']");
-	}
-	@Test
-	public void e03b_operation_summary_swaggerOnMethod_withFile() throws Exception {
-		Operation x = getSwaggerWithFile(new E03()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("b-operationId", x.getOperationId());
-		assertEquals("b-summary", x.getSummary());
-		assertEquals("b-description", x.getDescription());
-		assertObject(x.getDeprecated()).json().is("false");
-		assertObject(x.getSchemes()).json().is("['b-scheme']");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
-		)
-	)
-	public static class E04 {
-		@RestMethod(name=GET,path="/path/{foo}",
-			swagger=@MethodSwagger(
-				operationId="c-operationId",
-				summary="c-summary",
-				description="c-description",
-				deprecated="false",
-				schemes="d-scheme-1, d-scheme-2"
-			)
-		)
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void e04a_operation_summary_swaggerOnAnnotation() throws Exception {
-		Operation x = getSwagger(new E04()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("c-operationId", x.getOperationId());
-		assertEquals("c-summary", x.getSummary());
-		assertEquals("c-description", x.getDescription());
-		assertObject(x.getSchemes()).json().is("['d-scheme-1','d-scheme-2']");
-	}
-	@Test
-	public void e04b_operation_summary_swaggerOnAnnotation_withFile() throws Exception {
-		Operation x = getSwaggerWithFile(new E04()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("c-operationId", x.getOperationId());
-		assertEquals("c-summary", x.getSummary());
-		assertEquals("c-description", x.getDescription());
-		assertObject(x.getSchemes()).json().is("['d-scheme-1','d-scheme-2']");
-	}
-
-	@Rest(
-		messages="BasicRestInfoProviderTest",
-		swagger=@ResourceSwagger(
-			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
-		)
-	)
-	public static class E05 {
-		@RestMethod(name=GET,path="/path/{foo}",
-			swagger=@MethodSwagger(
-				summary="$L{foo}",
-				operationId="$L{foo}",
-				description="$L{foo}",
-				deprecated="$L{false}",
-				schemes="$L{foo}"
-			)
-		)
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void e05a_operation_summary_swaggerOnAnnotation_localized() throws Exception {
-		Operation x = getSwagger(new E05()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("l-foo", x.getOperationId());
-		assertEquals("l-foo", x.getSummary());
-		assertEquals("l-foo", x.getDescription());
-		assertObject(x.getDeprecated()).json().is("false");
-		assertObject(x.getSchemes()).json().is("['l-foo']");
-	}
-	@Test
-	public void e05b_operation_summary_swaggerOnAnnotation_localized_withFile() throws Exception {
-		Operation x = getSwaggerWithFile(new E05()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("l-foo", x.getOperationId());
-		assertEquals("l-foo", x.getSummary());
-		assertEquals("l-foo", x.getDescription());
-		assertObject(x.getDeprecated()).json().is("false");
-		assertObject(x.getSchemes()).json().is("['l-foo']");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			"paths:{'/path/{foo}':{get:{summary:'a-summary',description:'a-description'}}}"
-		)
-	)
-	public static class E06 {
-		@RestMethod(name=GET,path="/path/{foo}",
-			summary="d-summary",
-			description="d-description"
-		)
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void e06a_operation_summary_RestMethod() throws Exception {
-		Operation x = getSwagger(new E06()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("a-summary", x.getSummary());
-		assertEquals("a-description", x.getDescription());
-	}
-	@Test
-	public void e06b_operation_summary_RestMethod_withFile() throws Exception {
-		Operation x = getSwaggerWithFile(new E06()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("a-summary", x.getSummary());
-		assertEquals("a-description", x.getDescription());
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger(
-			"paths:{'/path/{foo}':{get:{}}}"
-		)
-	)
-	public static class E07 {
-		@RestMethod(name=GET,path="/path/{foo}",
-			summary="d-summary",
-			description="d-description"
-		)
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void e07a_operation_summary_RestMethod() throws Exception {
-		Operation x = getSwagger(new E07()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("d-summary", x.getSummary());
-		assertEquals("d-description", x.getDescription());
-	}
-	@Test
-	public void e07b_operation_summary_RestMethod_withFile() throws Exception {
-		Operation x = getSwaggerWithFile(new E07()).getPaths().get("/path/{foo}").get("get");
-		assertEquals("d-summary", x.getSummary());
-		assertEquals("d-description", x.getDescription());
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/tags
-	//=================================================================================================================
-
-	@Rest
-	public static class MD01 {
-
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void md01_operation_tags_default() throws Exception {
-		assertObject(getSwagger(new MD01()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("null");
-		assertObject(getSwaggerWithFile(new MD01()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['s-tag']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
-	public static class MD02 {
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void md02_operation_tags_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new MD02()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['a-tag']");
-		assertObject(getSwaggerWithFile(new MD02()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['a-tag']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
-	public static class MD03 {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger("tags:['b-tag']"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void md03_operation_tags_swaggerOnMethod() throws Exception {
-		assertObject(getSwagger(new MD03()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['b-tag']");
-		assertObject(getSwaggerWithFile(new MD03()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['b-tag']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
-	public static class MD04a {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(tags="['c-tag-1','c-tag-2']"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void md04a_operation_tags_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new MD04a()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['c-tag-1','c-tag-2']");
-		assertObject(getSwaggerWithFile(new MD04a()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['c-tag-1','c-tag-2']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
-	public static class MD04b {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(tags="c-tag-1, c-tag-2"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void md04b_operation_tags_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new MD04b()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['c-tag-1','c-tag-2']");
-		assertObject(getSwaggerWithFile(new MD04b()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['c-tag-1','c-tag-2']");
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:'a-tags'}}}"))
-	public static class MD05 {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(tags="$L{foo}"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void md05_operation_tags_swaggerOnAnnotation_localized() throws Exception {
-		assertObject(getSwagger(new MD05()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['l-foo']");
-		assertObject(getSwaggerWithFile(new MD05()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['l-foo']");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/externalDocs
-	//=================================================================================================================
-
-	@Rest
-	public static class ME01 {
-
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void me01_operation_externalDocs_default() throws Exception {
-		assertObject(getSwagger(new ME01()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("null");
-		assertObject(getSwaggerWithFile(new ME01()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'s-description',url:'s-url'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
-	public static class ME02 {
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void me02_operation_externalDocs_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new ME02()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'a-description',url:'a-url'}");
-		assertObject(getSwaggerWithFile(new ME02()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'a-description',url:'a-url'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
-	public static class ME03 {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger("externalDocs:{description:'b-description',url:'b-url'}"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void me03_operation_externalDocs_swaggerOnMethod() throws Exception {
-		assertObject(getSwagger(new ME03()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'b-description',url:'b-url'}");
-		assertObject(getSwaggerWithFile(new ME03()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'b-description',url:'b-url'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
-	public static class ME04a {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(externalDocs=@ExternalDocs(description="c-description",url="c-url")))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void me04a_operation_externalDocs_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new ME04a()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'c-description',url:'c-url'}");
-		assertObject(getSwaggerWithFile(new ME04a()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'c-description',url:'c-url'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
-	public static class ME04b {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(externalDocs=@ExternalDocs("{description:'d-description',url:'d-url'}")))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void me04b_operation_externalDocs_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new ME04b()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'d-description',url:'d-url'}");
-		assertObject(getSwaggerWithFile(new ME04b()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'d-description',url:'d-url'}");
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
-	public static class ME05 {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(externalDocs=@ExternalDocs("{description:'$L{foo}',url:'$L{foo}'}")))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void me05_operation_externalDocs_swaggerOnAnnotation_localized() throws Exception {
-		assertObject(getSwagger(new ME05()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'l-foo',url:'l-foo'}");
-		assertObject(getSwaggerWithFile(new ME05()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'l-foo',url:'l-foo'}");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/consumes
-	//=================================================================================================================
-
-	@Rest
-	public static class MF01 {
-
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mf01_operation_consumes_default() throws Exception {
-		assertObject(getSwagger(new MF01()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("null");
-		assertObject(getSwaggerWithFile(new MF01()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['s-consumes']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
-	public static class MF02 {
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mf02_operation_consumes_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new MF02()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['a-consumes']");
-		assertObject(getSwaggerWithFile(new MF02()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['a-consumes']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
-	public static class MF03 {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger("consumes:['b-consumes']"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mf03_operation_consumes_swaggerOnMethod() throws Exception {
-		assertObject(getSwagger(new MF03()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['b-consumes']");
-		assertObject(getSwaggerWithFile(new MF03()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['b-consumes']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
-	public static class MF04a {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(consumes="['c-consumes-1','c-consumes-2']"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mf04a_operation_consumes_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new MF04a()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['c-consumes-1','c-consumes-2']");
-		assertObject(getSwaggerWithFile(new MF04a()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['c-consumes-1','c-consumes-2']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
-	public static class MF04b {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(consumes="c-consumes-1, c-consumes-2"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mf04b_operation_consumes_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new MF04b()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['c-consumes-1','c-consumes-2']");
-		assertObject(getSwaggerWithFile(new MF04b()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['c-consumes-1','c-consumes-2']");
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
-	public static class MF05 {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(consumes="['$L{foo}']"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void me05_operation_consumes_swaggerOnAnnotation_localized() throws Exception {
-		assertObject(getSwagger(new MF05()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['l-foo']");
-		assertObject(getSwaggerWithFile(new MF05()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['l-foo']");
-	}
-
-	@Rest(parsers={JsonParser.class})
-	public static class MF06a {
-		@RestMethod(name=PUT,path="/path2/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mf06a_operation_consumes_parsersOnClass() throws Exception {
-		assertObject(getSwagger(new MF06a()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("null");
-		assertObject(getSwaggerWithFile(new MF06a()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("null");
-	}
-
-	@Rest(parsers={JsonParser.class})
-	public static class MF06b {
-		@RestMethod(name=PUT,path="/path2/{foo}",parsers={XmlParser.class})
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mf06b_operation_consumes_parsersOnClassAndMethod() throws Exception {
-		assertObject(getSwagger(new MF06b()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("['text/xml','application/xml']");
-		assertObject(getSwaggerWithFile(new MF06b()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("['text/xml','application/xml']");
-	}
-
-	@Rest(parsers={JsonParser.class},swagger=@ResourceSwagger("paths:{'/path2/{foo}':{put:{consumes:['a-consumes']}}}"))
-	public static class MF06c {
-		@RestMethod(name=PUT,path="/path2/{foo}",parsers={XmlParser.class})
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mf06c_operation_consumes_parsersOnClassAndMethodWithSwagger() throws Exception {
-		assertObject(getSwagger(new MF06c()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("['a-consumes']");
-		assertObject(getSwaggerWithFile(new MF06c()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("['a-consumes']");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/produces
-	//=================================================================================================================
-
-	@Rest
-	public static class MG01 {
-
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mg01_operation_produces_default() throws Exception {
-		assertObject(getSwagger(new MG01()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("null");
-		assertObject(getSwaggerWithFile(new MG01()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['s-produces']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
-	public static class MG02 {
-		@RestMethod(name=GET,path="/path/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mg02_operation_produces_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new MG02()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['a-produces']");
-		assertObject(getSwaggerWithFile(new MG02()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['a-produces']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
-	public static class MG03 {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger("produces:['b-produces']"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mg03_operation_produces_swaggerOnMethod() throws Exception {
-		assertObject(getSwagger(new MG03()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['b-produces']");
-		assertObject(getSwaggerWithFile(new MG03()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['b-produces']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
-	public static class MG04a {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(produces="['c-produces-1','c-produces-2']"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mg04a_operation_produces_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new MG04a()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['c-produces-1','c-produces-2']");
-		assertObject(getSwaggerWithFile(new MG04a()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['c-produces-1','c-produces-2']");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
-	public static class MG04b {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(produces="c-produces-1, c-produces-2"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mg04b_operation_produces_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new MG04b()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['c-produces-1','c-produces-2']");
-		assertObject(getSwaggerWithFile(new MG04b()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['c-produces-1','c-produces-2']");
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
-	public static class MG05 {
-		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(produces="['$L{foo}']"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mg05_operation_produces_swaggerOnAnnotation_localized() throws Exception {
-		assertObject(getSwagger(new MG05()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['l-foo']");
-		assertObject(getSwaggerWithFile(new MG05()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['l-foo']");
-	}
-
-	@Rest(serializers={JsonSerializer.class})
-	public static class MG06a {
-		@RestMethod(name=PUT,path="/path2/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mg06a_operation_produces_serializersOnClass() throws Exception {
-		assertObject(getSwagger(new MG06a()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("null");
-		assertObject(getSwaggerWithFile(new MG06a()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("null");
-	}
-
-	@Rest(serializers={JsonSerializer.class})
-	public static class MG06b {
-		@RestMethod(name=PUT,path="/path2/{foo}",serializers={XmlSerializer.class})
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mg06b_operation_produces_serializersOnClassAndMethod() throws Exception {
-		assertObject(getSwagger(new MG06b()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("['text/xml']");
-		assertObject(getSwaggerWithFile(new MG06b()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("['text/xml']");
-	}
-
-	@Rest(serializers={JsonSerializer.class},swagger=@ResourceSwagger("paths:{'/path2/{foo}':{put:{produces:['a-produces']}}}"))
-	public static class MG06c {
-		@RestMethod(name=PUT,path="/path2/{foo}",serializers={XmlSerializer.class})
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mg06c_operation_produces_serializersOnClassAndMethodWithSwagger() throws Exception {
-		assertObject(getSwagger(new MG06c()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("['a-produces']");
-		assertObject(getSwaggerWithFile(new MG06c()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("['a-produces']");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/deprecated
-	//=================================================================================================================
-
-	@Rest
-	public static class MH06 {
-		@RestMethod(name=GET,path="/path2/{foo}")
-		@Deprecated
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mh06_operation_deprecated_Deprecated() throws Exception {
-		assertObject(getSwagger(new MH06()).getPaths().get("/path2/{foo}").get("get").getDeprecated()).json().is("true");
-		assertObject(getSwaggerWithFile(new MH06()).getPaths().get("/path2/{foo}").get("get").getDeprecated()).json().is("true");
-	}
-
-	@Rest
-	@Deprecated
-	public static class MH07 {
-		@RestMethod(name=GET,path="/path2/{foo}")
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void mh07_operation_deprecated_Deprecated() throws Exception {
-		assertObject(getSwagger(new MH07()).getPaths().get("/path2/{foo}").get("get").getDeprecated()).json().is("true");
-		assertObject(getSwaggerWithFile(new MH07()).getPaths().get("/path2/{foo}").get("get").getDeprecated()).json().is("true");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/parameters/query
-	//=================================================================================================================
-
-	@Rest
-	public static class NA01 {
-		@RestMethod(name=GET,path="/path/{foo}/query")
-		public Foo doFoo(@Query("foo") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void na01a_query_type_default() throws Exception {
-		ParameterInfo x = getSwagger(new NA01()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
-		assertEquals("object", x.getType());
-		assertEquals(null, x.getDescription());
-		assertEquals(null, x.getRequired());
-		assertEquals(null, x.getAllowEmptyValue());
-		assertEquals(null, x.getExclusiveMaximum());
-		assertEquals(null, x.getExclusiveMinimum());
-		assertEquals(null, x.getUniqueItems());
-		assertEquals(null, x.getFormat());
-		assertEquals(null, x.getCollectionFormat());
-		assertEquals(null, x.getPattern());
-		assertEquals(null, x.getMaximum());
-		assertEquals(null, x.getMinimum());
-		assertEquals(null, x.getMultipleOf());
-		assertEquals(null, x.getMaxLength());
-		assertEquals(null, x.getMinLength());
-		assertEquals(null, x.getMaxItems());
-		assertEquals(null, x.getMinItems());
-	}
-	@Test
-	public void na01b_query_type_default_withFile() throws Exception {
-		ParameterInfo x = getSwaggerWithFile(new NA01()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
-		assertEquals("string", x.getType());
-		assertEquals("s-description", x.getDescription());
-		assertObject(x.getRequired()).json().is("true");
-		assertObject(x.getAllowEmptyValue()).json().is("true");
-		assertObject(x.getExclusiveMaximum()).json().is("true");
-		assertObject(x.getExclusiveMinimum()).json().is("true");
-		assertObject(x.getUniqueItems()).json().is("true");
-		assertEquals("s-format", x.getFormat());
-		assertEquals("s-collectionFormat", x.getCollectionFormat());
-		assertEquals("s-pattern", x.getPattern());
-		assertObject(x.getMaximum()).json().is("1.0");
-		assertObject(x.getMinimum()).json().is("1.0");
-		assertObject(x.getMultipleOf()).json().is("1.0");
-		assertObject(x.getMaxLength()).json().is("1");
-		assertObject(x.getMinLength()).json().is("1");
-		assertObject(x.getMaxItems()).json().is("1");
-		assertObject(x.getMinItems()).json().is("1");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger({
-			"paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',",
-				"name:'foo',",
-				"type:'int32',",
-				"description:'a-description',",
-				"required:false,",
-				"allowEmptyValue:false,",
-				"exclusiveMaximum:false,",
-				"exclusiveMinimum:false,",
-				"uniqueItems:false,",
-				"format:'a-format',",
-				"collectionFormat:'a-collectionFormat',",
-				"pattern:'a-pattern',",
-				"maximum:2.0,",
-				"minimum:2.0,",
-				"multipleOf:2.0,",
-				"maxLength:2,",
-				"minLength:2,",
-				"maxItems:2,",
-				"minItems:2",
-			"}]}}}"
-		})
-	)
-	public static class NA02 {
-		@RestMethod(name=GET,path="/path/{foo}/query")
-		public Foo doFoo(@Query("foo") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void na02a_query_type_swaggerOnClass() throws Exception {
-		ParameterInfo x = getSwagger(new NA02()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
-		assertEquals("int32", x.getType());
-		assertEquals("a-description", x.getDescription());
-		assertObject(x.getRequired()).json().is("false");
-		assertObject(x.getAllowEmptyValue()).json().is("false");
-		assertObject(x.getExclusiveMaximum()).json().is("false");
-		assertObject(x.getExclusiveMinimum()).json().is("false");
-		assertObject(x.getUniqueItems()).json().is("false");
-		assertEquals("a-format", x.getFormat());
-		assertEquals("a-collectionFormat", x.getCollectionFormat());
-		assertEquals("a-pattern", x.getPattern());
-		assertObject(x.getMaximum()).json().is("2.0");
-		assertObject(x.getMinimum()).json().is("2.0");
-		assertObject(x.getMultipleOf()).json().is("2.0");
-		assertObject(x.getMaxLength()).json().is("2");
-		assertObject(x.getMinLength()).json().is("2");
-		assertObject(x.getMaxItems()).json().is("2");
-		assertObject(x.getMinItems()).json().is("2");
-	}
-	@Test
-	public void na02b_query_type_swaggerOnClass_withFile() throws Exception {
-		ParameterInfo x = getSwaggerWithFile(new NA02()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
-		assertEquals("int32", x.getType());
-		assertEquals("a-description", x.getDescription());
-		assertObject(x.getRequired()).json().is("false");
-		assertObject(x.getAllowEmptyValue()).json().is("false");
-		assertObject(x.getExclusiveMaximum()).json().is("false");
-		assertObject(x.getExclusiveMinimum()).json().is("false");
-		assertObject(x.getUniqueItems()).json().is("false");
-		assertEquals("a-format", x.getFormat());
-		assertEquals("a-collectionFormat", x.getCollectionFormat());
-		assertEquals("a-pattern", x.getPattern());
-		assertObject(x.getMaximum()).json().is("2.0");
-		assertObject(x.getMinimum()).json().is("2.0");
-		assertObject(x.getMultipleOf()).json().is("2.0");
-		assertObject(x.getMaxLength()).json().is("2");
-		assertObject(x.getMinLength()).json().is("2");
-		assertObject(x.getMaxItems()).json().is("2");
-		assertObject(x.getMinItems()).json().is("2");
-	}
-
-	@Rest(
-		swagger=@ResourceSwagger({
-			"paths:{'/path/{foo}/query':{get:{parameters:[{",
-				"'in':'query',",
-				"name:'foo',",
-				"type:'int32',",
-				"description:'a-description',",
-				"required:false,",
-				"allowEmptyValue:false,",
-				"exclusiveMaximum:false,",
-				"exclusiveMinimum:false,",
-				"uniqueItems:false,",
-				"format:'a-format',",
-				"collectionFormat:'a-collectionFormat',",
-				"pattern:'a-pattern',",
-				"maximum:2.0,",
-				"minimum:2.0,",
-				"multipleOf:2.0,",
-				"maxLength:2,",
-				"minLength:2,",
-				"maxItems:2,",
-				"minItems:2",
-			"}]}}}"
-		})
-	)
-	public static class NA03 {
-		@RestMethod(name=GET,path="/path/{foo}/query",
-			swagger=@MethodSwagger({
-				"parameters:[{",
-					"'in':'query',",
-					"name:'foo',",
-					"type:'int64',",
-					"description:'b-description',",
-					"required:'true',",
-					"allowEmptyValue:'true',",
-					"exclusiveMaximum:'true',",
-					"exclusiveMinimum:'true',",
-					"uniqueItems:'true',",
-					"format:'b-format',",
-					"collectionFormat:'b-collectionFormat',",
-					"pattern:'b-pattern',",
-					"maximum:3.0,",
-					"minimum:3.0,",
-					"multipleOf:3.0,",
-					"maxLength:3,",
-					"minLength:3,",
-					"maxItems:3,",
-					"minItems:3",
-				"}]"
-			}))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void na03a_query_type_swaggerOnMethod() throws Exception {
-		ParameterInfo x = getSwagger(new NA03()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
-		assertEquals("int64", x.getType());
-		assertEquals("b-description", x.getDescription());
-		assertObject(x.getRequired()).json().is("true");
-		assertObject(x.getAllowEmptyValue()).json().is("true");
-		assertObject(x.getExclusiveMaximum()).json().is("true");
-		assertObject(x.getExclusiveMinimum()).json().is("true");
-		assertObject(x.getUniqueItems()).json().is("true");
-		assertEquals("b-format", x.getFormat());
-		assertEquals("b-collectionFormat", x.getCollectionFormat());
-		assertEquals("b-pattern", x.getPattern());
-		assertObject(x.getMaximum()).json().is("3.0");
-		assertObject(x.getMinimum()).json().is("3.0");
-		assertObject(x.getMultipleOf()).json().is("3.0");
-		assertObject(x.getMaxLength()).json().is("3");
-		assertObject(x.getMinLength()).json().is("3");
-		assertObject(x.getMaxItems()).json().is("3");
-		assertObject(x.getMinItems()).json().is("3");
-	}
-	@Test
-	public void na03b_query_type_swaggerOnMethod_withFile() throws Exception {
-		ParameterInfo x = getSwaggerWithFile(new NA03()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
-		assertEquals("int64", x.getType());
-		assertEquals("b-description", x.getDescription());
-		assertObject(x.getRequired()).json().is("true");
-		assertObject(x.getAllowEmptyValue()).json().is("true");
-		assertObject(x.getExclusiveMaximum()).json().is("true");
-		assertObject(x.getExclusiveMinimum()).json().is("true");
-		assertObject(x.getUniqueItems()).json().is("true");
-		assertEquals("b-format", x.getFormat());
-		assertEquals("b-collectionFormat", x.getCollectionFormat());
-		assertEquals("b-pattern", x.getPattern());
-		assertObject(x.getMaximum()).json().is("3.0");
-		assertObject(x.getMinimum()).json().is("3.0");
-		assertObject(x.getMultipleOf()).json().is("3.0");
-		assertObject(x.getMaxLength()).json().is("3");
-		assertObject(x.getMinLength()).json().is("3");
-		assertObject(x.getMaxItems()).json().is("3");
-		assertObject(x.getMinItems()).json().is("3");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/parameters/query/example
-	//=================================================================================================================
-
-	@Rest
-	public static class NR01 {
-		@RestMethod(name=GET,path="/path/{foo}/query")
-		public Foo doFoo(@Query("foo") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void nr01_query_example_default() throws Exception {
-		assertEquals(null, getSwagger(new NR01()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-		assertEquals("{id:1}", getSwaggerWithFile(new NR01()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',name:'foo',x-example:'{id:2}'}]}}}"))
-	public static class NR02 {
-		@RestMethod(name=GET,path="/path/{foo}/query")
-		public Foo doFoo(@Query("foo") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void nr02_query_example_swaggerOnClass() throws Exception {
-		assertEquals("{id:2}", getSwagger(new NR02()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-		assertEquals("{id:2}", getSwaggerWithFile(new NR02()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',name:'foo',x-example:'{id:2}'}]}}}"))
-	public static class NR03 {
-		@RestMethod(name=GET,path="/path/{foo}/query",swagger=@MethodSwagger("parameters:[{'in':'query',name:'foo',x-example:'{id:3}'}]"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void nr03_query_example_swaggerOnMethod() throws Exception {
-		assertEquals("{id:3}", getSwagger(new NR03()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-		assertEquals("{id:3}", getSwaggerWithFile(new NR03()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',name:'foo',x-example:'{id:2}'}]}}}"))
-	public static class NR04 {
-		@RestMethod(name=GET,path="/path/{foo}/query")
-		public Foo doFoo(@Query(n="foo",ex="{id:4}") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void nr04_query_example_swaggerOnAnnotation() throws Exception {
-		assertEquals("{id:4}", getSwagger(new NR04()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-		assertEquals("{id:4}", getSwaggerWithFile(new NR04()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',name:'foo',x-example:'{id:2}'}]}}}"))
-	public static class NR05 {
-		@RestMethod(name=GET,path="/path/{foo}/query")
-		public Foo doFoo(@Query(n="foo",ex="{id:$L{5}}") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void nr05_query_example_swaggerOnAnnotation_localized() throws Exception {
-		assertEquals("{id:5}", getSwagger(new NR05()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-		assertEquals("{id:5}", getSwaggerWithFile(new NR05()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/parameters/body/examples
-	//=================================================================================================================
-
-	@Rest
-	public static class NS01 {
-		@RestMethod(name=GET,path="/path/{foo}/body")
-		public Foo doFoo(@Body Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void ns01_body_examples_default() throws Exception {
-		assertEquals(null, getSwagger(new NS01()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples());
-		assertObject(getSwaggerWithFile(new NS01()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'a'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/body':{get:{parameters:[{'in':'body',x-examples:{foo:'b'}}]}}}"))
-	public static class NS02 {
-		@RestMethod(name=GET,path="/path/{foo}/body")
-		public Foo doFoo(@Body Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void ns02_body_examples_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new NS02()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'b'}");
-		assertObject(getSwaggerWithFile(new NS02()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'b'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/body':{get:{parameters:[{'in':'body',x-examples:{foo:'b'}}]}}}"))
-	public static class NS03 {
-		@RestMethod(name=GET,path="/path/{foo}/body",swagger=@MethodSwagger("parameters:[{'in':'body',x-examples:{foo:'c'}}]"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void ns03_body_examples_swaggerOnMethods() throws Exception {
-		assertObject(getSwagger(new NS03()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'c'}");
-		assertObject(getSwaggerWithFile(new NS03()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'c'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/body':{get:{parameters:[{'in':'body',x-examples:{foo:'b'}}]}}}"))
-	public static class NS04 {
-		@RestMethod(name=GET,path="/path/{foo}/body")
-		public Foo doFoo(@Body(exs="{foo:'d'}") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void ns04_body_examples_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new NS04()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'d'}");
-		assertObject(getSwaggerWithFile(new NS04()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'d'}");
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/body':{get:{parameters:[{'in':'body',examples:{foo:'b'}}]}}}"))
-	public static class NS05 {
-		@RestMethod(name=GET,path="/path/{foo}/body")
-		public Foo doFoo(@Body(exs="{foo:'$L{foo}'}") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void ns05_body_examples_swaggerOnAnnotation_localized() throws Exception {
-		assertObject(getSwagger(new NS05()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'l-foo'}");
-		assertObject(getSwaggerWithFile(new NS05()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'l-foo'}");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/parameters/query/schema
-	//=================================================================================================================
-
-	@Rest
-	public static class NT01 {
-		@RestMethod(name=GET,path="/path/{foo}/query")
-		public Foo doFoo(@Query("foo") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void nt01_query_schema_default() throws Exception {
-		assertObject(getSwagger(new NT01()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{properties:{id:{format:'int32',type:'integer'}}}");
-		assertObject(getSwaggerWithFile(new NT01()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'#/definitions/Foo'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{in:'query',name:'foo',schema:{$ref:'b'}}]}}}"))
-	public static class NT02 {
-		@RestMethod(name=GET,path="/path/{foo}/query")
-		public Foo doFoo(@Query("foo") Foo foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void nt02_query_schema_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new NT02()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'b'}");
-		assertObject(getSwaggerWithFile(new NT02()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'b'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{in:'query',name:'foo',schema:{$ref:'b'}}]}}}"))
-	public static class NT03 {
-
-		@RestMethod(name=GET,path="/path/{foo}/query",swagger=@MethodSwagger("parameters:[{'in':'query',name:'foo',schema:{$ref:'c'}}]"))
-		public Foo doFoo() {
-			return null;
-		}
-	}
-
-	@Test
-	public void nt03_query_schema_swaggerOnMethnt() throws Exception {
-		assertObject(getSwagger(new NT03()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'c'}");
-		assertObject(getSwaggerWithFile(new NT03()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'c'}");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/responses/<response>/description
-	//=================================================================================================================
-
-	@Rest
-	public static class OA01a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OA01x> foo) {}
-	}
-	@Rest
-	public static class OA01b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OA01x doFoo() { return null;}
-	}
-	@Response(code=100)
-	public static class OA01x {
-		public String foo;
-	}
-
-	@Test
-	public void oa01a_responses_100_description_default() throws Exception {
-		assertEquals("Continue", getSwagger(new OA01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("s-100-description", getSwaggerWithFile(new OA01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-	}
-	@Test
-	public void oa01b_responses_100_description_default() throws Exception {
-		assertEquals("Continue", getSwagger(new OA01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("s-100-description", getSwaggerWithFile(new OA01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
-	public static class OA02 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(@ResponseStatus Value<Integer> foo) {}
-	}
-
-	@Test
-	public void oa02_response_100_description_swaggerOnClass() throws Exception {
-		assertEquals("a-100-description", getSwagger(new OA02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("a-100-description", getSwaggerWithFile(new OA02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
-	public static class OA03 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{description:'b-100-description'}}"))
-		public void doFoo(@ResponseStatus Value<Integer> foo) {}
-	}
-
-	@Test
-	public void oa03_response_100_description_swaggerOnMethod() throws Exception {
-		assertEquals("b-100-description", getSwagger(new OA03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("b-100-description", getSwaggerWithFile(new OA03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
-	public static class OA04a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OA04x> foo) {}
-	}
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
-	public static class OA04b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OA04x doFoo() {return null;}
-	}
-	@Response(code=100,description="c-100-description")
-	public static class OA04x {}
-
-	@Test
-	public void oa04a_response_100_description_swaggerOnAnnotation() throws Exception {
-		assertEquals("c-100-description", getSwagger(new OA04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("c-100-description", getSwaggerWithFile(new OA04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-	}
-	@Test
-	public void oa04b_response_100_description_swaggerOnAnnotation() throws Exception {
-		assertEquals("c-100-description", getSwagger(new OA04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("c-100-description", getSwaggerWithFile(new OA04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
-	public static class OA05a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OA05x> foo) {}
-	}
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
-	public static class OA05b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OA05x doFoo() {return null;}
-	}
-	@Response(code=100,description="$L{foo}")
-	public static class OA05x {}
-
-	@Test
-	public void oa05a_response_100_description_swaggerOnAnnotation_localized() throws Exception {
-		assertEquals("l-foo", getSwagger(new OA05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("l-foo", getSwaggerWithFile(new OA05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-	}
-	@Test
-	public void oa05b_response_100_description_swaggerOnAnnotation_localized() throws Exception {
-		assertEquals("l-foo", getSwagger(new OA05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-		assertEquals("l-foo", getSwaggerWithFile(new OA05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/responses/<response>/headers
-	//=================================================================================================================
-
-	@Rest
-	public static class OB01a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OB01x> foo) {}
-	}
-	@Rest
-	public static class OB01b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OB01x doFoo() {return null;}
-	}
-	@Response(code=100)
-	public static class OB01x {
-		public String foo;
-	}
-
-	@Test
-	public void ob01a_responses_100_headers_default() throws Exception {
-		assertEquals(null, getSwagger(new OB01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
-		assertObject(getSwaggerWithFile(new OB01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'s-description',type:'integer',format:'int32'}}");
-	}
-	@Test
-	public void ob01b_responses_100_headers_default() throws Exception {
-		assertEquals(null, getSwagger(new OB01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
-		assertObject(getSwaggerWithFile(new OB01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'s-description',type:'integer',format:'int32'}}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
-	public static class OB02 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public Foo doFoo(@ResponseStatus Value<Integer> foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void ob02_response_100_headers_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new OB02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}");
-		assertObject(getSwaggerWithFile(new OB02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
-	public static class OB03 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{headers:{'X-Foo':{description:'c-description',type:'integer',format:'int32'}}}}"))
-		public Foo doFoo(@ResponseStatus Value<Integer> foo) {
-			return null;
-		}
-	}
-
-	@Test
-	public void ob03_response_100_headers_swaggerOnMethod() throws Exception {
-		assertObject(getSwagger(new OB03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'c-description',type:'integer',format:'int32'}}");
-		assertObject(getSwaggerWithFile(new OB03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'c-description',type:'integer',format:'int32'}}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
-	public static class OB04a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OB04x> foo) {}
-	}
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
-	public static class OB04b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OB04x doFoo() {return null;}
-	}
-	@Response(code=100,headers=@ResponseHeader(name="X-Foo",description="d-description",type="integer",format="int32"))
-	public static class OB04x {}
-
-	@Test
-	public void ob04a_response_100_headers_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new OB04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}");
-		assertObject(getSwaggerWithFile(new OB04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}");
-	}
-	@Test
-	public void ob04b_response_100_headers_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new OB04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}");
-		assertObject(getSwaggerWithFile(new OB04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}");
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
-	public static class OB05a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OB05x> foo) {}
-	}
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
-	public static class OB05b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OB05x doFoo() {return null;}
-	}
-	@Response(code=100,headers=@ResponseHeader(name="X-Foo",description="$L{foo}",type="integer",format="int32"))
-	public static class OB05x {}
-
-	@Test
-	public void ob05a_response_100_headers_swaggerOnAnnotation_localized() throws Exception {
-		assertObject(getSwagger(new OB05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}");
-		assertObject(getSwaggerWithFile(new OB05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}");
-	}
-	@Test
-	public void ob05b_response_100_headers_swaggerOnAnnotation_localized() throws Exception {
-		assertObject(getSwagger(new OB05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}");
-		assertObject(getSwaggerWithFile(new OB05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/responses/<response>/example
-	//=================================================================================================================
-
-	@Rest
-	public static class OC01a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OC01x> foo) {}
-	}
-	@Rest
-	public static class OC01b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OC01x doFoo() {return null;}
-	}
-	@Response(code=100)
-	public static class OC01x {
-		public String foo;
-	}
-
-	@Test
-	public void oc01a_responses_100_example_default() throws Exception {
-		assertEquals(null, getSwagger(new OC01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-		assertEquals("{foo:'a'}", getSwaggerWithFile(new OC01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-	}
-	@Test
-	public void oc01b_responses_100_example_default() throws Exception {
-		assertEquals(null, getSwagger(new OC01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-		assertEquals("{foo:'a'}", getSwaggerWithFile(new OC01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
-	public static class OC02 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(@ResponseStatus Value<Integer> foo) {}
-	}
-
-	@Test
-	public void oc02_response_100_example_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new OC02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample()).json().is("{foo:'b'}");
-		assertObject(getSwaggerWithFile(new OC02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample()).json().is("{foo:'b'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
-	public static class OC03 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{example:{foo:'c'}}}"))
-		public void doFoo(@ResponseStatus Value<Integer> foo) {}
-	}
-
-	@Test
-	public void oc03_response_100_example_swaggerOnMethod() throws Exception {
-		assertObject(getSwagger(new OC03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample()).json().is("{foo:'c'}");
-		assertObject(getSwaggerWithFile(new OC03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample()).json().is("{foo:'c'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
-	public static class OC04a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OC04x> foo) {}
-	}
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
-	public static class OC04b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OC04x doFoo() {return null;}
-	}
-	@Response(code=100,example="{foo:'d'}")
-	public static class OC04x {
-		public String foo;
-	}
-
-	@Test
-	public void oc04a_response_100_example_swaggerOnAnnotation() throws Exception {
-		assertEquals("{foo:'d'}", getSwagger(new OC04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-		assertEquals("{foo:'d'}", getSwaggerWithFile(new OC04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-	}
-	@Test
-	public void oc04b_response_100_example_swaggerOnAnnotation() throws Exception {
-		assertEquals("{foo:'d'}", getSwagger(new OC04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-		assertEquals("{foo:'d'}", getSwaggerWithFile(new OC04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
-	public static class OC05a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OC05x> foo) {}
-	}
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
-	public static class OC05b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OC05x doFoo() {return null;}
-	}
-	@Response(code=100,example="{foo:'$L{foo}'}")
-	public static class OC05x {
-		public String foo;
-	}
-
-	@Test
-	public void oc05a_response_100_example_swaggerOnAnnotation_localized() throws Exception {
-		assertEquals("{foo:'l-foo'}", getSwagger(new OC05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-		assertEquals("{foo:'l-foo'}", getSwaggerWithFile(new OC05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-	}
-	@Test
-	public void oc05b_response_100_example_swaggerOnAnnotation_localized() throws Exception {
-		assertEquals("{foo:'l-foo'}", getSwagger(new OC05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-		assertEquals("{foo:'l-foo'}", getSwaggerWithFile(new OC05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/responses/<response>/examples
-	//=================================================================================================================
-
-	@Rest
-	public static class OD01a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OD01x> foo) {}
-	}
-	@Rest
-	public static class OD01b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OD01x doFoo() {return null;}
-	}
-	@Response(code=100)
-	public static class OD01x {
-		public String foo;
-	}
-
-	@Test
-	public void od01a_responses_100_examples_default() throws Exception {
-		assertEquals(null, getSwagger(new OD01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
-		assertObject(getSwaggerWithFile(new OD01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void od01b_responses_100_examples_default() throws Exception {
-		assertEquals(null, getSwagger(new OD01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
-		assertObject(getSwaggerWithFile(new OD01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:'a'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
-	public static class OD02 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(@ResponseStatus Value<Integer> foo) {}
-	}
-
-	@Test
-	public void od02_response_100_examples_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new OD02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'b'}}");
-		assertObject(getSwaggerWithFile(new OD02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'b'}}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
-	public static class OD03 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{examples:{foo:{bar:'c'}}}}"))
-		public void doFoo(@ResponseStatus Value<Integer> foo) {}
-	}
-
-	@Test
-	public void od03_response_100_examples_swaggerOnMethod() throws Exception {
-		assertObject(getSwagger(new OD03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'c'}}");
-		assertObject(getSwaggerWithFile(new OD03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'c'}}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
-	public static class OD04a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OD04x> foo) {}
-	}
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
-	public static class OD04b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OD04x doFoo() {return null;}
-	}
-	@Response(code=100,examples="{foo:{bar:'d'}}")
-	public static class OD04x {}
-
-	@Test
-	public void od04a_response_100_examples_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new OD04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'d'}}");
-		assertObject(getSwaggerWithFile(new OD04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'d'}}");
-	}
-	@Test
-	public void od04b_response_100_examples_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new OD04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'d'}}");
-		assertObject(getSwaggerWithFile(new OD04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'d'}}");
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
-	public static class OD05a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OD05x> foo) {}
-	}
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
-	public static class OD05b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OD05x doFoo() {return null;}
-	}
-	@Response(code=100,examples="{foo:{bar:'$L{foo}'}}")
-	public static class OD05x {}
-
-	@Test
-	public void od05a_response_100_examples_swaggerOnAnnotation_lodalized() throws Exception {
-		assertObject(getSwagger(new OD05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'l-foo'}}");
-		assertObject(getSwaggerWithFile(new OD05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'l-foo'}}");
-	}
-	@Test
-	public void od05b_response_100_examples_swaggerOnAnnotation_lodalized() throws Exception {
-		assertObject(getSwagger(new OD05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'l-foo'}}");
-		assertObject(getSwaggerWithFile(new OD05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'l-foo'}}");
-	}
-
-	//=================================================================================================================
-	// /paths/<path>/<method>/responses/<response>/schema
-	//=================================================================================================================
-
-	@Rest
-	public static class OE01a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OE01x> foo) {}
-	}
-	@Rest
-	public static class OE01b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OE01x doFoo() {return null;}
-	}
-	@Response(code=100)
-	public static class OE01x extends Foo {}
-
-	@Test
-	public void oe01a_responses_100_schema_default() throws Exception {
-		assertObject(getSwagger(new OE01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{type:'object',properties:{id:{format:'int32',type:'integer'}}}");
-		assertObject(getSwaggerWithFile(new OE01a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{type:'array',items:{'$ref':'#/definitions/Foo'}}");
-	}
-	@Test
-	public void oe01b_responses_100_schema_default() throws Exception {
-		assertObject(getSwagger(new OE01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{type:'object',properties:{id:{format:'int32',type:'integer'}}}");
-		assertObject(getSwaggerWithFile(new OE01b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{type:'array',items:{'$ref':'#/definitions/Foo'}}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
-	public static class OE02 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(@ResponseStatus Value<Integer> foo) {}
-	}
-
-	@Test
-	public void oe02_response_100_schema_swaggerOnClass() throws Exception {
-		assertObject(getSwagger(new OE02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'b'}");
-		assertObject(getSwaggerWithFile(new OE02()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'b'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
-	public static class OE03 {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{schema:{$ref:'c'}}}}"))
-		public void doFoo(@ResponseStatus Value<Integer> foo) {}
-	}
-
-	@Test
-	public void oe03_response_100_schema_swaggerOnMethoe() throws Exception {
-		assertObject(getSwagger(new OE03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'c'}");
-		assertObject(getSwaggerWithFile(new OE03()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'c'}");
-	}
-
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
-	public static class OE04a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OE04x> foo) {}
-	}
-	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
-	public static class OE04b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OE04x doFoo() {return null;}
-	}
-	@Response(code=100,schema=@Schema($ref="d"))
-	public static class OE04x extends Foo {}
-
-	@Test
-	public void oe04a_response_100_schema_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new OE04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'d'}");
-		assertObject(getSwaggerWithFile(new OE04a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'d'}");
-	}
-	@Test
-	public void oe04b_response_100_schema_swaggerOnAnnotation() throws Exception {
-		assertObject(getSwagger(new OE04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'d'}");
-		assertObject(getSwaggerWithFile(new OE04b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'d'}");
-	}
-
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
-	public static class OE05a {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public void doFoo(Value<OE05x> foo) {}
-	}
-	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
-	public static class OE05b {
-		@RestMethod(name=GET,path="/path/{foo}/responses/100")
-		public OE05x doFoo() {return null;}
-	}
-	@Response(code=100,schema=@Schema("{$ref:'$L{foo}'}"))
-	public static class OE05x extends Foo {}
-
-	@Test
-	public void oe05a_response_100_schema_swaggerOnAnnotation_loealized() throws Exception {
-		assertObject(getSwagger(new OE05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'l-foo'}");
-		assertObject(getSwaggerWithFile(new OE05a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'l-foo'}");
-	}
-	@Test
-	public void oe05b_response_100_schema_swaggerOnAnnotation_loealized() throws Exception {
-		assertObject(getSwagger(new OE05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'l-foo'}");
-		assertObject(getSwaggerWithFile(new OE05b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'l-foo'}");
-	}
-
-	@Bean(typeName="Foo")
-	public static class Foo {
-		public int id;
-	}
-
-	//=================================================================================================================
-	// Example bean with getter-only property.
-	//=================================================================================================================
-
-	@Rest
-	public static class P extends BasicRestServlet {
-		private static final long serialVersionUID = 1L;
-
-		@RestMethod(name=GET,path="/")
-		public P01 doFoo(@Body P01 body) {
-			return null;
-		}
-	}
-
-	@Bean(sort=true)
-	public static class P01 {
-		private int f1;
-
-		public P01 setF1(int f1) {
-			this.f1 = f1;
-			return this;
-		}
-
-		public int getF1() {
-			return f1;
-		}
-
-		public int getF2() {
-			return 2;
-		}
-
-		@Example
-		public static P01 example() {
-			return new P01().setF1(1);
-		}
-	}
-
-	static MockRestClient p = MockRestClient.build(P.class);
-
-	@Test
-	public void p01_bodyWithReadOnlyProperty() throws Exception {
-		Swagger s = JsonParser.DEFAULT.parse(p.options("/").accept("application/json").run().getBody().asString(), Swagger.class);
-		Operation o = s.getOperation("/", "get");
-		ParameterInfo pi = o.getParameter("body", null);
-		assertEquals("{\n\tf1: 1,\n\tf2: 2\n}", pi.getExamples().get("application/json+simple"));
-		ResponseInfo ri = o.getResponse("200");
-		assertEquals("{\n\tf1: 1,\n\tf2: 2\n}", ri.getExamples().get("application/json+simple"));
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BeanContextPropertiesTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BeanContextPropertiesTest.java
deleted file mode 100644
index 4768b11..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/BeanContextPropertiesTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-// ***************************************************************************************************************************

-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

-// * with the License.  You may obtain a copy of the License at                                                              *

-// *                                                                                                                         *

-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

-// *                                                                                                                         *

-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

-// * specific language governing permissions and limitations under the License.                                              *

-// ***************************************************************************************************************************

-package org.apache.juneau.rest;

-

-import static org.apache.juneau.http.HttpMethod.*;

-import static org.junit.runners.MethodSorters.*;

-

-import java.util.*;

-

-import org.apache.juneau.*;

-import org.apache.juneau.annotation.*;

-import org.apache.juneau.http.annotation.Header;

-import org.apache.juneau.http.annotation.Path;

-import org.apache.juneau.http.annotation.Query;

-import org.apache.juneau.rest.annotation.*;

-import org.apache.juneau.rest.mock2.*;

-import org.apache.juneau.transforms.*;

-import org.junit.*;

-

-@FixMethodOrder(NAME_ASCENDING)

-public class BeanContextPropertiesTest  {

-

-	//=================================================================================================================

-	// Validate that transforms defined on class transform to underlying bean context.

-	//=================================================================================================================

-

-	@Rest

-	@BeanConfig(pojoSwaps=TemporalDateSwap.IsoInstant.class)

-	public static class A {

-		@RestMethod(name=GET, path="/{d1}")

-		public String testClassTransforms(@Path("d1") Date d1, @Query("d2") Date d2, @Header("X-D3") Date d3) throws Exception {

-			TemporalDateSwap df = TemporalDateSwap.IsoInstant.class.newInstance();

-			BeanSession session = BeanContext.DEFAULT.createSession();

-			return "d1="+df.swap(session, d1)+",d2="+df.swap(session, d2)+",d3="+df.swap(session, d3)+"";

-		}

-	}

-	static MockRestClient a = MockRestClient.build(A.class);

-

-	@Test

-	public void a01_testClassTransforms() throws Exception {

-		a.get("/2001-07-04T15:30:45Z?d2=2001-07-05T15:30:45Z").header("X-D3", "2001-07-06T15:30:45Z").run()

-			.assertBody().is("d1=2001-07-04T15:30:45Z,d2=2001-07-05T15:30:45Z,d3=2001-07-06T15:30:45Z");

-	}

-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/DebugModeTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/DebugModeTest.java
deleted file mode 100644
index c7b9881..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/DebugModeTest.java
+++ /dev/null
@@ -1,1196 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.util.logging.*;
-
-import javax.servlet.http.*;
-
-import org.apache.juneau.internal.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.config.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class DebugModeTest {
-
-	public static final CaptureCallLogger LOGGER = new CaptureCallLogger();
-
-	public static class CaptureCallLogger extends BasicRestCallLogger {
-
-		private volatile String msg;
-
-		public static CaptureCallLogger create() {
-			return LOGGER;
-		}
-
-		private CaptureCallLogger() {
-			super(null);
-		}
-
-		@Override
-		protected synchronized void log(Level level, String msg, Throwable e) {
-			this.msg = StringUtils.emptyIfNull(msg);
-		}
-
-		synchronized CaptureCallLogger reset() {
-			this.msg = null;
-			return this;
-		}
-
-		synchronized String getMessage() {
-			return msg;
-		}
-
-		public synchronized CaptureCallLogger assertMessageContains(String s) {
-			assertNotNull(msg);
-			if (! msg.contains(s))
-				assertEquals("Substring not found.", s, msg);
-			return this;
-		}
-	}
-
-	private static void assertLogged(boolean b) {
-		assertEquals(b, LOGGER.getMessage() != null);
-		LOGGER.reset();
-	}
-
-	private static void assertLoggedContains(String s) {
-		String msg = LOGGER.getMessage();
-		assertLogged(true);
-		if (! msg.contains(s))
-			assertEquals("Substring not found.", s, msg);
-		LOGGER.reset();
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @Rest(debug=""), various @RestMethod(debug)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest(callLogger=CaptureCallLogger.class)
-	public static class A1 implements BasicUniversalRest {
-		@RestMethod
-		public boolean getA01(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getA02(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getA03(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getA04(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="foo")
-		public boolean getA05(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA06(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA07(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-	}
-	static MockRestClient a1 = MockRestClient.buildSimpleJson(A1.class);
-	static MockRestClient a1d = MockRestClient.create(A1.class).simpleJson().header("X-Debug", true).build();
-
-	@Test
-	public void a01_debugDefault() throws Exception {
-
-		a1.get("/a01").run().assertBody().is("false");
-		assertLogged(false);
-		a1d.get("/a01").run().assertBody().is("false");
-		assertLogged(false);
-
-		a1.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-		a1d.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-
-		a1.get("/a03").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a03");
-		a1d.get("/a03").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a03");
-
-		a1.get("/a04").run().assertBody().is("false");
-		assertLogged(false);
-		a1d.get("/a04").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a04");
-
-		a1.get("/a05").run().assertBody().is("false");
-		assertLogged(false);
-		a1d.get("/a05").run().assertBody().is("false");
-		assertLogged(false);
-
-		a1.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-		a1d.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-
-		a1.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-		a1d.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-	}
-
-	@Rest(callLogger=CaptureCallLogger.class)
-	public static class A1a extends BasicRest {
-		@RestMethod
-		public boolean getA01(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getA02(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getA03(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getA04(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="foo")
-		public boolean getA05(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA06(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA07(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-	}
-	static MockRestClient a1a = MockRestClient.buildSimpleJson(A1a.class);
-	static MockRestClient a1ad = MockRestClient.create(A1a.class).simpleJson().header("X-Debug", true).build();
-
-	@Test
-	public void a01a_debugDefault() throws Exception {
-
-		a1a.get("/a01").run().assertBody().is("false");
-		assertLogged(false);
-		a1ad.get("/a01").run().assertBody().is("false");
-		assertLogged(false);
-
-		a1a.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-		a1ad.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-
-		a1a.get("/a03").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a03");
-		a1ad.get("/a03").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a03");
-
-		a1a.get("/a04").run().assertBody().is("false");
-		assertLogged(false);
-		a1ad.get("/a04").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a04");
-
-		a1a.get("/a05").run().assertBody().is("false");
-		assertLogged(false);
-		a1ad.get("/a05").run().assertBody().is("false");
-		assertLogged(false);
-
-		a1a.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-		a1ad.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-
-		a1a.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-		a1ad.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @Rest(debug="true"), various @RestMethod(debug)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest(callLogger=CaptureCallLogger.class, debug="true")
-	public static class A2 implements BasicUniversalRest {
-		@RestMethod
-		public boolean getA01(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getA02(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getA03(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getA04(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="foo")
-		public boolean getA05(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA06(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA07(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-	}
-	static MockRestClient a2 = MockRestClient.buildSimpleJson(A2.class);
-	static MockRestClient a2d = MockRestClient.create(A2.class).simpleJson().header("X-Debug", true).build();
-
-	@Test
-	public void a02_debugTrue() throws Exception {
-
-		a2.get("/a01").run().assertBody().is("true");
-		assertLogged(true);
-		a2d.get("/a01").run().assertBody().is("true");
-		assertLogged(true);
-
-		a2.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-		a2d.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-
-		a2.get("/a03").run().assertBody().is("true");
-		assertLogged(true);
-		a2d.get("/a03").run().assertBody().is("true");
-		assertLogged(true);
-
-		a2.get("/a04").run().assertBody().is("false");
-		assertLogged(false);
-		a2d.get("/a04").run().assertBody().is("true");
-		assertLogged(true);
-
-		a2.get("/a05").run().assertBody().is("true");
-		assertLogged(true);
-		a2d.get("/a05").run().assertBody().is("true");
-		assertLogged(true);
-
-		a2.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-		a2d.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-
-		a2.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-		a2d.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @Rest(debug="false"), various @RestMethod(debug)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest(callLogger=CaptureCallLogger.class,debug="false")
-	public static class A3 implements BasicUniversalRest {
-		@RestMethod
-		public boolean getA01(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getA02(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getA03(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getA04(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="foo")
-		public boolean getA05(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA06(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA07(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-	}
-	static MockRestClient a3 = MockRestClient.buildSimpleJson(A3.class);
-	static MockRestClient a3d = MockRestClient.create(A3.class).simpleJson().header("X-Debug", true).build();
-
-	@Test
-	public void a03_restDebugFalse() throws Exception {
-
-		a3.get("/a01").run().assertBody().is("false");
-		assertLogged(false);
-		a3d.get("/a01").run().assertBody().is("false");
-		assertLogged(false);
-
-		a3.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-		a3d.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-
-		a3.get("/a03").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a03");
-		a3d.get("/a03").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a03");
-
-		a3.get("/a04").run().assertBody().is("false");
-		assertLogged(false);
-		a3d.get("/a04").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a04");
-
-		a3.get("/a05").run().assertBody().is("false");
-		assertLogged(false);
-		a3d.get("/a05").run().assertBody().is("false");
-		assertLogged(false);
-
-		a3.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-		a3d.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-
-		a3.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-		a3d.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @Rest(debug="per-request"), various @RestMethod(debug)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest(callLogger=CaptureCallLogger.class,debug="per-request")
-	public static class A4 implements BasicUniversalRest {
-		@RestMethod
-		public boolean getA01(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getA02(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getA03(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getA04(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="foo")
-		public boolean getA05(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA06(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getA07(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-	}
-	static MockRestClient a4 = MockRestClient.buildSimpleJson(A4.class);
-	static MockRestClient a4d = MockRestClient.create(A4.class).simpleJson().header("X-Debug", true).build();
-
-	@Test
-	public void a04_debugPerRequest() throws Exception {
-
-		a4.get("/a01").run().assertBody().is("false");
-		assertLogged(false);
-		a4d.get("/a01").run().assertBody().is("true");
-		assertLogged(true);
-
-		a4.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-		a4d.get("/a02").run().assertBody().is("false");
-		assertLogged(false);
-
-		a4.get("/a03").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a03");
-		a4d.get("/a03").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a03");
-
-		a4.get("/a04").run().assertBody().is("false");
-		assertLogged(false);
-		a4d.get("/a04").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /a04");
-
-		a4.get("/a05").run().assertBody().is("false");
-		assertLogged(false);
-		a4d.get("/a05").run().assertBody().is("true");
-		assertLogged(true);
-
-		a4.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-		a4d.get("/a06").run().assertBody().is("true");
-		assertLogged(true);
-
-		a4.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-		a4d.get("/a07").run().assertBody().is("false");
-		assertLogged(false);
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Implement RestCallLogger directly.
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class B1 implements BasicUniversalRest, RestCallLogger {
-		@RestMethod
-		public boolean getB01(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getB02(RestRequest req) {
-			return req.isDebug();
-		}
-		@Override
-		public void log(RestCallLoggerConfig config, HttpServletRequest req, HttpServletResponse res) {
-			LOGGER.log(config, req, res);
-		}
-	}
-	static MockRestClient b1 = MockRestClient.buildSimpleJson(B1.class);
-
-	@Test
-	public void b01_debugDefault() throws Exception {
-
-		b1.get("/b01").run().assertBody().is("false");
-		assertLogged(false);
-		b1.get("/b02").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /b02");
-	}
-
-	@Rest
-	public static class B2 extends BasicRest {
-		@RestMethod
-		public boolean getB01(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getB02(RestRequest req) {
-			return req.isDebug();
-		}
-		@Override
-		public void log(RestCallLoggerConfig config, HttpServletRequest req, HttpServletResponse res) {
-			LOGGER.log(config, req, res);
-		}
-	}
-	static MockRestClient b2 = MockRestClient.buildSimpleJson(B2.class);
-
-	@Test
-	public void b02_debugDefault() throws Exception {
-
-		b2.get("/b01").run().assertBody().is("false");
-		assertLogged(false);
-		b2.get("/b02").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /b02");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @Rest(debugOn=""), various @RestMethod(debug)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest(
-		callLogger=CaptureCallLogger.class,
-		debugOn=""
-			+ "C1.getC02a=false,C1.getC02b=false,C1.getC02c=FALSE,C1.getC02d=FALSE,C1.getC02e=FALSE,C1.getC02f=FALSE,"
-			+ " C1.getC03a , C1.getC03b = true , C1.getC03c = TRUE , C1.getC03d = TRUE , C1.getC03e = TRUE , C1.getC03f = TRUE , "
-			+ "C1.getC04a=per-request,C1.getC04b=per-request,C1.getC04c=PER-REQUEST,C1.getC04d=PER-REQUEST,C1.getC04e=PER-REQUEST,C1.getC04f=PER-REQUEST,"
-			+ "C1.getC05a=foo,C1.getC05b=,C1.getC05c=foo,C1.getC05d=foo,C1.getC05e=foo,C1.getC05f=foo,"
-	)
-	public static class C1 implements BasicUniversalRest {
-
-		@RestMethod
-		public boolean getC01a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC01b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC01c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC01d(RestRequest req) {
-			return req.isDebug();
-		}
-
-		// debug=false
-		@RestMethod
-		public boolean getC02a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC02b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC02c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC02d(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC02e(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC02f(RestRequest req) {
-			return req.isDebug();
-		}
-
-		// debug=true
-		@RestMethod
-		public boolean getC03a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC03b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC03c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC03d(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC03e(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC03f(RestRequest req) {
-			return req.isDebug();
-		}
-
-		// debug=per-request
-		@RestMethod
-		public boolean getC04a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC04b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC04c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC04d(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC04e(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC04f(RestRequest req) {
-			return req.isDebug();
-		}
-
-		// debug=foo
-		@RestMethod
-		public boolean getC05a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC05b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC05c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC05d(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC05e(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC05f(RestRequest req) {
-			return req.isDebug();
-		}
-
-		@RestMethod
-		public boolean getC06a(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC06b(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC06c(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC06d(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-
-		@RestMethod
-		public boolean getC07a(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC07b(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC07c(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC07d(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-	}
-	static MockRestClient c1 = MockRestClient.buildSimpleJson(C1.class);
-	static MockRestClient c1d = MockRestClient.create(C1.class).simpleJson().header("X-Debug", true).build();
-
-	@Test
-	public void c01_debugDefault() throws Exception {
-
-		c1.get("/c01a").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c01a").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c01b").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c01b").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c01c").run().assertBody().is("true");
-		assertLogged(true);
-		c1d.get("/c01c").run().assertBody().is("true");
-		assertLogged(true);
-		c1.get("/c01d").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c01d").run().assertBody().is("true");
-		assertLogged(true);
-
-		c1.get("/c02a").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c02a").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c02b").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c02b").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c02c").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c02c").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c02d").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c02d").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c02e").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c02e").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c02f").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c02f").run().assertBody().is("false");
-		assertLogged(false);
-
-		c1.get("/c03a").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03a");
-		c1d.get("/c03a").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03a");
-		c1.get("/c03b").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03b");
-		c1d.get("/c03b").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03b");
-		c1.get("/c03c").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03c");
-		c1d.get("/c03c").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03c");
-		c1.get("/c03d").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03d");
-		c1d.get("/c03d").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03d");
-		c1.get("/c03e").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03e");
-		c1d.get("/c03e").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03e");
-		c1.get("/c03f").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03f");
-		c1d.get("/c03f").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03f");
-
-		c1.get("/c04a").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c04a").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04a");
-		c1.get("/c04b").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c04b").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04b");
-		c1.get("/c04c").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c04c").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04c");
-		c1.get("/c04d").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c04d").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04d");
-		c1.get("/c04e").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c04e").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04e");
-		c1.get("/c04f").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c04f").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04f");
-
-		c1.get("/c05a").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c05a").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c05b").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c05b").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c05c").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c05c").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c05d").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c05d").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c05e").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c05e").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c05f").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c05f").run().assertBody().is("false");
-		assertLogged(false);
-
-		c1.get("/c06a").run().assertBody().is("true");
-		assertLogged(true);
-		c1d.get("/c06a").run().assertBody().is("true");
-		assertLogged(true);
-		c1.get("/c06b").run().assertBody().is("true");
-		assertLogged(true);
-		c1d.get("/c06b").run().assertBody().is("true");
-		assertLogged(true);
-		c1.get("/c06c").run().assertBody().is("true");
-		assertLogged(true);
-		c1d.get("/c06c").run().assertBody().is("true");
-		assertLogged(true);
-		c1.get("/c06d").run().assertBody().is("true");
-		assertLogged(true);
-		c1d.get("/c06d").run().assertBody().is("true");
-		assertLogged(true);
-
-		c1.get("/c07a").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c07a").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c07b").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c07b").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c07c").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c07c").run().assertBody().is("false");
-		assertLogged(false);
-		c1.get("/c07d").run().assertBody().is("false");
-		assertLogged(false);
-		c1d.get("/c07d").run().assertBody().is("false");
-		assertLogged(false);
-	}
-
-	static {
-		System.setProperty("C2DebugEnabled", "C2=true");
-	}
-	@Rest(
-		callLogger=CaptureCallLogger.class,
-		debugOn="$S{C2DebugEnabled},"
-			+ "C2.getC02a=false,C2.getC02b=false,C2.getC02c=FALSE,C2.getC02d=FALSE,C2.getC02e=FALSE,C2.getC02f=FALSE,"
-			+ " C2.getC03a , C2.getC03b = true , C2.getC03c = TRUE , C2.getC03d = TRUE , C2.getC03e = TRUE , C2.getC03f = TRUE , "
-			+ "C2.getC04a=per-request,C2.getC04b=per-request,C2.getC04c=PER-REQUEST,C2.getC04d=PER-REQUEST,C2.getC04e=PER-REQUEST,C2.getC04f=PER-REQUEST,"
-			+ "C2.getC05a=foo,C2.getC05b=,C2.getC05c=foo,C2.getC05d=foo,C2.getC05e=foo,C2.getC05f=foo,"
-	)
-	public static class C2 implements BasicUniversalRest {
-
-		@RestMethod
-		public boolean getC01a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC01b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC01c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC01d(RestRequest req) {
-			return req.isDebug();
-		}
-
-		// debug=false
-		@RestMethod
-		public boolean getC02a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC02b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC02c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC02d(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC02e(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC02f(RestRequest req) {
-			return req.isDebug();
-		}
-
-		// debug=true
-		@RestMethod
-		public boolean getC03a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC03b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC03c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC03d(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC03e(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC03f(RestRequest req) {
-			return req.isDebug();
-		}
-
-		// debug=per-request
-		@RestMethod
-		public boolean getC04a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC04b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC04c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC04d(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC04e(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC04f(RestRequest req) {
-			return req.isDebug();
-		}
-
-		// debug=foo
-		@RestMethod
-		public boolean getC05a(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC05b(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod
-		public boolean getC05c(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC05d(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC05e(RestRequest req) {
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC05f(RestRequest req) {
-			return req.isDebug();
-		}
-
-		@RestMethod
-		public boolean getC06a(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC06b(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC06c(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC06d(RestRequest req) throws Exception {
-			req.setDebug();
-			return req.isDebug();
-		}
-
-		@RestMethod
-		public boolean getC07a(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-		@RestMethod(debug="false")
-		public boolean getC07b(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-		@RestMethod(debug="true")
-		public boolean getC07c(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-		@RestMethod(debug="per-request")
-		public boolean getC07d(RestRequest req) throws Exception {
-			req.setDebug(false);
-			return req.isDebug();
-		}
-	}
-	static MockRestClient c2 = MockRestClient.buildSimpleJson(C2.class);
-	static MockRestClient c2d = MockRestClient.create(C2.class).simpleJson().header("X-Debug", true).build();
-
-	@Test
-	public void c02_debugTrue() throws Exception {
-
-		c2.get("/c01a").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c01a").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c01b").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c01b").run().assertBody().is("false");
-		assertLogged(false);
-		c2.get("/c01c").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c01c").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c01d").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c01d").run().assertBody().is("true");
-		assertLogged(true);
-
-		c2.get("/c02a").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c02a").run().assertBody().is("false");
-		assertLogged(false);
-		c2.get("/c02b").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c02b").run().assertBody().is("false");
-		assertLogged(false);
-		c2.get("/c02c").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c02c").run().assertBody().is("false");
-		assertLogged(false);
-		c2.get("/c02d").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c02d").run().assertBody().is("false");
-		assertLogged(false);
-		c2.get("/c02e").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c02e").run().assertBody().is("false");
-		assertLogged(false);
-		c2.get("/c02f").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c02f").run().assertBody().is("false");
-		assertLogged(false);
-
-		c2.get("/c03a").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03a");
-		c2d.get("/c03a").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03a");
-		c2.get("/c03b").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03b");
-		c2d.get("/c03b").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03b");
-		c2.get("/c03c").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03c");
-		c2d.get("/c03c").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03c");
-		c2.get("/c03d").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03d");
-		c2d.get("/c03d").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03d");
-		c2.get("/c03e").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03e");
-		c2d.get("/c03e").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03e");
-		c2.get("/c03f").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03f");
-		c2d.get("/c03f").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c03f");
-
-		c2.get("/c04a").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c04a").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04a");
-		c2.get("/c04b").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c04b").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04b");
-		c2.get("/c04c").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c04c").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04c");
-		c2.get("/c04d").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c04d").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04d");
-		c2.get("/c04e").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c04e").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04e");
-		c2.get("/c04f").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c04f").run().assertBody().is("true");
-		assertLoggedContains("[200] HTTP GET /c04f");
-
-		c2.get("/c05a").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c05a").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c05b").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c05b").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c05c").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c05c").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c05d").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c05d").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c05e").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c05e").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c05f").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c05f").run().assertBody().is("true");
-		assertLogged(true);
-
-		c2.get("/c06a").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c06a").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c06b").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c06b").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c06c").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c06c").run().assertBody().is("true");
-		assertLogged(true);
-		c2.get("/c06d").run().assertBody().is("true");
-		assertLogged(true);
-		c2d.get("/c06d").run().assertBody().is("true");
-		assertLogged(true);
-
-		c2.get("/c07a").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c07a").run().assertBody().is("false");
-		assertLogged(false);
-		c2.get("/c07b").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c07b").run().assertBody().is("false");
-		assertLogged(false);
-		c2.get("/c07c").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c07c").run().assertBody().is("false");
-		assertLogged(false);
-		c2.get("/c07d").run().assertBody().is("false");
-		assertLogged(false);
-		c2d.get("/c07d").run().assertBody().is("false");
-		assertLogged(false);
-	}
-
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_AcceptCharset_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_AcceptCharset_Test.java
new file mode 100644
index 0000000..9cf7ec8
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_AcceptCharset_Test.java
@@ -0,0 +1,119 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.io.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.Body;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.plaintext.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.apache.juneau.serializer.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Header_AcceptCharset_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Test that Q-values are being resolved correctly.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(defaultCharset="utf-8",serializers=PlainTextSerializer.class)
+	public static class A {
+		@RestMethod
+		public String a() {
+			return "foo";
+		}
+	}
+
+	@Test
+	public void a01_qValues() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/a").accept("text/plain").acceptCharset("utf-8").run().assertCharset().is("utf-8");
+		a.get("/a").accept("text/plain").acceptCharset("iso-8859-1").run().assertCharset().is("iso-8859-1");
+		a.get("/a").accept("text/plain").acceptCharset("bad,utf-8").run().assertCharset().is("utf-8");
+		a.get("/a").accept("text/plain").acceptCharset("utf-8,bad").run().assertCharset().is("utf-8");
+		a.get("/a").accept("text/plain").acceptCharset("bad;q=0.9,utf-8;q=0.1").run().assertCharset().is("utf-8");
+		a.get("/a").accept("text/plain").acceptCharset("bad;q=0.1,utf-8;q=0.9").run().assertCharset().is("utf-8");
+		a.get("/a").accept("text/plain").acceptCharset("utf-8;q=0.9,iso-8859-1;q=0.1").run().assertCharset().is("utf-8");
+		a.get("/a").accept("text/plain").acceptCharset("utf-8;q=0.1,iso-8859-1;q=0.9").run().assertCharset().is("iso-8859-1");
+		a.get("/a").accept("text/plain").acceptCharset("*").run().assertCharset().is("utf-8");
+		a.get("/a").accept("text/plain").acceptCharset("bad,iso-8859-1;q=0.5,*;q=0.1").run().assertCharset().is("iso-8859-1");
+		a.get("/a").accept("text/plain").acceptCharset("bad,iso-8859-1;q=0.1,*;q=0.5").run().assertCharset().is("utf-8");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Validate various Accept-Charset variations.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(defaultCharset="utf-8")
+	public static class B {
+
+		@RestMethod(name=PUT, parsers=TestParser.class, serializers=TestSerializer.class)
+		public String a(@Body String in) {
+			return in;
+		}
+
+		public static class TestParser extends InputStreamParser {
+			public TestParser(PropertyStore ps) {
+				super(ps, "text/plain");
+			}
+			@Override /* Parser */
+			public InputStreamParserSession createSession(final ParserSessionArgs args) {
+				return new InputStreamParserSession(args) {
+					@Override /* ParserSession */
+					@SuppressWarnings("unchecked")
+					protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {
+						return (T)args.getProperty(ReaderParser.RPARSER_streamCharset).toString();
+					}
+				};
+			}
+		}
+
+		public static class TestSerializer extends OutputStreamSerializer {
+			public TestSerializer(PropertyStore ps) {
+				super(ps, "text/plain", null);
+			}
+			@Override /* Serializer */
+			public OutputStreamSerializerSession createSession(SerializerSessionArgs args) {
+				return new OutputStreamSerializerSession(args) {
+					@Override /* SerializerSession */
+					protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException {
+						try (Writer w = new OutputStreamWriter(out.getOutputStream())) {
+							Object sc = args.getProperty(WriterSerializer.WSERIALIZER_streamCharset);
+							w.append(o.toString()).append('/').append(sc == null ? null : sc.toString());
+						}
+					}
+				};
+			}
+		}
+	}
+
+	@Test
+	public void b01_charsetOnResponse() throws Exception {
+		RestClient b = MockRestClient.buildLax(B.class);
+		b.put("/a", null).plainText().run().assertBody().is("UTF-8/UTF-8");
+		b.put("/a", null).plainText().acceptCharset("Shift_JIS").run().assertBody().is("UTF-8/Shift_JIS");
+		b.put("/a?noTrace=true", null).plainText().acceptCharset("BAD").run().assertCode().is(406).assertBody().contains("No supported charsets in header 'Accept-Charset': 'BAD'");
+		b.put("/a", null).plainText().acceptCharset("UTF-8").run().assertBody().is("UTF-8/UTF-8");
+		b.put("/a", null).plainText().acceptCharset("bad,iso-8859-1").run().assertBody().is("UTF-8/ISO-8859-1");
+		b.put("/a", null).plainText().acceptCharset("bad;q=0.9,iso-8859-1;q=0.1").run().assertBody().is("UTF-8/ISO-8859-1");
+		b.put("/a", null).plainText().acceptCharset("bad;q=0.1,iso-8859-1;q=0.9").run().assertBody().is("UTF-8/ISO-8859-1");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/AcceptEncodingTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_AcceptEncoding_Test.java
similarity index 67%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/AcceptEncodingTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_AcceptEncoding_Test.java
index 441215a..2cfb232 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/AcceptEncodingTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_AcceptEncoding_Test.java
@@ -10,7 +10,7 @@
 // * "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.rest.headers;

+package org.apache.juneau.rest;

 

 import static org.junit.Assert.*;

 import static org.junit.runners.MethodSorters.*;

@@ -19,28 +19,18 @@
 

 import org.apache.juneau.encoders.*;

 import org.apache.juneau.internal.*;

-import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.RestResponse;

 import org.apache.juneau.rest.annotation.*;

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class AcceptEncodingTest {

+public class Header_AcceptEncoding_Test {

 

-	//=================================================================================================================

-	// Setup classes

-	//=================================================================================================================

-

-	public static class MyEncoder extends GzipEncoder {

-		@Override /* ConfigEncoder */

-		public String[] getCodings() {

-			return new String[]{"mycoding"};

-		}

-	}

-

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Test with no compression enabled.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest

 	public static class A {

@@ -49,28 +39,22 @@
 			return "foo";

 		}

 	}

-	static MockRestClient a = MockRestClient.buildLax(A.class);

 

 	@Test

 	public void a01_noCompression() throws Exception {

+		RestClient a = MockRestClient.buildLax(A.class);

 		a.get("/").run().assertBody().is("foo");

 		a.get("/").acceptEncoding("").run().assertBody().is("foo");

 		a.get("/").acceptEncoding("*").run().assertBody().is("foo");

 		a.get("/").acceptEncoding("identity").run().assertBody().is("foo");

-	}

 

-	@Test

-	public void a02_noCompression_qValues() throws Exception {

 		// The following should all match identity.

 		a.get("/").acceptEncoding("mycoding").run().assertBody().is("foo");

 		a.get("/").acceptEncoding("identity;q=0.8,mycoding;q=0.6").run().assertBody().is("foo");

 		a.get("/").acceptEncoding("mycoding;q=0.8,identity;q=0.6").run().assertBody().is("foo");

 		a.get("/").acceptEncoding("mycoding;q=0.8,*;q=0.6").run().assertBody().is("foo");

 		a.get("/").acceptEncoding("*;q=0.8,myencoding;q=0.6").run().assertBody().is("foo");

-	}

 

-	@Test

-	public void a03_noCompression_nomatch() throws Exception {

 		a.get("?noTrace=true").acceptEncoding("mycoding,identity;q=0").run()

 			.assertCode().is(406)

 			.assertBody().contains(

@@ -109,62 +93,53 @@
 			);

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Test with compression enabled.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest(encoders=MyEncoder.class)

 	public static class B {

 		@RestMethod

-		public String b01() {

+		public String get() {

 			return "foo";

 		}

 	}

-	static MockRestClient b = MockRestClient.buildLax(B.class);

 

 	@Test

-	public void b01_withCompression_identity() throws Exception {

-		b.get("/b01").run().assertBody().is("foo");

-		b.get("/b01").acceptEncoding("").run().assertBody().is("foo");

-		b.get("/b01").acceptEncoding("identity").run().assertBody().is("foo");

-	}

-	@Test

-	public void b02_withCompression_identity_qValues() throws Exception {

-		b.get("/b01").acceptEncoding("identity;q=0.8,mycoding;q=0.6").run().assertBody().is("foo");

-	}

-	@Test

-	public void b03_withCompression_gzip() throws Exception {

-		assertEquals("foo", StringUtils.decompress(b.get("/b01").acceptEncoding("*").run().getBody().asBytes()));

-		assertEquals("foo", StringUtils.decompress(b.get("/b01").acceptEncoding("mycoding").run().getBody().asBytes()));

-	}

-	@Test

-	public void b04_withCompression_gzip_qValues() throws Exception {

-		assertEquals("foo", StringUtils.decompress(b.get("/b01").acceptEncoding("mycoding,identity;q=0").run().getBody().asBytes()));

-		assertEquals("foo", StringUtils.decompress(b.get("/b01").acceptEncoding("mycoding,*;q=0").run().getBody().asBytes()));

-		assertEquals("foo", StringUtils.decompress(b.get("/b01").acceptEncoding("mycoding;q=0.8,identity;q=0.6").run().getBody().asBytes()));

-		assertEquals("foo", StringUtils.decompress(b.get("/b01").acceptEncoding("mycoding;q=0.8,*;q=0.6").run().getBody().asBytes()));

-	}

-	@Test

-	public void b05_withCompression_nomatch() throws Exception {

-		b.get("/b01?noTrace=true").acceptEncoding("identity;q=0").run()

+	public void b01_withCompression() throws Exception {

+		RestClient b = MockRestClient.buildLax(B.class);

+		b.get("/").run().assertBody().is("foo");

+		b.get("/").acceptEncoding("").run().assertBody().is("foo");

+		b.get("/").acceptEncoding("identity").run().assertBody().is("foo");

+		b.get("/").acceptEncoding("identity;q=0.8,mycoding;q=0.6").run().assertBody().is("foo");

+

+		assertEquals("foo", StringUtils.decompress(b.get("/").acceptEncoding("*").run().getBody().asBytes()));

+		assertEquals("foo", StringUtils.decompress(b.get("/").acceptEncoding("mycoding").run().getBody().asBytes()));

+

+		assertEquals("foo", StringUtils.decompress(b.get("/").acceptEncoding("mycoding,identity;q=0").run().getBody().asBytes()));

+		assertEquals("foo", StringUtils.decompress(b.get("/").acceptEncoding("mycoding,*;q=0").run().getBody().asBytes()));

+		assertEquals("foo", StringUtils.decompress(b.get("/").acceptEncoding("mycoding;q=0.8,identity;q=0.6").run().getBody().asBytes()));

+		assertEquals("foo", StringUtils.decompress(b.get("/").acceptEncoding("mycoding;q=0.8,*;q=0.6").run().getBody().asBytes()));

+

+		b.get("?noTrace=true").acceptEncoding("identity;q=0").run()

 			.assertCode().is(406)

 			.assertBody().contains(

 				"Unsupported encoding in request header 'Accept-Encoding': 'identity;q=0'",

 				"Supported codings: ['mycoding','identity']"

 			);

-		b.get("/b01?noTrace=true").acceptEncoding("identity;q=0.0").run()

+		b.get("?noTrace=true").acceptEncoding("identity;q=0.0").run()

 			.assertCode().is(406)

 			.assertBody().contains(

 				"Unsupported encoding in request header 'Accept-Encoding': 'identity;q=0.0'",

 				"Supported codings: ['mycoding','identity']"

 			);

-		b.get("/b01?noTrace=true").acceptEncoding("*;q=0").run()

+		b.get("?noTrace=true").acceptEncoding("*;q=0").run()

 			.assertCode().is(406)

 			.assertBody().contains(

 				"Unsupported encoding in request header 'Accept-Encoding': '*;q=0'",

 				"Supported codings: ['mycoding','identity']"

 			);

-		b.get("/b01?noTrace=true").acceptEncoding("*;q=0.0").run()

+		b.get("?noTrace=true").acceptEncoding("*;q=0.0").run()

 			.assertCode().is(406)

 			.assertBody().contains(

 				"Unsupported encoding in request header 'Accept-Encoding': '*;q=0.0'",

@@ -172,16 +147,15 @@
 			);

 	}

 

-

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Test with compression enabled but with servlet using output stream directly.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest(encoders=MyEncoder.class)

 	@SuppressWarnings("resource")

 	public static class C {

 		@RestMethod

-		public void c01(RestResponse res) throws Exception {

+		public void a(RestResponse res) throws Exception {

 			// This method bypasses the content type and encoding from

 			// the serializers and encoders when calling getOutputStream() directly.

 			res.setContentType("text/direct");

@@ -190,7 +164,7 @@
 			os.flush();

 		}

 		@RestMethod

-		public void c02(RestResponse res) throws Exception {

+		public void b(RestResponse res) throws Exception {

 			// This method bypasses the content type and encoding from

 			// the serializers and encoders when calling getWriter() directly.

 			Writer w = res.getWriter();

@@ -198,7 +172,7 @@
 			w.flush();

 		}

 		@RestMethod

-		public void c03(RestResponse res) throws Exception {

+		public void c(RestResponse res) throws Exception {

 			// This method uses getNegotiatedWriter() which should use GZip encoding.

 			Writer w = res.getNegotiatedWriter();

 			w.append("foo");

@@ -206,70 +180,76 @@
 			w.close();

 		}

 		@RestMethod(encoders={IdentityEncoder.class})

-		public void c04(RestResponse res) throws Exception {

+		public void d(RestResponse res) throws Exception {

 			// This method overrides the set of encoders at the method level and so shouldn't use GZip encoding.

 			Writer w = res.getNegotiatedWriter();

 			w.append("foo");

 			w.flush();

 		}

 	}

-	static MockRestClient c = MockRestClient.build(C.class);

 

 	@Test

-	public void c01_direct1() throws Exception {

-		c.get("/c01")

+	public void c01_direct() throws Exception {

+		RestClient c = MockRestClient.build(C.class);

+

+		c.get("/a")

 			.acceptEncoding("mycoding")

 			.run()

 			.assertStringHeader("Content-Encoding").doesNotExist() // Should not be set

 			.assertStringHeader("Content-Type").is("text/direct")

 			.assertBody().is("foo");

-		c.get("/c01")

+		c.get("/a")

 			.acceptEncoding("*")

 			.run()

 			.assertStringHeader("Content-Encoding").doesNotExist() // Should not be set

 			.assertStringHeader("Content-Type").is("text/direct")

 			.assertBody().is("foo");

-	}

-	@Test

-	public void c02_direct2() throws Exception {

-		c.get("/c02")

+

+		c.get("/b")

 			.acceptEncoding("mycoding")

 			.run()

 			.assertStringHeader("Content-Encoding").doesNotExist() // Should not be set

 			.assertBody().is("foo");

-		c.get("/c02")

+		c.get("/b")

 			.acceptEncoding("*")

 			.run()

 			.assertStringHeader("Content-Encoding").doesNotExist() // Should not be set

 			.assertBody().is("foo");

-	}

-	@Test

-	public void c03_direct3() throws Exception {

+

 		byte[] body;

-		body = c.get("/c03")

+		body = c.get("/c")

 			.acceptEncoding("mycoding")

 			.run()

 			.assertStringHeader("Content-Encoding").is("mycoding")

 			.getBody().asBytes();

 		assertEquals("foo", StringUtils.decompress(body));

-		body = c.get("/c03")

+		body = c.get("/c")

 			.acceptEncoding("*")

 			.run()

 			.assertStringHeader("Content-Encoding").is("mycoding")

 			.getBody().asBytes();

 		assertEquals("foo", StringUtils.decompress(body));

+

+		c.get("/d")

+			.acceptEncoding("mycoding")

+			.run()

+			.assertStringHeader("Content-Encoding").doesNotExist() // Should not be set

+			.assertBody().is("foo");

+		c.get("/d")

+			.acceptEncoding("*")

+			.run()

+			.assertStringHeader("Content-Encoding").doesNotExist() // Should not be set

+			.assertBody().is("foo");

 	}

-	@Test

-	public void c04_direct4() throws Exception {

-		c.get("/c04")

-			.acceptEncoding("mycoding")

-			.run()

-			.assertStringHeader("Content-Encoding").doesNotExist() // Should not be set

-			.assertBody().is("foo");

-		c.get("/c04")

-			.acceptEncoding("*")

-			.run()

-			.assertStringHeader("Content-Encoding").doesNotExist() // Should not be set

-			.assertBody().is("foo");

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Helpers

+	//------------------------------------------------------------------------------------------------------------------

+

+	public static class MyEncoder extends GzipEncoder {

+		@Override /* ConfigEncoder */

+		public String[] getCodings() {

+			return new String[]{"mycoding"};

+		}

 	}

 }

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_Accept_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_Accept_Test.java
new file mode 100644
index 0000000..66a29d1
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_Accept_Test.java
@@ -0,0 +1,262 @@
+// ***************************************************************************************************************************

+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

+// * with the License.  You may obtain a copy of the License at                                                              *

+// *                                                                                                                         *

+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

+// *                                                                                                                         *

+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

+// * specific language governing permissions and limitations under the License.                                              *

+// ***************************************************************************************************************************

+package org.apache.juneau.rest;

+

+import static org.junit.runners.MethodSorters.*;

+

+import java.io.IOException;

+

+import org.apache.juneau.*;

+import org.apache.juneau.http.annotation.Body;

+import org.apache.juneau.rest.annotation.*;

+import org.apache.juneau.rest.client2.*;

+import org.apache.juneau.rest.mock2.*;

+import org.apache.juneau.serializer.*;

+import org.junit.*;

+

+@FixMethodOrder(NAME_ASCENDING)

+public class Header_Accept_Test {

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Setup classes

+	//------------------------------------------------------------------------------------------------------------------

+

+	public static class DummySerializer extends WriterSerializer {

+		String name;

+		DummySerializer(PropertyStore ps, String name, String produces) {

+			super(ps, produces, null);

+			this.name = name;

+		}

+		@Override /* Serializer */

+		public WriterSerializerSession createSession(SerializerSessionArgs args) {

+			return new WriterSerializerSession(args) {

+				@Override /* SerializerSession */

+				protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException {

+					out.getWriter().write(name);

+				}

+			};

+		}

+	}

+

+	public static class S1 extends DummySerializer { public S1(PropertyStore ps) {super(ps, "s1", "text/s1");}}

+	public static class S2 extends DummySerializer { public S2(PropertyStore ps) {super(ps, "s2", "text/s2");}}

+	public static class S3 extends DummySerializer { public S3(PropertyStore ps) {super(ps, "s3", "text/s3");}}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Accept headers on servlet annotation are picked up.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Accept : text/s2 "},

+		serializers={S1.class,S2.class}

+	)

+	public static class A {

+		@RestMethod

+		public String put(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void a01_defaultHeadersOnServletAnnotation() throws Exception {

+		RestClient a = MockRestClient.buildLax(A.class);

+		a.put("/", null)

+			.run()

+			.assertBody().is("s2");

+		a.put("/", null)

+			.accept("text/s1")

+			.run()

+			.assertBody().is("s1");

+		a.put("/", null)

+			.accept("text/s2")

+			.run()

+			.assertBody().is("s2");

+		a.put("?noTrace=true", null)

+			.accept("text/s3")

+			.run()

+			.assertCode().is(406)

+			.assertBody().contains("Unsupported media-type in request header 'Accept': 'text/s3'");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Accept headers on servlet annotation are picked up

+	// when @RestMethod.parsers/serializers annotations are used.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Accept : text/s2 "},

+		serializers={S1.class,S2.class}

+	)

+	public static class B {

+		@RestMethod(serializers=S3.class)

+		public String put(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void b01_restMethodWithParsersSerializers() throws Exception {

+		RestClient b = MockRestClient.buildLax(B.class);

+		b.put("/", null).accept("text/s3").run().assertBody().is("s3");

+		b.put("?noTrace=true", null)

+			.accept("text/s4")

+			.run()

+			.assertCode().is(406)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Accept': 'text/s4'",

+				"Supported media-types: ['text/s3']"

+			);

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Accept headers on servlet annotation are picked up

+	// when @RestMethod.addParsers/addSerializers annotations are used.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Accept : text/s2 "},

+		serializers={S1.class,S2.class}

+	)

+	public static class C {

+		@RestMethod(serializers={S3.class,Inherit.class})

+		public String put(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void c01_restMethodAddParsersSerializersInherit() throws Exception {

+		RestClient c = MockRestClient.buildLax(C.class);

+		c.put("/", null)

+			.run()

+			.assertBody().is("s2");

+		c.put("/", null)

+			.accept("text/s1")

+			.run()

+			.assertBody().is("s1");

+		c.put("/", null)

+			.accept("text/s2")

+			.run()

+			.assertBody().is("s2");

+		c.put("/", null)

+			.accept("text/s3")

+			.run()

+			.assertBody().is("s3");

+		c.put("?noTrace=true", null)

+			.accept("text/s4")

+			.run()

+			.assertCode().is(406)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Accept': 'text/s4'",

+				"Supported media-types: ['text/s3','text/s1','text/s2']"

+			);

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Various Accept incantations.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Accept : text/s2 "},

+		serializers={S1.class,S2.class}

+	)

+	public static class D {

+		@RestMethod

+		public String put(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void d01_accept_valid() throws Exception {

+		RestClient d = MockRestClient.buildLax(D.class);

+		// "*/*" should match the first serializer, not the default serializer.

+		d.put("/", null).accept("*/*").run().assertBody().is("s1");

+		// "text/*" should match the first serializer, not the default serializer.

+		d.put("/", null).accept("text/*").run().assertBody().is("s1");

+		d.put("/", null).accept("bad/*,text/*").run().assertBody().is("s1");

+		d.put("/", null).accept("text/*,bad/*").run().assertBody().is("s1");

+		d.put("/", null).accept("text/s1;q=0.5,text/s2").run().assertBody().is("s2");

+		d.put("/", null).accept("text/s1,text/s2;q=0.5").run().assertBody().is("s1");

+		d.put("?noTrace=true", null)

+			.accept("bad/*")

+			.run()

+			.assertCode().is(406)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Accept': 'bad/*'",

+				"Supported media-types: ['text/s1','text/s2']"

+			);

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Accept headers on method annotation are picked up

+	// when @RestMethod.parsers/serializers annotations are used.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Accept : text/s2 "},

+		serializers={S1.class,S2.class}

+	)

+	public static class E {

+		@RestMethod(reqHeaders={"Accept: text/s3"}, serializers=S3.class)

+		public String put(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void e01_restMethodParserSerializerAnnotations() throws Exception {

+		RestClient e = MockRestClient.buildLax(E.class);

+		e.put("/", null).run().assertBody().is("s3");

+		e.put("/", null).accept("text/s3").run().assertBody().is("s3");

+		e.put("?noTrace=true", null)

+			.accept("text/s1")

+			.run()

+			.assertCode().is(406)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Accept': 'text/s1'",

+				"Supported media-types: ['text/s3']"

+			);

+		e.put("?noTrace=true", null).accept("text/s2").run()

+			.assertCode().is(406)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Accept': 'text/s2'",

+				"Supported media-types: ['text/s3']"

+			);

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Accept headers on method annotation are picked up

+	// 	when @RestMethod.addParsers/addSerializers annotations are used.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Accept : text/s2 "},

+		serializers={S1.class,S2.class}

+	)

+	public static class F {

+		@RestMethod(reqHeaders={"Accept: text/s3"}, serializers={Inherit.class, S3.class})

+		public String put(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void f01_restMethodAddParsersSerializersAnnotations() throws Exception {

+		RestClient f = MockRestClient.build(F.class);

+		f.put("/", null).run().assertBody().is("s3");

+		f.put("/", null).accept("text/s1").run().assertBody().is("s1");

+		f.put("/", null).accept("text/s2").run().assertBody().is("s2");

+		f.put("/", null).accept("text/s3").run().assertBody().is("s3");

+	}

+}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ContentTypeTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_ContentType_Test.java
similarity index 62%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ContentTypeTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_ContentType_Test.java
index 55551d0..eb436cf 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ContentTypeTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Header_ContentType_Test.java
@@ -10,7 +10,7 @@
 // * "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.rest.headers;

+package org.apache.juneau.rest;

 

 import static org.apache.juneau.http.HttpMethod.*;

 import static org.junit.runners.MethodSorters.*;

@@ -20,17 +20,199 @@
 import org.apache.juneau.*;

 import org.apache.juneau.http.annotation.Body;

 import org.apache.juneau.parser.*;

-import org.apache.juneau.rest.*;

 import org.apache.juneau.rest.annotation.*;

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class ContentTypeTest {

+public class Header_ContentType_Test {

 

-	//=================================================================================================================

-	// Setup classes

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Content-Type headers on servlet annotation are picked up.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Content-Type : text/p2 "},

+		parsers={P1.class,P2.class}

+	)

+	public static class A {

+		@RestMethod(name=PUT)

+		public String a(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void a01_defaultHeadersOnServletAnnotation() throws Exception {

+		RestClient a = MockRestClient.buildLax(A.class);

+		a.put("/a", null, "")

+			.run()

+			.assertBody().is("p2");

+		a.put("/a", null, "text/p1")

+			.run()

+			.assertBody().is("p1");

+		a.put("/a", null, "text/p2")

+			.run()

+			.assertBody().is("p2");

+		a.put("/a?noTrace=true", null, "text/p3")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains("Unsupported media-type in request header 'Content-Type': 'text/p3'");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Content-Type headers on servlet annotation are picked up

+	// when @RestMethod.parsers/serializers annotations are used.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Content-Type : text/p2 "},

+		parsers={P1.class,P2.class}

+	)

+	public static class B {

+		@RestMethod(name=PUT, parsers=P3.class)

+		public String a(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void b01_restMethodWithParsersSerializers() throws Exception {

+		RestClient b = MockRestClient.buildLax(B.class);

+		b.put("/a", null).contentType("text/p3").run().assertBody().is("p3");

+		b.put("/a?noTrace=true", null, "")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Content-Type': 'text/p2'",

+				"Supported media-types: ['text/p3']"

+			);

+		b.put("/a?noTrace=true", null, "text/p1")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Content-Type': 'text/p1'",

+				"Supported media-types: ['text/p3']"

+			);

+		b.put("/a?noTrace=true", null, "text/p2")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Content-Type': 'text/p2'",

+				"Supported media-types: ['text/p3']"

+			);

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Content-Type headers on servlet annotation are picked up

+	// when @RestMethod.addParsers/addSerializers annotations are used.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Content-Type : text/p2 "},

+		parsers={P1.class,P2.class}

+	)

+	public static class C {

+		@RestMethod(name=PUT, parsers={P3.class,Inherit.class})

+		public String a(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void c01_restMethodAddParsersSerializersInherit() throws Exception {

+		RestClient c = MockRestClient.buildLax(C.class);

+		c.put("/a", null, "").run().assertBody().is("p2");

+		c.put("/a", null, "text/p1").run().assertBody().is("p1");

+		c.put("/a", null, "text/p2").run().assertBody().is("p2");

+		c.put("/a", null, "text/p3").run().assertBody().is("p3");

+		c.put("/a?noTrace=true", null).contentType("text/p4")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Content-Type': 'text/p4'",

+				"Supported media-types: ['text/p3','text/p1','text/p2']"

+			);

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Content-Type headers on method annotation are picked up

+	// when @RestMethod.parsers/serializers annotations are used.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Content-Type : text/p2 "},

+		parsers={P1.class,P2.class}

+	)

+	public static class D {

+		@RestMethod(name=PUT, reqHeaders={"Content-Type: text/p3"}, parsers=P3.class)

+		public String a(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void d01_restMethodParserSerializerAnnotations() throws Exception {

+		RestClient d = MockRestClient.buildLax(D.class);

+		d.put("/a", null, "")

+			.run()

+			.assertBody().is("p3");

+		d.put("/a", null, "text/p3")

+			.run()

+			.assertBody().is("p3");

+		d.put("/a?noTrace=true", null, "text/p1")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Content-Type': 'text/p1'",

+				"Supported media-types: ['text/p3']"

+			);

+		d.put("/a?noTrace=true", null, "text/p2")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Content-Type': 'text/p2'",

+				"Supported media-types: ['text/p3']"

+			);

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test that default Content-Type headers on method annotation are picked up

+	// 	when @RestMethod.addParsers/addSerializers annotations are used.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		reqHeaders={" Content-Type : text/p2 "},

+		parsers={P1.class,P2.class}

+	)

+	public static class E {

+		@RestMethod(name=PUT, reqHeaders={"Content-Type: text/p3"}, parsers={Inherit.class,P3.class})

+		public String a(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void e01_restMethodAddParsersSerializersAnnotations() throws Exception {

+		RestClient e = MockRestClient.build(E.class);

+		e.put("/a", null, "")

+			.run()

+			.assertBody().is("p3");

+		e.put("/a", null, "text/p1")

+			.run()

+			.assertBody().is("p1");

+		e.put("/a", null, "text/p2")

+			.run()

+			.assertBody().is("p2");

+		e.put("/a", null, "text/p3")

+			.run()

+			.assertBody().is("p3");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Helpers

+	//------------------------------------------------------------------------------------------------------------------

 

 	public static class DummyParser extends ReaderParser {

 		String name;

@@ -53,202 +235,4 @@
 	public static class P1 extends DummyParser { public P1(PropertyStore ps) {super(ps, "p1", "text/p1");}}

 	public static class P2 extends DummyParser { public P2(PropertyStore ps) {super(ps, "p2", "text/p2");}}

 	public static class P3 extends DummyParser { public P3(PropertyStore ps) {super(ps, "p3", "text/p3");}}

-

-	//=================================================================================================================

-	// Test that default Content-Type headers on servlet annotation are picked up.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Content-Type : text/p2 "},

-		parsers={P1.class,P2.class}

-	)

-	public static class A {

-		@RestMethod(name=PUT)

-		public String a01(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient a = MockRestClient.buildLax(A.class);

-

-	@Test

-	public void a01_defaultHeadersOnServletAnnotation_valid() throws Exception {

-		a.put("/a01", null, "")

-			.run()

-			.assertBody().is("p2");

-		a.put("/a01", null, "text/p1")

-			.run()

-			.assertBody().is("p1");

-		a.put("/a01", null, "text/p2")

-			.run()

-			.assertBody().is("p2");

-	}

-

-	@Test

-	public void a02_defaultHeadersOnServletAnnotation_invalid() throws Exception {

-		a.put("/a01?noTrace=true", null, "text/p3")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains("Unsupported media-type in request header 'Content-Type': 'text/p3'");

-	}

-

-	//=================================================================================================================

-	// Test that default Content-Type headers on servlet annotation are picked up

-	// when @RestMethod.parsers/serializers annotations are used.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Content-Type : text/p2 "},

-		parsers={P1.class,P2.class}

-	)

-	public static class B {

-		@RestMethod(name=PUT, parsers=P3.class)

-		public String b(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient b = MockRestClient.buildLax(B.class);

-

-	@Test

-	public void b01_restMethodWithParsersSerializers_valid() throws Exception {

-		b.put("/b", null).contentType("text/p3").run().assertBody().is("p3");

-	}

-

-	@Test

-	public void b02_restMethodWithParsersSerializers_invalid() throws Exception {

-		b.put("/b?noTrace=true", null, "")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Content-Type': 'text/p2'",

-				"Supported media-types: ['text/p3']"

-			);

-		b.put("/b?noTrace=true", null, "text/p1")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Content-Type': 'text/p1'",

-				"Supported media-types: ['text/p3']"

-			);

-		b.put("/b?noTrace=true", null, "text/p2")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Content-Type': 'text/p2'",

-				"Supported media-types: ['text/p3']"

-			);

-	}

-

-	//=================================================================================================================

-	// Test that default Content-Type headers on servlet annotation are picked up

-	// when @RestMethod.addParsers/addSerializers annotations are used.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Content-Type : text/p2 "},

-		parsers={P1.class,P2.class}

-	)

-	public static class C {

-		@RestMethod(name=PUT, parsers={P3.class,Inherit.class})

-		public String c(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient c = MockRestClient.buildLax(C.class);

-

-	@Test

-	public void c01_restMethodAddParsersSerializersInherit() throws Exception {

-		c.put("/c", null, "").run().assertBody().is("p2");

-		c.put("/c", null, "text/p1").run().assertBody().is("p1");

-		c.put("/c", null, "text/p2").run().assertBody().is("p2");

-		c.put("/c", null, "text/p3").run().assertBody().is("p3");

-	}

-

-	@Test

-	public void c02_restMethodAddParsersSerializersInherit_invalid() throws Exception {

-		c.put("/c?noTrace=true", null).contentType("text/p4")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Content-Type': 'text/p4'",

-				"Supported media-types: ['text/p3','text/p1','text/p2']"

-			);

-	}

-

-	//=================================================================================================================

-	// Test that default Content-Type headers on method annotation are picked up

-	// when @RestMethod.parsers/serializers annotations are used.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Content-Type : text/p2 "},

-		parsers={P1.class,P2.class}

-	)

-	public static class E {

-		@RestMethod(name=PUT, reqHeaders={"Content-Type: text/p3"}, parsers=P3.class)

-		public String e(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient e = MockRestClient.buildLax(E.class);

-

-	@Test

-	public void e01_restMethodParserSerializerAnnotations_valid() throws Exception {

-		e.put("/e", null, "")

-			.run()

-			.assertBody().is("p3");

-		e.put("/e", null, "text/p3")

-			.run()

-			.assertBody().is("p3");

-	}

-	@Test

-	public void e02_restMethodParserSerializerAnnotations_invalid() throws Exception {

-		e.put("/e?noTrace=true", null, "text/p1")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Content-Type': 'text/p1'",

-				"Supported media-types: ['text/p3']"

-			);

-		e.put("/e?noTrace=true", null, "text/p2")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Content-Type': 'text/p2'",

-				"Supported media-types: ['text/p3']"

-			);

-	}

-

-	//=================================================================================================================

-	// Test that default Content-Type headers on method annotation are picked up

-	// 	when @RestMethod.addParsers/addSerializers annotations are used.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Content-Type : text/p2 "},

-		parsers={P1.class,P2.class}

-	)

-	public static class F {

-		@RestMethod(name=PUT, reqHeaders={"Content-Type: text/p3"}, parsers={Inherit.class,P3.class})

-		public String f(@Body String in) {

-			return in;

-		}

-	}

-

-	private static MockRestClient f = MockRestClient.build(F.class);

-

-	@Test

-	public void f01_restMethodAddParsersSerializersAnnotations_valid() throws Exception {

-		f.put("/f", null, "")

-			.run()

-			.assertBody().is("p3");

-		f.put("/f", null, "text/p1")

-			.run()

-			.assertBody().is("p1");

-		f.put("/f", null, "text/p2")

-			.run()

-			.assertBody().is("p2");

-		f.put("/f", null, "text/p3")

-			.run()

-			.assertBody().is("p3");

-	}

 }

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/NlsTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Nls_Test.java
similarity index 70%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/NlsTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Nls_Test.java
index b09c9f1..0636b77 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/NlsTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Nls_Test.java
@@ -19,38 +19,37 @@
 import org.apache.juneau.*;

 import org.apache.juneau.dto.swagger.*;

 import org.apache.juneau.rest.annotation.*;

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.apache.juneau.serializer.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class NlsTest {

+public class Nls_Test {

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Test getting an NLS property defined on a class or method.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest(

-		serializers={A01.class},

+		serializers={A1.class},

 		reqAttrs={"TestProperty:$L{key1}"},

 		messages="NlsTest"

 	)

 	public static class A {

 		@RestMethod

-		public String a01() {

+		public String a() {

 			return null;

 		}

 		@RestMethod(

 			reqAttrs={"TestProperty:$L{key2}"}

 		)

-		public String a02() {

+		public String b() {

 			return null;

 		}

 	}

-	static MockRestClient a = MockRestClient.build(A.class);

-

-	public static class A01 extends WriterSerializer {

-		public A01(PropertyStore ps) {

+	public static class A1 extends WriterSerializer {

+		public A1(PropertyStore ps) {

 			super(ps, "text/plain", null);

 		}

 		@Override /* Serializer */

@@ -65,18 +64,15 @@
 	}

 

 	@Test

-	public void a01_fromClass() throws Exception {

-		a.get("/a01").run().assertBody().is("value1");

+	public void a01_basic() throws Exception {

+		RestClient a = MockRestClient.build(A.class);

+		a.get("/a").run().assertBody().is("value1");

+		a.get("/b").run().assertBody().is("value2");

 	}

 

-	@Test

-	public void a02_fromMethod() throws Exception {

-		a.get("/a02").run().assertBody().is("value2");

-	}

-

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Test OPTIONS pages without NLS

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest(title="test")

 	public static class B {

@@ -86,29 +82,29 @@
 			return req.getSwagger();

 		}

 	}

-	static MockRestClient b = MockRestClient.build(B.class);

 

 	@Test

 	public void b01_optionsPageWithoutNls() throws Exception {

+		MockRestClient b = MockRestClient.build(B.class);

 		b.options("/").run().assertBody().contains("foo");

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Test Missing resource bundles.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest

 	public static class C {

 		@RestMethod

-		public String test(RestRequest req) {

+		public String a(RestRequest req) {

 			// Missing resource bundle should cause {!!x} string.

 			return req.getMessage("bad", 1, 2, 3);

 		}

 	}

-	static MockRestClient c = MockRestClient.build(C.class);

 

 	@Test

 	public void c01_missingResourceBundle() throws Exception {

-		c.get("/test").run().assertBody().is("{!bad}");

+		MockRestClient c = MockRestClient.build(C.class);

+		c.get("/a").run().assertBody().is("{!bad}");

 	}

 }

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/PathsTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Paths_Test.java
similarity index 95%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/PathsTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Paths_Test.java
index 235c48f..bd1c684 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/PathsTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Paths_Test.java
@@ -22,11 +22,11 @@
 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class PathsTest {

+public class Paths_Test {

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Setup

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	static OMap getPaths(RestRequest req) {

 		return OMap.of()

@@ -41,9 +41,9 @@
 			.a("servletParentURI", req.getUriContext().getRootRelativeServletPathParent());

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// No subpath

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest

 	public static class A {

@@ -190,9 +190,9 @@
 		;

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Subpath in method

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	public static class B {

 		@RestMethod(name=GET, path="/subpath/*")

@@ -338,15 +338,15 @@
 		;

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Child resource

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

-	@Rest(children={C01.class})

+	@Rest(children={C1.class})

 	public static class C {}

 

 	@Rest(path="/a")

-	public static class C01 {

+	public static class C1 {

 		@RestMethod(name=GET,path="/*")

 		public OMap get(RestRequest req, @Path("/*") String r) {

 			return getPaths(req).append("pathRemainder2", r).append("method",3);

@@ -490,15 +490,15 @@
 		;

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Child resource and subpath in method

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

-	@Rest(children={D01.class})

+	@Rest(children={D1.class})

 	public static class D {}

 

 	@Rest(path="/a")

-	public static class D01 {

+	public static class D1 {

 		@RestMethod(name=GET, path="/subpath/*")

 		public OMap get(RestRequest req, @Path("/*") String r) {

 			return getPaths(req).append("pathRemainder2", r).append("method",4);

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerConfigTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerConfig_Test.java
similarity index 99%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerConfigTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerConfig_Test.java
index cf6b63e..e310cf9 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerConfigTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerConfig_Test.java
@@ -24,7 +24,7 @@
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestCallLoggerConfigTest {
+public class RestCallLoggerConfig_Test {
 
 	private MockServletRequest req() {
 		return MockServletRequest.create();
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerRuleTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerRule_Test.java
similarity index 99%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerRuleTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerRule_Test.java
index 98ba08a..1f446ef 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerRuleTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestCallLoggerRule_Test.java
@@ -22,7 +22,7 @@
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestCallLoggerRuleTest {
+public class RestCallLoggerRule_Test {
 
 	static final Throwable T1 = new IndexOutOfBoundsException();
 	static final Throwable T2 = new NoSuchMethodError();
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/ThreadLocalObjectsTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestContext_ThreadLocals_Test.java
similarity index 81%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/ThreadLocalObjectsTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestContext_ThreadLocals_Test.java
index 0c108f9..8241ee8 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/ThreadLocalObjectsTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestContext_ThreadLocals_Test.java
@@ -20,17 +20,17 @@
 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class ThreadLocalObjectsTest {

+public class RestContext_ThreadLocals_Test {

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Thread-locals on top-level resource.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@SuppressWarnings("serial")

 	@Rest(path="/a")

 	public static class A extends BasicRestServlet {

 		@RestMethod

-		public void getA01() throws Exception {

+		public void a() throws Exception {

 			getResponse().getWriter().append(getRequest().getQuery("foo"));

 		}

 

@@ -44,14 +44,14 @@
 

 	@Test

 	public void a01() throws Exception {

-		a.get("/a01?foo=bar").run()

+		a.get("/a?foo=bar").run()

 			.assertBody().contains("bar")

 		;

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Thread-locals on child resource.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@SuppressWarnings("serial")

 	@Rest(

@@ -70,7 +70,7 @@
 

 	@Test

 	public void b01() throws Exception {

-		b.get("/a/a01?foo=bar").run()

+		b.get("/a/a?foo=bar").run()

 			.assertBody().contains("bar")

 		;

 	}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Params_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Params_Test.java
new file mode 100644
index 0000000..118dc2f
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Params_Test.java
@@ -0,0 +1,414 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.apache.juneau.internal.IOUtils.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.io.*;
+import java.util.*;
+
+import javax.servlet.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.config.*;
+import org.apache.juneau.cp.Messages;
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.encoders.*;
+import org.apache.juneau.http.header.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.plaintext.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.RestResponse;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class RestMethod_Params_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Various parameters
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(messages="RestParamsTest")
+	public static class A {
+		@RestMethod
+		public String a(ResourceBundle t) {
+			return t == null ? null : t.getString("foo");
+		}
+		@RestMethod
+		public String b(Messages t) {
+			return t == null ? null : t.getString("foo");
+		}
+		@RestMethod(name=POST)
+		public String c(InputStream t) throws IOException {
+			return read(t);
+		}
+		@RestMethod(name=POST)
+		public String d(ServletInputStream t) throws IOException {
+			return read(t);
+		}
+		@RestMethod(name=POST)
+		public String e(Reader t) throws IOException {
+			return read(t);
+		}
+		@RestMethod
+		public void f(OutputStream t) throws IOException {
+			t.write("OK".getBytes());
+		}
+		@RestMethod
+		public void g(ServletOutputStream t) throws IOException {
+			t.write("OK".getBytes());
+		}
+		@RestMethod
+		public void h(Writer t) throws IOException {
+			t.write("OK");
+		}
+		@RestMethod
+		public boolean i(RequestHeaders t) {
+			return t != null;
+		}
+		@RestMethod
+		public boolean j(RequestQuery t) {
+			return t != null;
+		}
+		@RestMethod
+		public boolean k(RequestFormData t) {
+			return t != null;
+		}
+		@RestMethod
+		public String l(@Method String t) {
+			return t;
+		}
+		@SuppressWarnings("deprecation")
+		@RestMethod
+		public boolean m(RestLogger t) {
+			return t != null;
+		}
+		@RestMethod
+		public boolean n(RestContext t) {
+			return t != null;
+		}
+		@RestMethod(parsers={JsonParser.class})
+		public String o(Parser t) {
+			return t.getClass().getName();
+		}
+		@RestMethod
+		public String p(Locale t) {
+			return t.toString();
+		}
+		@RestMethod
+		public boolean q(Swagger t) {
+			return t != null;
+		}
+		@RestMethod
+		public boolean r(RequestPath t) {
+			return t != null;
+		}
+		@RestMethod
+		public boolean s(RequestBody t) {
+			return t != null;
+		}
+		@RestMethod
+		public boolean t(Config t) {
+			return t != null;
+		}
+	}
+
+	@Test
+	public void a01_params() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/a").acceptLanguage("en-US").run().assertBody().is("bar");
+		a.get("/a").acceptLanguage("ja-JP").run().assertBody().is("baz");
+		a.get("/b").acceptLanguage("en-US").run().assertBody().is("bar");
+		a.get("/b").acceptLanguage("ja-JP").run().assertBody().is("baz");
+		a.post("/c", "foo").run().assertBody().is("foo");
+		a.post("/d", "foo").run().assertBody().is("foo");
+		a.post("/e", "foo").run().assertBody().is("foo");
+		a.get("/f").run().assertBody().is("OK");
+		a.get("/g").run().assertBody().is("OK");
+		a.get("/h").run().assertBody().is("OK");
+		a.get("/i").run().assertBody().is("true");
+		a.get("/j").run().assertBody().is("true");
+		a.get("/k").run().assertBody().is("true");
+		a.get("/l").run().assertBody().is("GET");
+		a.get("/m").run().assertBody().is("true");
+		a.get("/n").run().assertBody().is("true");
+		a.get("/o").contentType("application/json").run().assertBody().is("org.apache.juneau.json.JsonParser");
+		a.get("/p").acceptLanguage("en-US").run().assertBody().is("en_US");
+		a.get("/p").acceptLanguage("ja-JP").run().assertBody().is("ja_JP");
+		a.get("/q").run().assertBody().is("true");
+		a.get("/r").run().assertBody().is("true");
+		a.get("/s").run().assertBody().is("true");
+		a.get("/t").run().assertBody().is("true");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Headers
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(
+		serializers=B1a.class,
+		parsers=B1b.class,
+		encoders=B1c.class,
+		allowedHeaderParams="*"
+	)
+	public static class B1 {
+
+		@RestMethod
+		public String accept(Accept accept) {
+			return accept.getValue();
+		}
+		@RestMethod
+		public String acceptCharset(AcceptCharset acceptCharset) {
+			return acceptCharset.getValue();
+		}
+		@RestMethod
+		public String acceptEncoding(AcceptEncoding acceptEncoding) {
+			return acceptEncoding.getValue();
+		}
+		@RestMethod
+		public String acceptLanguage(AcceptLanguage acceptLanguage) {
+			return acceptLanguage.getValue();
+		}
+		@RestMethod
+		public String authorization(Authorization authorization) {
+			return authorization.getValue();
+		}
+		@RestMethod
+		public String cacheControl(CacheControl cacheControl) {
+			return cacheControl.getValue();
+		}
+		@RestMethod
+		public String connection(Connection connection) {
+			return connection.getValue();
+		}
+		@RestMethod
+		public String contentLength(ContentLength contentLength) {
+			return contentLength.getValue();
+		}
+		@RestMethod
+		public String contentType(ContentType contentType) {
+			return contentType.getValue();
+		}
+		@RestMethod
+		public String date(org.apache.juneau.http.header.Date date) {
+			return date.getValue();
+		}
+		@RestMethod
+		public String expect(Expect expect) {
+			return expect.getValue();
+		}
+		@RestMethod
+		public String from(From from) {
+			return from.getValue();
+		}
+		@RestMethod
+		public String host(Host host) {
+			return host.getValue();
+		}
+		@RestMethod
+		public String ifMatch(IfMatch ifMatch) {
+			return ifMatch.getValue();
+		}
+		@RestMethod
+		public String ifModifiedSince(IfModifiedSince ifModifiedSince) {
+			return ifModifiedSince.getValue();
+		}
+		@RestMethod
+		public String ifNoneMatch(IfNoneMatch ifNoneMatch) {
+			return ifNoneMatch.getValue();
+		}
+		@RestMethod
+		public String ifRange(IfRange ifRange) {
+			return ifRange.getValue();
+		}
+		@RestMethod
+		public String ifUnmodifiedSince(IfUnmodifiedSince ifUnmodifiedSince) {
+			return ifUnmodifiedSince.getValue();
+		}
+		@RestMethod
+		public String maxForwards(MaxForwards maxForwards) {
+			return maxForwards.getValue();
+		}
+		@RestMethod
+		public String pragma(Pragma pragma) {
+			return pragma.getValue();
+		}
+		@RestMethod
+		public String proxyAuthorization(ProxyAuthorization proxyAuthorization) {
+			return proxyAuthorization.getValue();
+		}
+		@RestMethod
+		public String range(Range range) {
+			return range.getValue();
+		}
+		@RestMethod
+		public String referer(Referer referer) {
+			return referer.getValue();
+		}
+		@RestMethod
+		public String te(TE te) {
+			return te.getValue();
+		}
+		@RestMethod
+		public String upgrade(Upgrade upgrade) {
+			return upgrade.getValue();
+		}
+		@RestMethod
+		public String userAgent(UserAgent userAgent) {
+			return userAgent.getValue();
+		}
+		@RestMethod
+		public String warning(Warning warning) {
+			return warning.getValue();
+		}
+	}
+
+	public static class B1a extends PlainTextSerializer {
+		public B1a(PropertyStore ps) {
+			super(ps, "text/plain", "*/*");
+		}
+	}
+
+	public static class B1b extends PlainTextParser {
+		public B1b(PropertyStore ps) {
+			super(ps, "*/*");
+		}
+	}
+
+	public static class B1c extends IdentityEncoder {
+		@Override /* ConfigEncoder */
+		public String[] getCodings() {
+			return new String[]{"*"};
+		}
+	}
+
+	@Test
+	public void b01_headers() throws Exception {
+		RestClient b = MockRestClient.build(B1.class);
+
+		b.get("/accept").accept("text/foo").run().assertBody().is("text/foo");
+		b.get("/accept").accept("text/foo+bar").run().assertBody().is("text/foo+bar");
+		b.get("/accept").accept("text/*").run().assertBody().is("text/*");
+		b.get("/accept").accept("*/foo").run().assertBody().is("*/foo");
+		b.get("/accept").accept("text/foo;q=1.0").run().assertBody().is("text/foo");
+		b.get("/accept").accept("text/foo;q=0.9").run().assertBody().is("text/foo;q=0.9");
+		b.get("/accept").accept("text/foo;x=X;q=0.9;y=Y").run().assertBody().is("text/foo;x=X;q=0.9;y=Y");
+		b.get("/accept?Accept=text/foo").run().assertBody().is("text/foo");
+		b.get("/acceptCharset").acceptCharset("UTF-8").run().assertBody().is("UTF-8");
+		b.get("/acceptCharset?Accept-Charset=UTF-8").run().assertBody().is("UTF-8");
+		b.get("/acceptEncoding").acceptEncoding("foo").run().assertBody().is("foo");
+		b.get("/acceptEncoding").acceptEncoding("*").run().assertBody().is("*");
+		b.get("/acceptEncoding?Accept-Encoding=*").run().assertBody().is("*");
+		b.get("/acceptLanguage").acceptLanguage("foo").run().assertBody().is("foo");
+		b.get("/acceptLanguage?Accept-Language=foo").acceptLanguage("foo").run().assertBody().is("foo");
+		b.get("/authorization").authorization("foo").run().assertBody().is("foo");
+		b.get("/authorization?Authorization=foo").run().assertBody().is("foo");
+		b.get("/cacheControl").cacheControl("foo").run().assertBody().is("foo");
+		b.get("/cacheControl?Cache-Control=foo").run().assertBody().is("foo");
+		b.get("/connection").connection("foo").run().assertBody().is("foo");
+		b.get("/connection?Connection=foo").run().assertBody().is("foo");
+		b.get("/contentLength").contentLength(0).run().assertBody().is("0");
+		b.get("/contentLength?Content-Length=0").run().assertBody().is("0");
+		b.get("/contentType").contentType("text/foo").run().assertBody().is("text/foo");
+		b.get("/contentType?Content-Type=text/foo").run().assertBody().is("text/foo");
+		b.get("/date").date("Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");
+		b.get("/date?Date=Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");
+		b.get("/expect").expect("100-continue").run().assertBody().is("100-continue");
+		b.get("/expect?Expect=100-continue").run().assertBody().is("100-continue");
+		b.get("/from").from("foo").run().assertBody().is("foo");
+		b.get("/from?From=foo").run().assertBody().is("foo");
+		b.get("/host").host("localhost").run().assertBody().is("localhost");
+		b.get("/host?Host=localhost").run().assertBody().is("localhost");
+		b.get("/ifMatch").ifMatch("\"foo\"").run().assertBody().is("\"foo\"");
+		b.get("/ifMatch").ifMatch("W/\"foo\"").run().assertBody().is("W/\"foo\"");
+		b.get("/ifMatch").ifMatch("W/\"foo\",\"bar\"").run().assertBody().is("W/\"foo\",\"bar\"");
+		b.get("/ifMatch?If-Match=\"foo\"").run().assertBody().is("\"foo\"");
+		b.get("/ifModifiedSince").ifModifiedSince("Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");
+		b.get("/ifModifiedSince?If-Modified-Since=Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");
+		b.get("/ifNoneMatch").ifNoneMatch("\"foo\"").run().assertBody().is("\"foo\"");
+		b.get("/ifNoneMatch").ifNoneMatch("W/\"foo\"").run().assertBody().is("W/\"foo\"");
+		b.get("/ifNoneMatch").ifNoneMatch("W/\"foo\",\"bar\"").run().assertBody().is("W/\"foo\",\"bar\"");
+		b.get("/ifNoneMatch?If-None-Match=\"foo\"").run().assertBody().is("\"foo\"");
+		b.get("/ifRange").ifRange("\"foo\"").run().assertBody().is("\"foo\"");
+		b.get("/ifRange?If-Range=\"foo\"").run().assertBody().is("\"foo\"");
+		b.get("/ifUnmodifiedSince").ifUnmodifiedSince("Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");
+		b.get("/ifUnmodifiedSince?If-Unmodified-Since=Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");
+		b.get("/maxForwards").maxForwards(123).run().assertBody().is("123");
+		b.get("/maxForwards?Max-Forwards=123").run().assertBody().is("123");
+		b.get("/pragma").pragma("foo").run().assertBody().is("foo");
+		b.get("/pragma?Pragma=foo").run().assertBody().is("foo");
+		b.get("/proxyAuthorization").proxyAuthorization("foo").run().assertBody().is("foo");
+		b.get("/proxyAuthorization?Proxy-Authorization=foo").run().assertBody().is("foo");
+		b.get("/range").range("foo").run().assertBody().is("foo");
+		b.get("/range?Range=foo").run().assertBody().is("foo");
+		b.get("/referer").referer("foo").run().assertBody().is("foo");
+		b.get("/referer?Referer=foo").run().assertBody().is("foo");
+		b.get("/te").te("foo").run().assertBody().is("foo");
+		b.get("/te?TE=foo").run().assertBody().is("foo");
+		b.get("/upgrade").upgrade("foo").run().assertBody().is("foo");
+		b.get("/upgrade?Upgrade=foo").run().assertBody().is("foo");
+		b.get("/userAgent").userAgent("foo").run().assertBody().is("foo");
+		b.get("/userAgent?User-Agent=foo").run().assertBody().is("foo");
+		b.get("/warning").warning("foo").run().assertBody().is("foo");
+		b.get("/warning?Warning=foo").run().assertBody().is("foo");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Custom header.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(
+		paramResolvers=B2a.class,
+		allowedHeaderParams="Custom"
+	)
+	public static class B2 {
+		@RestMethod
+		public String a(B2b customHeader) {
+			return customHeader.toString();
+		}
+	}
+
+	public static class B2a extends RestMethodParam {
+		public B2a() {
+			super(RestParamType.HEADER, "Custom", B2b.class);
+		}
+		@Override
+		public Object resolve(RestRequest req, RestResponse res) throws Exception {
+			return new B2b(req.getHeader("Custom"));
+		}
+	}
+
+	public static class B2b {
+		public String value;
+		public B2b(String value) {
+			this.value = value;
+		}
+		@Override
+		public String toString() {
+			return value;
+		}
+	}
+
+	@Test
+	public void b02_customHeader() throws Exception {
+		RestClient b = MockRestClient.build(B2.class);
+		b.get("/a").header("Custom", "foo").run().assertBody().is("foo");
+		b.get("/a?Custom=foo").run().assertBody().is("foo");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Returns_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Returns_Test.java
new file mode 100644
index 0000000..bce0a56
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Returns_Test.java
@@ -0,0 +1,188 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.rest.testutils.TestUtils.*;
+
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.apache.juneau.http.*;
+import org.apache.juneau.http.response.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class RestMethod_Returns_Test {
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Response beans
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+		@RestMethod public Accepted accepted() { return new Accepted(); }
+		@RestMethod public AlreadyReported alreadyReported() { return new AlreadyReported(); }
+		@RestMethod(path="/continue") public Continue _continue() { return new Continue(); }
+		@RestMethod public Created created() { return new Created(); }
+		@RestMethod public EarlyHints earlyHints() { return new EarlyHints(); }
+		@RestMethod public Found found() { return new Found(); }
+		@RestMethod public IMUsed imUsed() { return new IMUsed(); }
+		@RestMethod public MovedPermanently movedPermanently() { return new MovedPermanently(); }
+		@RestMethod public MultipleChoices multipleChoices() { return new MultipleChoices(); }
+		@RestMethod public MultiStatus multiStatus() { return new MultiStatus(); }
+		@RestMethod public NoContent noContent() { return new NoContent(); }
+		@RestMethod public NonAuthoritiveInformation nonAuthoritiveInformation() { return new NonAuthoritiveInformation(); }
+		@RestMethod public NotModified notModified() { return new NotModified(); }
+		@RestMethod public Ok ok() { return new Ok(); }
+		@RestMethod public PartialContent partialContent() { return new PartialContent(); }
+		@RestMethod public PermanentRedirect permanentRedirect() { return new PermanentRedirect(); }
+		@RestMethod public Processing processing() { return new Processing(); }
+		@RestMethod public ResetContent resetContent() { return new ResetContent(); }
+		@RestMethod public SeeOther seeOther() { return new SeeOther(); }
+		@RestMethod public SwitchingProtocols switchingProtocols() { return new SwitchingProtocols(); }
+		@RestMethod public TemporaryRedirect temporaryRedirect() { return new TemporaryRedirect(); }
+		@RestMethod public UseProxy useProxy() { return new UseProxy(); }
+	}
+
+	@Test
+	public void a01_responseBeans() throws Exception {
+		RestClient c = client(A.class);
+		c.get("/accepted").run().assertStatus().code().is(Accepted.CODE).assertBody().is(Accepted.MESSAGE);
+		c.get("/alreadyReported").run().assertStatus().code().is(AlreadyReported.CODE).assertBody().is(AlreadyReported.MESSAGE);
+		c.get("/continue").run().assertStatus().code().is(Continue.CODE + 1000).assertBody().is(Continue.MESSAGE);
+		c.get("/created").run().assertStatus().code().is(Created.CODE).assertBody().is(Created.MESSAGE);
+		c.get("/earlyHints").run().assertStatus().code().is(EarlyHints.CODE + 1000).assertBody().is(EarlyHints.MESSAGE);
+		c.get("/found").run().assertStatus().code().is(Found.CODE).assertBody().is(Found.MESSAGE);
+		c.get("/imUsed").run().assertStatus().code().is(IMUsed.CODE).assertBody().is(IMUsed.MESSAGE);
+		c.get("/movedPermanently").run().assertStatus().code().is(MovedPermanently.CODE).assertBody().is(MovedPermanently.MESSAGE);
+		c.get("/multipleChoices").run().assertStatus().code().is(MultipleChoices.CODE).assertBody().is(MultipleChoices.MESSAGE);
+		c.get("/multiStatus").run().assertStatus().code().is(MultiStatus.CODE).assertBody().is(MultiStatus.MESSAGE);
+		c.get("/noContent").run().assertStatus().code().is(NoContent.CODE).assertBody().isEmpty();
+		c.get("/nonAuthoritiveInformation").run().assertStatus().code().is(NonAuthoritiveInformation.CODE).assertBody().is(NonAuthoritiveInformation.MESSAGE);
+		c.get("/notModified").run().assertStatus().code().is(NotModified.CODE).assertBody().isEmpty();
+		c.get("/ok").run().assertStatus().code().is(Ok.CODE).assertBody().is(Ok.MESSAGE);
+		c.get("/partialContent").run().assertStatus().code().is(PartialContent.CODE).assertBody().is(PartialContent.MESSAGE);
+		c.get("/permanentRedirect").run().assertStatus().code().is(PermanentRedirect.CODE).assertBody().is(PermanentRedirect.MESSAGE);
+		c.get("/processing").run().assertStatus().code().is(Processing.CODE + 1000).assertBody().is(Processing.MESSAGE);
+		c.get("/resetContent").run().assertStatus().code().is(ResetContent.CODE).assertBody().isEmpty();
+		c.get("/seeOther").run().assertStatus().code().is(SeeOther.CODE).assertBody().is(SeeOther.MESSAGE);
+		c.get("/switchingProtocols").run().assertStatus().code().is(SwitchingProtocols.CODE + 1000).assertBody().is(SwitchingProtocols.MESSAGE);
+		c.get("/temporaryRedirect").run().assertStatus().code().is(TemporaryRedirect.CODE).assertBody().is(TemporaryRedirect.MESSAGE);
+		c.get("/useProxy").run().assertStatus().code().is(UseProxy.CODE).assertBody().is(UseProxy.MESSAGE);
+	}
+
+	@Test
+	public void a02_responseBeans_swagger() throws Exception {
+		Map<String,OperationMap> paths = getSwagger(A.class).getPaths();
+		assertEquals(Accepted.MESSAGE, paths.get("/accepted").get("get").getResponse(Accepted.CODE).getDescription());
+		assertEquals(AlreadyReported.MESSAGE, paths.get("/alreadyReported").get("get").getResponse(AlreadyReported.CODE).getDescription());
+		assertEquals(Continue.MESSAGE, paths.get("/continue").get("get").getResponse(Continue.CODE).getDescription());
+		assertEquals(Created.MESSAGE, paths.get("/created").get("get").getResponse(Created.CODE).getDescription());
+		assertEquals(EarlyHints.MESSAGE, paths.get("/earlyHints").get("get").getResponse(EarlyHints.CODE).getDescription());
+		assertEquals(Found.MESSAGE, paths.get("/found").get("get").getResponse(Found.CODE).getDescription());
+		assertEquals(IMUsed.MESSAGE, paths.get("/imUsed").get("get").getResponse(IMUsed.CODE).getDescription());
+		assertEquals(MovedPermanently.MESSAGE, paths.get("/movedPermanently").get("get").getResponse(MovedPermanently.CODE).getDescription());
+		assertEquals(MultipleChoices.MESSAGE, paths.get("/multipleChoices").get("get").getResponse(MultipleChoices.CODE).getDescription());
+		assertEquals(MultiStatus.MESSAGE, paths.get("/multiStatus").get("get").getResponse(MultiStatus.CODE).getDescription());
+		assertEquals(NoContent.MESSAGE, paths.get("/noContent").get("get").getResponse(NoContent.CODE).getDescription());
+		assertEquals(NonAuthoritiveInformation.MESSAGE, paths.get("/nonAuthoritiveInformation").get("get").getResponse(NonAuthoritiveInformation.CODE).getDescription());
+		assertEquals(NotModified.MESSAGE, paths.get("/notModified").get("get").getResponse(NotModified.CODE).getDescription());
+		assertEquals(Ok.MESSAGE, paths.get("/ok").get("get").getResponse(Ok.CODE).getDescription());
+		assertEquals(PartialContent.MESSAGE, paths.get("/partialContent").get("get").getResponse(PartialContent.CODE).getDescription());
+		assertEquals(PermanentRedirect.MESSAGE, paths.get("/permanentRedirect").get("get").getResponse(PermanentRedirect.CODE).getDescription());
+		assertEquals(Processing.MESSAGE, paths.get("/processing").get("get").getResponse(Processing.CODE).getDescription());
+		assertEquals(ResetContent.MESSAGE, paths.get("/resetContent").get("get").getResponse(ResetContent.CODE).getDescription());
+		assertEquals(SeeOther.MESSAGE, paths.get("/seeOther").get("get").getResponse(SeeOther.CODE).getDescription());
+		assertEquals(SwitchingProtocols.MESSAGE, paths.get("/switchingProtocols").get("get").getResponse(SwitchingProtocols.CODE).getDescription());
+		assertEquals(TemporaryRedirect.MESSAGE, paths.get("/temporaryRedirect").get("get").getResponse(TemporaryRedirect.CODE).getDescription());
+		assertEquals(UseProxy.MESSAGE, paths.get("/useProxy").get("get").getResponse(UseProxy.CODE).getDescription());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// BasicHttpResource
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class B {
+		@RestMethod
+		public BasicHttpResource a() throws Exception {
+			return BasicHttpResource.of("foo");
+		}
+		@RestMethod
+		public BasicHttpResource b() throws Exception {
+			return BasicHttpResource.of(null).header("Foo", "Bar");
+		}
+		@RestMethod
+		public BasicHttpResource c() throws Exception {
+			return BasicHttpResource.of(null).contentType("application/json");
+		}
+		@RestMethod
+		public BasicHttpResource d(RestRequest req) throws Exception {
+			return BasicHttpResource.of(()->req.getVarResolverSession().resolve("$RQ{foo}"));
+		}
+		@RestMethod
+		public BasicHttpResource e() throws Exception {
+			return BasicHttpResource.of(new ByteArrayInputStream("foo".getBytes()));
+		}
+		@RestMethod
+		public BasicHttpResource f() throws Exception {
+			return BasicHttpResource.of(new StringReader("foo"));
+		}
+		@RestMethod
+		public BasicHttpResource g() throws Exception {
+			return BasicHttpResource.of(new StringBuilder("foo"));
+		}
+	}
+
+	@Test
+	public void b01_BasicHttpResource() throws Exception {
+		RestClient b = MockRestClient.build(B.class);
+		b.get("/a")
+			.run()
+			.assertBody().is("foo");
+		b.get("/b")
+			.run()
+			.assertStringHeader("Foo").is("Bar");
+		b.get("/c")
+			.run()
+			.assertStringHeader("Content-Type").is("application/json");
+		b.get("/d?foo=bar")
+			.run()
+			.assertBody().is("bar");
+		b.get("/e")
+			.run()
+			.assertBody().is("foo");
+		b.get("/f")
+			.run()
+			.assertBody().is("foo");
+		b.get("/g")
+			.run()
+			.assertBody().is("foo");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Helper methods
+	//------------------------------------------------------------------------------------------------------------------
+
+	private static MockRestClient client(Class<?> c) {
+		return MockRestClient.create(c).disableRedirectHandling().ignoreErrors().build();
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/exceptions/BasicTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Throws_Test.java
similarity index 65%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/exceptions/BasicTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Throws_Test.java
index 1061191..fc18e6b 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/exceptions/BasicTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestMethod_Throws_Test.java
@@ -10,24 +10,27 @@
 // * "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.rest.exceptions;
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.rest.testutils.TestUtils.*;
 
 import static org.junit.Assert.*;
 import static org.junit.runners.MethodSorters.*;
-import static org.apache.juneau.rest.testutils.TestUtils.*;
+
+import java.util.*;
 
 import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
 import org.apache.juneau.rest.helper.*;
 import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
 import org.apache.juneau.http.exception.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.parser.*;
+import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class BasicTest {
-
+public class RestMethod_Throws_Test {
 	//-----------------------------------------------------------------------------------------------------------------
 	// Basic sanity tests
 	//-----------------------------------------------------------------------------------------------------------------
@@ -69,234 +72,137 @@
 		@RestMethod public void variantAlsoNegotiates() { throw new VariantAlsoNegotiates(); }
 	}
 
-	static MockRestClient a = MockRestClient.buildLax(A.class);
-
 	@Test
-	public void a01_badRequest() throws Exception {
+	public void a01_noArgs() throws Exception {
+		RestClient a = MockRestClient.buildLax(A.class);
 		a.get("/badRequest")
 			.run()
 			.assertCode().is(400)
 			.assertBody().is("Bad Request");
-	}
-	@Test
-	public void a02_conflict() throws Exception {
 		a.get("/conflict")
 			.run()
 			.assertCode().is(409)
 			.assertBody().is("Conflict");
-	}
-	@Test
-	public void a03_expectationFailed() throws Exception {
 		a.get("/expectationFailed")
 			.run()
 			.assertCode().is(417)
 			.assertBody().is("Expectation Failed");
-	}
-	@Test
-	public void a04_failedDependency() throws Exception {
 		a.get("/failedDependency")
 			.run()
 			.assertCode().is(424)
 			.assertBody().is("Failed Dependency");
-	}
-	@Test
-	public void a05_forbidden() throws Exception {
 		a.get("/forbidden")
 			.run()
 			.assertCode().is(403)
 			.assertBody().is("Forbidden");
-	}
-	@Test
-	public void a06_gone() throws Exception {
 		a.get("/gone")
 			.run()
 			.assertCode().is(410)
 			.assertBody().is("Gone");
-	}
-	@Test
-	public void a07_httpVersionNotSupported() throws Exception {
 		a.get("/httpVersionNotSupported")
 			.run()
 			.assertCode().is(505)
 			.assertBody().is("HTTP Version Not Supported");
-	}
-	@Test
-	public void a08_insufficientStorage() throws Exception {
 		a.get("/insufficientStorage")
 			.run()
 			.assertCode().is(507)
 			.assertBody().is("Insufficient Storage");
-	}
-	@Test
-	public void a09_internalServerError() throws Exception {
 		a.get("/internalServerError")
 			.run()
 			.assertCode().is(500)
 			.assertBody().is("Internal Server Error");
-	}
-	@Test
-	public void a10_lengthRequired() throws Exception {
 		a.get("/lengthRequired")
 			.run()
 			.assertCode().is(411)
 			.assertBody().is("Length Required");
-	}
-	@Test
-	public void a11_locked() throws Exception {
 		a.get("/locked")
 			.run()
 			.assertCode().is(423)
 			.assertBody().is("Locked");
-	}
-	@Test
-	public void a12_loopDetected() throws Exception {
 		a.get("/loopDetected")
 			.run()
 			.assertCode().is(508)
 			.assertBody().is("Loop Detected");
-	}
-	@Test
-	public void a13_methodNotAllowed() throws Exception {
 		a.get("/methodNotAllowed")
 			.run()
 			.assertCode().is(405)
 			.assertBody().is("Method Not Allowed");
-	}
-	@Test
-	public void a14_misdirectedRequest() throws Exception {
 		a.get("/misdirectedRequest")
 			.run()
 			.assertCode().is(421)
 			.assertBody().is("Misdirected Request");
-	}
-	@Test
-	public void a15_networkAuthenticationRequired() throws Exception {
 		a.get("/networkAuthenticationRequired")
 			.run()
 			.assertCode().is(511)
 			.assertBody().is("Network Authentication Required");
-	}
-	@Test
-	public void a16_notAcceptable() throws Exception {
 		a.get("/notAcceptable")
 			.run()
 			.assertCode().is(406)
 			.assertBody().is("Not Acceptable");
-	}
-	@Test
-	public void a17_notExtended() throws Exception {
 		a.get("/notExtended")
 			.run()
 			.assertCode().is(510)
 			.assertBody().is("Not Extended");
-	}
-	@Test
-	public void a18_notFound() throws Exception {
 		a.get("/notFound")
 			.run()
 			.assertCode().is(404)
 			.assertBody().is("Not Found");
-	}
-	@Test
-	public void a19_notImplemented() throws Exception {
 		a.get("/notImplemented")
 			.run()
 			.assertCode().is(501)
 			.assertBody().is("Not Implemented");
-	}
-	@Test
-	public void a20_payloadTooLarge() throws Exception {
 		a.get("/payloadTooLarge")
 			.run()
 			.assertCode().is(413)
 			.assertBody().is("Payload Too Large");
-	}
-	@Test
-	public void a21_preconditionFailed() throws Exception {
 		a.get("/preconditionFailed")
 			.run()
 			.assertCode().is(412)
 			.assertBody().is("Precondition Failed");
-	}
-	@Test
-	public void a22_preconditionRequired() throws Exception {
 		a.get("/preconditionRequired")
 			.run()
 			.assertCode().is(428)
 			.assertBody().is("Precondition Required");
-	}
-	@Test
-	public void a23_rangeNotSatisfiable() throws Exception {
 		a.get("/rangeNotSatisfiable")
 			.run()
 			.assertCode().is(416)
 			.assertBody().is("Range Not Satisfiable");
-	}
-	@Test
-	public void a24_requestHeaderFieldsTooLarge() throws Exception {
 		a.get("/requestHeaderFieldsTooLarge")
 			.run()
 			.assertCode().is(431)
 			.assertBody().is("Request Header Fields Too Large");
-	}
-	@Test
-	public void a25_serviceUnavailable() throws Exception {
 		a.get("/serviceUnavailable")
 			.run()
 			.assertCode().is(503)
 			.assertBody().is("Service Unavailable");
-	}
-	@Test
-	public void a26_tooManyRequests() throws Exception {
 		a.get("/tooManyRequests")
 			.run()
 			.assertCode().is(429)
 			.assertBody().is("Too Many Requests");
-	}
-	@Test
-	public void a27_unauthorized() throws Exception {
 		a.get("/unauthorized")
 			.run()
 			.assertCode().is(401)
 			.assertBody().is("Unauthorized");
-	}
-	@Test
-	public void a28_unavailableForLegalReasons() throws Exception {
 		a.get("/unavailableForLegalReasons")
 			.run()
 			.assertCode().is(451)
 			.assertBody().is("Unavailable For Legal Reasons");
-	}
-	@Test
-	public void a29_unprocessableEntity() throws Exception {
 		a.get("/unprocessableEntity")
 			.run()
 			.assertCode().is(422)
 			.assertBody().is("Unprocessable Entity");
-	}
-	@Test
-	public void a30_unsupportedMediaType() throws Exception {
 		a.get("/unsupportedMediaType")
 			.run()
 			.assertCode().is(415)
 			.assertBody().is("Unsupported Media Type");
-	}
-	@Test
-	public void a31_upgradeRequired() throws Exception {
 		a.get("/upgradeRequired")
 			.run()
 			.assertCode().is(426)
 			.assertBody().is("Upgrade Required");
-	}
-	@Test
-	public void a32_uriTooLong() throws Exception {
 		a.get("/uriTooLong")
 			.run()
 			.assertCode().is(414)
 			.assertBody().is("URI Too Long");
-	}
-	@Test
-	public void a33_variantAlsoNegotiates() throws Exception {
 		a.get("/variantAlsoNegotiates")
 			.run()
 			.assertCode().is(506)
@@ -344,234 +250,138 @@
 		@RestMethod public void variantAlsoNegotiates() { throw new VariantAlsoNegotiates("foo {0}", "bar"); }
 	}
 
-	static MockRestClient b = MockRestClient.buildLax(B.class);
 
 	@Test
-	public void b01_badRequest() throws Exception {
+	public void b01_userSpecifiedMessage() throws Exception {
+		RestClient b = MockRestClient.buildLax(B.class);
 		b.get("/badRequest")
 			.run()
 			.assertCode().is(400)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b02_conflict() throws Exception {
 		b.get("/conflict")
 			.run()
 			.assertCode().is(409)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b03_expectationFailed() throws Exception {
 		b.get("/expectationFailed")
 			.run()
 			.assertCode().is(417)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b04_failedDependency() throws Exception {
 		b.get("/failedDependency")
 			.run()
 			.assertCode().is(424)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b05_forbidden() throws Exception {
 		b.get("/forbidden")
 			.run()
 			.assertCode().is(403)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b06_gone() throws Exception {
 		b.get("/gone")
 			.run()
 			.assertCode().is(410)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b07_httpVersionNotSupported() throws Exception {
 		b.get("/httpVersionNotSupported")
 			.run()
 			.assertCode().is(505)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b08_insufficientStorage() throws Exception {
 		b.get("/insufficientStorage")
 			.run()
 			.assertCode().is(507)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b09_internalServerError() throws Exception {
 		b.get("/internalServerError")
 			.run()
 			.assertCode().is(500)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b10_lengthRequired() throws Exception {
 		b.get("/lengthRequired")
 			.run()
 			.assertCode().is(411)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b11_locked() throws Exception {
 		b.get("/locked")
 			.run()
 			.assertCode().is(423)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b12_loopDetected() throws Exception {
 		b.get("/loopDetected")
 			.run()
 			.assertCode().is(508)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b13_methodNotAllowed() throws Exception {
 		b.get("/methodNotAllowed")
 			.run()
 			.assertCode().is(405)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b14_misdirectedRequest() throws Exception {
 		b.get("/misdirectedRequest")
 			.run()
 			.assertCode().is(421)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b15_networkAuthenticationRequired() throws Exception {
 		b.get("/networkAuthenticationRequired")
 			.run()
 			.assertCode().is(511)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b16_notAcceptable() throws Exception {
 		b.get("/notAcceptable")
 			.run()
 			.assertCode().is(406)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b17_notExtended() throws Exception {
 		b.get("/notExtended")
 			.run()
 			.assertCode().is(510)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b18_notFound() throws Exception {
 		b.get("/notFound")
 			.run()
 			.assertCode().is(404)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b19_notImplemented() throws Exception {
 		b.get("/notImplemented")
 			.run()
 			.assertCode().is(501)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b20_payloadTooLarge() throws Exception {
 		b.get("/payloadTooLarge")
 			.run()
 			.assertCode().is(413)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b21_preconditionFailed() throws Exception {
 		b.get("/preconditionFailed")
 			.run()
 			.assertCode().is(412)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b22_preconditionRequired() throws Exception {
 		b.get("/preconditionRequired")
 			.run()
 			.assertCode().is(428)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b23_rangeNotSatisfiable() throws Exception {
 		b.get("/rangeNotSatisfiable")
 			.run()
 			.assertCode().is(416)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b24_requestHeaderFieldsTooLarge() throws Exception {
 		b.get("/requestHeaderFieldsTooLarge")
 			.run()
 			.assertCode().is(431)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b25_serviceUnavailable() throws Exception {
 		b.get("/serviceUnavailable")
 			.run()
 			.assertCode().is(503)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b26_tooManyRequests() throws Exception {
 		b.get("/tooManyRequests")
 			.run()
 			.assertCode().is(429)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b27_unauthorized() throws Exception {
 		b.get("/unauthorized")
 			.run()
 			.assertCode().is(401)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b28_unavailableForLegalReasons() throws Exception {
 		b.get("/unavailableForLegalReasons")
 			.run()
 			.assertCode().is(451)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b29_unprocessableEntity() throws Exception {
 		b.get("/unprocessableEntity")
 			.run()
 			.assertCode().is(422)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b30_unsupportedMediaType() throws Exception {
 		b.get("/unsupportedMediaType")
 			.run()
 			.assertCode().is(415)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b31_upgradeRequired() throws Exception {
 		b.get("/upgradeRequired")
 			.run()
 			.assertCode().is(426)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b32_uriTooLong() throws Exception {
 		b.get("/uriTooLong")
 			.run()
 			.assertCode().is(414)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void b33_variantAlsoNegotiates() throws Exception {
 		b.get("/variantAlsoNegotiates")
 			.run()
 			.assertCode().is(506)
@@ -621,234 +431,137 @@
 		@RestMethod public void variantAlsoNegotiates() { throw new VariantAlsoNegotiates(t); }
 	}
 
-	static MockRestClient c = MockRestClient.buildLax(C.class);
-
 	@Test
-	public void c01_badRequest() throws Exception {
+	public void c01_nestedThrowable() throws Exception {
+		RestClient c = MockRestClient.buildLax(C.class);
 		c.get("/badRequest")
 			.run()
 			.assertCode().is(400)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c02_conflict() throws Exception {
 		c.get("/conflict")
 			.run()
 			.assertCode().is(409)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c03_expectationFailed() throws Exception {
 		c.get("/expectationFailed")
 			.run()
 			.assertCode().is(417)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c04_failedDependency() throws Exception {
 		c.get("/failedDependency")
 			.run()
 			.assertCode().is(424)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c05_forbidden() throws Exception {
 		c.get("/forbidden")
 			.run()
 			.assertCode().is(403)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c06_gone() throws Exception {
 		c.get("/gone")
 			.run()
 			.assertCode().is(410)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c07_httpVersionNotSupported() throws Exception {
 		c.get("/httpVersionNotSupported")
 			.run()
 			.assertCode().is(505)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c08_insufficientStorage() throws Exception {
 		c.get("/insufficientStorage")
 			.run()
 			.assertCode().is(507)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c09_internalServerError() throws Exception {
 		c.get("/internalServerError")
 			.run()
 			.assertCode().is(500)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c10_lengthRequired() throws Exception {
 		c.get("/lengthRequired")
 			.run()
 			.assertCode().is(411)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c11_locked() throws Exception {
 		c.get("/locked")
 			.run()
 			.assertCode().is(423)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c12_loopDetected() throws Exception {
 		c.get("/loopDetected")
 			.run()
 			.assertCode().is(508)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c13_methodNotAllowed() throws Exception {
 		c.get("/methodNotAllowed")
 			.run()
 			.assertCode().is(405)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c14_misdirectedRequest() throws Exception {
 		c.get("/misdirectedRequest")
 			.run()
 			.assertCode().is(421)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c15_networkAuthenticationRequired() throws Exception {
 		c.get("/networkAuthenticationRequired")
 			.run()
 			.assertCode().is(511)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c16_notAcceptable() throws Exception {
 		c.get("/notAcceptable")
 			.run()
 			.assertCode().is(406)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c17_notExtended() throws Exception {
 		c.get("/notExtended")
 			.run()
 			.assertCode().is(510)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c18_notFound() throws Exception {
 		c.get("/notFound")
 			.run()
 			.assertCode().is(404)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c19_notImplemented() throws Exception {
 		c.get("/notImplemented")
 			.run()
 			.assertCode().is(501)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c20_payloadTooLarge() throws Exception {
 		c.get("/payloadTooLarge")
 			.run()
 			.assertCode().is(413)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c21_preconditionFailed() throws Exception {
 		c.get("/preconditionFailed").
 			run()
 			.assertCode().is(412)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c22_preconditionRequired() throws Exception {
 		c.get("/preconditionRequired")
 			.run()
 			.assertCode().is(428)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c23_rangeNotSatisfiable() throws Exception {
 		c.get("/rangeNotSatisfiable")
 			.run()
 			.assertCode().is(416)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c24_requestHeaderFieldsTooLarge() throws Exception {
 		c.get("/requestHeaderFieldsTooLarge")
 			.run()
 			.assertCode().is(431)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c25_serviceUnavailable() throws Exception {
 		c.get("/serviceUnavailable")
 			.run()
 			.assertCode().is(503)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c26_tooManyRequests() throws Exception {
 		c.get("/tooManyRequests")
 			.run()
 			.assertCode().is(429)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c27_unauthorized() throws Exception {
 		c.get("/unauthorized")
 			.run()
 			.assertCode().is(401)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c28_unavailableForLegalReasons() throws Exception {
 		c.get("/unavailableForLegalReasons")
 			.run()
 			.assertCode().is(451)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c29_unprocessableEntity() throws Exception {
 		c.get("/unprocessableEntity")
 			.run()
 			.assertCode().is(422)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c30_unsupportedMediaType() throws Exception {
 		c.get("/unsupportedMediaType")
 			.run()
 			.assertCode().is(415)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c31_upgradeRequired() throws Exception {
 		c.get("/upgradeRequired")
 			.run()
 			.assertCode().is(426)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c32_uriTooLong() throws Exception {
 		c.get("/uriTooLong")
 			.run()
 			.assertCode().is(414)
 			.assertBody().is("foo");
-	}
-	@Test
-	public void c33_variantAlsoNegotiates() throws Exception {
 		c.get("/variantAlsoNegotiates")
 			.run()
 			.assertCode().is(506)
@@ -896,234 +609,137 @@
 		@RestMethod public void variantAlsoNegotiates() { throw new VariantAlsoNegotiates(t, "foo {0}", "bar"); }
 	}
 
-	static MockRestClient d = MockRestClient.buildLax(D.class);
-
 	@Test
-	public void d01_badRequest() throws Exception {
+	public void d01_nestedThrowableWithMessage() throws Exception {
+		RestClient d = MockRestClient.buildLax(D.class);
 		d.get("/badRequest")
 			.run()
 			.assertCode().is(400)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d02_conflict() throws Exception {
 		d.get("/conflict")
 			.run()
 			.assertCode().is(409)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d03_expectationFailed() throws Exception {
 		d.get("/expectationFailed")
 			.run()
 			.assertCode().is(417)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d04_failedDependency() throws Exception {
 		d.get("/failedDependency")
 			.run()
 			.assertCode().is(424)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d05_forbidden() throws Exception {
 		d.get("/forbidden")
 			.run()
 			.assertCode().is(403)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d06_gone() throws Exception {
 		d.get("/gone")
 			.run()
 			.assertCode().is(410)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d07_httpVersionNotSupported() throws Exception {
 		d.get("/httpVersionNotSupported")
 			.run()
 			.assertCode().is(505)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d08_insufficientStorage() throws Exception {
 		d.get("/insufficientStorage")
 			.run()
 			.assertCode().is(507)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d09_internalServerError() throws Exception {
 		d.get("/internalServerError")
 			.run()
 			.assertCode().is(500)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d10_lengthRequired() throws Exception {
 		d.get("/lengthRequired")
 			.run()
 			.assertCode().is(411)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d11_locked() throws Exception {
 		d.get("/locked")
 			.run()
 			.assertCode().is(423)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d12_loopDetected() throws Exception {
 		d.get("/loopDetected")
 			.run()
 			.assertCode().is(508)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d13_methodNotAllowed() throws Exception {
 		d.get("/methodNotAllowed")
 			.run()
 			.assertCode().is(405)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d14_misdirectedRequest() throws Exception {
 		d.get("/misdirectedRequest")
 			.run()
 			.assertCode().is(421)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d15_networkAuthenticationRequired() throws Exception {
 		d.get("/networkAuthenticationRequired")
 			.run()
 			.assertCode().is(511)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d16_notAcceptable() throws Exception {
 		d.get("/notAcceptable")
 			.run()
 			.assertCode().is(406)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d17_notExtended() throws Exception {
 		d.get("/notExtended")
 			.run()
 			.assertCode().is(510)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d18_notFound() throws Exception {
 		d.get("/notFound")
 			.run()
 			.assertCode().is(404)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d19_notImplemented() throws Exception {
 		d.get("/notImplemented")
 			.run()
 			.assertCode().is(501)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d20_payloadTooLarge() throws Exception {
 		d.get("/payloadTooLarge")
 			.run()
 			.assertCode().is(413)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d21_preconditionFailed() throws Exception {
 		d.get("/preconditionFailed")
 			.run()
 			.assertCode().is(412)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d22_preconditionRequired() throws Exception {
 		d.get("/preconditionRequired")
 			.run()
 			.assertCode().is(428)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d23_rangeNotSatisfiable() throws Exception {
 		d.get("/rangeNotSatisfiable")
 			.run()
 			.assertCode().is(416)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d24_requestHeaderFieldsTooLarge() throws Exception {
 		d.get("/requestHeaderFieldsTooLarge")
 			.run()
 			.assertCode().is(431)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d25_serviceUnavailable() throws Exception {
 		d.get("/serviceUnavailable")
 			.run()
 			.assertCode().is(503)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d26_tooManyRequests() throws Exception {
 		d.get("/tooManyRequests")
 			.run()
 			.assertCode().is(429)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d27_unauthorized() throws Exception {
 		d.get("/unauthorized")
 			.run()
 			.assertCode().is(401)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d28_unavailableForLegalReasons() throws Exception {
 		d.get("/unavailableForLegalReasons")
 			.run()
 			.assertCode().is(451)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d29_unprocessableEntity() throws Exception {
 		d.get("/unprocessableEntity")
 			.run()
 			.assertCode().is(422)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d30_unsupportedMediaType() throws Exception {
 		d.get("/unsupportedMediaType")
 			.run()
 			.assertCode().is(415)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d31_upgradeRequired() throws Exception {
 		d.get("/upgradeRequired")
 			.run()
 			.assertCode().is(426)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d32_uriTooLong() throws Exception {
 		d.get("/uriTooLong")
 			.run()
 			.assertCode().is(414)
 			.assertBody().is("foo bar");
-	}
-	@Test
-	public void d33_variantAlsoNegotiates() throws Exception {
 		d.get("/variantAlsoNegotiates")
 			.run()
 			.assertCode().is(506)
@@ -1139,10 +755,9 @@
 		@RestMethod public void badRequest() { throw new BadRequest(t, "foo {0}", "bar"); }
 	}
 
-	static MockRestClient e = MockRestClient.buildLax(E.class);
-
 	@Test
-	public void e01_badRequest() throws Exception {
+	public void e01_useAcceptForSerialization() throws Exception {
+		RestClient e = MockRestClient.buildLax(E.class);
 		e.get("/badRequest")
 			.json()
 			.run()
@@ -1191,172 +806,43 @@
 		@RestMethod public void variantAlsoNegotiates() throws VariantAlsoNegotiates {}
 	}
 
-	static Swagger f = getSwagger(F.class);
+	@Test
+	public void f01_swagger() throws Exception {
+		Map<String,OperationMap> paths = getSwagger(F.class).getPaths();
 
-	@Test
-	public void f01_badRequest() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/badRequest").get("get").getResponse(BadRequest.CODE);
-		assertEquals(BadRequest.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f02_conflict() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/conflict").get("get").getResponse(Conflict.CODE);
-		assertEquals(Conflict.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f03_expectationFailed() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/expectationFailed").get("get").getResponse(ExpectationFailed.CODE);
-		assertEquals(ExpectationFailed.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f04_failedDependency() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/failedDependency").get("get").getResponse(FailedDependency.CODE);
-		assertEquals(FailedDependency.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f05_forbidden() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/forbidden").get("get").getResponse(Forbidden.CODE);
-		assertEquals(Forbidden.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f06_gone() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/gone").get("get").getResponse(Gone.CODE);
-		assertEquals(Gone.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f07_httpVersionNotSupported() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/httpVersionNotSupported").get("get").getResponse(HttpVersionNotSupported.CODE);
-		assertEquals(HttpVersionNotSupported.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f08_insufficientStorage() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/insufficientStorage").get("get").getResponse(InsufficientStorage.CODE);
-		assertEquals(InsufficientStorage.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f09_internalServerError() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/internalServerError").get("get").getResponse(InternalServerError.CODE);
-		assertEquals(InternalServerError.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f10_lengthRequired() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/lengthRequired").get("get").getResponse(LengthRequired.CODE);
-		assertEquals(LengthRequired.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f11_locked() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/locked").get("get").getResponse(Locked.CODE);
-		assertEquals(Locked.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f12_loopDetected() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/loopDetected").get("get").getResponse(LoopDetected.CODE);
-		assertEquals(LoopDetected.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f13_methodNotAllowed() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/methodNotAllowed").get("get").getResponse(MethodNotAllowed.CODE);
-		assertEquals(MethodNotAllowed.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f14_misdirectedRequest() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/misdirectedRequest").get("get").getResponse(MisdirectedRequest.CODE);
-		assertEquals(MisdirectedRequest.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f15_networkAuthenticationRequired() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/networkAuthenticationRequired").get("get").getResponse(NetworkAuthenticationRequired.CODE);
-		assertEquals(NetworkAuthenticationRequired.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f16_notAcceptable() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/notAcceptable").get("get").getResponse(NotAcceptable.CODE);
-		assertEquals(NotAcceptable.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f17_notExtended() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/notExtended").get("get").getResponse(NotExtended.CODE);
-		assertEquals(NotExtended.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f18_notFound() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/notFound").get("get").getResponse(NotFound.CODE);
-		assertEquals(NotFound.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f19_notImplemented() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/notImplemented").get("get").getResponse(NotImplemented.CODE);
-		assertEquals(NotImplemented.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f20_payloadTooLarge() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/payloadTooLarge").get("get").getResponse(PayloadTooLarge.CODE);
-		assertEquals(PayloadTooLarge.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f21_preconditionFailed() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/preconditionFailed").get("get").getResponse(PreconditionFailed.CODE);
-		assertEquals(PreconditionFailed.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f22_preconditionRequired() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/preconditionRequired").get("get").getResponse(PreconditionRequired.CODE);
-		assertEquals(PreconditionRequired.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f23_rangeNotSatisfiable() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/rangeNotSatisfiable").get("get").getResponse(RangeNotSatisfiable.CODE);
-		assertEquals(RangeNotSatisfiable.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f24_requestHeaderFieldsTooLarge() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/requestHeaderFieldsTooLarge").get("get").getResponse(RequestHeaderFieldsTooLarge.CODE);
-		assertEquals(RequestHeaderFieldsTooLarge.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f25_serviceUnavailable() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/serviceUnavailable").get("get").getResponse(ServiceUnavailable.CODE);
-		assertEquals(ServiceUnavailable.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f26_tooManyRequests() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/tooManyRequests").get("get").getResponse(TooManyRequests.CODE);
-		assertEquals(TooManyRequests.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f27_unauthorized() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/unauthorized").get("get").getResponse(Unauthorized.CODE);
-		assertEquals(Unauthorized.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f28_unavailableForLegalReasons() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/unavailableForLegalReasons").get("get").getResponse(UnavailableForLegalReasons.CODE);
-		assertEquals(UnavailableForLegalReasons.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f29_unprocessableEntity() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/unprocessableEntity").get("get").getResponse(UnprocessableEntity.CODE);
-		assertEquals(UnprocessableEntity.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f30_unsupportedMediaType() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/unsupportedMediaType").get("get").getResponse(UnsupportedMediaType.CODE);
-		assertEquals(UnsupportedMediaType.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f31_upgradeRequired() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/upgradeRequired").get("get").getResponse(UpgradeRequired.CODE);
-		assertEquals(UpgradeRequired.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f32_uriTooLong() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/uriTooLong").get("get").getResponse(UriTooLong.CODE);
-		assertEquals(UriTooLong.MESSAGE, ri.getDescription());
-	}
-	@Test
-	public void f33_variantAlsoNegotiates() throws Exception {
-		ResponseInfo ri = f.getPaths().get("/variantAlsoNegotiates").get("get").getResponse(VariantAlsoNegotiates.CODE);
-		assertEquals(VariantAlsoNegotiates.MESSAGE, ri.getDescription());
+		assertEquals(BadRequest.MESSAGE, paths.get("/badRequest").get("get").getResponse(BadRequest.CODE).getDescription());
+		assertEquals(Conflict.MESSAGE, paths.get("/conflict").get("get").getResponse(Conflict.CODE).getDescription());
+		assertEquals(ExpectationFailed.MESSAGE, paths.get("/expectationFailed").get("get").getResponse(ExpectationFailed.CODE).getDescription());
+		assertEquals(FailedDependency.MESSAGE, paths.get("/failedDependency").get("get").getResponse(FailedDependency.CODE).getDescription());
+		assertEquals(Forbidden.MESSAGE, paths.get("/forbidden").get("get").getResponse(Forbidden.CODE).getDescription());
+		assertEquals(Gone.MESSAGE, paths.get("/gone").get("get").getResponse(Gone.CODE).getDescription());
+		assertEquals(HttpVersionNotSupported.MESSAGE, paths.get("/httpVersionNotSupported").get("get").getResponse(HttpVersionNotSupported.CODE).getDescription());
+		assertEquals(InsufficientStorage.MESSAGE, paths.get("/insufficientStorage").get("get").getResponse(InsufficientStorage.CODE).getDescription());
+		assertEquals(InternalServerError.MESSAGE, paths.get("/internalServerError").get("get").getResponse(InternalServerError.CODE).getDescription());
+		assertEquals(LengthRequired.MESSAGE, paths.get("/lengthRequired").get("get").getResponse(LengthRequired.CODE).getDescription());
+		assertEquals(Locked.MESSAGE, paths.get("/locked").get("get").getResponse(Locked.CODE).getDescription());
+		assertEquals(LoopDetected.MESSAGE, paths.get("/loopDetected").get("get").getResponse(LoopDetected.CODE).getDescription());
+		assertEquals(MethodNotAllowed.MESSAGE, paths.get("/methodNotAllowed").get("get").getResponse(MethodNotAllowed.CODE).getDescription());
+		assertEquals(MisdirectedRequest.MESSAGE, paths.get("/misdirectedRequest").get("get").getResponse(MisdirectedRequest.CODE).getDescription());
+		assertEquals(NetworkAuthenticationRequired.MESSAGE, paths.get("/networkAuthenticationRequired").get("get").getResponse(NetworkAuthenticationRequired.CODE).getDescription());
+		assertEquals(NotAcceptable.MESSAGE, paths.get("/notAcceptable").get("get").getResponse(NotAcceptable.CODE).getDescription());
+		assertEquals(NotExtended.MESSAGE, paths.get("/notExtended").get("get").getResponse(NotExtended.CODE).getDescription());
+		assertEquals(NotFound.MESSAGE, paths.get("/notFound").get("get").getResponse(NotFound.CODE).getDescription());
+		assertEquals(NotImplemented.MESSAGE, paths.get("/notImplemented").get("get").getResponse(NotImplemented.CODE).getDescription());
+		assertEquals(PayloadTooLarge.MESSAGE, paths.get("/payloadTooLarge").get("get").getResponse(PayloadTooLarge.CODE).getDescription());
+		assertEquals(PreconditionFailed.MESSAGE, paths.get("/preconditionFailed").get("get").getResponse(PreconditionFailed.CODE).getDescription());
+		assertEquals(PreconditionRequired.MESSAGE, paths.get("/preconditionRequired").get("get").getResponse(PreconditionRequired.CODE).getDescription());
+		assertEquals(RangeNotSatisfiable.MESSAGE, paths.get("/rangeNotSatisfiable").get("get").getResponse(RangeNotSatisfiable.CODE).getDescription());
+		assertEquals(RequestHeaderFieldsTooLarge.MESSAGE, paths.get("/requestHeaderFieldsTooLarge").get("get").getResponse(RequestHeaderFieldsTooLarge.CODE).getDescription());
+		assertEquals(ServiceUnavailable.MESSAGE, paths.get("/serviceUnavailable").get("get").getResponse(ServiceUnavailable.CODE).getDescription());
+		assertEquals(TooManyRequests.MESSAGE, paths.get("/tooManyRequests").get("get").getResponse(TooManyRequests.CODE).getDescription());
+		assertEquals(Unauthorized.MESSAGE, paths.get("/unauthorized").get("get").getResponse(Unauthorized.CODE).getDescription());
+		assertEquals(UnavailableForLegalReasons.MESSAGE, paths.get("/unavailableForLegalReasons").get("get").getResponse(UnavailableForLegalReasons.CODE).getDescription());
+		assertEquals(UnprocessableEntity.MESSAGE, paths.get("/unprocessableEntity").get("get").getResponse(UnprocessableEntity.CODE).getDescription());
+		assertEquals(UnsupportedMediaType.MESSAGE, paths.get("/unsupportedMediaType").get("get").getResponse(UnsupportedMediaType.CODE).getDescription());
+		assertEquals(UpgradeRequired.MESSAGE, paths.get("/upgradeRequired").get("get").getResponse(UpgradeRequired.CODE).getDescription());
+		assertEquals(UriTooLong.MESSAGE, paths.get("/uriTooLong").get("get").getResponse(UriTooLong.CODE).getDescription());
+		assertEquals(VariantAlsoNegotiates.MESSAGE, paths.get("/variantAlsoNegotiates").get("get").getResponse(VariantAlsoNegotiates.CODE).getDescription());
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -1366,14 +852,13 @@
 	@Rest
 	public static class G {
 		@RestMethod
-		public SeeOtherRoot thrownObjectDoesntMatchReturnType() throws Exception { throw new NotFound(); }
+		public SeeOtherRoot a() throws Exception { throw new NotFound(); }
 	}
 
-	static MockRestClient g = MockRestClient.buildLax(G.class);
-
 	@Test
 	public void g01_thrownObjectDoesntMatchReturnType() throws Exception {
-		g.get("/thrownObjectDoesntMatchReturnType")
+		RestClient g = MockRestClient.buildLax(G.class);
+		g.get("/a")
 			.run()
 			.assertCode().is(404);
 	}
@@ -1385,16 +870,15 @@
 	@Rest
 	public static class H {
 		@RestMethod
-		public void getFoo() throws Exception {
+		public void a() throws Exception {
 			throw new ParseException("Test");
 		}
 	}
 
-	static MockRestClient h = MockRestClient.buildLax(H.class);
-
 	@Test
 	public void h01_parseExceptionCausesBadRequest() throws Exception {
-		h.get("/foo")
+		RestClient h = MockRestClient.buildLax(H.class);
+		h.get("/a")
 			.run()
 			.assertCode().is(400);
 	}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestParamsTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestParamsTest.java
deleted file mode 100644
index 95dea0e..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestParamsTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import static org.apache.juneau.http.HttpMethod.*;
-import static org.apache.juneau.internal.IOUtils.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.io.*;
-import java.util.*;
-
-import javax.servlet.*;
-
-import org.apache.juneau.config.*;
-import org.apache.juneau.cp.Messages;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class RestParamsTest {
-
-	//=================================================================================================================
-	// Various parameters
-	//=================================================================================================================
-
-	@Rest(messages="RestParamsTest")
-	public static class A {
-		@RestMethod
-		public String a01(ResourceBundle t) {
-			return t == null ? null : t.getString("foo");
-		}
-		@RestMethod
-		public String a02(Messages t) {
-			return t == null ? null : t.getString("foo");
-		}
-		@RestMethod(name=POST)
-		public String a03(InputStream t) throws IOException {
-			return read(t);
-		}
-		@RestMethod(name=POST)
-		public String a04(ServletInputStream t) throws IOException {
-			return read(t);
-		}
-		@RestMethod(name=POST)
-		public String a05(Reader t) throws IOException {
-			return read(t);
-		}
-		@RestMethod
-		public void a06(OutputStream t) throws IOException {
-			t.write("OK".getBytes());
-		}
-		@RestMethod
-		public void a07(ServletOutputStream t) throws IOException {
-			t.write("OK".getBytes());
-		}
-		@RestMethod
-		public void a08(Writer t) throws IOException {
-			t.write("OK");
-		}
-		@RestMethod
-		public boolean a09(RequestHeaders t) {
-			return t != null;
-		}
-		@RestMethod
-		public boolean a10(RequestQuery t) {
-			return t != null;
-		}
-		@RestMethod
-		public boolean a11(RequestFormData t) {
-			return t != null;
-		}
-		@RestMethod
-		public String a12(@Method String t) {
-			return t;
-		}
-		@SuppressWarnings("deprecation")
-		@RestMethod
-		public boolean a13(RestLogger t) {
-			return t != null;
-		}
-		@RestMethod
-		public boolean a14(RestContext t) {
-			return t != null;
-		}
-		@RestMethod(parsers={JsonParser.class})
-		public String a15(Parser t) {
-			return t.getClass().getName();
-		}
-		@RestMethod
-		public String a16(Locale t) {
-			return t.toString();
-		}
-		@RestMethod
-		public boolean a17(Swagger t) {
-			return t != null;
-		}
-		@RestMethod
-		public boolean a18(RequestPath t) {
-			return t != null;
-		}
-		@RestMethod
-		public boolean a19(RequestBody t) {
-			return t != null;
-		}
-		@RestMethod
-		public boolean a20(Config t) {
-			return t != null;
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01_ResourceBundle() throws Exception {
-		a.get("/a01").acceptLanguage("en-US").run().assertBody().is("bar");
-		a.get("/a01").acceptLanguage("ja-JP").run().assertBody().is("baz");
-	}
-	@Test
-	public void a02_MessageBundle() throws Exception {
-		a.get("/a02").acceptLanguage("en-US").run().assertBody().is("bar");
-		a.get("/a02").acceptLanguage("ja-JP").run().assertBody().is("baz");
-	}
-	@Test
-	public void a03_InputStream() throws Exception {
-		a.post("/a03", "foo").run().assertBody().is("foo");
-	}
-	@Test
-	public void a04_ServletInputStream() throws Exception {
-		a.post("/a04", "foo").run().assertBody().is("foo");
-	}
-	@Test
-	public void a05_Reader() throws Exception {
-		a.post("/a05", "foo").run().assertBody().is("foo");
-	}
-	@Test
-	public void a06_OutputStream() throws Exception {
-		a.get("/a06").run().assertBody().is("OK");
-	}
-	@Test
-	public void a07_ServletOutputStream() throws Exception {
-		a.get("/a07").run().assertBody().is("OK");
-	}
-	@Test
-	public void a08_Writer() throws Exception {
-		a.get("/a08").run().assertBody().is("OK");
-	}
-	@Test
-	public void a09_RequestHeaders() throws Exception {
-		a.get("/a09").run().assertBody().is("true");
-	}
-	@Test
-	public void a10_RequestQuery() throws Exception {
-		a.get("/a10").run().assertBody().is("true");
-	}
-	@Test
-	public void a11_RequestFormData() throws Exception {
-		a.get("/a11").run().assertBody().is("true");
-	}
-	@Test
-	public void a12_HttpMethod() throws Exception {
-		a.get("/a12").run().assertBody().is("GET");
-	}
-	@Test
-	public void a13_RestLogger() throws Exception {
-		a.get("/a13").run().assertBody().is("true");
-	}
-	@Test
-	public void a14_RestContext() throws Exception {
-		a.get("/a14").run().assertBody().is("true");
-	}
-	@Test
-	public void a15_Parser() throws Exception {
-		a.get("/a15").contentType("application/json").run().assertBody().is("org.apache.juneau.json.JsonParser");
-	}
-	@Test
-	public void a16_Locale() throws Exception {
-		a.get("/a16").acceptLanguage("en-US").run().assertBody().is("en_US");
-		a.get("/a16").acceptLanguage("ja-JP").run().assertBody().is("ja_JP");
-	}
-	@Test
-	public void a17_Swagger() throws Exception {
-		a.get("/a17").run().assertBody().is("true");
-	}
-	@Test
-	public void a18_RequestPathMatch() throws Exception {
-		a.get("/a18").run().assertBody().is("true");
-	}
-	@Test
-	public void a19_RequestBody() throws Exception {
-		a.get("/a19").run().assertBody().is("true");
-	}
-	@Test
-	public void a20_Config() throws Exception {
-		a.get("/a20").run().assertBody().is("true");
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Rest_PredefinedStatusCodes_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Rest_PredefinedStatusCodes_Test.java
new file mode 100644
index 0000000..f60fb87
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Rest_PredefinedStatusCodes_Test.java
@@ -0,0 +1,236 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.io.*;
+
+import org.apache.juneau.http.annotation.Body;
+import org.apache.juneau.http.annotation.Header;
+import org.apache.juneau.http.annotation.Path;
+import org.apache.juneau.http.annotation.Query;
+import org.apache.juneau.json.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Rest_PredefinedStatusCodes_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// OK (200)
+	//------------------------------------------------------------------------------------------------------------------
+	@Rest
+	public static class A {
+		@RestMethod(name=PUT)
+		public Reader a(@Body String b) {
+			return new StringReader(b);
+		}
+	}
+
+	@Test
+	public void a01_OK() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.put("/a", "foo")
+			.run()
+			.assertCode().is(200);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Bad Request (400)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(parsers=JsonParser.class)
+	public static class B {
+		@RestMethod(name=PUT)
+		public String a(@Body B1 in) {
+			return "OK";
+		}
+		public static class B1 {
+			public String f1;
+		}
+		@RestMethod(name=PUT)
+		public String b(@Body B2 in) {
+			return "OK";
+		}
+		public static class B2 {
+			public int f1;
+		}
+		@RestMethod(name=PUT)
+		public String c(@Body B3 in) {
+			return "OK";
+		}
+		public static class B3 {
+			public int f1;
+			private B3(){}
+		}
+		@RestMethod(name=PUT)
+		public String d(@Body B4 in) {
+			return "OK";
+		}
+		public class B4 {
+			public B4(){}
+		}
+		@RestMethod(name=PUT)
+		public String e(@Body B5 in) {
+			return "OK";
+		}
+		static class B5 {
+			public B5(){}
+		}
+		@RestMethod(name=PUT)
+		public String f(@Body B6 in) {
+			return "OK";
+		}
+		public static class B6 {
+			public int f1;
+			private B6(){}
+			public static B6 valueOf(String s) {
+				throw new RuntimeException("Test error");
+			}
+		}
+		@RestMethod(name=PUT, path="/g/{a1}")
+		public String g(@Query("p1") int t1, @Path("a1") int a1, @Header("h1") int h1) {
+			return "OK";
+		}
+	}
+
+	@Test
+	public void b01_badRequest() throws Exception {
+		RestClient b = MockRestClient.buildLax(B.class);
+		b.put("/a?noTrace=true", "{f2:'foo'}", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"Unknown property 'f2' encountered while trying to parse into class"
+			);
+		b.put("/a?noTrace=true", "{f1:'foo', f2:'foo'}", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"Unknown property 'f2' encountered while trying to parse into class"
+			);
+		b.put("/b?noTrace=true", "{f1:'foo'}", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"Invalid number"
+			);
+		b.put("/c?noTrace=true", "{f1:1}", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"could not be instantiated"
+			);
+		b.put("/d?noTrace=true", "{f1:1}", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"could not be instantiated"
+			);
+		b.put("/e?noTrace=true", "{f1:1}", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"Class is not public"
+			);
+		b.put("/f?noTrace=true", "'foo'", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"Test error"
+			);
+		b.put("/g/123?noTrace=true&p1=foo", "'foo'", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"Could not parse query parameter 'p1'."
+			);
+		b.put("/g/foo?noTrace=true&p1=1", "'foo'", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"Could not parse path parameter 'a1'."
+			);
+		b.put("/g/123?noTrace=true&p1=1", "'foo'", "application/json")
+			.header("h1", "foo")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains(
+				"Could not parse header 'h1'."
+			);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Not Found (404) and Method Not Allowed (405)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class C {
+		@RestMethod(name=GET, path="/")
+		public String a() {
+			return "OK";
+		}
+	}
+	private static MockRestClient c = MockRestClient.buildLax(C.class);
+
+	@Test
+	public void c01_badPath() throws Exception {
+		c.get("/bad?noTrace=true")
+			.run()
+			.assertCode().is(404)
+			.assertBody().contains(
+				"Method 'GET' not found on resource with matching pattern on path '/bad'"
+			);
+	}
+	public void c02_badMethod() throws Exception {
+		c.put("?noTrace=true", null)
+			.run()
+			.assertCode().is(405)
+			.assertBody().contains(
+				"Method 'PUT' not found on resource."
+			);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Precondition Failed (412)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class D {
+		@RestMethod(name=GET, matchers=NeverMatcher.class)
+		public String d() {
+			return "OK";
+		}
+		public static class NeverMatcher extends RestMatcher {
+			@Override /* RestMatcher */
+			public boolean matches(RestRequest req) {
+				return false;
+			}
+		}
+	}
+	private static MockRestClient d = MockRestClient.buildLax(D.class);
+
+	@Test
+	public void d01() throws Exception {
+		d.get("/d?noTrace=true")
+			.run()
+			.assertCode().is(412)
+			.assertBody().contains(
+				"Method 'GET' not found on resource on path '/d' with matching matcher."
+			);
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/StaticFilesMappingTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/StaticFilesMapping_Test.java
similarity index 99%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/StaticFilesMappingTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/StaticFilesMapping_Test.java
index 01727e1..2d220e8 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/StaticFilesMappingTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/StaticFilesMapping_Test.java
@@ -21,7 +21,7 @@
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class StaticFilesMappingTest {
+public class StaticFilesMapping_Test {
 
 	private static Collection<StaticFileMapping> parse(String input) throws ParseException {
 		return StaticFileMapping.parse(null, input);
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/StatusCodesTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/StatusCodesTest.java
deleted file mode 100644
index c8caa5e..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/StatusCodesTest.java
+++ /dev/null
@@ -1,262 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest;
-
-import static org.apache.juneau.http.HttpMethod.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.io.*;
-
-import org.apache.juneau.http.annotation.Body;
-import org.apache.juneau.http.annotation.Header;
-import org.apache.juneau.http.annotation.Path;
-import org.apache.juneau.http.annotation.Query;
-import org.apache.juneau.json.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class StatusCodesTest {
-
-	//=================================================================================================================
-	// OK (200)
-	//=================================================================================================================
-	@Rest
-	public static class A {
-		@RestMethod(name=PUT)
-		public Reader a01(@Body String b) {
-			return new StringReader(b);
-		}
-	}
-	private static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01a_OK() throws Exception {
-		a.put("/a01", "foo")
-			.run()
-			.assertCode().is(200);
-	}
-
-	//=================================================================================================================
-	// Bad Request (400)
-	//=================================================================================================================
-
-	@Rest(parsers=JsonParser.class)
-	public static class B {
-		@RestMethod(name=PUT, path="/nonExistentBeanProperties")
-		public String b01(@Body B01 in) {
-			return "OK";
-		}
-		public static class B01 {
-			public String f1;
-		}
-		@RestMethod(name=PUT, path="/wrongDataType")
-		public String b02(@Body B02 in) {
-			return "OK";
-		}
-		public static class B02 {
-			public int f1;
-		}
-		@RestMethod(name=PUT, path="/parseIntoNonConstructableBean")
-		public String b03(@Body B03 in) {
-			return "OK";
-		}
-		public static class B03 {
-			public int f1;
-			private B03(){}
-		}
-		@RestMethod(name=PUT, path="/parseIntoNonStaticInnerClass")
-		public String b04(@Body B04 in) {
-			return "OK";
-		}
-		public class B04 {
-			public B04(){}
-		}
-		@RestMethod(name=PUT, path="/parseIntoNonPublicInnerClass")
-		public String b05(@Body B05 in) {
-			return "OK";
-		}
-		static class B05 {
-			public B05(){}
-		}
-		@RestMethod(name=PUT, path="/thrownConstructorException")
-		public String b06(@Body B06 in) {
-			return "OK";
-		}
-		public static class B06 {
-			public int f1;
-			private B06(){}
-			public static B06 valueOf(String s) {
-				throw new RuntimeException("Test error");
-			}
-		}
-		@RestMethod(name=PUT, path="/setParameterToInvalidTypes/{a1}")
-		public String b07(@Query("p1") int t1, @Path("a1") int a1, @Header("h1") int h1) {
-			return "OK";
-		}
-	}
-	private static MockRestClient b = MockRestClient.buildLax(B.class);
-
-	@Test
-	public void b01a_nonExistentBeanProperties() throws Exception {
-		b.put("/nonExistentBeanProperties?noTrace=true", "{f2:'foo'}", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"Unknown property 'f2' encountered while trying to parse into class 'org.apache.juneau.rest.StatusCodesTest$B$B01'"
-			);
-	}
-	@Test
-	public void b01b_nonExistentBeanProperties() throws Exception {
-		b.put("/nonExistentBeanProperties?noTrace=true", "{f1:'foo', f2:'foo'}", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"Unknown property 'f2' encountered while trying to parse into class 'org.apache.juneau.rest.StatusCodesTest$B$B01'"
-			);
-	}
-	@Test
-	public void b02_wrongDataType() throws Exception {
-		b.put("/wrongDataType?noTrace=true", "{f1:'foo'}", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"Invalid number"
-			);
-	}
-	@Test
-	public void b03_parseIntoNonConstructableBean() throws Exception {
-		b.put("/parseIntoNonConstructableBean?noTrace=true", "{f1:1}", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"could not be instantiated"
-			);
-	}
-	@Test
-	public void b04_parseIntoNonStaticInnerClass() throws Exception {
-		b.put("/parseIntoNonStaticInnerClass?noTrace=true", "{f1:1}", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"could not be instantiated"
-			);
-	}
-	@Test
-	public void b05_parseIntoNonStaticInnerClass() throws Exception {
-		b.put("/parseIntoNonPublicInnerClass?noTrace=true", "{f1:1}", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"Class is not public"
-			);
-	}
-	@Test
-	public void b06_thrownConstructorException() throws Exception {
-		b.put("/thrownConstructorException?noTrace=true", "'foo'", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"Test error"
-			);
-	}
-	@Test
-	public void b07a_setParameterToInvalidTypes_Query() throws Exception {
-		b.put("/setParameterToInvalidTypes/123?noTrace=true&p1=foo", "'foo'", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"Could not parse query parameter 'p1'."
-			);
-	}
-	@Test
-	public void b07a_setParameterToInvalidTypes_Path() throws Exception {
-		b.put("/setParameterToInvalidTypes/foo?noTrace=true&p1=1", "'foo'", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"Could not parse path parameter 'a1'."
-			);
-	}
-	@Test
-	public void b07a_setParameterToInvalidTypes_Header() throws Exception {
-		b.put("/setParameterToInvalidTypes/123?noTrace=true&p1=1", "'foo'", "application/json")
-			.header("h1", "foo")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains(
-				"Could not parse header 'h1'."
-			);
-	}
-
-	//=================================================================================================================
-	// Not Found (404) and Method Not Allowed (405)
-	//=================================================================================================================
-
-	@Rest
-	public static class C {
-		@RestMethod(name=GET, path="/")
-		public String c01() {
-			return "OK";
-		}
-	}
-	private static MockRestClient c = MockRestClient.buildLax(C.class);
-
-	@Test
-	public void c01_badPath() throws Exception {
-		c.get("/bad?noTrace=true")
-			.run()
-			.assertCode().is(404)
-			.assertBody().contains(
-				"Method 'GET' not found on resource with matching pattern on path '/bad'"
-			);
-	}
-	public void c02_badMethod() throws Exception {
-		c.put("?noTrace=true", null)
-			.run()
-			.assertCode().is(405)
-			.assertBody().contains(
-				"Method 'PUT' not found on resource."
-			);
-	}
-
-	//=================================================================================================================
-	// Precondition Failed (412)
-	//=================================================================================================================
-
-	@Rest
-	public static class D {
-		@RestMethod(name=GET, matchers=NeverMatcher.class)
-		public String d() {
-			return "OK";
-		}
-		public static class NeverMatcher extends RestMatcher {
-			@Override /* RestMatcher */
-			public boolean matches(RestRequest req) {
-				return false;
-			}
-		}
-	}
-	private static MockRestClient d = MockRestClient.buildLax(D.class);
-
-	@Test
-	public void d01() throws Exception {
-		d.get("/d?noTrace=true")
-			.run()
-			.assertCode().is(412)
-			.assertBody().contains(
-				"Method 'GET' not found on resource on path '/d' with matching matcher."
-			);
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Swagger_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Swagger_Test.java
new file mode 100644
index 0000000..0abbce1
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/Swagger_Test.java
@@ -0,0 +1,2350 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest;
+
+import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.runners.MethodSorters.*;
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.http.HttpMethod.*;
+import java.io.*;
+import java.util.*;
+
+import org.apache.juneau.json.*;
+import org.apache.juneau.jsonschema.annotation.ExternalDocs;
+import org.apache.juneau.jsonschema.annotation.Schema;
+import org.apache.juneau.xml.*;
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.http.annotation.Body;
+import org.apache.juneau.http.annotation.Contact;
+import org.apache.juneau.http.annotation.License;
+import org.apache.juneau.http.annotation.Query;
+import org.apache.juneau.http.annotation.Response;
+import org.apache.juneau.http.annotation.Tag;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Swagger_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Setup
+	//------------------------------------------------------------------------------------------------------------------
+
+	private Swagger getSwaggerWithFile(Object resource) throws Exception {
+		RestContext rc = RestContext.create(resource).classpathResourceFinder(TestClasspathResourceFinder.class).build();
+		RestRequest req = rc.createRequest(new RestCall(rc, new MockServletRequest(), null));
+		RestInfoProvider ip = rc.getInfoProvider();
+		return ip.getSwagger(req);
+	}
+
+	private static Swagger getSwagger(Object resource) throws Exception {
+		RestContext rc = RestContext.create(resource).build();
+		RestRequest req = rc.createRequest(new RestCall(rc, new MockServletRequest(), null));
+		RestInfoProvider ip = rc.getInfoProvider();
+		return ip.getSwagger(req);
+	}
+
+	public static class TestClasspathResourceFinder extends BasicResourceFinder {
+		@Override
+		public InputStream findResource(Class<?> baseClass, String name, Locale locale) throws IOException {
+			if (name.endsWith(".json"))
+				return BasicRestInfoProvider.class.getResourceAsStream("BasicRestInfoProviderTest_swagger.json");
+			return super.findResource(baseClass, name, locale);
+		}
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /<root>
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A1 {}
+
+	@Test
+	public void a01_swagger_default() throws Exception {
+		Swagger x = getSwagger(new A1());
+		assertEquals("2.0", x.getSwagger());
+		assertEquals(null, x.getHost());
+		assertEquals(null, x.getBasePath());
+		assertEquals(null, x.getSchemes());
+	}
+	@Test
+	public void a01_swagger_default_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new A1());
+		assertEquals("0.0", x.getSwagger());
+		assertEquals("s-host", x.getHost());
+		assertEquals("s-basePath", x.getBasePath());
+		assertObject(x.getSchemes()).json().is("['s-scheme']");
+	}
+
+
+	@Rest(swagger=@ResourceSwagger("{swagger:'3.0',host:'a-host',basePath:'a-basePath',schemes:['a-scheme']}"))
+	public static class A2 {}
+
+	@Test
+	public void a02_swagger_ResourceSwagger_value() throws Exception {
+		Swagger x = getSwagger(new A2());
+		assertEquals("3.0", x.getSwagger());
+		assertEquals("a-host", x.getHost());
+		assertEquals("a-basePath", x.getBasePath());
+		assertObject(x.getSchemes()).json().is("['a-scheme']");
+	}
+	@Test
+	public void a02_swagger_ResourceSwagger_value_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new A2());
+		assertEquals("3.0", x.getSwagger());
+		assertEquals("a-host", x.getHost());
+		assertEquals("a-basePath", x.getBasePath());
+		assertObject(x.getSchemes()).json().is("['a-scheme']");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /info
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(
+		title="a-title",
+		description="a-description"
+	)
+	public static class B1 {}
+
+	@Test
+	public void b01a_info_Rest() throws Exception {
+		Info x = getSwagger(new B1()).getInfo();
+		assertEquals("a-title", x.getTitle());
+		assertEquals("a-description", x.getDescription());
+		assertEquals(null, x.getVersion());
+		assertEquals(null, x.getTermsOfService());
+		assertEquals(null, x.getContact());
+		assertEquals(null, x.getLicense());
+	}
+	@Test
+	public void b01b_info_Rest_withFile() throws Exception {
+		Info x = getSwaggerWithFile(new B1()).getInfo();
+		assertEquals("s-title", x.getTitle());
+		assertEquals("s-description", x.getDescription());
+		assertEquals("0.0.0", x.getVersion());
+		assertEquals("s-termsOfService", x.getTermsOfService());
+		assertObject(x.getContact()).json().is("{name:'s-name',url:'s-url',email:'s-email'}");
+		assertObject(x.getLicense()).json().is("{name:'s-name',url:'s-url'}");
+	}
+
+	@Rest(
+		messages="BasicRestInfoProviderTest",
+		title="$L{foo}",
+		description="$L{foo}"
+	)
+	public static class B2 {}
+
+	@Test
+	public void b02a_info_Rest_localized() throws Exception {
+		Info x = getSwagger(new B2()).getInfo();
+		assertEquals("l-foo", x.getTitle());
+		assertEquals("l-foo", x.getDescription());
+	}
+	@Test
+	public void b02b_info_Rest_localized_withFile() throws Exception {
+		Info x = getSwaggerWithFile(new B2()).getInfo();
+		assertEquals("s-title", x.getTitle());
+		assertEquals("s-description", x.getDescription());
+	}
+
+	@Rest(
+		title="a-title",
+		description="a-description",
+		swagger=@ResourceSwagger(
+			{
+				"info:{",
+					"title:'b-title',",
+					"description:'b-description',",
+					"version:'2.0.0',",
+					"termsOfService:'a-termsOfService',",
+					"contact:{name:'a-name',url:'a-url',email:'a-email'},",
+					"license:{name:'a-name',url:'a-url'}",
+				"}"
+			}
+		)
+	)
+	public static class B3 {}
+
+	@Test
+	public void b03a_info_ResourceSwagger_value() throws Exception {
+		Info x = getSwagger(new B3()).getInfo();
+		assertEquals("b-title", x.getTitle());
+		assertEquals("b-description", x.getDescription());
+		assertEquals("2.0.0", x.getVersion());
+		assertEquals("a-termsOfService", x.getTermsOfService());
+		assertObject(x.getContact()).json().is("{name:'a-name',url:'a-url',email:'a-email'}");
+		assertObject(x.getLicense()).json().is("{name:'a-name',url:'a-url'}");
+	}
+	@Test
+	public void b03b_info_ResourceSwagger_value_withFile() throws Exception {
+		Info x = getSwaggerWithFile(new B3()).getInfo();
+		assertEquals("b-title", x.getTitle());
+		assertEquals("b-description", x.getDescription());
+		assertEquals("2.0.0", x.getVersion());
+		assertEquals("a-termsOfService", x.getTermsOfService());
+		assertObject(x.getContact()).json().is("{name:'a-name',url:'a-url',email:'a-email'}");
+		assertObject(x.getLicense()).json().is("{name:'a-name',url:'a-url'}");
+	}
+
+	@Rest(
+		messages="BasicRestInfoProviderTest",
+		title="a-title",
+		description="a-description",
+		swagger=@ResourceSwagger("{info:{title:'$L{bar}',description:'$L{bar}'}}")
+	)
+	public static class B4 {}
+
+	@Test
+	public void b04_info_ResourceSwagger_value_localised() throws Exception {
+		assertEquals("l-bar", getSwagger(new B4()).getInfo().getTitle());
+		assertEquals("l-bar", getSwaggerWithFile(new B4()).getInfo().getTitle());
+		assertEquals("l-bar", getSwagger(new B4()).getInfo().getDescription());
+		assertEquals("l-bar", getSwaggerWithFile(new B4()).getInfo().getDescription());
+	}
+
+	@Rest(
+		title="a-title",
+		description="a-description",
+		swagger=@ResourceSwagger(
+			value= {
+				"info:{",
+					"title:'b-title',",
+					"description:'b-description',",
+					"version:'2.0.0',",
+					"termsOfService:'a-termsOfService',",
+					"contact:{name:'a-name',url:'a-url',email:'a-email'},",
+					"license:{name:'a-name',url:'a-url'}",
+				"}"
+			},
+			title="c-title",
+			description="c-description",
+			version="3.0.0",
+			termsOfService="b-termsOfService",
+			contact=@Contact(name="b-name",url="b-url",email="b-email"),
+			license=@License(name="b-name",url="b-url")
+		)
+	)
+	public static class B5 {}
+
+	@Test
+	public void b05a_info_ResourceSwagger_title() throws Exception {
+		Info x = getSwagger(new B5()).getInfo();
+		assertEquals("c-title", x.getTitle());
+		assertEquals("c-description", x.getDescription());
+		assertEquals("3.0.0", x.getVersion());
+		assertEquals("b-termsOfService", x.getTermsOfService());
+		assertObject(x.getContact()).json().is("{name:'b-name',url:'b-url',email:'b-email'}");
+		assertObject(x.getLicense()).json().is("{name:'b-name',url:'b-url'}");
+	}
+	@Test
+	public void b05b_info_ResourceSwagger_title_withFile() throws Exception {
+		Info x = getSwaggerWithFile(new B5()).getInfo();
+		assertEquals("c-title", x.getTitle());
+		assertEquals("c-description", x.getDescription());
+		assertEquals("3.0.0", x.getVersion());
+		assertEquals("b-termsOfService", x.getTermsOfService());
+		assertObject(x.getContact()).json().is("{name:'b-name',url:'b-url',email:'b-email'}");
+		assertObject(x.getLicense()).json().is("{name:'b-name',url:'b-url'}");
+	}
+
+	@Rest(
+		title="a-title",
+		description="a-description",
+		swagger=@ResourceSwagger(
+			value= {
+				"info:{",
+					"title:'b-title',",
+					"description:'b-description',",
+					"version:'2.0.0',",
+					"termsOfService:'a-termsOfService',",
+					"contact:{name:'a-name',url:'a-url',email:'a-email'},",
+					"license:{name:'a-name',url:'a-url'}",
+				"}"
+			},
+			title="$L{baz}",
+			description="$L{baz}",
+			version="$L{foo}",
+			termsOfService="$L{foo}",
+			contact=@Contact("{name:'$L{foo}',url:'$L{bar}',email:'$L{baz}'}"),
+			license=@License("{name:'$L{foo}',url:'$L{bar}'}")
+		),
+		messages="BasicRestInfoProviderTest"
+	)
+	public static class B6 {}
+
+	@Test
+	public void b06a_info_ResourceSwagger_title_localized() throws Exception {
+		Info x = getSwagger(new B6()).getInfo();
+		assertEquals("l-baz", x.getTitle());
+		assertEquals("l-baz", x.getDescription());
+		assertEquals("l-foo", x.getVersion());
+		assertEquals("l-foo", x.getTermsOfService());
+		assertObject(x.getContact()).json().is("{name:'l-foo',url:'l-bar',email:'l-baz'}");
+		assertObject(x.getLicense()).json().is("{name:'l-foo',url:'l-bar'}");
+	}
+	@Test
+	public void b06b_info_ResourceSwagger_title_localized_withFile() throws Exception {
+		Info x = getSwaggerWithFile(new B6()).getInfo();
+		assertEquals("l-baz", x.getTitle());
+		assertEquals("l-baz", x.getDescription());
+		assertEquals("l-foo", x.getVersion());
+		assertEquals("l-foo", x.getTermsOfService());
+		assertObject(x.getContact()).json().is("{name:'l-foo',url:'l-bar',email:'l-baz'}");
+		assertObject(x.getLicense()).json().is("{name:'l-foo',url:'l-bar'}");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			title="c-title",
+			description="c-description"
+		)
+	)
+	public static class B07 {}
+
+	@Test
+	public void b07a_title_ResourceSwagger_title_only() throws Exception {
+		Info x = getSwagger(new B07()).getInfo();
+		assertEquals("c-title", x.getTitle());
+		assertEquals("c-description", x.getDescription());
+	}
+	@Test
+	public void b07b_title_ResourceSwagger_title_only_withFile() throws Exception {
+		Info x = getSwaggerWithFile(new B07()).getInfo();
+		assertEquals("c-title", x.getTitle());
+		assertEquals("c-description", x.getDescription());
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /tags
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class C1 {}
+
+	@Test
+	public void c01a_tags_default() throws Exception {
+		Swagger x = getSwagger(new C1());
+		assertEquals(null, x.getTags());
+	}
+	@Test
+	public void c01b_tags_default_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C1());
+		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}}]");
+	}
+
+	// Tags in @ResourceSwagger(value) should override file.
+	@Rest(
+		swagger=@ResourceSwagger(
+			"{tags:[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]}"
+		)
+	)
+	public static class C2 {}
+
+	@Test
+	public void c02a_tags_ResourceSwagger_value() throws Exception {
+		Swagger x = getSwagger(new C2());
+		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]");
+	}
+	@Test
+	public void c02b_tags_ResourceSwagger_value_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C2());
+		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]");
+	}
+
+	// Tags in both @ResourceSwagger(value) and @ResourceSwagger(tags) should accumulate.
+	@Rest(
+		swagger=@ResourceSwagger(
+			value="{tags:[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]}",
+			tags=@Tag(name="b-name",description="b-description",externalDocs=@ExternalDocs(description="b-description",url="b-url"))
+		)
+	)
+	public static class C3 {}
+
+	@Test
+	public void c03a_tags_ResourceSwagger_tags() throws Exception {
+		Swagger x = getSwagger(new C3());
+		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
+	}
+	@Test
+	public void c03b_tags_ResourceSwagger_tags_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C3());
+		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
+	}
+
+	// Same as above but without [] outer characters.
+	@Rest(
+		swagger=@ResourceSwagger(
+			value="{tags:[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}}]}",
+			tags=@Tag(name="b-name",value=" { description:'b-description', externalDocs: { description:'b-description', url:'b-url' } } ")
+		)
+	)
+	public static class C4 {}
+
+	@Test
+	public void c04a_tags_ResourceSwagger_tags() throws Exception {
+		Swagger x = getSwagger(new C4());
+		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
+	}
+	@Test
+	public void c04b_tags_ResourceSwagger_tags_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C4());
+		assertObject(x.getTags()).json().is("[{name:'a-name',description:'a-description',externalDocs:{description:'a-description',url:'a-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
+	}
+
+	// Tags in both Swagger.json and @ResourceSwagger(tags) should accumulate.
+	@Rest(
+		swagger=@ResourceSwagger(
+			tags=@Tag(name="b-name",description="b-description",externalDocs=@ExternalDocs(description="b-description",url="b-url"))
+		)
+	)
+	public static class C5 {}
+
+	@Test
+	public void c05a_tags_ResourceSwagger_tags_only() throws Exception {
+		Swagger x = getSwagger(new C5());
+		assertObject(x.getTags()).json().is("[{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
+	}
+	@Test
+	public void c05b_tags_ResourceSwagger_tags_only_witFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C5());
+		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'b-name',description:'b-description',externalDocs:{description:'b-description',url:'b-url'}}]");
+	}
+
+	// Dup tag names should be overwritten
+	@Rest(
+		swagger=@ResourceSwagger(
+			tags={
+				@Tag(name="s-name",description="b-description",externalDocs=@ExternalDocs(description="b-description",url="b-url")),
+				@Tag(name="s-name",value="{description:'c-description',externalDocs:{description:'c-description',url:'c-url'}}")
+			}
+		)
+	)
+	public static class C6 {}
+
+	@Test
+	public void c06a_tags_ResourceSwagger_tags_dups() throws Exception {
+		Swagger x = getSwagger(new C6());
+		assertObject(x.getTags()).json().is("[{name:'s-name',description:'c-description',externalDocs:{description:'c-description',url:'c-url'}}]");
+	}
+	@Test
+	public void c06b_tags_ResourceSwagger_tags_dups_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C6());
+		assertObject(x.getTags()).json().is("[{name:'s-name',description:'c-description',externalDocs:{description:'c-description',url:'c-url'}}]");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			value="{tags:[{name:'$L{foo}',description:'$L{foo}',externalDocs:{description:'$L{foo}',url:'$L{foo}'}}]}",
+			tags=@Tag(name="$L{foo}",description="$L{foo}",externalDocs=@ExternalDocs(description="$L{foo}",url="$L{foo}"))
+		),
+		messages="BasicRestInfoProviderTest"
+	)
+	public static class C7 {}
+
+	@Test
+	public void c07a_tags_ResourceSwagger_tags_localised() throws Exception {
+		Swagger x = getSwagger(new C7());
+		assertObject(x.getTags()).json().is("[{name:'l-foo',description:'l-foo',externalDocs:{description:'l-foo',url:'l-foo'}}]");
+	}
+	@Test
+	public void c07b_tags_ResourceSwagger_tags_localised_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C7());
+		assertObject(x.getTags()).json().is("[{name:'l-foo',description:'l-foo',externalDocs:{description:'l-foo',url:'l-foo'}}]");
+	}
+
+	// Auto-detect tags defined on methods.
+	@Rest
+	public static class C8 {
+		@RestMethod(swagger=@MethodSwagger(tags="foo"))
+		public void a() {}
+	}
+
+	@Test
+	public void c08a_tags_ResourceSwagger_tags_loose() throws Exception {
+		Swagger x = getSwagger(new C8());
+		assertObject(x.getTags()).json().is("[{name:'foo'}]");
+	}
+	@Test
+	public void c08b_tags_ResourceSwagger_tags_loose_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C8());
+		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'foo'}]");
+	}
+
+	// Comma-delimited list
+	@Rest
+	public static class C9 {
+		@RestMethod(swagger=@MethodSwagger(tags=" foo, bar "))
+		public void a() {}
+	}
+
+	@Test
+	public void c09a_tags_ResourceSwagger_tags_loose_cdl() throws Exception {
+		Swagger x = getSwagger(new C9());
+		assertObject(x.getTags()).json().is("[{name:'foo'},{name:'bar'}]");
+	}
+	@Test
+	public void c09b_tags_ResourceSwagger_tags_loose_cdl_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C9());
+		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'foo'},{name:'bar'}]");
+	}
+
+	// OList
+	@Rest
+	public static class C10 {
+		@RestMethod(swagger=@MethodSwagger(tags="['foo', 'bar']"))
+		public void a() {}
+	}
+
+	@Test
+	public void c10a_tags_ResourceSwagger_tags_loose_olist() throws Exception {
+		Swagger x = getSwagger(new C10());
+		assertObject(x.getTags()).json().is("[{name:'foo'},{name:'bar'}]");
+	}
+	@Test
+	public void c10b_tags_ResourceSwagger_tags_loose_olist_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C10());
+		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'foo'},{name:'bar'}]");
+	}
+
+	// OList localized
+	@Rest(messages="BasicRestInfoProviderTest")
+	public static class C11 {
+		@RestMethod(swagger=@MethodSwagger(tags="['$L{foo}', '$L{bar}']"))
+		public void a() {}
+	}
+
+	@Test
+	public void c11a_tags_ResourceSwagger_tags_loose_olist_localized() throws Exception {
+		Swagger x = getSwagger(new C11());
+		assertObject(x.getTags()).json().is("[{name:'l-foo'},{name:'l-bar'}]");
+	}
+	@Test
+	public void c11b_tags_ResourceSwagger_tags_loose_olist_localized_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C11());
+		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'l-foo'},{name:'l-bar'}]");
+	}
+
+	// Comma-delimited list localized
+	@Rest(messages="BasicRestInfoProviderTest")
+	public static class C12 {
+		@RestMethod(swagger=@MethodSwagger(tags=" $L{foo}, $L{bar} "))
+		public void a() {}
+	}
+
+	@Test
+	public void c12a_tags_ResourceSwagger_tags_loose_cdl_localized() throws Exception {
+		Swagger x = getSwagger(new C12());
+		assertObject(x.getTags()).json().is("[{name:'l-foo'},{name:'l-bar'}]");
+	}
+	@Test
+	public void c12b_tags_ResourceSwagger_tags_loose_cdl_localized_withFile() throws Exception {
+		Swagger x = getSwaggerWithFile(new C12());
+		assertObject(x.getTags()).json().is("[{name:'s-name',description:'s-description',externalDocs:{description:'s-description',url:'s-url'}},{name:'l-foo'},{name:'l-bar'}]");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /externalDocs
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class D1 {}
+
+	@Test
+	public void d01a_externalDocs_default() throws Exception {
+		ExternalDocumentation x = getSwagger(new D1()).getExternalDocs();
+		assertEquals(null, x);
+	}
+	@Test
+	public void d01b_externalDocs_default_withFile() throws Exception {
+		ExternalDocumentation x = getSwaggerWithFile(new D1()).getExternalDocs();
+		assertObject(x).json().is("{description:'s-description',url:'s-url'}");
+	}
+
+
+	@Rest(
+		swagger=@ResourceSwagger("{externalDocs:{description:'a-description',url:'a-url'}}")
+	)
+	public static class D2 {}
+
+	@Test
+	public void d02a_externalDocs_ResourceSwagger_value() throws Exception {
+		ExternalDocumentation x = getSwagger(new D2()).getExternalDocs();
+		assertObject(x).json().is("{description:'a-description',url:'a-url'}");
+	}
+	@Test
+	public void d02b_externalDocs_ResourceSwagger_value_withFile() throws Exception {
+		ExternalDocumentation x = getSwaggerWithFile(new D2()).getExternalDocs();
+		assertObject(x).json().is("{description:'a-description',url:'a-url'}");
+	}
+
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			value="{externalDocs:{description:'a-description',url:'a-url'}}",
+			externalDocs=@ExternalDocs(description="b-description",url="b-url")
+		)
+	)
+	public static class D3 {}
+
+	@Test
+	public void d03a_externalDocs_ResourceSwagger_externalDocs() throws Exception {
+		ExternalDocumentation x = getSwagger(new D3()).getExternalDocs();
+		assertObject(x).json().is("{description:'b-description',url:'b-url'}");
+	}
+	@Test
+	public void d03b_externalDocs_ResourceSwagger_externalDocs_withFile() throws Exception {
+		ExternalDocumentation x = getSwaggerWithFile(new D3()).getExternalDocs();
+		assertObject(x).json().is("{description:'b-description',url:'b-url'}");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			value="{info:{externalDocs:{description:'a-description',url:'a-url'}}}",
+			externalDocs=@ExternalDocs(" description:'b-description', url:'b-url' ")
+			)
+	)
+	public static class D4 {}
+
+	@Test
+	public void d04a_externalDocs_ResourceSwagger_externalDocs() throws Exception {
+		ExternalDocumentation x = getSwagger(new D4()).getExternalDocs();
+		assertObject(x).json().is("{description:'b-description',url:'b-url'}");
+	}
+	@Test
+	public void d04b_externalDocs_ResourceSwagger_externalDocs_withFile() throws Exception {
+		ExternalDocumentation x = getSwaggerWithFile(new D4()).getExternalDocs();
+		assertObject(x).json().is("{description:'b-description',url:'b-url'}");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			value="{externalDocs:{description:'a-description',url:'a-url'}}",
+			externalDocs=@ExternalDocs("{description:'$L{foo}',url:'$L{bar}'}")
+		),
+		messages="BasicRestInfoProviderTest"
+	)
+	public static class D5 {}
+
+	@Test
+	public void d05a_externalDocs_ResourceSwagger_externalDocs_localised() throws Exception {
+		ExternalDocumentation x = getSwagger(new D5()).getExternalDocs();
+		assertObject(x).json().is("{description:'l-foo',url:'l-bar'}");
+	}
+	@Test
+	public void d05b_externalDocs_ResourceSwagger_externalDocs_localised_withFile() throws Exception {
+		ExternalDocumentation x = getSwaggerWithFile(new D5()).getExternalDocs();
+		assertObject(x).json().is("{description:'l-foo',url:'l-bar'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class E1 {
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void e01a_operation_summary_default() throws Exception {
+		Operation x = getSwagger(new E1()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("a", x.getOperationId());
+		assertEquals(null, x.getSummary());
+		assertEquals(null, x.getDescription());
+		assertEquals(null, x.getDeprecated());
+		assertEquals(null, x.getSchemes());
+	}
+	@Test
+	public void e01b_operation_summary_default_withFile() throws Exception {
+		Operation x = getSwaggerWithFile(new E1()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("s-operationId", x.getOperationId());
+		assertEquals("s-summary", x.getSummary());
+		assertEquals("s-description", x.getDescription());
+		assertObject(x.getDeprecated()).json().is("true");
+		assertObject(x.getSchemes()).json().is("['s-scheme']");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
+		)
+	)
+	public static class E2 {
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void e02a_operation_summary_swaggerOnClass() throws Exception {
+		Operation x = getSwagger(new E2()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("a-operationId", x.getOperationId());
+		assertEquals("a-summary", x.getSummary());
+		assertEquals("a-description", x.getDescription());
+		assertObject(x.getDeprecated()).json().is("false");
+		assertObject(x.getSchemes()).json().is("['a-scheme']");
+	}
+	@Test
+	public void e02b_operation_summary_swaggerOnClass_withFile() throws Exception {
+		Operation x = getSwaggerWithFile(new E2()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("a-operationId", x.getOperationId());
+		assertEquals("a-summary", x.getSummary());
+		assertEquals("a-description", x.getDescription());
+		assertObject(x.getDeprecated()).json().is("false");
+		assertObject(x.getSchemes()).json().is("['a-scheme']");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
+		)
+	)
+	public static class E3 {
+		@RestMethod(name=GET,path="/path/{foo}",
+			swagger=@MethodSwagger("operationId:'b-operationId',summary:'b-summary',description:'b-description',deprecated:false,schemes:['b-scheme']")
+		)
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void e03a_operation_summary_swaggerOnMethod() throws Exception {
+		Operation x = getSwagger(new E3()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("b-operationId", x.getOperationId());
+		assertEquals("b-summary", x.getSummary());
+		assertEquals("b-description", x.getDescription());
+		assertObject(x.getDeprecated()).json().is("false");
+		assertObject(x.getSchemes()).json().is("['b-scheme']");
+	}
+	@Test
+	public void e03b_operation_summary_swaggerOnMethod_withFile() throws Exception {
+		Operation x = getSwaggerWithFile(new E3()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("b-operationId", x.getOperationId());
+		assertEquals("b-summary", x.getSummary());
+		assertEquals("b-description", x.getDescription());
+		assertObject(x.getDeprecated()).json().is("false");
+		assertObject(x.getSchemes()).json().is("['b-scheme']");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
+		)
+	)
+	public static class E4 {
+		@RestMethod(name=GET,path="/path/{foo}",
+			swagger=@MethodSwagger(
+				operationId="c-operationId",
+				summary="c-summary",
+				description="c-description",
+				deprecated="false",
+				schemes="d-scheme-1, d-scheme-2"
+			)
+		)
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void e04a_operation_summary_swaggerOnAnnotation() throws Exception {
+		Operation x = getSwagger(new E4()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("c-operationId", x.getOperationId());
+		assertEquals("c-summary", x.getSummary());
+		assertEquals("c-description", x.getDescription());
+		assertObject(x.getSchemes()).json().is("['d-scheme-1','d-scheme-2']");
+	}
+	@Test
+	public void e04b_operation_summary_swaggerOnAnnotation_withFile() throws Exception {
+		Operation x = getSwaggerWithFile(new E4()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("c-operationId", x.getOperationId());
+		assertEquals("c-summary", x.getSummary());
+		assertEquals("c-description", x.getDescription());
+		assertObject(x.getSchemes()).json().is("['d-scheme-1','d-scheme-2']");
+	}
+
+	@Rest(
+		messages="BasicRestInfoProviderTest",
+		swagger=@ResourceSwagger(
+			"paths:{'/path/{foo}':{get:{operationId:'a-operationId',summary:'a-summary',description:'a-description',deprecated:false,schemes:['a-scheme']}}}"
+		)
+	)
+	public static class E5 {
+		@RestMethod(name=GET,path="/path/{foo}",
+			swagger=@MethodSwagger(
+				summary="$L{foo}",
+				operationId="$L{foo}",
+				description="$L{foo}",
+				deprecated="$L{false}",
+				schemes="$L{foo}"
+			)
+		)
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void e05a_operation_summary_swaggerOnAnnotation_localized() throws Exception {
+		Operation x = getSwagger(new E5()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("l-foo", x.getOperationId());
+		assertEquals("l-foo", x.getSummary());
+		assertEquals("l-foo", x.getDescription());
+		assertObject(x.getDeprecated()).json().is("false");
+		assertObject(x.getSchemes()).json().is("['l-foo']");
+	}
+	@Test
+	public void e05b_operation_summary_swaggerOnAnnotation_localized_withFile() throws Exception {
+		Operation x = getSwaggerWithFile(new E5()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("l-foo", x.getOperationId());
+		assertEquals("l-foo", x.getSummary());
+		assertEquals("l-foo", x.getDescription());
+		assertObject(x.getDeprecated()).json().is("false");
+		assertObject(x.getSchemes()).json().is("['l-foo']");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			"paths:{'/path/{foo}':{get:{summary:'a-summary',description:'a-description'}}}"
+		)
+	)
+	public static class E6 {
+		@RestMethod(name=GET,path="/path/{foo}",
+			summary="d-summary",
+			description="d-description"
+		)
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void e06a_operation_summary_RestMethod() throws Exception {
+		Operation x = getSwagger(new E6()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("a-summary", x.getSummary());
+		assertEquals("a-description", x.getDescription());
+	}
+	@Test
+	public void e06b_operation_summary_RestMethod_withFile() throws Exception {
+		Operation x = getSwaggerWithFile(new E6()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("a-summary", x.getSummary());
+		assertEquals("a-description", x.getDescription());
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger(
+			"paths:{'/path/{foo}':{get:{}}}"
+		)
+	)
+	public static class E7 {
+		@RestMethod(name=GET,path="/path/{foo}",
+			summary="d-summary",
+			description="d-description"
+		)
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void e07a_operation_summary_RestMethod() throws Exception {
+		Operation x = getSwagger(new E7()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("d-summary", x.getSummary());
+		assertEquals("d-description", x.getDescription());
+	}
+	@Test
+	public void e07b_operation_summary_RestMethod_withFile() throws Exception {
+		Operation x = getSwaggerWithFile(new E7()).getPaths().get("/path/{foo}").get("get");
+		assertEquals("d-summary", x.getSummary());
+		assertEquals("d-description", x.getDescription());
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/tags
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class F1 {
+
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void f01_operation_tags_default() throws Exception {
+		assertObject(getSwagger(new F1()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("null");
+		assertObject(getSwaggerWithFile(new F1()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['s-tag']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
+	public static class F2 {
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void f02_operation_tags_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new F2()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['a-tag']");
+		assertObject(getSwaggerWithFile(new F2()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['a-tag']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
+	public static class F3 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger("tags:['b-tag']"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void f03_operation_tags_swaggerOnMethod() throws Exception {
+		assertObject(getSwagger(new F3()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['b-tag']");
+		assertObject(getSwaggerWithFile(new F3()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['b-tag']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
+	public static class F4 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(tags="['c-tag-1','c-tag-2']"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void f04_operation_tags_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new F4()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['c-tag-1','c-tag-2']");
+		assertObject(getSwaggerWithFile(new F4()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['c-tag-1','c-tag-2']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:['a-tag']}}}"))
+	public static class F5 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(tags="c-tag-1, c-tag-2"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void f05_operation_tags_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new F5()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['c-tag-1','c-tag-2']");
+		assertObject(getSwaggerWithFile(new F5()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['c-tag-1','c-tag-2']");
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{tags:'a-tags'}}}"))
+	public static class F6 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(tags="$L{foo}"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void f06_operation_tags_swaggerOnAnnotation_localized() throws Exception {
+		assertObject(getSwagger(new F6()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['l-foo']");
+		assertObject(getSwaggerWithFile(new F6()).getPaths().get("/path/{foo}").get("get").getTags()).json().is("['l-foo']");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/externalDocs
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class G1 {
+
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void g01_operation_externalDocs_default() throws Exception {
+		assertObject(getSwagger(new G1()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("null");
+		assertObject(getSwaggerWithFile(new G1()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'s-description',url:'s-url'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
+	public static class G2 {
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void g02_operation_externalDocs_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new G2()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'a-description',url:'a-url'}");
+		assertObject(getSwaggerWithFile(new G2()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'a-description',url:'a-url'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
+	public static class G3 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger("externalDocs:{description:'b-description',url:'b-url'}"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void g03_operation_externalDocs_swaggerOnMethod() throws Exception {
+		assertObject(getSwagger(new G3()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'b-description',url:'b-url'}");
+		assertObject(getSwaggerWithFile(new G3()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'b-description',url:'b-url'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
+	public static class G4 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(externalDocs=@ExternalDocs(description="c-description",url="c-url")))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void g04_operation_externalDocs_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new G4()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'c-description',url:'c-url'}");
+		assertObject(getSwaggerWithFile(new G4()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'c-description',url:'c-url'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
+	public static class G5 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(externalDocs=@ExternalDocs("{description:'d-description',url:'d-url'}")))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void g05_operation_externalDocs_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new G5()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'d-description',url:'d-url'}");
+		assertObject(getSwaggerWithFile(new G5()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'d-description',url:'d-url'}");
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{externalDocs:{description:'a-description',url:'a-url'}}}}"))
+	public static class G6 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(externalDocs=@ExternalDocs("{description:'$L{foo}',url:'$L{foo}'}")))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void g06_operation_externalDocs_swaggerOnAnnotation_localized() throws Exception {
+		assertObject(getSwagger(new G6()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'l-foo',url:'l-foo'}");
+		assertObject(getSwaggerWithFile(new G6()).getPaths().get("/path/{foo}").get("get").getExternalDocs()).json().is("{description:'l-foo',url:'l-foo'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/consumes
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class H1 {
+
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void h01_operation_consumes_default() throws Exception {
+		assertObject(getSwagger(new H1()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("null");
+		assertObject(getSwaggerWithFile(new H1()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['s-consumes']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
+	public static class H2 {
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void h02_operation_consumes_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new H2()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['a-consumes']");
+		assertObject(getSwaggerWithFile(new H2()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['a-consumes']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
+	public static class H3 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger("consumes:['b-consumes']"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void h03_operation_consumes_swaggerOnMethod() throws Exception {
+		assertObject(getSwagger(new H3()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['b-consumes']");
+		assertObject(getSwaggerWithFile(new H3()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['b-consumes']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
+	public static class H4 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(consumes="['c-consumes-1','c-consumes-2']"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void h04_operation_consumes_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new H4()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['c-consumes-1','c-consumes-2']");
+		assertObject(getSwaggerWithFile(new H4()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['c-consumes-1','c-consumes-2']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
+	public static class H5 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(consumes="c-consumes-1, c-consumes-2"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void h05_operation_consumes_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new H5()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['c-consumes-1','c-consumes-2']");
+		assertObject(getSwaggerWithFile(new H5()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['c-consumes-1','c-consumes-2']");
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{consumes:['a-consumes']}}}"))
+	public static class H6 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(consumes="['$L{foo}']"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void h06_operation_consumes_swaggerOnAnnotation_localized() throws Exception {
+		assertObject(getSwagger(new H6()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['l-foo']");
+		assertObject(getSwaggerWithFile(new H6()).getPaths().get("/path/{foo}").get("get").getConsumes()).json().is("['l-foo']");
+	}
+
+	@Rest(parsers={JsonParser.class})
+	public static class H7 {
+		@RestMethod(name=PUT,path="/path2/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void h07_operation_consumes_parsersOnClass() throws Exception {
+		assertObject(getSwagger(new H7()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("null");
+		assertObject(getSwaggerWithFile(new H7()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("null");
+	}
+
+	@Rest(parsers={JsonParser.class})
+	public static class H8 {
+		@RestMethod(name=PUT,path="/path2/{foo}",parsers={XmlParser.class})
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void h08_operation_consumes_parsersOnClassAndMethod() throws Exception {
+		assertObject(getSwagger(new H8()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("['text/xml','application/xml']");
+		assertObject(getSwaggerWithFile(new H8()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("['text/xml','application/xml']");
+	}
+
+	@Rest(parsers={JsonParser.class},swagger=@ResourceSwagger("paths:{'/path2/{foo}':{put:{consumes:['a-consumes']}}}"))
+	public static class H9 {
+		@RestMethod(name=PUT,path="/path2/{foo}",parsers={XmlParser.class})
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void h09_operation_consumes_parsersOnClassAndMethodWithSwagger() throws Exception {
+		assertObject(getSwagger(new H9()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("['a-consumes']");
+		assertObject(getSwaggerWithFile(new H9()).getPaths().get("/path2/{foo}").get("put").getConsumes()).json().is("['a-consumes']");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/produces
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class I1 {
+
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void i01_operation_produces_default() throws Exception {
+		assertObject(getSwagger(new I1()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("null");
+		assertObject(getSwaggerWithFile(new I1()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['s-produces']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
+	public static class I2 {
+		@RestMethod(name=GET,path="/path/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void i02_operation_produces_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new I2()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['a-produces']");
+		assertObject(getSwaggerWithFile(new I2()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['a-produces']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
+	public static class I3 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger("produces:['b-produces']"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void i03_operation_produces_swaggerOnMethod() throws Exception {
+		assertObject(getSwagger(new I3()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['b-produces']");
+		assertObject(getSwaggerWithFile(new I3()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['b-produces']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
+	public static class I4 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(produces="['c-produces-1','c-produces-2']"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void i04_operation_produces_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new I4()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['c-produces-1','c-produces-2']");
+		assertObject(getSwaggerWithFile(new I4()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['c-produces-1','c-produces-2']");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
+	public static class I5 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(produces="c-produces-1, c-produces-2"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void i05_operation_produces_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new I5()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['c-produces-1','c-produces-2']");
+		assertObject(getSwaggerWithFile(new I5()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['c-produces-1','c-produces-2']");
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}':{get:{produces:['a-produces']}}}"))
+	public static class I6 {
+		@RestMethod(name=GET,path="/path/{foo}",swagger=@MethodSwagger(produces="['$L{foo}']"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void i06_operation_produces_swaggerOnAnnotation_localized() throws Exception {
+		assertObject(getSwagger(new I6()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['l-foo']");
+		assertObject(getSwaggerWithFile(new I6()).getPaths().get("/path/{foo}").get("get").getProduces()).json().is("['l-foo']");
+	}
+
+	@Rest(serializers={JsonSerializer.class})
+	public static class I7 {
+		@RestMethod(name=PUT,path="/path2/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void i07_operation_produces_serializersOnClass() throws Exception {
+		assertObject(getSwagger(new I7()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("null");
+		assertObject(getSwaggerWithFile(new I7()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("null");
+	}
+
+	@Rest(serializers={JsonSerializer.class})
+	public static class I8 {
+		@RestMethod(name=PUT,path="/path2/{foo}",serializers={XmlSerializer.class})
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void i08_operation_produces_serializersOnClassAndMethod() throws Exception {
+		assertObject(getSwagger(new I8()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("['text/xml']");
+		assertObject(getSwaggerWithFile(new I8()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("['text/xml']");
+	}
+
+	@Rest(serializers={JsonSerializer.class},swagger=@ResourceSwagger("paths:{'/path2/{foo}':{put:{produces:['a-produces']}}}"))
+	public static class I9 {
+		@RestMethod(name=PUT,path="/path2/{foo}",serializers={XmlSerializer.class})
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void i09_operation_produces_serializersOnClassAndMethodWithSwagger() throws Exception {
+		assertObject(getSwagger(new I9()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("['a-produces']");
+		assertObject(getSwaggerWithFile(new I9()).getPaths().get("/path2/{foo}").get("put").getProduces()).json().is("['a-produces']");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/deprecated
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class J1 {
+		@RestMethod(name=GET,path="/path2/{foo}")
+		@Deprecated
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void j01_operation_deprecated_Deprecated() throws Exception {
+		assertObject(getSwagger(new J1()).getPaths().get("/path2/{foo}").get("get").getDeprecated()).json().is("true");
+		assertObject(getSwaggerWithFile(new J1()).getPaths().get("/path2/{foo}").get("get").getDeprecated()).json().is("true");
+	}
+
+	@Rest
+	@Deprecated
+	public static class J2 {
+		@RestMethod(name=GET,path="/path2/{foo}")
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void j02_operation_deprecated_Deprecated() throws Exception {
+		assertObject(getSwagger(new J2()).getPaths().get("/path2/{foo}").get("get").getDeprecated()).json().is("true");
+		assertObject(getSwaggerWithFile(new J2()).getPaths().get("/path2/{foo}").get("get").getDeprecated()).json().is("true");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/parameters/query
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class K1 {
+		@RestMethod(name=GET,path="/path/{foo}/query")
+		public X a(@Query("foo") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void k01a_query_type_default() throws Exception {
+		ParameterInfo x = getSwagger(new K1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
+		assertEquals("object", x.getType());
+		assertEquals(null, x.getDescription());
+		assertEquals(null, x.getRequired());
+		assertEquals(null, x.getAllowEmptyValue());
+		assertEquals(null, x.getExclusiveMaximum());
+		assertEquals(null, x.getExclusiveMinimum());
+		assertEquals(null, x.getUniqueItems());
+		assertEquals(null, x.getFormat());
+		assertEquals(null, x.getCollectionFormat());
+		assertEquals(null, x.getPattern());
+		assertEquals(null, x.getMaximum());
+		assertEquals(null, x.getMinimum());
+		assertEquals(null, x.getMultipleOf());
+		assertEquals(null, x.getMaxLength());
+		assertEquals(null, x.getMinLength());
+		assertEquals(null, x.getMaxItems());
+		assertEquals(null, x.getMinItems());
+	}
+	@Test
+	public void k01b_query_type_default_withFile() throws Exception {
+		ParameterInfo x = getSwaggerWithFile(new K1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
+		assertEquals("string", x.getType());
+		assertEquals("s-description", x.getDescription());
+		assertObject(x.getRequired()).json().is("true");
+		assertObject(x.getAllowEmptyValue()).json().is("true");
+		assertObject(x.getExclusiveMaximum()).json().is("true");
+		assertObject(x.getExclusiveMinimum()).json().is("true");
+		assertObject(x.getUniqueItems()).json().is("true");
+		assertEquals("s-format", x.getFormat());
+		assertEquals("s-collectionFormat", x.getCollectionFormat());
+		assertEquals("s-pattern", x.getPattern());
+		assertObject(x.getMaximum()).json().is("1.0");
+		assertObject(x.getMinimum()).json().is("1.0");
+		assertObject(x.getMultipleOf()).json().is("1.0");
+		assertObject(x.getMaxLength()).json().is("1");
+		assertObject(x.getMinLength()).json().is("1");
+		assertObject(x.getMaxItems()).json().is("1");
+		assertObject(x.getMinItems()).json().is("1");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger({
+			"paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',",
+				"name:'foo',",
+				"type:'int32',",
+				"description:'a-description',",
+				"required:false,",
+				"allowEmptyValue:false,",
+				"exclusiveMaximum:false,",
+				"exclusiveMinimum:false,",
+				"uniqueItems:false,",
+				"format:'a-format',",
+				"collectionFormat:'a-collectionFormat',",
+				"pattern:'a-pattern',",
+				"maximum:2.0,",
+				"minimum:2.0,",
+				"multipleOf:2.0,",
+				"maxLength:2,",
+				"minLength:2,",
+				"maxItems:2,",
+				"minItems:2",
+			"}]}}}"
+		})
+	)
+	public static class K2 {
+		@RestMethod(name=GET,path="/path/{foo}/query")
+		public X a(@Query("foo") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void k02a_query_type_swaggerOnClass() throws Exception {
+		ParameterInfo x = getSwagger(new K2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
+		assertEquals("int32", x.getType());
+		assertEquals("a-description", x.getDescription());
+		assertObject(x.getRequired()).json().is("false");
+		assertObject(x.getAllowEmptyValue()).json().is("false");
+		assertObject(x.getExclusiveMaximum()).json().is("false");
+		assertObject(x.getExclusiveMinimum()).json().is("false");
+		assertObject(x.getUniqueItems()).json().is("false");
+		assertEquals("a-format", x.getFormat());
+		assertEquals("a-collectionFormat", x.getCollectionFormat());
+		assertEquals("a-pattern", x.getPattern());
+		assertObject(x.getMaximum()).json().is("2.0");
+		assertObject(x.getMinimum()).json().is("2.0");
+		assertObject(x.getMultipleOf()).json().is("2.0");
+		assertObject(x.getMaxLength()).json().is("2");
+		assertObject(x.getMinLength()).json().is("2");
+		assertObject(x.getMaxItems()).json().is("2");
+		assertObject(x.getMinItems()).json().is("2");
+	}
+	@Test
+	public void k02b_query_type_swaggerOnClass_withFile() throws Exception {
+		ParameterInfo x = getSwaggerWithFile(new K2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
+		assertEquals("int32", x.getType());
+		assertEquals("a-description", x.getDescription());
+		assertObject(x.getRequired()).json().is("false");
+		assertObject(x.getAllowEmptyValue()).json().is("false");
+		assertObject(x.getExclusiveMaximum()).json().is("false");
+		assertObject(x.getExclusiveMinimum()).json().is("false");
+		assertObject(x.getUniqueItems()).json().is("false");
+		assertEquals("a-format", x.getFormat());
+		assertEquals("a-collectionFormat", x.getCollectionFormat());
+		assertEquals("a-pattern", x.getPattern());
+		assertObject(x.getMaximum()).json().is("2.0");
+		assertObject(x.getMinimum()).json().is("2.0");
+		assertObject(x.getMultipleOf()).json().is("2.0");
+		assertObject(x.getMaxLength()).json().is("2");
+		assertObject(x.getMinLength()).json().is("2");
+		assertObject(x.getMaxItems()).json().is("2");
+		assertObject(x.getMinItems()).json().is("2");
+	}
+
+	@Rest(
+		swagger=@ResourceSwagger({
+			"paths:{'/path/{foo}/query':{get:{parameters:[{",
+				"'in':'query',",
+				"name:'foo',",
+				"type:'int32',",
+				"description:'a-description',",
+				"required:false,",
+				"allowEmptyValue:false,",
+				"exclusiveMaximum:false,",
+				"exclusiveMinimum:false,",
+				"uniqueItems:false,",
+				"format:'a-format',",
+				"collectionFormat:'a-collectionFormat',",
+				"pattern:'a-pattern',",
+				"maximum:2.0,",
+				"minimum:2.0,",
+				"multipleOf:2.0,",
+				"maxLength:2,",
+				"minLength:2,",
+				"maxItems:2,",
+				"minItems:2",
+			"}]}}}"
+		})
+	)
+	public static class K3 {
+		@RestMethod(name=GET,path="/path/{foo}/query",
+			swagger=@MethodSwagger({
+				"parameters:[{",
+					"'in':'query',",
+					"name:'foo',",
+					"type:'int64',",
+					"description:'b-description',",
+					"required:'true',",
+					"allowEmptyValue:'true',",
+					"exclusiveMaximum:'true',",
+					"exclusiveMinimum:'true',",
+					"uniqueItems:'true',",
+					"format:'b-format',",
+					"collectionFormat:'b-collectionFormat',",
+					"pattern:'b-pattern',",
+					"maximum:3.0,",
+					"minimum:3.0,",
+					"multipleOf:3.0,",
+					"maxLength:3,",
+					"minLength:3,",
+					"maxItems:3,",
+					"minItems:3",
+				"}]"
+			}))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void k03a_query_type_swaggerOnMethod() throws Exception {
+		ParameterInfo x = getSwagger(new K3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
+		assertEquals("int64", x.getType());
+		assertEquals("b-description", x.getDescription());
+		assertObject(x.getRequired()).json().is("true");
+		assertObject(x.getAllowEmptyValue()).json().is("true");
+		assertObject(x.getExclusiveMaximum()).json().is("true");
+		assertObject(x.getExclusiveMinimum()).json().is("true");
+		assertObject(x.getUniqueItems()).json().is("true");
+		assertEquals("b-format", x.getFormat());
+		assertEquals("b-collectionFormat", x.getCollectionFormat());
+		assertEquals("b-pattern", x.getPattern());
+		assertObject(x.getMaximum()).json().is("3.0");
+		assertObject(x.getMinimum()).json().is("3.0");
+		assertObject(x.getMultipleOf()).json().is("3.0");
+		assertObject(x.getMaxLength()).json().is("3");
+		assertObject(x.getMinLength()).json().is("3");
+		assertObject(x.getMaxItems()).json().is("3");
+		assertObject(x.getMinItems()).json().is("3");
+	}
+	@Test
+	public void k03b_query_type_swaggerOnMethod_withFile() throws Exception {
+		ParameterInfo x = getSwaggerWithFile(new K3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo");
+		assertEquals("int64", x.getType());
+		assertEquals("b-description", x.getDescription());
+		assertObject(x.getRequired()).json().is("true");
+		assertObject(x.getAllowEmptyValue()).json().is("true");
+		assertObject(x.getExclusiveMaximum()).json().is("true");
+		assertObject(x.getExclusiveMinimum()).json().is("true");
+		assertObject(x.getUniqueItems()).json().is("true");
+		assertEquals("b-format", x.getFormat());
+		assertEquals("b-collectionFormat", x.getCollectionFormat());
+		assertEquals("b-pattern", x.getPattern());
+		assertObject(x.getMaximum()).json().is("3.0");
+		assertObject(x.getMinimum()).json().is("3.0");
+		assertObject(x.getMultipleOf()).json().is("3.0");
+		assertObject(x.getMaxLength()).json().is("3");
+		assertObject(x.getMinLength()).json().is("3");
+		assertObject(x.getMaxItems()).json().is("3");
+		assertObject(x.getMinItems()).json().is("3");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/parameters/query/example
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class L1 {
+		@RestMethod(name=GET,path="/path/{foo}/query")
+		public X a(@Query("foo") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void l01_query_example_default() throws Exception {
+		assertEquals(null, getSwagger(new L1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+		assertEquals("{id:1}", getSwaggerWithFile(new L1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',name:'foo',x-example:'{id:2}'}]}}}"))
+	public static class L2 {
+		@RestMethod(name=GET,path="/path/{foo}/query")
+		public X a(@Query("foo") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void l02_query_example_swaggerOnClass() throws Exception {
+		assertEquals("{id:2}", getSwagger(new L2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+		assertEquals("{id:2}", getSwaggerWithFile(new L2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',name:'foo',x-example:'{id:2}'}]}}}"))
+	public static class L3 {
+		@RestMethod(name=GET,path="/path/{foo}/query",swagger=@MethodSwagger("parameters:[{'in':'query',name:'foo',x-example:'{id:3}'}]"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void l03_query_example_swaggerOnMethod() throws Exception {
+		assertEquals("{id:3}", getSwagger(new L3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+		assertEquals("{id:3}", getSwaggerWithFile(new L3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',name:'foo',x-example:'{id:2}'}]}}}"))
+	public static class L4 {
+		@RestMethod(name=GET,path="/path/{foo}/query")
+		public X a(@Query(n="foo",ex="{id:4}") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void l04_query_example_swaggerOnAnnotation() throws Exception {
+		assertEquals("{id:4}", getSwagger(new L4()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+		assertEquals("{id:4}", getSwaggerWithFile(new L4()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{'in':'query',name:'foo',x-example:'{id:2}'}]}}}"))
+	public static class L5 {
+		@RestMethod(name=GET,path="/path/{foo}/query")
+		public X a(@Query(n="foo",ex="{id:$L{5}}") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void l05_query_example_swaggerOnAnnotation_localized() throws Exception {
+		assertEquals("{id:5}", getSwagger(new L5()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+		assertEquals("{id:5}", getSwaggerWithFile(new L5()).getPaths().get("/path/{foo}/query").get("get").getParameter("query", "foo").getExample());
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/parameters/body/examples
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class M1 {
+		@RestMethod(name=GET,path="/path/{foo}/body")
+		public X a(@Body X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void m01_body_examples_default() throws Exception {
+		assertEquals(null, getSwagger(new M1()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples());
+		assertObject(getSwaggerWithFile(new M1()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'a'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/body':{get:{parameters:[{'in':'body',x-examples:{foo:'b'}}]}}}"))
+	public static class M2 {
+		@RestMethod(name=GET,path="/path/{foo}/body")
+		public X a(@Body X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void m02_body_examples_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new M2()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'b'}");
+		assertObject(getSwaggerWithFile(new M2()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'b'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/body':{get:{parameters:[{'in':'body',x-examples:{foo:'b'}}]}}}"))
+	public static class M3 {
+		@RestMethod(name=GET,path="/path/{foo}/body",swagger=@MethodSwagger("parameters:[{'in':'body',x-examples:{foo:'c'}}]"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void m03_body_examples_swaggerOnMethods() throws Exception {
+		assertObject(getSwagger(new M3()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'c'}");
+		assertObject(getSwaggerWithFile(new M3()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'c'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/body':{get:{parameters:[{'in':'body',x-examples:{foo:'b'}}]}}}"))
+	public static class M4 {
+		@RestMethod(name=GET,path="/path/{foo}/body")
+		public X a(@Body(exs="{foo:'d'}") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void m04_body_examples_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new M4()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'d'}");
+		assertObject(getSwaggerWithFile(new M4()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'d'}");
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/body':{get:{parameters:[{'in':'body',examples:{foo:'b'}}]}}}"))
+	public static class M5 {
+		@RestMethod(name=GET,path="/path/{foo}/body")
+		public X a(@Body(exs="{foo:'$L{foo}'}") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void m05_body_examples_swaggerOnAnnotation_localized() throws Exception {
+		assertObject(getSwagger(new M5()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'l-foo'}");
+		assertObject(getSwaggerWithFile(new M5()).getPaths().get("/path/{foo}/body").get("get").getParameter("body",null).getExamples()).json().is("{foo:'l-foo'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/parameters/query/schema
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class N1 {
+		@RestMethod(name=GET,path="/path/{foo}/query")
+		public X a(@Query("foo") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void n01_query_schema_default() throws Exception {
+		assertObject(getSwagger(new N1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{properties:{a:{format:'int32',type:'integer'}}}");
+		assertObject(getSwaggerWithFile(new N1()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'#/definitions/Foo'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{in:'query',name:'foo',schema:{$ref:'b'}}]}}}"))
+	public static class N2 {
+		@RestMethod(name=GET,path="/path/{foo}/query")
+		public X a(@Query("foo") X foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void n02_query_schema_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new N2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'b'}");
+		assertObject(getSwaggerWithFile(new N2()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'b'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/query':{get:{parameters:[{in:'query',name:'foo',schema:{$ref:'b'}}]}}}"))
+	public static class N3 {
+
+		@RestMethod(name=GET,path="/path/{foo}/query",swagger=@MethodSwagger("parameters:[{'in':'query',name:'foo',schema:{$ref:'c'}}]"))
+		public X a() {
+			return null;
+		}
+	}
+
+	@Test
+	public void n03_query_schema_swaggerOnMethnt() throws Exception {
+		assertObject(getSwagger(new N3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'c'}");
+		assertObject(getSwaggerWithFile(new N3()).getPaths().get("/path/{foo}/query").get("get").getParameter("query","foo").getSchema()).json().is("{'$ref':'c'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/responses/<response>/description
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class O1a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<O1c> foo) {}
+	}
+	@Rest
+	public static class O1b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public O1c a() { return null;}
+	}
+	@Response(code=100)
+	public static class O1c {
+		public String a;
+	}
+
+	@Test
+	public void o01a_responses_100_description_default() throws Exception {
+		assertEquals("Continue", getSwagger(new O1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("s-100-description", getSwaggerWithFile(new O1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+	@Test
+	public void o01b_responses_100_description_default() throws Exception {
+		assertEquals("Continue", getSwagger(new O1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("s-100-description", getSwaggerWithFile(new O1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
+	public static class O2 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(@ResponseStatus Value<Integer> foo) {}
+	}
+
+	@Test
+	public void o02_response_100_description_swaggerOnClass() throws Exception {
+		assertEquals("a-100-description", getSwagger(new O2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("a-100-description", getSwaggerWithFile(new O2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
+	public static class O3 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{description:'b-100-description'}}"))
+		public void a(@ResponseStatus Value<Integer> foo) {}
+	}
+
+	@Test
+	public void o03_response_100_description_swaggerOnMethod() throws Exception {
+		assertEquals("b-100-description", getSwagger(new O3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("b-100-description", getSwaggerWithFile(new O3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
+	public static class O4a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<O4c> foo) {}
+	}
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
+	public static class O4b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public O4c a() {return null;}
+	}
+	@Response(code=100,description="c-100-description")
+	public static class O4c {}
+
+	@Test
+	public void o04a_response_100_description_swaggerOnAnnotation() throws Exception {
+		assertEquals("c-100-description", getSwagger(new O4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("c-100-description", getSwaggerWithFile(new O4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+	@Test
+	public void o04b_response_100_description_swaggerOnAnnotation() throws Exception {
+		assertEquals("c-100-description", getSwagger(new O4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("c-100-description", getSwaggerWithFile(new O4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
+	public static class O5a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<O5c> foo) {}
+	}
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{description:'a-100-description'}}}}}"))
+	public static class O5b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public O5c a() {return null;}
+	}
+	@Response(code=100,description="$L{foo}")
+	public static class O5c {}
+
+	@Test
+	public void o05a_response_100_description_swaggerOnAnnotation_localized() throws Exception {
+		assertEquals("l-foo", getSwagger(new O5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("l-foo", getSwaggerWithFile(new O5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+	@Test
+	public void o05b_response_100_description_swaggerOnAnnotation_localized() throws Exception {
+		assertEquals("l-foo", getSwagger(new O5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+		assertEquals("l-foo", getSwaggerWithFile(new O5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getDescription());
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/responses/<response>/headers
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class P1a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<P1c> foo) {}
+	}
+	@Rest
+	public static class P1b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public P1c a() {return null;}
+	}
+	@Response(code=100)
+	public static class P1c {
+		public String a;
+	}
+
+	@Test
+	public void p01a_responses_100_headers_default() throws Exception {
+		assertEquals(null, getSwagger(new P1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+		assertObject(getSwaggerWithFile(new P1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'s-description',type:'integer',format:'int32'}}");
+	}
+	@Test
+	public void p01b_responses_100_headers_default() throws Exception {
+		assertEquals(null, getSwagger(new P1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders());
+		assertObject(getSwaggerWithFile(new P1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'s-description',type:'integer',format:'int32'}}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
+	public static class P2 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public X a(@ResponseStatus Value<Integer> foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void p02_response_100_headers_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new P2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}");
+		assertObject(getSwaggerWithFile(new P2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
+	public static class P3 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{headers:{'X-Foo':{description:'c-description',type:'integer',format:'int32'}}}}"))
+		public X a(@ResponseStatus Value<Integer> foo) {
+			return null;
+		}
+	}
+
+	@Test
+	public void p03_response_100_headers_swaggerOnMethod() throws Exception {
+		assertObject(getSwagger(new P3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'c-description',type:'integer',format:'int32'}}");
+		assertObject(getSwaggerWithFile(new P3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'c-description',type:'integer',format:'int32'}}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
+	public static class P4a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<P4c> foo) {}
+	}
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
+	public static class P4b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public P4c a() {return null;}
+	}
+	@Response(code=100,headers=@ResponseHeader(name="X-Foo",description="d-description",type="integer",format="int32"))
+	public static class P4c {}
+
+	@Test
+	public void p04a_response_100_headers_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new P4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}");
+		assertObject(getSwaggerWithFile(new P4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}");
+	}
+	@Test
+	public void p04b_response_100_headers_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new P4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}");
+		assertObject(getSwaggerWithFile(new P4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'d-description',type:'integer',format:'int32'}}");
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
+	public static class P5a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<P5c> foo) {}
+	}
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{headers:{'X-Foo':{description:'b-description',type:'integer',format:'int32'}}}}}}}"))
+	public static class P5b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public P5c a() {return null;}
+	}
+	@Response(code=100,headers=@ResponseHeader(name="X-Foo",description="$L{foo}",type="integer",format="int32"))
+	public static class P5c {}
+
+	@Test
+	public void p05a_response_100_headers_swaggerOnAnnotation_localized() throws Exception {
+		assertObject(getSwagger(new P5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}");
+		assertObject(getSwaggerWithFile(new P5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}");
+	}
+	@Test
+	public void p05b_response_100_headers_swaggerOnAnnotation_localized() throws Exception {
+		assertObject(getSwagger(new P5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}");
+		assertObject(getSwaggerWithFile(new P5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getHeaders()).json().is("{'X-Foo':{description:'l-foo',type:'integer',format:'int32'}}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/responses/<response>/example
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class Q1a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<Q1c> foo) {}
+	}
+	@Rest
+	public static class Q1b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public Q1c a() {return null;}
+	}
+	@Response(code=100)
+	public static class Q1c {
+		public String a;
+	}
+
+	@Test
+	public void q01a_responses_100_example_default() throws Exception {
+		assertEquals(null, getSwagger(new Q1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertEquals("{foo:'a'}", getSwaggerWithFile(new Q1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	}
+	@Test
+	public void q01b_responses_100_example_default() throws Exception {
+		assertEquals(null, getSwagger(new Q1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertEquals("{foo:'a'}", getSwaggerWithFile(new Q1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
+	public static class Q2 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(@ResponseStatus Value<Integer> foo) {}
+	}
+
+	@Test
+	public void q02_response_100_example_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new Q2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample()).json().is("{foo:'b'}");
+		assertObject(getSwaggerWithFile(new Q2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample()).json().is("{foo:'b'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
+	public static class Q3 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{example:{foo:'c'}}}"))
+		public void a(@ResponseStatus Value<Integer> foo) {}
+	}
+
+	@Test
+	public void q03_response_100_example_swaggerOnMethod() throws Exception {
+		assertObject(getSwagger(new Q3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample()).json().is("{foo:'c'}");
+		assertObject(getSwaggerWithFile(new Q3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample()).json().is("{foo:'c'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
+	public static class Q4a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<Q4c> foo) {}
+	}
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
+	public static class Q4b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public Q4c a() {return null;}
+	}
+	@Response(code=100,example="{foo:'d'}")
+	public static class Q4c {
+		public String a;
+	}
+
+	@Test
+	public void q04a_response_100_example_swaggerOnAnnotation() throws Exception {
+		assertEquals("{foo:'d'}", getSwagger(new Q4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertEquals("{foo:'d'}", getSwaggerWithFile(new Q4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	}
+	@Test
+	public void q04b_response_100_example_swaggerOnAnnotation() throws Exception {
+		assertEquals("{foo:'d'}", getSwagger(new Q4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertEquals("{foo:'d'}", getSwaggerWithFile(new Q4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
+	public static class Q5a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<Q5c> foo) {}
+	}
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{example:{foo:'b'}}}}}}"))
+	public static class Q5b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public Q5c a() {return null;}
+	}
+	@Response(code=100,example="{foo:'$L{foo}'}")
+	public static class Q5c {
+		public String a;
+	}
+
+	@Test
+	public void q05a_response_100_example_swaggerOnAnnotation_localized() throws Exception {
+		assertEquals("{foo:'l-foo'}", getSwagger(new Q5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertEquals("{foo:'l-foo'}", getSwaggerWithFile(new Q5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	}
+	@Test
+	public void q05b_response_100_example_swaggerOnAnnotation_localized() throws Exception {
+		assertEquals("{foo:'l-foo'}", getSwagger(new Q5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+		assertEquals("{foo:'l-foo'}", getSwaggerWithFile(new Q5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExample());
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/responses/<response>/examples
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class R1a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<R1c> foo) {}
+	}
+	@Rest
+	public static class R1b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public R1c a() {return null;}
+	}
+	@Response(code=100)
+	public static class R1c {
+		public String a;
+	}
+
+	@Test
+	public void r01a_responses_100_examples_default() throws Exception {
+		assertEquals(null, getSwagger(new R1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+		assertObject(getSwaggerWithFile(new R1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:'a'}");
+	}
+	@Test
+	public void r01b_responses_100_examples_default() throws Exception {
+		assertEquals(null, getSwagger(new R1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples());
+		assertObject(getSwaggerWithFile(new R1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:'a'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
+	public static class R2 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(@ResponseStatus Value<Integer> foo) {}
+	}
+
+	@Test
+	public void r02_response_100_examples_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new R2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'b'}}");
+		assertObject(getSwaggerWithFile(new R2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'b'}}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
+	public static class R3 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{examples:{foo:{bar:'c'}}}}"))
+		public void a(@ResponseStatus Value<Integer> foo) {}
+	}
+
+	@Test
+	public void r03_response_100_examples_swaggerOnMethod() throws Exception {
+		assertObject(getSwagger(new R3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'c'}}");
+		assertObject(getSwaggerWithFile(new R3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'c'}}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
+	public static class R4a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<R4c> foo) {}
+	}
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
+	public static class R4b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public R4c a() {return null;}
+	}
+	@Response(code=100,examples="{foo:{bar:'d'}}")
+	public static class R4c {}
+
+	@Test
+	public void r04a_response_100_examples_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new R4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'d'}}");
+		assertObject(getSwaggerWithFile(new R4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'d'}}");
+	}
+	@Test
+	public void r04b_response_100_examples_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new R4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'d'}}");
+		assertObject(getSwaggerWithFile(new R4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'d'}}");
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
+	public static class R5a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<R5c> foo) {}
+	}
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{examples:{foo:{bar:'b'}}}}}}}"))
+	public static class R5b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public R5c a() {return null;}
+	}
+	@Response(code=100,examples="{foo:{bar:'$L{foo}'}}")
+	public static class R5c {}
+
+	@Test
+	public void r05a_response_100_examples_swaggerOnAnnotation_lodalized() throws Exception {
+		assertObject(getSwagger(new R5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'l-foo'}}");
+		assertObject(getSwaggerWithFile(new R5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'l-foo'}}");
+	}
+	@Test
+	public void r05b_response_100_examples_swaggerOnAnnotation_lodalized() throws Exception {
+		assertObject(getSwagger(new R5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'l-foo'}}");
+		assertObject(getSwaggerWithFile(new R5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getExamples()).json().is("{foo:{bar:'l-foo'}}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// /paths/<path>/<method>/responses/<response>/schema
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class S1a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<S1c> foo) {}
+	}
+	@Rest
+	public static class S1b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public S1c a() {return null;}
+	}
+	@Response(code=100)
+	public static class S1c extends X {}
+
+	@Test
+	public void s01a_responses_100_schema_default() throws Exception {
+		assertObject(getSwagger(new S1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{type:'object',properties:{a:{format:'int32',type:'integer'}}}");
+		assertObject(getSwaggerWithFile(new S1a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{type:'array',items:{'$ref':'#/definitions/Foo'}}");
+	}
+	@Test
+	public void s01b_responses_100_schema_default() throws Exception {
+		assertObject(getSwagger(new S1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{type:'object',properties:{a:{format:'int32',type:'integer'}}}");
+		assertObject(getSwaggerWithFile(new S1b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{type:'array',items:{'$ref':'#/definitions/Foo'}}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
+	public static class S2 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(@ResponseStatus Value<Integer> foo) {}
+	}
+
+	@Test
+	public void s02_response_100_schema_swaggerOnClass() throws Exception {
+		assertObject(getSwagger(new S2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'b'}");
+		assertObject(getSwaggerWithFile(new S2()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'b'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
+	public static class S3 {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100",swagger=@MethodSwagger("responses:{100:{schema:{$ref:'c'}}}}"))
+		public void a(@ResponseStatus Value<Integer> foo) {}
+	}
+
+	@Test
+	public void s03_response_100_schema_swaggerOnMethoe() throws Exception {
+		assertObject(getSwagger(new S3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'c'}");
+		assertObject(getSwaggerWithFile(new S3()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'c'}");
+	}
+
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
+	public static class S4a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<S4c> foo) {}
+	}
+	@Rest(swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
+	public static class S4b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public S4c a() {return null;}
+	}
+	@Response(code=100,schema=@Schema($ref="d"))
+	public static class S4c extends X {}
+
+	@Test
+	public void s04a_response_100_schema_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new S4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'d'}");
+		assertObject(getSwaggerWithFile(new S4a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'d'}");
+	}
+	@Test
+	public void s04b_response_100_schema_swaggerOnAnnotation() throws Exception {
+		assertObject(getSwagger(new S4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'d'}");
+		assertObject(getSwaggerWithFile(new S4b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'d'}");
+	}
+
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
+	public static class S5a {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public void a(Value<S5c> foo) {}
+	}
+	@Rest(messages="BasicRestInfoProviderTest", swagger=@ResourceSwagger("paths:{'/path/{foo}/responses/100':{get:{responses:{100:{schema:{$ref:'b'}}}}}}"))
+	public static class S5b {
+		@RestMethod(name=GET,path="/path/{foo}/responses/100")
+		public S5c a() {return null;}
+	}
+	@Response(code=100,schema=@Schema("{$ref:'$L{foo}'}"))
+	public static class S5c extends X {}
+
+	@Test
+	public void s05a_response_100_schema_swaggerOnAnnotation_loealized() throws Exception {
+		assertObject(getSwagger(new S5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'l-foo'}");
+		assertObject(getSwaggerWithFile(new S5a()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'l-foo'}");
+	}
+	@Test
+	public void s05b_response_100_schema_swaggerOnAnnotation_loealized() throws Exception {
+		assertObject(getSwagger(new S5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'l-foo'}");
+		assertObject(getSwaggerWithFile(new S5b()).getPaths().get("/path/{foo}/responses/100").get("get").getResponse(100).getSchema()).json().is("{'$ref':'l-foo'}");
+	}
+
+	@Bean(typeName="Foo")
+	public static class X {
+		public int a;
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Example bean with getter-only property.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class T1 extends BasicRestServlet {
+		private static final long serialVersionUID = 1L;
+
+		@RestMethod(name=GET,path="/")
+		public T2 a(@Body T2 body) {
+			return null;
+		}
+	}
+
+	@Bean(sort=true)
+	public static class T2 {
+		private int f1;
+
+		public T2 setF1(int f1) {
+			this.f1 = f1;
+			return this;
+		}
+
+		public int getF1() {
+			return f1;
+		}
+
+		public int getF2() {
+			return 2;
+		}
+
+		@Example
+		public static T2 example() {
+			return new T2().setF1(1);
+		}
+	}
+
+
+	@Test
+	public void t01_bodyWithReadOnlyProperty() throws Exception {
+		MockRestClient p = MockRestClient.build(T1.class);
+		Swagger s = JsonParser.DEFAULT.parse(p.options("/").accept("application/json").run().getBody().asString(), Swagger.class);
+		Operation o = s.getOperation("/", "get");
+		ParameterInfo pi = o.getParameter("body", null);
+		assertEquals("{\n\tf1: 1,\n\tf2: 2\n}", pi.getExamples().get("application/json+simple"));
+		ResponseInfo ri = o.getResponse("200");
+		assertEquals("{\n\tf1: 1,\n\tf2: 2\n}", ri.getExamples().get("application/json+simple"));
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestResourcePojoSwapsTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/BeanConfig_Swaps_Test.java
similarity index 67%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestResourcePojoSwapsTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/BeanConfig_Swaps_Test.java
index ebd2700..a1d1f75 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestResourcePojoSwapsTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/BeanConfig_Swaps_Test.java
@@ -10,7 +10,7 @@
 // * "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.rest.annotation2;

+package org.apache.juneau.rest.annotation;

 

 import static org.apache.juneau.http.HttpMethod.*;

 import static org.junit.runners.MethodSorters.*;

@@ -21,18 +21,18 @@
 import org.apache.juneau.http.annotation.Path;

 import org.apache.juneau.json.*;

 import org.apache.juneau.parser.*;

-import org.apache.juneau.rest.annotation.*;

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.apache.juneau.serializer.*;

 import org.apache.juneau.transform.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class RestResourcePojoSwapsTest {

+public class BeanConfig_Swaps_Test {

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Basic tests

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	public static class A {

 		public int f1;

@@ -85,53 +85,49 @@
 

 	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class)

 	@BeanConfig(swaps={SwapA1.class})

-	public static class A01_Parent {}

+	public static class A2 {}

 

 	@Rest

 	@BeanConfig(swaps={SwapA2.class})

-	public static class A01 extends A01_Parent {

+	public static class A1 extends A2 {

 

-		@RestMethod(name=GET, path="/classTransformOverridesParentClassTransform")

-		public A a01a() {

+		@RestMethod

+		public A a() {

 			return new A(); // Should return "A2-1".

 		}

-		@RestMethod(name=PUT, path="/classTransformOverridesParentClassTransform")

-		public A a01b(@Body A a) {

+		@RestMethod(name=PUT)

+		public A b(@Body A a) {

 			return a; // Should return "A2-1".

 		}

-		@RestMethod(name=PUT, path="/classTransformOverridesParentClassTransform/{a}")

-		public A a01c(@Path("a") A a) {

+		@RestMethod(name=PUT, path="/c/{a}")

+		public A c(@Path("a") A a) {

 			return a; // Should return "A2-1".

 		}

-		@RestMethod(name=GET, path="/methodTransformOverridesClassTransform")

+		@RestMethod

 		@BeanConfig(swaps={SwapA3.class})

-		public A a02a() {

+		public A d() {

 			return new A(); // Should return "A3-1".

 		}

-		@RestMethod(name=PUT, path="/methodTransformOverridesClassTransform")

+		@RestMethod(name=PUT)

 		@BeanConfig(swaps={SwapA3.class})

-		public A a02b(@Body A a) {

+		public A e(@Body A a) {

 			return a; // Should return "A3-1".

 		}

-		@RestMethod(name=PUT, path="/methodTransformOverridesClassTransform/{a}")

+		@RestMethod(name=PUT, path="/f/{a}")

 		@BeanConfig(swaps={SwapA3.class})

-		public A a02c(@Path("a") A a) {

+		public A f(@Path("a") A a) {

 			return a; // Should return "A3-1".

 		}

 	}

-	static MockRestClient a = MockRestClient.build(A01.class);

 

 	@Test

-	public void a01_classTransformOverridesParentClassTransform() throws Exception {

-		a.get("/classTransformOverridesParentClassTransform").json().run().assertBody().is("'A2-0'");

-		a.put("/classTransformOverridesParentClassTransform", "'A2-1'", "application/json").run().assertBody().is("'A2-1'");

-		a.put("/classTransformOverridesParentClassTransform/A2-2", null, "application/json").run().assertBody().is("'A2-2'");

-	}

-

-	@Test

-	public void a02_methodTransformOverridesClassTransform() throws Exception {

-		a.get("/methodTransformOverridesClassTransform").json().run().assertBody().is("'A3-0'");

-		a.put("/methodTransformOverridesClassTransform", "'A3-1'", "application/json").run().assertBody().is("'A3-1'");

-		a.put("/methodTransformOverridesClassTransform/A3-2", null, "application/json").run().assertBody().is("'A3-2'");

+	public void a01_swaps() throws Exception {

+		RestClient a = MockRestClient.build(A1.class);

+		a.get("/a").json().run().assertBody().is("'A2-0'");

+		a.put("/b", "'A2-1'", "application/json").run().assertBody().is("'A2-1'");

+		a.put("/c/A2-2", null, "application/json").run().assertBody().is("'A2-2'");

+		a.get("/d").json().run().assertBody().is("'A3-0'");

+		a.put("/e", "'A3-1'", "application/json").run().assertBody().is("'A3-1'");

+		a.put("/f/A3-2", null, "application/json").run().assertBody().is("'A3-2'");

 	}

 }

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Body_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Body_Test.java
new file mode 100644
index 0000000..8b44d43
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Body_Test.java
@@ -0,0 +1,1006 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.collections.*;
+import org.apache.juneau.http.annotation.Body;
+import org.apache.juneau.http.annotation.HasQuery;
+import org.apache.juneau.http.annotation.Query;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.marshall.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.apache.juneau.testutils.pojos.*;
+import org.apache.juneau.uon.*;
+import org.apache.juneau.urlencoding.*;
+import org.apache.juneau.urlencoding.annotation.*;
+import org.apache.juneau.urlencoding.annotation.UrlEncoding;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Body_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @Body on parameter
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class, defaultAccept="text/json")
+	public static class A {
+		@RestMethod(name=PUT, path="/String")
+		public String a(@Body String b) {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/Integer")
+		public Integer b(@Body Integer b) {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/int")
+		public Integer c(@Body int b) {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/Boolean")
+		public Boolean d(@Body Boolean b) {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/boolean")
+		public Boolean e(@Body boolean b) {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/float")
+		public float f(@Body float f) {
+			return f;
+		}
+		@RestMethod(name=PUT, path="/Float")
+		public Float g(@Body Float f) {
+			return f;
+		}
+		@RestMethod(name=PUT, path="/Map")
+		public TreeMap<String,Integer> h(@Body TreeMap<String,Integer> m) {
+			return m;
+		}
+		@RestMethod(name=PUT, path="/enum")
+		public TestEnum i(@Body TestEnum e) {
+			return e;
+		}
+		public static class A11 {
+			public String f1;
+		}
+		@RestMethod(name=PUT, path="/Bean")
+		public A11 j(@Body A11 b) {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/InputStream")
+		public String k(@Body InputStream b) throws Exception {
+			return IOUtils.read(b);
+		}
+		@RestMethod(name=PUT, path="/Reader")
+		public String l(@Body Reader b) throws Exception {
+			return IOUtils.read(b);
+		}
+		@RestMethod(name=PUT, path="/InputStreamTransform")
+		public A14 m(@Body A14 b) throws Exception {
+			return b;
+		}
+		public static class A14 {
+			String s;
+			public A14(InputStream in) throws Exception { this.s = IOUtils.read(in); }
+			@Override public String toString() { return s; }
+		}
+		@RestMethod(name=PUT, path="/ReaderTransform")
+		public A15 n(@Body A15 b) throws Exception {
+			return b;
+		}
+		public static class A15 {
+			private String s;
+			public A15(Reader in) throws Exception { this.s = IOUtils.read(in); }
+			@Override public String toString() { return s; }
+		}
+		@RestMethod(name=PUT, path="/StringTransform")
+		public A16 o(@Body A16 b) throws Exception { return b; }
+		public static class A16 {
+			private String s;
+			public A16(String s) throws Exception { this.s = s; }
+			@Override public String toString() { return s; }
+		}
+	}
+
+	@Test
+	public void a01_onParameters() throws Exception {
+		RestClient a = MockRestClient.buildLax(A.class);
+
+		a.put("/String", "foo")
+			.json()
+			.run()
+			.assertBody().is("'foo'");
+		// If no Content-Type specified, should be treated as plain-text.
+		a.put("/String", "'foo'")
+			.run()
+			.assertBody().is("'\\'foo\\''");
+		// If Content-Type not matched, should be treated as plain-text.
+		a.put("/String", "'foo'").contentType("")
+			.run()
+			.assertBody().is("'\\'foo\\''");
+		a.put("/String", "'foo'").contentType("text/plain")
+			.run()
+			.assertBody().is("'\\'foo\\''");
+		a.put("/String?body=foo", null)
+			.run()
+			.assertBody().is("'foo'");
+		a.put("/String?body=null", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/String?body=", null)
+			.run()
+			.assertBody().is("''");
+
+		a.put("/Integer", "123").json()
+			.run()
+			.assertBody().is("123");
+		// Integer takes in a String arg, so it can be parsed without Content-Type.
+		a.put("/Integer", "123")
+			.run()
+			.assertBody().is("123");
+		a.put("/Integer?body=123", null)
+			.run()
+			.assertBody().is("123");
+		a.put("/Integer?body=-123", null)
+			.run()
+			.assertBody().is("-123");
+		a.put("/Integer?body=null", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Integer?body=", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Integer?body=bad&noTrace=true", null)
+			.run()
+			.assertCode().is(400);
+
+		a.put("/int", "123").json()
+			.run()
+			.assertBody().is("123");
+		a.put("/int", "123")
+			.run()
+			.assertBody().is("123"); // Uses part parser.
+		a.put("/int?body=123", null)
+			.run()
+			.assertBody().is("123");
+		a.put("/int?body=-123", null)
+			.run()
+			.assertBody().is("-123");
+		a.put("/int?body=null", null)
+			.run()
+			.assertBody().is("0");
+		a.put("/int?body=", null)
+			.run()
+			.assertBody().is("0");
+		a.put("/int?body=bad&noTrace=true", null)
+			.run()
+			.assertCode().is(400);
+
+		a.put("/Boolean", "true").json()
+			.run()
+			.assertBody().is("true");
+		// Boolean takes in a String arg, so it can be parsed without Content-Type.
+		a.put("/Boolean", "true")
+			.run()
+			.assertBody().is("true");
+		a.put("/Boolean?body=true", null)
+			.run()
+			.assertBody().is("true");
+		a.put("/Boolean?body=false", null)
+			.run()
+			.assertBody().is("false");
+		a.put("/Boolean?body=null", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Boolean?body=", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Boolean?body=bad&noTrace=true", null)
+			.run()
+			.assertCode().is(400);
+
+		a.put("/boolean", "true").json()
+			.run()
+			.assertBody().is("true");
+		a.put("/boolean", "true")
+			.run()
+			.assertBody().is("true"); // Uses part parser.
+		a.put("/boolean?body=true", null)
+			.run()
+			.assertBody().is("true");
+		a.put("/boolean?body=false", null)
+			.run()
+			.assertBody().is("false");
+		a.put("/boolean?body=null", null)
+			.run()
+			.assertBody().is("false");
+		a.put("/boolean?body=", null)
+			.run()
+			.assertBody().is("false");
+		a.put("/boolean?body=bad&noTrace=true", null)
+			.run()
+			.assertCode().is(400);
+
+		a.put("/float", "1.23").json()
+			.run()
+			.assertBody().is("1.23");
+		a.put("/float", "1.23")
+			.run()
+			.assertBody().is("1.23");  // Uses part parser.
+		a.put("/float?body=1.23", null)
+			.run()
+			.assertBody().is("1.23");
+		a.put("/float?body=-1.23", null)
+			.run()
+			.assertBody().is("-1.23");
+		a.put("/float?body=null", null)
+			.run()
+			.assertBody().is("0.0");
+		a.put("/float?body=", null)
+			.run()
+			.assertBody().is("0.0");
+		a.put("/float?body=bad&noTrace=true", null)
+			.run()
+			.assertCode().is(400);
+
+		a.put("/Float", "1.23").json()
+			.run()
+			.assertBody().is("1.23");
+		// Float takes in a String arg, so it can be parsed without Content-Type.
+		a.put("/Float", "1.23")
+			.run()
+			.assertBody().is("1.23");
+		a.put("/Float?body=1.23", null)
+			.run()
+			.assertBody().is("1.23");
+		a.put("/Float?body=-1.23", null)
+			.run()
+			.assertBody().is("-1.23");
+		a.put("/Float?body=null", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Float?body=", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Float?body=bad&noTrace=true", null)
+			.run()
+			.assertCode().is(400);
+
+		a.put("/Map", "{foo:123}", "application/json")
+			.run()
+			.assertBody().is("{foo:123}");
+		a.put("/Map", "(foo=123)", "text/openapi")
+			.run()
+			.assertCode().is(415);
+		a.put("/Map?body=(foo=123)", null)
+			.run()
+			.assertBody().is("{foo:123}");
+		a.put("/Map?body=()", null)
+			.run()
+			.assertBody().is("{}");
+		a.put("/Map?body=null", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Map?body=", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Map?body=bad&noTrace=true", null)
+			.run()
+			.assertCode().is(400);
+
+		a.put("/enum", "'ONE'", "application/json")
+			.run()
+			.assertBody().is("'ONE'");
+		a.put("/enum", "ONE")
+			.run()
+			.assertBody().is("'ONE'");
+		a.put("/enum?body=ONE", null)
+			.run()
+			.assertBody().is("'ONE'");
+		a.put("/enum?body=TWO", null)
+			.run()
+			.assertBody().is("'TWO'");
+		a.put("/enum?body=null", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/enum?body=", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/enum?body=bad&noTrace=true", null)
+			.run()
+			.assertCode().is(400);
+
+		a.put("/Bean", "{f1:'a'}", "application/json")
+			.run()
+			.assertBody().is("{f1:'a'}");
+		a.put("/Bean", "(f1=a)", "text/openapi")
+			.run()
+			.assertCode().is(415);
+		a.put("/Bean?body=(f1=a)", null)
+			.run()
+			.assertBody().is("{f1:'a'}");
+		a.put("/Bean?body=()", null)
+			.run()
+			.assertBody().is("{}");
+		a.put("/Bean?body=null", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Bean?body=", null)
+			.run()
+			.assertBody().is("null");
+		a.put("/Bean?body=bad&noTrace=true", null)
+			.run()
+			.assertCode().is(400);
+
+		// Content-Type should always be ignored.
+		a.put("/InputStream", "'a'", "application/json")
+			.run()
+			.assertBody().is("'\\'a\\''");
+		a.put("/InputStream", "'a'")
+			.run()
+			.assertBody().is("'\\'a\\''");
+		a.put("/InputStream?body=a", null)
+			.run()
+			.assertBody().is("'a'");
+		a.put("/InputStream?body=null", null)
+			.run()
+			.assertBody().is("'null'");
+		a.put("/InputStream?body=", null)
+			.run()
+			.assertBody().is("''");
+
+		// Content-Type should always be ignored.
+		a.put("/Reader", "'a'", "application/json")
+			.run()
+			.assertBody().is("'\\'a\\''");
+		a.put("/Reader", "'a'")
+			.run()
+			.assertBody().is("'\\'a\\''");
+		a.put("/Reader?body=a", null)
+			.run()
+			.assertBody().is("'a'");
+		a.put("/Reader?body=null", null)
+			.run()
+			.assertBody().is("'null'");
+		a.put("/Reader?body=", null)
+			.run()
+			.assertBody().is("''");
+
+		// It's not currently possible to pass in a &body parameter for InputStream/Reader transforms.
+
+		// Input stream transform requests must not specify Content-Type or else gets resolved as POJO.
+		a.put("/InputStreamTransform?noTrace=true", "'a'", "application/json")
+			.run()
+			.assertBody().contains("Bad Request");
+		a.put("/InputStreamTransform", "'a'")
+			.run()
+			.assertBody().is("'\\'a\\''");
+
+		// Reader transform requests must not specify Content-Type or else gets resolved as POJO.
+		a.put("/ReaderTransform?noTrace=true", "'a'", "application/json")
+			.run()
+			.assertBody().contains("Bad Request");
+		a.put("/ReaderTransform", "'a'")
+			.run()
+			.assertBody().is("'\\'a\\''");
+
+		// When Content-Type specified and matched, treated as a parsed POJO.
+		a.put("/StringTransform", "'a'", "application/json")
+			.run()
+			.assertBody().is("'a'");
+		// When Content-Type not matched, treated as plain text.
+		a.put("/StringTransform", "'a'")
+			.run()
+			.assertBody().is("'\\'a\\''");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @Body on POJO
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class, defaultAccept="application/json")
+	public static class B {
+		@RestMethod(name=PUT, path="/StringTransform")
+		public B1 a(B1 b) {
+			return b;
+		}
+		@Body
+		public static class B1 {
+			private String val;
+			public B1(String val) { this.val = val; }
+			@Override public String toString() { return val; }
+		}
+		@RestMethod(name=PUT, path="/Bean")
+		public B2 b(B2 b) {
+			return b;
+		}
+		@Body
+		public static class B2 {
+			public String f1;
+		}
+		@RestMethod(name=PUT, path="/BeanList")
+		public B3 c(B3 b) {
+			return b;
+		}
+		@SuppressWarnings("serial")
+		@Body
+		public static class B3 extends LinkedList<B2> {}
+		@RestMethod(name=PUT, path="/InputStreamTransform")
+		public B4 d(B4 b) throws Exception {
+			return b;
+		}
+		@Body
+		public static class B4 {
+			String s;
+			public B4(InputStream in) throws Exception { this.s = IOUtils.read(in); }
+			@Override public String toString() { return s; }
+		}
+		@RestMethod(name=PUT, path="/ReaderTransform")
+		public B5 e(B5 b) throws Exception {
+			return b;
+		}
+		@Body
+		public static class B5 {
+			private String s;
+			public B5(Reader in) throws Exception { this.s = IOUtils.read(in); }
+			@Override public String toString() { return s; }
+		}
+	}
+
+	@Test
+	public void b01_onPojos() throws Exception {
+		RestClient b = MockRestClient.buildLax(B.class);
+		b.put("/StringTransform", "'foo'", "application/json")
+			.run()
+			.assertBody().is("'foo'");
+		// When Content-Type not matched, treated as plain text.
+		b.put("/StringTransform", "'foo'")
+			.run()
+			.assertBody().is("'\\'foo\\''");
+		b.put("/Bean", "{f1:'a'}", "application/json")
+			.run()
+			.assertBody().is("{f1:'a'}");
+		b.put("/Bean", "(f1=a)", "text/openapi")
+			.run()
+			.assertCode().is(415);
+		b.put("/BeanList", "[{f1:'a'}]", "application/json")
+			.run()
+			.assertBody().is("[{f1:'a'}]");
+		b.put("/BeanList", "(f1=a)", "text/openapi")
+			.run()
+			.assertCode().is(415);
+		b.put("/InputStreamTransform", "a")
+			.run()
+			.assertBody().is("'a'");
+		// When Content-Type matched, treated as parsed POJO.
+		b.put("/InputStreamTransform?noTrace=true", "a", "application/json")
+			.run()
+			.assertBody().contains("Bad Request");
+		b.put("/ReaderTransform", "a")
+			.run()
+			.assertBody().is("'a'");
+		// When Content-Type matched, treated as parsed POJO.
+		b.put("/ReaderTransform?noTrace=true", "a", "application/json")
+			.run()
+			.assertBody().contains("Bad Request");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// No serializers or parsers needed when using only streams and readers.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class D {
+		@RestMethod(name=PUT, path="/String")
+		public Reader a(@Body Reader b) throws Exception {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/InputStream")
+		public InputStream b(@Body InputStream b) throws Exception {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/Reader")
+		public Reader c(@Body Reader b) throws Exception {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/StringTransform")
+		public Reader d(@Body D1 b) throws Exception {
+			return new StringReader(b.toString());
+		}
+		public static class D1 {
+			private String s;
+			public D1(String in) throws Exception { this.s = in; }
+			@Override public String toString() { return s; }
+		}
+		@RestMethod(name=PUT, path="/InputStreamTransform")
+		public Reader e(@Body D2 b) throws Exception {
+			return new StringReader(b.toString());
+		}
+		public static class D2 {
+			String s;
+			public D2(InputStream in) throws Exception { this.s = IOUtils.read(in); }
+			@Override public String toString() { return s; }
+		}
+		@RestMethod(name=PUT, path="/ReaderTransform")
+		public Reader f(@Body D3 b) throws Exception {
+			return new StringReader(b.toString());
+		}
+		public static class D3 {
+			private String s;
+			public D3(Reader in) throws Exception{ this.s = IOUtils.read(in); }
+			@Override public String toString() { return s; }
+		}
+		@RestMethod(name=PUT, path="/StringTransformBodyOnPojo")
+		public Reader g(D4 b) throws Exception {
+			return new StringReader(b.toString());
+		}
+		@Body
+		public static class D4 {
+			private String s;
+			public D4(String in) throws Exception { this.s = in; }
+			@Override public String toString() { return s; }
+		}
+		@RestMethod(name=PUT, path="/InputStreamTransformBodyOnPojo")
+		public Reader h(D5 b) throws Exception {
+			return new StringReader(b.toString());
+		}
+		@Body
+		public static class D5 {
+			String s;
+			public D5(InputStream in) throws Exception { this.s = IOUtils.read(in); }
+			@Override public String toString() { return s; }
+		}
+
+		@RestMethod(name=PUT, path="/ReaderTransformBodyOnPojo")
+		public Reader i(D6 b) throws Exception {
+			return new StringReader(b.toString());
+		}
+		@Body
+		public static class D6 {
+			private String s;
+			public D6(Reader in) throws Exception{ this.s = IOUtils.read(in); }
+			@Override public String toString() { return s; }
+		}
+	}
+
+	@Test
+	public void d01_noMediaTypesOnStreams() throws Exception {
+		RestClient d = MockRestClient.buildLax(D.class);
+		d.put("/String", "a")
+			.run()
+			.assertBody().is("a");
+		d.put("/String", "a", "application/json")
+			.run()
+			.assertBody().is("a");
+		d.put("/InputStream", "a")
+			.run()
+			.assertBody().is("a");
+		d.put("/InputStream", "a", "application/json")
+			.run()
+			.assertBody().is("a");
+		d.put("/Reader", "a")
+			.run()
+			.assertBody().is("a");
+		d.put("/Reader", "a", "application/json")
+			.run()
+			.assertBody().is("a");
+		d.put("/StringTransform", "a")
+			.run()
+			.assertBody().is("a");
+		d.put("/StringTransform?noTrace=true", "a", "application/json")
+			.run()
+			.assertCode().is(415);
+		d.put("/InputStreamTransform", "a")
+			.run()
+			.assertBody().is("a");
+		d.put("/InputStreamTransform", "a", "application/json")
+			.run()
+			.assertBody().is("a");
+		d.put("/ReaderTransform", "a")
+			.run()
+			.assertBody().is("a");
+		d.put("/ReaderTransform", "a", "application/json")
+			.run()
+			.assertBody().is("a");
+		d.put("/StringTransformBodyOnPojo", "a")
+			.run()
+			.assertBody().is("a");
+		d.put("/StringTransformBodyOnPojo?noTrace=true", "a", "application/json")
+			.run()
+			.assertCode().is(415);
+		d.put("/InputStreamTransformBodyOnPojo", "a")
+			.run()
+			.assertBody().is("a");
+		d.put("/InputStreamTransformBodyOnPojo", "a", "application/json")
+			.run()
+			.assertBody().is("a");
+		d.put("/ReaderTransformBodyOnPojo", "a")
+			.run()
+			.assertBody().is("a");
+		d.put("/ReaderTransformBodyOnPojo", "a", "application/json")
+			.run()
+			.assertBody().is("a");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Complex POJOs
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class, defaultAccept="application/json")
+	public static class E {
+		@RestMethod(name=PUT, path="/B")
+		public XBeans.XB a(@Body XBeans.XB b) {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/C")
+		public XBeans.XC b(@Body XBeans.XC c) {
+			return c;
+		}
+	}
+
+	@Test
+	public void e01_complexPojos() throws Exception {
+		RestClient e = MockRestClient.build(E.class);
+		String expected;
+
+		expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
+		e.put("/B", SimpleJsonSerializer.DEFAULT.toString(XBeans.XB.INSTANCE), "application/json")
+			.run()
+			.assertBody().is(expected);
+
+		expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
+		e.put("/B?body=" + UonSerializer.DEFAULT.serialize(XBeans.XB.INSTANCE), "a")
+			.run()
+			.assertBody().is(expected);
+
+		expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
+		e.put("/C", SimpleJsonSerializer.DEFAULT.toString(XBeans.XB.INSTANCE), "application/json")
+			.run()
+			.assertBody().is(expected);
+
+		expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
+		e.put("/C?body=" + UonSerializer.DEFAULT.serialize(XBeans.XB.INSTANCE), "a")
+			.run()
+			.assertBody().is(expected);
+	}
+
+	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class, defaultAccept="application/json")
+	@BeanConfig(applyBean={@Bean(on="A,B,C",sort=true)})
+	@UrlEncodingConfig(applyUrlEncoding={@UrlEncoding(on="C",expandedParams=true)})
+	public static class E2 {
+		@RestMethod(name=PUT, path="/B")
+		public XBeans.XE a(@Body XBeans.XE b) {
+			return b;
+		}
+		@RestMethod(name=PUT, path="/C")
+		public XBeans.XF b(@Body XBeans.XF c) {
+			return c;
+		}
+	}
+
+	@Test
+	public void e02_complexPojos() throws Exception {
+		RestClient e2 = MockRestClient.build(E2.class);
+		String expected;
+
+		expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
+		e2.put("/B", SimpleJsonSerializer.DEFAULT.builder().applyAnnotations(XBeans.Annotations.class).build().toString(XBeans.XE.INSTANCE), "application/json")
+			.run()
+			.assertBody().is(expected);
+
+		expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
+		e2.put("/B?body=" + UonSerializer.DEFAULT.builder().applyAnnotations(XBeans.Annotations.class).build().serialize(XBeans.XE.INSTANCE), "a")
+			.run()
+			.assertBody().is(expected);
+
+		expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
+		e2.put("/C", SimpleJsonSerializer.DEFAULT.builder().applyAnnotations(XBeans.Annotations.class).build().toString(XBeans.XE.INSTANCE), "application/json")
+			.run()
+			.assertBody().is(expected);
+
+		expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
+		e2.put("/C?body=" + UonSerializer.DEFAULT.builder().applyAnnotations(XBeans.Annotations.class).build().serialize(XBeans.XE.INSTANCE), "a")
+			.run()
+			.assertBody().is(expected);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Form POSTS with @Body parameter
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=JsonSerializer.class,parsers=JsonParser.class)
+	public static class F {
+		@RestMethod(name=POST, path="/*")
+		public Reader a(
+				@Body F1 bean,
+				@HasQuery("p1") boolean hqp1, @HasQuery("p2") boolean hqp2,
+				@Query("p1") String qp1, @Query("p2") int qp2) throws Exception {
+			return new StringReader("bean=["+SimpleJsonSerializer.DEFAULT.toString(bean)+"],qp1=["+qp1+"],qp2=["+qp2+"],hqp1=["+hqp1+"],hqp2=["+hqp2+"]");
+		}
+		public static class F1 {
+			public String p1;
+			public int p2;
+		}
+	}
+
+	@Test
+	public void f01_formPostAsContent() throws Exception {
+		RestClient f = MockRestClient.build(F.class);
+		f.post("/", "{p1:'p1',p2:2}", "application/json")
+			.run()
+			.assertBody().is("bean=[{p1:'p1',p2:2}],qp1=[null],qp2=[0],hqp1=[false],hqp2=[false]");
+		f.post("/", "{}", "application/json")
+			.run()
+			.assertBody().is("bean=[{p2:0}],qp1=[null],qp2=[0],hqp1=[false],hqp2=[false]");
+		f.post("?p1=p3&p2=4", "{p1:'p1',p2:2}", "application/json")
+			.run()
+			.assertBody().is("bean=[{p1:'p1',p2:2}],qp1=[p3],qp2=[4],hqp1=[true],hqp2=[true]");
+		f.post("?p1=p3&p2=4", "{}", "application/json")
+			.run()
+			.assertBody().is("bean=[{p2:0}],qp1=[p3],qp2=[4],hqp1=[true],hqp2=[true]");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Test multi-part parameter keys on bean properties of type array/Collection (i.e. &key=val1,&key=val2)
+	// using @UrlEncoding(expandedParams=true) annotation on bean.
+	// A simple round-trip test to verify that both serializing and parsing works.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=UrlEncodingSerializer.class,parsers=UrlEncodingParser.class)
+	public static class G {
+		@RestMethod(name=POST,path="/")
+		public XBeans.XC a(@Body XBeans.XC content) throws Exception {
+			return content;
+		}
+	}
+
+	@Test
+	public void g01_multiPartParameterKeysOnCollections() throws Exception {
+		RestClient g = MockRestClient.build(G.class);
+		String in = ""
+			+ "f01=a&f01=b"
+			+ "&f02=c&f02=d"
+			+ "&f03=1&f03=2"
+			+ "&f04=3&f04=4"
+			+ "&f05=@(e,f)&f05=@(g,h)"
+			+ "&f06=@(i,j)&f06=@(k,l)"
+			+ "&f07=(a=a,b=1,c=true)&f07=(a=b,b=2,c=false)"
+			+ "&f08=(a=a,b=1,c=true)&f08=(a=b,b=2,c=false)"
+			+ "&f09=@((a=a,b=1,c=true))&f09=@((a=b,b=2,c=false))"
+			+ "&f10=@((a=a,b=1,c=true))&f10=@((a=b,b=2,c=false))"
+			+ "&f11=a&f11=b"
+			+ "&f12=c&f12=d"
+			+ "&f13=1&f13=2"
+			+ "&f14=3&f14=4"
+			+ "&f15=@(e,f)&f15=@(g,h)"
+			+ "&f16=@(i,j)&f16=@(k,l)"
+			+ "&f17=(a=a,b=1,c=true)&f17=(a=b,b=2,c=false)"
+			+ "&f18=(a=a,b=1,c=true)&f18=(a=b,b=2,c=false)"
+			+ "&f19=@((a=a,b=1,c=true))&f19=@((a=b,b=2,c=false))"
+			+ "&f20=@((a=a,b=1,c=true))&f20=@((a=b,b=2,c=false))";
+		g.post("/", in, "application/x-www-form-urlencoded")
+			.run()
+			.assertBody().is(in);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Test multi-part parameter keys on bean properties of type array/Collection (i.e. &key=val1,&key=val2)
+	// using URLENC_expandedParams property.
+	// A simple round-trip test to verify that both serializing and parsing works.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=UrlEncodingSerializer.class,parsers=UrlEncodingParser.class)
+	public static class H {
+		@RestMethod(name=POST,path="/",
+			properties={
+				@Property(name=UrlEncodingSerializer.URLENC_expandedParams, value="true"),
+				@Property(name=UrlEncodingParser.URLENC_expandedParams, value="true")
+			}
+		)
+		public XBeans.XB a(@Body XBeans.XB content) throws Exception {
+			return content;
+		}
+	}
+
+	@Test
+	public void h01_multiPartParameterKeysOnCollections_usingExpandedParams() throws Exception {
+		RestClient h = MockRestClient.build(H.class);
+		String in = ""
+			+ "f01=a&f01=b"
+			+ "&f02=c&f02=d"
+			+ "&f03=1&f03=2"
+			+ "&f04=3&f04=4"
+			+ "&f05=@(e,f)&f05=@(g,h)"
+			+ "&f06=@(i,j)&f06=@(k,l)"
+			+ "&f07=(a=a,b=1,c=true)&f07=(a=b,b=2,c=false)"
+			+ "&f08=(a=a,b=1,c=true)&f08=(a=b,b=2,c=false)"
+			+ "&f09=@((a=a,b=1,c=true))&f09=@((a=b,b=2,c=false))"
+			+ "&f10=@((a=a,b=1,c=true))&f10=@((a=b,b=2,c=false))"
+			+ "&f11=a&f11=b"
+			+ "&f12=c&f12=d"
+			+ "&f13=1&f13=2"
+			+ "&f14=3&f14=4"
+			+ "&f15=@(e,f)&f15=@(g,h)"
+			+ "&f16=@(i,j)&f16=@(k,l)"
+			+ "&f17=(a=a,b=1,c=true)&f17=(a=b,b=2,c=false)"
+			+ "&f18=(a=a,b=1,c=true)&f18=(a=b,b=2,c=false)"
+			+ "&f19=@((a=a,b=1,c=true))&f19=@((a=b,b=2,c=false))"
+			+ "&f20=@((a=a,b=1,c=true))&f20=@((a=b,b=2,c=false))";
+		h.post("/", in, "application/x-www-form-urlencoded")
+			.run()
+			.assertBody().is(in);
+	}
+
+	@Rest(serializers=UrlEncodingSerializer.class,parsers=UrlEncodingParser.class)
+	@BeanConfig(applyBean={@Bean(on="A,B,C",sort=true)})
+	@UrlEncodingConfig(applyUrlEncoding={@UrlEncoding(on="C",expandedParams=true)})
+	public static class H2 {
+		@RestMethod(name=POST,path="/",
+			properties={
+				@Property(name=UrlEncodingSerializer.URLENC_expandedParams, value="true"),
+				@Property(name=UrlEncodingParser.URLENC_expandedParams, value="true")
+			}
+		)
+		public XBeans.XE a(@Body XBeans.XE content) throws Exception {
+			return content;
+		}
+	}
+
+	@Test
+	public void h02_multiPartParameterKeysOnCollections_usingExpandedParams() throws Exception {
+		RestClient h2 = MockRestClient.build(H2.class);
+		String in = ""
+			+ "f01=a&f01=b"
+			+ "&f02=c&f02=d"
+			+ "&f03=1&f03=2"
+			+ "&f04=3&f04=4"
+			+ "&f05=@(e,f)&f05=@(g,h)"
+			+ "&f06=@(i,j)&f06=@(k,l)"
+			+ "&f07=(a=a,b=1,c=true)&f07=(a=b,b=2,c=false)"
+			+ "&f08=(a=a,b=1,c=true)&f08=(a=b,b=2,c=false)"
+			+ "&f09=@((a=a,b=1,c=true))&f09=@((a=b,b=2,c=false))"
+			+ "&f10=@((a=a,b=1,c=true))&f10=@((a=b,b=2,c=false))"
+			+ "&f11=a&f11=b"
+			+ "&f12=c&f12=d"
+			+ "&f13=1&f13=2"
+			+ "&f14=3&f14=4"
+			+ "&f15=@(e,f)&f15=@(g,h)"
+			+ "&f16=@(i,j)&f16=@(k,l)"
+			+ "&f17=(a=a,b=1,c=true)&f17=(a=b,b=2,c=false)"
+			+ "&f18=(a=a,b=1,c=true)&f18=(a=b,b=2,c=false)"
+			+ "&f19=@((a=a,b=1,c=true))&f19=@((a=b,b=2,c=false))"
+			+ "&f20=@((a=a,b=1,c=true))&f20=@((a=b,b=2,c=false))";
+		h2.post("/", in, "application/x-www-form-urlencoded")
+			.run()
+			.assertBody().is(in);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Test behavior of @Body(required=true).
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=JsonSerializer.class,parsers=JsonParser.class)
+	public static class I {
+		@RestMethod(name=POST)
+		public XBeans.XB a(@Body(r=true) XBeans.XB content) throws Exception {
+			return content;
+		}
+		@RestMethod(name=POST)
+		@BeanConfig(applyBean={@Bean(on="A,B,C",sort=true)})
+		@UrlEncodingConfig(applyUrlEncoding={@UrlEncoding(on="C",expandedParams=true)})
+		public XBeans.XE b(@Body(r=true) XBeans.XE content) throws Exception {
+			return content;
+		}
+	}
+
+	@Test
+	public void i01_required() throws Exception {
+		RestClient i = MockRestClient.buildLax(I.class);
+
+		i.post("/a", "", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains("Required value not provided.");
+		i.post("/a", "{}", "application/json")
+			.run()
+			.assertCode().is(200);
+
+		i.post("/b", "", "application/json")
+			.run()
+			.assertCode().is(400)
+			.assertBody().contains("Required value not provided.");
+		i.post("/b", "{}", "application/json")
+			.run()
+			.assertCode().is(200);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Optional body parameter.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class,parsers=JsonParser.class)
+	public static class J {
+		@RestMethod(name=POST)
+		public Object a(@Body Optional<Integer> body) throws Exception {
+			assertNotNull(body);
+			return body;
+		}
+		@RestMethod(name=POST)
+		public Object b(@Body Optional<ABean> body) throws Exception {
+			assertNotNull(body);
+			return body;
+		}
+		@RestMethod(name=POST)
+		public Object c(@Body Optional<List<ABean>> body) throws Exception {
+			assertNotNull(body);
+			return body;
+		}
+		@RestMethod(name=POST)
+		public Object d(@Body List<Optional<ABean>> body) throws Exception {
+			return body;
+		}
+	}
+
+	@Test
+	public void j01_optionalParams() throws Exception {
+		RestClient j = MockRestClient.buildJson(J.class);
+		j.post("/a", 123)
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("123");
+		j.post("/a", null)
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+
+		j.post("/b", ABean.get())
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("{a:1,b:'foo'}");
+		j.post("/b", null)
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+
+		String body1 = SimpleJson.DEFAULT.toString(AList.of(ABean.get()));
+		j.post("/c", body1, "application/json")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+		j.post("/c", null)
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+
+		String body2 = SimpleJson.DEFAULT.toString(AList.of(Optional.of(ABean.get())));
+		j.post("/d", body2, "application/json")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+		j.post("/d", null)
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java
new file mode 100644
index 0000000..bdd17de
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/FormData_Test.java
@@ -0,0 +1,214 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.apache.juneau.testutils.pojos.*;
+import org.apache.juneau.urlencoding.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class FormData_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Simple tests
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(parsers=UrlEncodingParser.class)
+	public static class A {
+		@RestMethod(method=POST)
+		public String a(RestRequest req, @FormData(name="p1",allowEmptyValue=true) String p1, @FormData(name="p2",allowEmptyValue=true) int p2) throws Exception {
+			RequestFormData f = req.getFormData();
+			return "p1=["+p1+","+req.getFormData().getString("p1")+","+f.get("p1", String.class)+"],p2=["+p2+","+req.getFormData().getString("p2")+","+f.get("p2", int.class)+"]";
+		}
+	}
+
+	@Test
+	public void a01_basic() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.post("/a", "p1=p1&p2=2").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[p1,p1,p1],p2=[2,2,2]");
+		a.post("/a", "p1&p2").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.post("/a", "p1=&p2=").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[,,],p2=[0,,0]");
+		a.post("/a", "").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.post("/a", "p1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.post("/a", "p1=").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[,,],p2=[0,null,0]");
+		a.post("/a", "p2").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.post("/a", "p2=").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,,0]");
+		a.post("/a", "p1=foo&p2").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[foo,foo,foo],p2=[0,null,0]");
+		a.post("/a", "p1&p2=1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[1,1,1]");
+		String x = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
+		a.post("/a", "p1="+x+"&p2=1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[a/b%c=d e,a/b%c=d e,a/b%c=d e],p2=[1,1,1]");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// UON parameters
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class B {
+		@RestMethod(name=POST)
+		public String a(RestRequest req, @FormData(value="p1") String p1) throws Exception {
+			RequestFormData f = req.getFormData();
+			return "p1=["+p1+","+req.getFormData().getString("p1")+","+f.get("p1", String.class)+"]";
+		}
+		@RestMethod(name=POST)
+		public String b(RestRequest req, @FormData(value="p1",format="uon") String p1) throws Exception {
+			RequestFormData f = req.getFormData();
+			return "p1=["+p1+","+req.getFormData().getString("p1")+","+f.get("p1", String.class)+"]";
+		}
+	}
+
+	@Test
+	public void b01_uonParameters() throws Exception {
+		RestClient b = MockRestClient.build(B.class);
+
+		b.post("/a", "p1=p1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[p1,p1,p1]");
+		b.post("/a", "p1='p1'").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=['p1','p1','p1']");
+
+		b.post("/b", "p1=p1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[p1,p1,p1]");
+		b.post("/b", "p1='p1'").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[p1,'p1','p1']");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Default values.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class C {
+		@RestMethod(name=POST, defaultFormData={"f1:1","f2=2"," f3 : 3 "})
+		public OMap a(RequestFormData formData) {
+			return OMap.of()
+				.a("f1", formData.getString("f1"))
+				.a("f2", formData.getString("f2"))
+				.a("f3", formData.getString("f3"));
+		}
+		@RestMethod(name=POST)
+		public OMap b(@FormData("f1") String f1, @FormData("f2") String f2, @FormData("f3") String f3) {
+			return OMap.of()
+				.a("f1", f1)
+				.a("f2", f2)
+				.a("f3", f3);
+		}
+		@RestMethod(name=POST)
+		public OMap c(@FormData(value="f1",_default="1") String f1, @FormData(value="f2",_default="2") String f2, @FormData(value="f3",_default="3") String f3) {
+			return OMap.of()
+				.a("f1", f1)
+				.a("f2", f2)
+				.a("f3", f3);
+		}
+		@RestMethod(name=POST, defaultFormData={"f1:1","f2=2"," f3 : 3 "})
+		public OMap d(@FormData(value="f1",_default="4") String f1, @FormData(value="f2",_default="5") String f2, @FormData(value="f3",_default="6") String f3) {
+			return OMap.of()
+				.a("f1", f1)
+				.a("f2", f2)
+				.a("f3", f3);
+		}
+	}
+
+	@Test
+	public void c01_defaultFormData() throws Exception {
+		RestClient c = MockRestClient.build(C.class);
+
+		c.post("/a", null).contentType("application/x-www-form-urlencoded").run().assertBody().is("{f1:'1',f2:'2',f3:'3'}");
+		c.post("/a", null).contentType("application/x-www-form-urlencoded").formData("f1",4).formData("f2",5).formData("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
+
+		c.post("/b", null).contentType("application/x-www-form-urlencoded").run().assertBody().is("{f1:null,f2:null,f3:null}");
+		c.post("/b", null).contentType("application/x-www-form-urlencoded").formData("f1",4).formData("f2",5).formData("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
+
+		c.post("/c", null).contentType("application/x-www-form-urlencoded").run().assertBody().is("{f1:'1',f2:'2',f3:'3'}");
+		c.post("/c", null).contentType("application/x-www-form-urlencoded").formData("f1",4).formData("f2",5).formData("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
+
+		c.post("/d", null).contentType("application/x-www-form-urlencoded").run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
+		c.post("/d", null).contentType("application/x-www-form-urlencoded").formData("f1",7).formData("f2",8).formData("f3",9).run().assertBody().is("{f1:'7',f2:'8',f3:'9'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Optional form data parameter.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class)
+	public static class D {
+		@RestMethod(name=POST)
+		public Object a(@FormData("f1") Optional<Integer> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod(name=POST)
+		public Object b(@FormData("f1") Optional<ABean> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod(name=POST)
+		public Object c(@FormData("f1") Optional<List<ABean>> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod(name=POST)
+		public Object d(@FormData("f1") List<Optional<ABean>> f1) throws Exception {
+			return f1;
+		}
+	}
+
+	@Test
+	public void d01_optionalParams() throws Exception {
+		RestClient d = MockRestClient.create(D.class).accept("application/json").contentType("application/x-www-form-urlencoded").build();
+
+		d.post("/a", "f1=123")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("123");
+		d.post("/a", "null")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+
+		d.post("/b", "f1=a=1,b=foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("{a:1,b:'foo'}");
+		d.post("/b", "null")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+
+		d.post("/c", "f1=@((a=1,b=foo))")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+		d.post("/c", "null")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+
+		d.post("/d", "f1=@((a=1,b=foo))")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+		d.post("/d", "null")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HasFormData_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HasFormData_Test.java
new file mode 100644
index 0000000..46753ac
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HasFormData_Test.java
@@ -0,0 +1,57 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.juneau.http.annotation.HasFormData;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class HasFormData_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Simple tests
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+		@RestMethod(method=POST)
+		public String a(RestRequest req, @HasFormData("p1") boolean p1, @HasFormData("p2") Boolean p2) throws Exception {
+			RequestFormData f = req.getFormData();
+			return "p1=["+p1+","+f.containsKey("p1")+"],p2=["+p2+","+f.containsKey("p2")+"]";
+		}
+	}
+
+	@Test
+	public void a01_basic() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.post("/a", "p1=p1&p2=2").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.post("/a", "p1&p2").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.post("/a", "p1=&p2=").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.post("/a", null).run().assertBody().is("p1=[false,false],p2=[false,false]");
+		a.post("/a", "p1").run().assertBody().is("p1=[true,true],p2=[false,false]");
+		a.post("/a", "p1=").run().assertBody().is("p1=[true,true],p2=[false,false]");
+		a.post("/a", "p2").run().assertBody().is("p1=[false,false],p2=[true,true]");
+		a.post("/a", "p2=").run().assertBody().is("p1=[false,false],p2=[true,true]");
+		a.post("/a", "p1=foo&p2").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.post("/a", "p1&p2=1").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		String x = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
+		a.post("/a", "p1="+x+"&p2=1").run().assertBody().is("p1=[true,true],p2=[true,true]");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HasQuery_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HasQuery_Test.java
new file mode 100644
index 0000000..b7c20e0
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HasQuery_Test.java
@@ -0,0 +1,76 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.juneau.http.annotation.HasQuery;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class HasQuery_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Simple tests
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+		@RestMethod
+		public String a(RestRequest req, @HasQuery("p1") boolean p1, @HasQuery("p2") Boolean p2) throws Exception {
+			RequestQuery q = req.getQuery();
+			return "p1=["+p1+","+q.containsKey("p1")+"],p2=["+p2+","+q.containsKey("p2")+"]";
+		}
+		@RestMethod(name=POST)
+		public String b(RestRequest req, @HasQuery("p1") boolean p1, @HasQuery("p2") Boolean p2) throws Exception {
+			RequestQuery q = req.getQuery();
+			return "p1=["+p1+","+q.containsKey("p1")+"],p2=["+p2+","+q.containsKey("p2")+"]";
+		}
+	}
+
+	@Test
+	public void a01_basic() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+
+		a.get("/a?p1=p1&p2=2").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.get("/a?p1&p2").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.get("/a?p1=&p2=").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.get("/a").run().assertBody().is("p1=[false,false],p2=[false,false]");
+		a.get("/a?p1").run().assertBody().is("p1=[true,true],p2=[false,false]");
+		a.get("/a?p1=").run().assertBody().is("p1=[true,true],p2=[false,false]");
+		a.get("/a?p2").run().assertBody().is("p1=[false,false],p2=[true,true]");
+		a.get("/a?p2=").run().assertBody().is("p1=[false,false],p2=[true,true]");
+		a.get("/a?p1=foo&p2").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.get("/a?p1&p2=1").run().assertBody().is("p1=[true,true],p2=[true,true]");
+		String x1 = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
+		a.get("/a?p1="+x1+"&p2=1").run().assertBody().is("p1=[true,true],p2=[true,true]");
+
+		a.post("/b?p1=p1&p2=2", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.post("/b?p1&p2", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.post("/b?p1=&p2=", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.post("/b", null).run().assertBody().is("p1=[false,false],p2=[false,false]");
+		a.post("/b?p1", null).run().assertBody().is("p1=[true,true],p2=[false,false]");
+		a.post("/b?p1=", null).run().assertBody().is("p1=[true,true],p2=[false,false]");
+		a.post("/b?p2", null).run().assertBody().is("p1=[false,false],p2=[true,true]");
+		a.post("/b?p2=", null).run().assertBody().is("p1=[false,false],p2=[true,true]");
+		a.post("/b?p1=foo&p2", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
+		a.post("/b?p1&p2=1", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
+		String x2 = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
+		a.post("/b?p1="+x2+"&p2=1", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Header_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Header_Test.java
new file mode 100644
index 0000000..e64edfd
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Header_Test.java
@@ -0,0 +1,212 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.apache.juneau.testutils.pojos.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Header_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Optional header parameter.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class)
+	public static class A {
+		@RestMethod
+		public Object a(@Header("f1") Optional<Integer> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod
+		public Object b(@Header("f1") Optional<ABean> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod
+		public Object c(@Header("f1") Optional<List<ABean>> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod
+		public Object d(@Header("f1") List<Optional<ABean>> f1) throws Exception {
+			return f1;
+		}
+	}
+
+	@Test
+	public void a01_optionalParams() throws Exception {
+		RestClient a = MockRestClient.buildJson(A.class);
+
+		a.get("/a").header("f1", 123)
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("123");
+		a.get("/a")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+
+		a.get("/b")
+			.header("f1", "a=1,b=foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("{a:1,b:'foo'}");
+		a.get("/b")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+
+		a.get("/c")
+			.header("f1", "@((a=1,b=foo))")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+		a.get("/c")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+
+		a.get("/d")
+			.header("f1", "@((a=1,b=foo))")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+		a.get("/d")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Default values - Annotated headers.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class B {
+		@RestMethod
+		public OMap a(@Header(name="H1") String h1, @Header("H2") String h2, @Header("H3") String h3) {
+			return OMap.of()
+				.a("h1", h1)
+				.a("h2", h2)
+				.a("h3", h3);
+		}
+	}
+
+	@Test
+	public void b01_annotatedHeaders() throws Exception {
+		RestClient b = MockRestClient.build(B.class);
+		b.get("/a").run().assertBody().is("{h1:null,h2:null,h3:null}");
+		b.get("/a").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+		b.get("/a").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Default values - Annotated headers, case-insensitive matching.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class C {
+		@RestMethod
+		public OMap a(@Header("h1") String h1, @Header("h2") String h2, @Header("h3") String h3) {
+			return OMap.of()
+				.a("h1", h1)
+				.a("h2", h2)
+				.a("h3", h3);
+		}
+	}
+
+	@Test
+	public void c01_annotatedHeadersCaseInsensitive() throws Exception {
+		RestClient c = MockRestClient.build(C.class);
+		c.get("/a").run().assertBody().is("{h1:null,h2:null,h3:null}");
+		c.get("/a").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+		c.get("/a").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Default values - Annotated headers with default values.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class D1 {
+		@RestMethod
+		public OMap a(@Header(name="h1",_default="1") String h1, @Header(name="h2",_default="2") String h2, @Header(name="h3",_default="3") String h3) {
+			return OMap.of()
+				.a("h1", h1)
+				.a("h2", h2)
+				.a("h3", h3);
+		}
+	}
+
+	@Test
+	public void d01_annotatedHeadersDefault() throws Exception {
+		RestClient d1 = MockRestClient.build(D1.class);
+		d1.get("/a").run().assertBody().is("{h1:'1',h2:'2',h3:'3'}");
+		d1.get("/a").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+		d1.get("/a").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+	}
+
+	@Rest
+	public static class D2 {
+		@RestMethod
+		public OMap a(@Header(value="h1",_default="1") String h1, @Header(value="h2",_default="2") String h2, @Header(value="h3",_default="3") String h3) {
+			return OMap.of()
+				.a("h1", h1)
+				.a("h2", h2)
+				.a("h3", h3);
+		}
+	}
+
+	@Test
+	public void d02_annotatedHeadersDefault() throws Exception {
+		RestClient d2 = MockRestClient.build(D2.class);
+		d2.get("/a").run().assertBody().is("{h1:'1',h2:'2',h3:'3'}");
+		d2.get("/a").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+		d2.get("/a").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Default values - Annotated headers with default values and default request headers.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class E {
+		@RestMethod(reqHeaders={"H1:1","H2=2"," H3 : 3 "})
+		public OMap a(@Header(value="h1",_default="4") String h1, @Header(value="h2",_default="5") String h2, @Header(value="h3",_default="6") String h3) {
+			return OMap.of()
+				.a("h1", h1)
+				.a("h2", h2)
+				.a("h3", h3);
+		}
+	}
+
+	@Test
+	public void e01_annotatedAndDefaultHeaders() throws Exception {
+		RestClient e = MockRestClient.build(E.class);
+		e.get("/a").run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+		e.get("/a").header("H1",7).header("H2",8).header("H3",9).run().assertBody().is("{h1:'7',h2:'8',h3:'9'}");
+		e.get("/a").header("h1",7).header("h2",8).header("h3",9).run().assertBody().is("{h1:'7',h2:'8',h3:'9'}");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocAsideTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocAsideTest.java
deleted file mode 100644
index 7903fbc..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocAsideTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial","deprecation"})
-public class HtmlDocAsideTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(aside={"a01a","a01b","INHERIT"}))
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02", htmldoc=@HtmlDoc(aside={"a02a","a02b"}))
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03", htmldoc=@HtmlDoc(aside={"INHERIT","a03a","a03b"}))
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04", htmldoc=@HtmlDoc(aside={"a04a","INHERIT","a04b"}))
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05", htmldoc=@HtmlDoc(aside={"a05a","a05b","INHERIT"}))
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<aside>a01a a01b</aside>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<aside>a02a a02b</aside>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<aside>a01a a01b a03a a03b</aside>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<aside>a04a a01a a01b a04b</aside>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<aside>a05a a05b a01a a01b</aside>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(aside={"INHERIT","b01a","b01b"}))
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02", htmldoc=@HtmlDoc(aside={"b02a","b02b"}))
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03", htmldoc=@HtmlDoc(aside={"INHERIT","b03a","b03b"}))
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04", htmldoc=@HtmlDoc(aside={"b04a","INHERIT","b04b"}))
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05", htmldoc=@HtmlDoc(aside={"b05a","b05b","INHERIT"}))
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<aside>a01a a01b b01a b01b</aside>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<aside>b02a b02b</aside>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<aside>a01a a01b b01a b01b b03a b03b</aside>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<aside>b04a a01a a01b b01a b01b b04b</aside>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<aside>b05a b05b a01a a01b b01a b01b</aside>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigAsideTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigAsideTest.java
deleted file mode 100644
index 25a70fa..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigAsideTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial"})
-public class HtmlDocConfigAsideTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(aside={"a01a","a01b","INHERIT"})
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02")
-		@HtmlDocConfig(aside={"a02a","a02b"})
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03")
-		@HtmlDocConfig(aside={"INHERIT","a03a","a03b"})
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04")
-		@HtmlDocConfig(aside={"a04a","INHERIT","a04b"})
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05")
-		@HtmlDocConfig(aside={"a05a","a05b","INHERIT"})
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<aside>a01a a01b</aside>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<aside>a02a a02b</aside>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<aside>a01a a01b a03a a03b</aside>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<aside>a04a a01a a01b a04b</aside>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<aside>a05a a05b a01a a01b</aside>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(aside={"INHERIT","b01a","b01b"})
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02")
-		@HtmlDocConfig(aside={"b02a","b02b"})
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03")
-		@HtmlDocConfig(aside={"INHERIT","b03a","b03b"})
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04")
-		@HtmlDocConfig(aside={"b04a","INHERIT","b04b"})
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05")
-		@HtmlDocConfig(aside={"b05a","b05b","INHERIT"})
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<aside>a01a a01b b01a b01b</aside>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<aside>b02a b02b</aside>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<aside>a01a a01b b01a b01b b03a b03b</aside>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<aside>b04a a01a a01b b01a b01b b04b</aside>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<aside>b05a b05b a01a a01b b01a b01b</aside>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigFooterTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigFooterTest.java
deleted file mode 100644
index 2365478..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigFooterTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial"})
-public class HtmlDocConfigFooterTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(footer={"a01a","a01b"})
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02")
-		@HtmlDocConfig(footer={"a02a","a02b"})
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03")
-		@HtmlDocConfig(footer={"INHERIT","a03a","a03b"})
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04")
-		@HtmlDocConfig(footer={"a04a","INHERIT","a04b"})
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05")
-		@HtmlDocConfig(footer={"a05a","a05b","INHERIT"})
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<footer>a01a a01b</footer>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<footer>a02a a02b</footer>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<footer>a01a a01b a03a a03b</footer>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<footer>a04a a01a a01b a04b</footer>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<footer>a05a a05b a01a a01b</footer>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(footer={"b01a","INHERIT","b01b"})
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02")
-		@HtmlDocConfig(footer={"b02a","b02b"})
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03")
-		@HtmlDocConfig(footer={"INHERIT","b03a","b03b"})
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04")
-		@HtmlDocConfig(footer={"b04a","INHERIT","b04b"})
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05")
-		@HtmlDocConfig(footer={"b05a","b05b","INHERIT"})
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<footer>b01a a01a a01b b01b</footer>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<footer>b02a b02b</footer>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<footer>b01a a01a a01b b01b b03a b03b</footer>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<footer>b04a b01a a01a a01b b01b b04b</footer>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<footer>b05a b05b b01a a01a a01b b01b</footer>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigHeaderTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigHeaderTest.java
deleted file mode 100644
index 37dd887..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigHeaderTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial"})
-public class HtmlDocConfigHeaderTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(header={"a01a","a01b"})
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02")
-		@HtmlDocConfig(header={"a02a","a02b"})
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03")
-		@HtmlDocConfig(header={"INHERIT","a03a","a03b"})
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04")
-		@HtmlDocConfig(header={"a04a","INHERIT","a04b"})
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05")
-		@HtmlDocConfig(header={"a05a","a05b","INHERIT"})
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<header>a01a a01b</header>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<header>a02a a02b</header>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<header>a01a a01b a03a a03b</header>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<header>a04a a01a a01b a04b</header>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<header>a05a a05b a01a a01b</header>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(header={"b01a","b01b","INHERIT"})
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02")
-		@HtmlDocConfig(header={"b02a","b02b"})
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03")
-		@HtmlDocConfig(header={"INHERIT","b03a","b03b"})
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04")
-		@HtmlDocConfig(header={"b04a","INHERIT","b04b"})
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05")
-		@HtmlDocConfig(header={"b05a","b05b","INHERIT"})
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<header>b01a b01b a01a a01b</header>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<header>b02a b02b</header>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<header>b01a b01b a01a a01b b03a b03b</header>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<header>b04a b01a b01b a01a a01b b04b</header>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<header>b05a b05b b01a b01b a01a a01b</header>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigNavTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigNavTest.java
deleted file mode 100644
index 466f151..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigNavTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial"})
-public class HtmlDocConfigNavTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(navlinks={"NONE"},nav={"a01a","a01b"})
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02")
-		@HtmlDocConfig(nav={"a02a","a02b"})
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03")
-		@HtmlDocConfig(nav={"INHERIT","a03a","a03b"})
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04")
-		@HtmlDocConfig(nav={"a04a","INHERIT","a04b"})
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05")
-		@HtmlDocConfig(nav={"a05a","a05b","INHERIT"})
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<nav>a01a a01b</nav>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<nav>a02a a02b</nav>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<nav>a01a a01b a03a a03b</nav>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<nav>a04a a01a a01b a04b</nav>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<nav>a05a a05b a01a a01b</nav>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(nav={"INHERIT","b01a","b01b"})
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02")
-		@HtmlDocConfig(nav={"b02a","b02b"})
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03")
-		@HtmlDocConfig(nav={"INHERIT","b03a","b03b"})
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04")
-		@HtmlDocConfig(nav={"b04a","INHERIT","b04b"})
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05")
-		@HtmlDocConfig(nav={"b05a","b05b","INHERIT"})
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<nav>a01a a01b b01a b01b</nav>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<nav>b02a b02b</nav>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<nav>a01a a01b b01a b01b b03a b03b</nav>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<nav>b04a a01a a01b b01a b01b b04b</nav>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<nav>b05a b05b a01a a01b b01a b01b</nav>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigNavlinksTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigNavlinksTest.java
deleted file mode 100644
index d0c5eb6..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigNavlinksTest.java
+++ /dev/null
@@ -1,245 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial"})
-public class HtmlDocConfigNavlinksTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(navlinks={"a01a","a01b"})
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02")
-		@HtmlDocConfig(navlinks={"a02a","a02b"})
-		public Object test2() {
-			return "OK";
-		}
-		@RestMethod(path="/a03")
-		@HtmlDocConfig(navlinks={"INHERIT","a03a","a03b"})
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04")
-		@HtmlDocConfig(navlinks={"a04a","INHERIT","a04b"})
-		public Object test4() {
-			return "OK";
-		}
-		@RestMethod(path="/a05")
-		@HtmlDocConfig(navlinks={"a05a","a05b","INHERIT"})
-		public Object test5() {
-			return "OK";
-		}
-		@RestMethod(path="/a06")
-		@HtmlDocConfig(navlinks={"INHERIT","[0]:a06a","[3]:a06b"})
-		public Object test6a() {
-			return "OK";
-		}
-		@RestMethod(path="/a07")
-		@HtmlDocConfig(navlinks={"[1]:a07a","[2]:a07b","INHERIT"})
-		public Object test6b() {
-			return "OK";
-		}
-		@RestMethod(path="/a08")
-		@HtmlDocConfig(navlinks={"[1]:a08a","[0]:a08b"})
-		public Object test6c() {
-			return "OK";
-		}
-		@RestMethod(path="/a09")
-		@HtmlDocConfig(navlinks={"INHERIT","foo[0]:a09a","bar[3]:a09b"})
-		public Object test6d() {
-			return "OK";
-		}
-		@RestMethod(path="/a10")
-		@HtmlDocConfig(navlinks={"foo[1]:a10a","bar[2]:a10b","INHERIT"})
-		public Object test6e() {
-			return "OK";
-		}
-		@RestMethod(path="/a11")
-		@HtmlDocConfig(navlinks={"foo[1]:a11a","bar[0]:a11b"})
-		public Object test6f() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li></ol></nav>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<nav><ol><li>a02a</li><li>a02b</li></ol></nav>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li><li>a03a</li><li>a03b</li></ol></nav>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<nav><ol><li>a04a</li><li>a01a</li><li>a01b</li><li>a04b</li></ol></nav>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<nav><ol><li>a05a</li><li>a05b</li><li>a01a</li><li>a01b</li></ol></nav>");
-	}
-	@Test
-	public void a06() throws Exception {
-		a.get("/a06").accept("text/html").run().assertBody().contains("<nav><ol><li>a06a</li><li>a01a</li><li>a01b</li><li>a06b</li></ol></nav>");
-	}
-	@Test
-	public void a07() throws Exception {
-		a.get("/a07").accept("text/html").run().assertBody().contains("<nav><ol><li>a07a</li><li>a07b</li><li>a01a</li><li>a01b</li></ol></nav>");
-	}
-	@Test
-	public void a08() throws Exception {
-		a.get("/a08").accept("text/html").run().assertBody().contains("<nav><ol><li>a08b</li><li>a08a</li></ol></nav>");
-	}
-	@Test
-	public void a09() throws Exception {
-		a.get("/a09").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/a09a\">foo</a></li><li>a01a</li><li>a01b</li><li><a href=\"/a09b\">bar</a></li></ol></nav>");
-	}
-	@Test
-	public void a10() throws Exception {
-		a.get("/a10").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/a10a\">foo</a></li><li><a href=\"/a10b\">bar</a></li><li>a01a</li><li>a01b</li></ol></nav>");
-	}
-	@Test
-	public void a11() throws Exception {
-		a.get("/a11").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/a11b\">bar</a></li><li><a href=\"/a11a\">foo</a></li></ol></nav>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(navlinks={"INHERIT","b01a","b01b"})
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02")
-		@HtmlDocConfig(navlinks={"b02a","b02b"})
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03")
-		@HtmlDocConfig(navlinks={"INHERIT","b03a","b03b"})
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04")
-		@HtmlDocConfig(navlinks={"b04a","INHERIT","b04b"})
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05")
-		@HtmlDocConfig(navlinks={"b05a","b05b","INHERIT"})
-		public Object b05() {
-			return "OK";
-		}
-		@RestMethod(path="/b06")
-		@HtmlDocConfig(navlinks={"INHERIT","[0]:b06a","[3]:b06b"})
-		public Object b06() {
-			return "OK";
-		}
-		@RestMethod(path="/b07")
-		@HtmlDocConfig(navlinks={"[1]:b07a","[2]:b07b","INHERIT"})
-		public Object b07() {
-			return "OK";
-		}
-		@RestMethod(path="/b08")
-		@HtmlDocConfig(navlinks={"[1]:b08a","[0]:b08b"})
-		public Object b08() {
-			return "OK";
-		}
-		@RestMethod(path="/b09")
-		@HtmlDocConfig(navlinks={"INHERIT","foo[0]:b09a","bar[3]:b09b"})
-		public Object b09() {
-			return "OK";
-		}
-		@RestMethod(path="/b10")
-		@HtmlDocConfig(navlinks={"foo[1]:b10a","bar[2]:b10b","INHERIT"})
-		public Object b10() {
-			return "OK";
-		}
-		@RestMethod(path="/b11")
-		@HtmlDocConfig(navlinks={"foo[1]:b11a","bar[0]:b11b"})
-		public Object b11() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<nav><ol><li>b02a</li><li>b02b</li></ol></nav>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li><li>b03a</li><li>b03b</li></ol></nav>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<nav><ol><li>b04a</li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li><li>b04b</li></ol></nav>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<nav><ol><li>b05a</li><li>b05b</li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b06() throws Exception {
-		b.get("/b06").accept("text/html").run().assertBody().contains("<nav><ol><li>b06a</li><li>a01a</li><li>a01b</li><li>b06b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b07() throws Exception {
-		b.get("/b07").accept("text/html").run().assertBody().contains("<nav><ol><li>b07a</li><li>b07b</li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b08() throws Exception {
-		b.get("/b08").accept("text/html").run().assertBody().contains("<nav><ol><li>b08b</li><li>b08a</li></ol></nav>");
-	}
-	@Test
-	public void b09() throws Exception {
-		b.get("/b09").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/b09a\">foo</a></li><li>a01a</li><li>a01b</li><li><a href=\"/b09b\">bar</a></li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b10() throws Exception {
-		b.get("/b10").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/b10a\">foo</a></li><li><a href=\"/b10b\">bar</a></li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b11() throws Exception {
-		b.get("/b11").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/b11b\">bar</a></li><li><a href=\"/b11a\">foo</a></li></ol></nav>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigScriptTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigScriptTest.java
deleted file mode 100644
index db0ed23..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigScriptTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial"})
-public class HtmlDocConfigScriptTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(script={"a01a","a01b"})
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02")
-		@HtmlDocConfig(script={"a02a","a02b"})
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03")
-		@HtmlDocConfig(script={"INHERIT","a03a","a03b"})
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04")
-		@HtmlDocConfig(script={"a04a","INHERIT","a04b"})
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05")
-		@HtmlDocConfig(script={"a05a","a05b","INHERIT"})
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<script>a01a\n a01b\n</script>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<script>a02a\n a02b\n</script>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<script>a01a\n a01b\n a03a\n a03b\n</script>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<script>a04a\n a01a\n a01b\n a04b\n</script>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<script>a05a\n a05b\n a01a\n a01b\n</script>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(script={"b01a","b01b"})
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02")
-		@HtmlDocConfig(script={"b02a","b02b"})
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03")
-		@HtmlDocConfig(script={"INHERIT","b03a","b03b"})
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04")
-		@HtmlDocConfig(script={"b04a","INHERIT","b04b"})
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05")
-		@HtmlDocConfig(script={"b05a","b05b","INHERIT"})
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<script>b01a\n b01b\n</script>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<script>b02a\n b02b\n</script>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<script>b01a\n b01b\n b03a\n b03b\n</script>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<script>b04a\n b01a\n b01b\n b04b\n</script>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<script>b05a\n b05b\n b01a\n b01b\n</script>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigStyleTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigStyleTest.java
deleted file mode 100644
index b0339ce..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocConfigStyleTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial"})
-public class HtmlDocConfigStyleTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(style={"a01a","a01b"},stylesheet="a01s",nowrap="false")
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02")
-		@HtmlDocConfig(style={"a02a","a02b"},stylesheet="a02s")
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03")
-		@HtmlDocConfig(style={"INHERIT","a03a","a03b"})
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04")
-		@HtmlDocConfig(style={"a04a","INHERIT","a04b"})
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05")
-		@HtmlDocConfig(style={"a05a","a05b","INHERIT"})
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a01a a01b</style>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<style>@import \"/a02s\"; a02a a02b</style>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a01a a01b a03a a03b</style>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a04a a01a a01b a04b</style>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a05a a05b a01a a01b</style>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@Rest()
-	@HtmlDocConfig(style={"b01a","b01b"},stylesheet="b01s")
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02")
-		@HtmlDocConfig(style={"b02a","b02b"},stylesheet="b02s")
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03")
-		@HtmlDocConfig(style={"INHERIT","b03a","b03b"})
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04")
-		@HtmlDocConfig(style={"b04a","INHERIT","b04b"})
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05")
-		@HtmlDocConfig(style={"b05a","b05b","INHERIT"})
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b01a b01b</style>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<style>@import \"/b02s\"; b02a b02b</style>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b01a b01b b03a b03b</style>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b04a b01a b01b b04b</style>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b05a b05b b01a b01b</style>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocFooterTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocFooterTest.java
deleted file mode 100644
index 9574759..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocFooterTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial","deprecation"})
-public class HtmlDocFooterTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(footer={"a01a","a01b"}))
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02", htmldoc=@HtmlDoc(footer={"a02a","a02b"}))
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03", htmldoc=@HtmlDoc(footer={"INHERIT","a03a","a03b"}))
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04", htmldoc=@HtmlDoc(footer={"a04a","INHERIT","a04b"}))
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05", htmldoc=@HtmlDoc(footer={"a05a","a05b","INHERIT"}))
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<footer>a01a a01b</footer>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<footer>a02a a02b</footer>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<footer>a01a a01b a03a a03b</footer>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<footer>a04a a01a a01b a04b</footer>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<footer>a05a a05b a01a a01b</footer>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(footer={"b01a","INHERIT","b01b"}))
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02", htmldoc=@HtmlDoc(footer={"b02a","b02b"}))
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03", htmldoc=@HtmlDoc(footer={"INHERIT","b03a","b03b"}))
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04", htmldoc=@HtmlDoc(footer={"b04a","INHERIT","b04b"}))
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05", htmldoc=@HtmlDoc(footer={"b05a","b05b","INHERIT"}))
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<footer>b01a a01a a01b b01b</footer>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<footer>b02a b02b</footer>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<footer>b01a a01a a01b b01b b03a b03b</footer>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<footer>b04a b01a a01a a01b b01b b04b</footer>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<footer>b05a b05b b01a a01a a01b b01b</footer>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocHeaderTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocHeaderTest.java
deleted file mode 100644
index c2e7db8..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocHeaderTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial","deprecation"})
-public class HtmlDocHeaderTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(header={"a01a","a01b"}))
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02", htmldoc=@HtmlDoc(header={"a02a","a02b"}))
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03", htmldoc=@HtmlDoc(header={"INHERIT","a03a","a03b"}))
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04", htmldoc=@HtmlDoc(header={"a04a","INHERIT","a04b"}))
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05", htmldoc=@HtmlDoc(header={"a05a","a05b","INHERIT"}))
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<header>a01a a01b</header>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<header>a02a a02b</header>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<header>a01a a01b a03a a03b</header>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<header>a04a a01a a01b a04b</header>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<header>a05a a05b a01a a01b</header>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(header={"b01a","b01b","INHERIT"}))
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02", htmldoc=@HtmlDoc(header={"b02a","b02b"}))
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03", htmldoc=@HtmlDoc(header={"INHERIT","b03a","b03b"}))
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04", htmldoc=@HtmlDoc(header={"b04a","INHERIT","b04b"}))
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05", htmldoc=@HtmlDoc(header={"b05a","b05b","INHERIT"}))
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<header>b01a b01b a01a a01b</header>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<header>b02a b02b</header>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<header>b01a b01b a01a a01b b03a b03b</header>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<header>b04a b01a b01b a01a a01b b04b</header>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<header>b05a b05b b01a b01b a01a a01b</header>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavTest.java
deleted file mode 100644
index 62a964f..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial","deprecation"})
-public class HtmlDocNavTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(navlinks={"NONE"},nav={"a01a","a01b"}))
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02", htmldoc=@HtmlDoc(nav={"a02a","a02b"}))
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03", htmldoc=@HtmlDoc(nav={"INHERIT","a03a","a03b"}))
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04", htmldoc=@HtmlDoc(nav={"a04a","INHERIT","a04b"}))
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05", htmldoc=@HtmlDoc(nav={"a05a","a05b","INHERIT"}))
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<nav>a01a a01b</nav>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<nav>a02a a02b</nav>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<nav>a01a a01b a03a a03b</nav>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<nav>a04a a01a a01b a04b</nav>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<nav>a05a a05b a01a a01b</nav>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(nav={"INHERIT","b01a","b01b"}))
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02", htmldoc=@HtmlDoc(nav={"b02a","b02b"}))
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03", htmldoc=@HtmlDoc(nav={"INHERIT","b03a","b03b"}))
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04", htmldoc=@HtmlDoc(nav={"b04a","INHERIT","b04b"}))
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05", htmldoc=@HtmlDoc(nav={"b05a","b05b","INHERIT"}))
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<nav>a01a a01b b01a b01b</nav>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<nav>b02a b02b</nav>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<nav>a01a a01b b01a b01b b03a b03b</nav>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<nav>b04a a01a a01b b01a b01b b04b</nav>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<nav>b05a b05b a01a a01b b01a b01b</nav>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavlinksTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavlinksTest.java
deleted file mode 100644
index 2ae0c97..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavlinksTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial","deprecation"})
-public class HtmlDocNavlinksTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(navlinks={"a01a","a01b"}))
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02", htmldoc=@HtmlDoc(navlinks={"a02a","a02b"}))
-		public Object test2() {
-			return "OK";
-		}
-		@RestMethod(path="/a03", htmldoc=@HtmlDoc(navlinks={"INHERIT","a03a","a03b"}))
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04", htmldoc=@HtmlDoc(navlinks={"a04a","INHERIT","a04b"}))
-		public Object test4() {
-			return "OK";
-		}
-		@RestMethod(path="/a05", htmldoc=@HtmlDoc(navlinks={"a05a","a05b","INHERIT"}))
-		public Object test5() {
-			return "OK";
-		}
-		@RestMethod(path="/a06", htmldoc=@HtmlDoc(navlinks={"INHERIT","[0]:a06a","[3]:a06b"}))
-		public Object test6a() {
-			return "OK";
-		}
-		@RestMethod(path="/a07", htmldoc=@HtmlDoc(navlinks={"[1]:a07a","[2]:a07b","INHERIT"}))
-		public Object test6b() {
-			return "OK";
-		}
-		@RestMethod(path="/a08", htmldoc=@HtmlDoc(navlinks={"[1]:a08a","[0]:a08b"}))
-		public Object test6c() {
-			return "OK";
-		}
-		@RestMethod(path="/a09", htmldoc=@HtmlDoc(navlinks={"INHERIT","foo[0]:a09a","bar[3]:a09b"}))
-		public Object test6d() {
-			return "OK";
-		}
-		@RestMethod(path="/a10", htmldoc=@HtmlDoc(navlinks={"foo[1]:a10a","bar[2]:a10b","INHERIT"}))
-		public Object test6e() {
-			return "OK";
-		}
-		@RestMethod(path="/a11", htmldoc=@HtmlDoc(navlinks={"foo[1]:a11a","bar[0]:a11b"}))
-		public Object test6f() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li></ol></nav>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<nav><ol><li>a02a</li><li>a02b</li></ol></nav>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li><li>a03a</li><li>a03b</li></ol></nav>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<nav><ol><li>a04a</li><li>a01a</li><li>a01b</li><li>a04b</li></ol></nav>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<nav><ol><li>a05a</li><li>a05b</li><li>a01a</li><li>a01b</li></ol></nav>");
-	}
-	@Test
-	public void a06() throws Exception {
-		a.get("/a06").accept("text/html").run().assertBody().contains("<nav><ol><li>a06a</li><li>a01a</li><li>a01b</li><li>a06b</li></ol></nav>");
-	}
-	@Test
-	public void a07() throws Exception {
-		a.get("/a07").accept("text/html").run().assertBody().contains("<nav><ol><li>a07a</li><li>a07b</li><li>a01a</li><li>a01b</li></ol></nav>");
-	}
-	@Test
-	public void a08() throws Exception {
-		a.get("/a08").accept("text/html").run().assertBody().contains("<nav><ol><li>a08b</li><li>a08a</li></ol></nav>");
-	}
-	@Test
-	public void a09() throws Exception {
-		a.get("/a09").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/a09a\">foo</a></li><li>a01a</li><li>a01b</li><li><a href=\"/a09b\">bar</a></li></ol></nav>");
-	}
-	@Test
-	public void a10() throws Exception {
-		a.get("/a10").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/a10a\">foo</a></li><li><a href=\"/a10b\">bar</a></li><li>a01a</li><li>a01b</li></ol></nav>");
-	}
-	@Test
-	public void a11() throws Exception {
-		a.get("/a11").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/a11b\">bar</a></li><li><a href=\"/a11a\">foo</a></li></ol></nav>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(navlinks={"INHERIT","b01a","b01b"}))
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02", htmldoc=@HtmlDoc(navlinks={"b02a","b02b"}))
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03", htmldoc=@HtmlDoc(navlinks={"INHERIT","b03a","b03b"}))
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04", htmldoc=@HtmlDoc(navlinks={"b04a","INHERIT","b04b"}))
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05", htmldoc=@HtmlDoc(navlinks={"b05a","b05b","INHERIT"}))
-		public Object b05() {
-			return "OK";
-		}
-		@RestMethod(path="/b06", htmldoc=@HtmlDoc(navlinks={"INHERIT","[0]:b06a","[3]:b06b"}))
-		public Object b06() {
-			return "OK";
-		}
-		@RestMethod(path="/b07", htmldoc=@HtmlDoc(navlinks={"[1]:b07a","[2]:b07b","INHERIT"}))
-		public Object b07() {
-			return "OK";
-		}
-		@RestMethod(path="/b08", htmldoc=@HtmlDoc(navlinks={"[1]:b08a","[0]:b08b"}))
-		public Object b08() {
-			return "OK";
-		}
-		@RestMethod(path="/b09", htmldoc=@HtmlDoc(navlinks={"INHERIT","foo[0]:b09a","bar[3]:b09b"}))
-		public Object b09() {
-			return "OK";
-		}
-		@RestMethod(path="/b10", htmldoc=@HtmlDoc(navlinks={"foo[1]:b10a","bar[2]:b10b","INHERIT"}))
-		public Object b10() {
-			return "OK";
-		}
-		@RestMethod(path="/b11", htmldoc=@HtmlDoc(navlinks={"foo[1]:b11a","bar[0]:b11b"}))
-		public Object b11() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<nav><ol><li>b02a</li><li>b02b</li></ol></nav>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<nav><ol><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li><li>b03a</li><li>b03b</li></ol></nav>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<nav><ol><li>b04a</li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li><li>b04b</li></ol></nav>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<nav><ol><li>b05a</li><li>b05b</li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b06() throws Exception {
-		b.get("/b06").accept("text/html").run().assertBody().contains("<nav><ol><li>b06a</li><li>a01a</li><li>a01b</li><li>b06b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b07() throws Exception {
-		b.get("/b07").accept("text/html").run().assertBody().contains("<nav><ol><li>b07a</li><li>b07b</li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b08() throws Exception {
-		b.get("/b08").accept("text/html").run().assertBody().contains("<nav><ol><li>b08b</li><li>b08a</li></ol></nav>");
-	}
-	@Test
-	public void b09() throws Exception {
-		b.get("/b09").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/b09a\">foo</a></li><li>a01a</li><li>a01b</li><li><a href=\"/b09b\">bar</a></li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b10() throws Exception {
-		b.get("/b10").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/b10a\">foo</a></li><li><a href=\"/b10b\">bar</a></li><li>a01a</li><li>a01b</li><li>b01a</li><li>b01b</li></ol></nav>");
-	}
-	@Test
-	public void b11() throws Exception {
-		b.get("/b11").accept("text/html").run().assertBody().contains("<nav><ol><li><a href=\"/b11b\">bar</a></li><li><a href=\"/b11a\">foo</a></li></ol></nav>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocScriptTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocScriptTest.java
deleted file mode 100644
index 8278802..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocScriptTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial","deprecation"})
-public class HtmlDocScriptTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(script={"a01a","a01b"}))
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02", htmldoc=@HtmlDoc(script={"a02a","a02b"}))
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03", htmldoc=@HtmlDoc(script={"INHERIT","a03a","a03b"}))
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04", htmldoc=@HtmlDoc(script={"a04a","INHERIT","a04b"}))
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05", htmldoc=@HtmlDoc(script={"a05a","a05b","INHERIT"}))
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<script>a01a\n a01b\n</script>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<script>a02a\n a02b\n</script>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<script>a01a\n a01b\n a03a\n a03b\n</script>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<script>a04a\n a01a\n a01b\n a04b\n</script>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<script>a05a\n a05b\n a01a\n a01b\n</script>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(script={"b01a","b01b"}))
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02", htmldoc=@HtmlDoc(script={"b02a","b02b"}))
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03", htmldoc=@HtmlDoc(script={"INHERIT","b03a","b03b"}))
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04", htmldoc=@HtmlDoc(script={"b04a","INHERIT","b04b"}))
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05", htmldoc=@HtmlDoc(script={"b05a","b05b","INHERIT"}))
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<script>b01a\n b01b\n</script>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<script>b02a\n b02b\n</script>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<script>b01a\n b01b\n b03a\n b03b\n</script>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<script>b04a\n b01a\n b01b\n b04b\n</script>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<script>b05a\n b05b\n b01a\n b01b\n</script>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocStyleTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocStyleTest.java
deleted file mode 100644
index 7288332..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/HtmlDocStyleTest.java
+++ /dev/null
@@ -1,124 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-@SuppressWarnings({"serial","deprecation"})
-public class HtmlDocStyleTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(style={"a01a","a01b"},stylesheet="a01s",nowrap="false"))
-	public static class A extends BasicRestServlet {
-		@RestMethod(path="/a01")
-		public Object a01() {
-			return "OK";
-		}
-		@RestMethod(path="/a02", htmldoc=@HtmlDoc(style={"a02a","a02b"},stylesheet="a02s"))
-		public Object a02() {
-			return "OK";
-		}
-		@RestMethod(path="/a03", htmldoc=@HtmlDoc(style={"INHERIT","a03a","a03b"}))
-		public Object a03() {
-			return "OK";
-		}
-		@RestMethod(path="/a04", htmldoc=@HtmlDoc(style={"a04a","INHERIT","a04b"}))
-		public Object a04() {
-			return "OK";
-		}
-		@RestMethod(path="/a05", htmldoc=@HtmlDoc(style={"a05a","a05b","INHERIT"}))
-		public Object a05() {
-			return "OK";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a01a a01b</style>");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").accept("text/html").run().assertBody().contains("<style>@import \"/a02s\"; a02a a02b</style>");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a01a a01b a03a a03b</style>");
-	}
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a04a a01a a01b a04b</style>");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").accept("text/html").run().assertBody().contains("<style>@import \"/a01s\"; a05a a05b a01a a01b</style>");
-	}
-
-	//=================================================================================================================
-	// Inheritance
-	//=================================================================================================================
-
-	@RestResource(htmldoc=@HtmlDoc(style={"b01a","b01b"},stylesheet="b01s"))
-	public static class B extends A {
-		@RestMethod(path="/b01")
-		public Object b01() {
-			return "OK";
-		}
-		@RestMethod(path="/b02", htmldoc=@HtmlDoc(style={"b02a","b02b"},stylesheet="b02s"))
-		public Object b02() {
-			return "OK";
-		}
-		@RestMethod(path="/b03", htmldoc=@HtmlDoc(style={"INHERIT","b03a","b03b"}))
-		public Object b03() {
-			return "OK";
-		}
-		@RestMethod(path="/b04", htmldoc=@HtmlDoc(style={"b04a","INHERIT","b04b"}))
-		public Object b04() {
-			return "OK";
-		}
-		@RestMethod(path="/b05", htmldoc=@HtmlDoc(style={"b05a","b05b","INHERIT"}))
-		public Object b05() {
-			return "OK";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b01a b01b</style>");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").accept("text/html").run().assertBody().contains("<style>@import \"/b02s\"; b02a b02b</style>");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b01a b01b b03a b03b</style>");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b04a b01a b01b b04b</style>");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").accept("text/html").run().assertBody().contains("<style>@import \"/b01s\"; b05a b05b b01a b01b</style>");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathRemainderAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/PathRemainder_Test.java
similarity index 71%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathRemainderAnnotationTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/PathRemainder_Test.java
index 3b92c08..0ab07f8 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathRemainderAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/PathRemainder_Test.java
@@ -10,7 +10,7 @@
 // * "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.rest.annotation2;
+package org.apache.juneau.rest.annotation;
 
 import static org.apache.juneau.http.HttpMethod.*;
 import static org.junit.Assert.*;
@@ -20,43 +20,37 @@
 
 import org.apache.juneau.http.annotation.Path;
 import org.apache.juneau.json.*;
-import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
 import org.apache.juneau.rest.mock2.*;
 import org.apache.juneau.testutils.pojos.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class PathRemainderAnnotationTest {
+public class PathRemainder_Test {
 
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// Simple tests
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest
 	public static class A  {
 		@RestMethod(name=GET, path="/*")
-		public String b(@Path("/*") String remainder) {
+		public String a(@Path("/*") String remainder) {
 			return remainder;
 		}
 	}
-	static MockRestClient a = MockRestClient.build(A.class);
 
 	@Test
-	public void a01_withoutRemainder() throws Exception {
+	public void a01_basic() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
 		a.get("/").run().assertBody().is("");
-	}
-	@Test
-	public void a02_withRemainder() throws Exception {
 		a.get("/foo").run().assertBody().is("foo");
-	}
-	@Test
-	public void a03_withRemainder2() throws Exception {
 		a.get("/foo/bar").run().assertBody().is("foo/bar");
 	}
 
-	//=================================================================================================================
-	// Optional path remainer parameter.
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
+	// Optional path remainder parameter.
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(serializers=SimpleJsonSerializer.class)
 	public static class B {
@@ -80,34 +74,22 @@
 			return f1;
 		}
 	}
-	static MockRestClient b = MockRestClient.buildJson(B.class);
 
 	@Test
-	public void b01_optionalParam_integer() throws Exception {
+	public void b01_optionalParam() throws Exception {
+		RestClient b = MockRestClient.buildJson(B.class);
 		b.get("/a/123")
 			.run()
 			.assertCode().is(200)
 			.assertBody().is("123");
-	}
-
-	@Test
-	public void b02_optionalParam_bean() throws Exception {
 		b.get("/b/a=1,b=foo")
 			.run()
 			.assertCode().is(200)
 			.assertBody().is("{a:1,b:'foo'}");
-	}
-
-	@Test
-	public void b03_optionalParam_listOfBeans() throws Exception {
 		b.get("/c/@((a=1,b=foo))")
 			.run()
 			.assertCode().is(200)
 			.assertBody().is("[{a:1,b:'foo'}]");
-	}
-
-	@Test
-	public void b04_optionalParam_listOfOptionals() throws Exception {
 		b.get("/d/@((a=1,b=foo))")
 			.run()
 			.assertCode().is(200)
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Path_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Path_Test.java
new file mode 100644
index 0000000..7fe8653
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Path_Test.java
@@ -0,0 +1,890 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.marshall.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.RestResponse;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.apache.juneau.testutils.pojos.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Path_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Basic tests
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A  {
+		@RestMethod(name=GET, path="/")
+		public void a(RestResponse res) {
+			res.setOutput(GET);
+		}
+		@RestMethod(name=GET, path="/a")
+		public String b() {
+			return "GET /a";
+		}
+		@RestMethod(name=GET, path="/a/{foo}")
+		public String c(RestResponse res, @Path("foo") String foo) {
+			return "GET /a " + foo;
+		}
+		@RestMethod(name=GET, path="/a/{foo}/{bar}")
+		public String d(RestResponse res, @Path("foo") String foo, @Path("bar") String bar) {
+			return "GET /a " + foo + "," + bar;
+		}
+		@RestMethod(name=GET, path="/a/{foo}/{bar}/*")
+		public String e(@Path("foo") String foo, @Path("bar") int bar, @Path("/*") String remainder) {
+			return "GET /a "+foo+","+bar+",r="+remainder;
+		}
+	}
+
+	@Test
+	public void a01_basic() throws Exception {
+		RestClient a = MockRestClient.buildLax(A.class);
+
+		a.get("/bad?noTrace=true")
+			.run()
+			.assertCode().is(404);
+
+		a.get(null)
+			.run()
+			.assertBody().is("GET");
+		a.get()
+			.run()
+			.assertBody().is("GET");
+
+		a.get("/a")
+			.run()
+			.assertBody().is("GET /a");
+
+		a.get("/a/foo")
+			.run()
+			.assertBody().is("GET /a foo");
+
+		a.get("/a/foo/bar")
+			.run()
+			.assertBody().is("GET /a foo,bar");
+
+		a.get("/a/foo/123/baz")
+			.run()
+			.assertBody().is("GET /a foo,123,r=baz");
+
+		// URL-encoded part should not get decoded before finding method to invoke.
+		// This should match /get1/{foo} and not /get1/{foo}/{bar}
+		// NOTE:  When testing on Tomcat, must specify the following system property:
+		// -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
+		a.get("/a/x%2Fy")
+			.run()
+			.assertBody().is("GET /a x/y");
+		a.get("/a/x%2Fy/x%2Fy")
+			.run()
+			.assertBody().is("GET /a x/y,x/y");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Primitives
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class B  {
+		@RestMethod(name=GET, path="/a/{x}/foo")
+		public String a(@Path("x") int x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/b/{x}/foo")
+		public String b(@Path("x") short x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/c/{x}/foo")
+		public String c(@Path("x") long x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/d/{x}/foo")
+		public String d(@Path("x") char x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/e/{x}/foo")
+		public String e(@Path("x") float x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/f/{x}/foo")
+		public String f(@Path("x") double x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/g/{x}/foo")
+		public String g(@Path("x") byte x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/h/{x}/foo")
+		public String h(@Path("x") boolean x) {
+			return String.valueOf(x);
+		}
+	}
+
+	@Test
+	public void b01_primitives() throws Exception {
+		RestClient b = MockRestClient.buildLax(B.class);
+
+		b.get("/a/123/foo")
+			.run()
+			.assertBody().is("123");
+		b.get("/a/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		b.get("/b/123/foo")
+			.run()
+			.assertBody().is("123");
+		b.get("/b/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		b.get("/c/123/foo")
+			.run()
+			.assertBody().is("123");
+		b.get("/c/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		b.get("/d/c/foo")
+			.run()
+			.assertBody().is("c");
+		b.get("/d/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		b.get("/e/1.23/foo")
+			.run()
+			.assertBody().is("1.23");
+		b.get("/e/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		b.get("/f/1.23/foo")
+			.run()
+			.assertBody().is("1.23");
+		b.get("/f/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		b.get("/g/123/foo")
+			.run()
+			.assertBody().is("123");
+		b.get("/g/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		b.get("/h/true/foo")
+			.run()
+			.assertBody().is("true");
+		b.get("/h/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Primitive objects
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class C  {
+		@RestMethod(name=GET, path="/a/{x}/foo")
+		public String a(@Path("x") Integer x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/b/{x}/foo")
+		public String b(@Path("x") Short x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/c/{x}/foo")
+		public String c(@Path("x") Long x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/d/{x}/foo")
+		public String d(@Path("x") Character x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/e/{x}/foo")
+		public String e(@Path("x") Float x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/f/{x}/foo")
+		public String f(@Path("x") Double x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/g/{x}/foo")
+		public String g(@Path("x") Byte x) {
+			return String.valueOf(x);
+		}
+		@RestMethod(name=GET, path="/h/{x}/foo")
+		public String h(@Path("x") Boolean x) {
+			return String.valueOf(x);
+		}
+	}
+
+	@Test
+	public void c01_primitiveObjects() throws Exception {
+		RestClient c = MockRestClient.buildLax(C.class);
+
+		c.get("/a/123/foo")
+			.run()
+			.assertBody().is("123");
+		c.get("/a/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		c.get("/b/123/foo")
+			.run()
+			.assertBody().is("123");
+		c.get("/b/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		c.get("/c/123/foo")
+			.run()
+			.assertBody().is("123");
+		c.get("/c/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		c.get("/d/c/foo")
+			.run()
+			.assertBody().is("c");
+		c.get("/d/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		c.get("/e/1.23/foo")
+			.run()
+			.assertBody().is("1.23");
+		c.get("/e/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		c.get("/f/1.23/foo")
+			.run()
+			.assertBody().is("1.23");
+		c.get("/f/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		c.get("/g/123/foo")
+			.run()
+			.assertBody().is("123");
+		c.get("/g/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+
+		c.get("/h/true/foo")
+			.run()
+			.assertBody().is("true");
+		c.get("/h/bad/foo?noTrace=true")
+			.run()
+			.assertCode().is(400);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// POJOs convertible from strings
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class D {
+		// Object with forString(String) method
+		@RestMethod(name=GET, path="/a/{uuid}")
+		public UUID a(RestResponse res, @Path("uuid") UUID uuid) {
+			return uuid;
+		}
+	}
+
+	@Test
+	public void d01_pojosConvertibleFromStrings() throws Exception {
+		RestClient d = MockRestClient.build(D.class);
+
+		UUID uuid = UUID.randomUUID();
+		d.get("/a/" + uuid)
+			.run()
+			.assertBody().is(uuid.toString());
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @Path annotation without name.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class E  {
+		@RestMethod(name=GET, path="/x/{foo}/{bar}")
+		public Object a(@Path String foo, @Path String bar) {
+			return OMap.of("m", "normal1", "foo", foo, "bar", bar);
+		}
+		@RestMethod(name=GET, path="/x/{foo}/x/{bar}/x")
+		public Object b(@Path String foo, @Path String bar) {
+			return OMap.of("m", "normal2", "foo", foo, "bar", bar);
+		}
+		@RestMethod(name=GET, path="/y/{0}/{1}")
+		public Object c(@Path String foo, @Path String bar) {
+			return OMap.of("m", "numbers1", "0", foo, "1", bar);
+		}
+		@RestMethod(name=GET, path="/y/{0}/y/{1}/y")
+		public Object d(@Path String foo, @Path String bar) {
+			return OMap.of("m", "numbers2", "0", foo, "1", bar);
+		}
+		@RestMethod(name=GET, path="/z/{1}/z/{0}/z")
+		public Object e(@Path String foo, @Path String bar) {
+			return OMap.of("m", "numbers3", "0", foo, "1", bar);
+		}
+	}
+
+	@Test
+	public void e01_withoutName() throws Exception {
+		RestClient e = MockRestClient.build(E.class);
+		e.get("/x/x1/x2")
+			.run()
+			.assertBody().is("{m:'normal1',foo:'x1',bar:'x2'}");
+		e.get("/x/x1/x/x2/x")
+			.run()
+			.assertBody().is("{m:'normal2',foo:'x1',bar:'x2'}");
+		e.get("/y/y1/y2")
+			.run()
+			.assertBody().is("{m:'numbers1','0':'y1','1':'y2'}");
+		e.get("/y/y1/y/y2/y")
+			.run()
+			.assertBody().is("{m:'numbers2','0':'y1','1':'y2'}");
+		e.get("/z/z1/z/z2/z")
+			.run()
+			.assertBody().is("{m:'numbers3','0':'z2','1':'z1'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Path variables on class.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(path="/f/{a}/{b}")
+	public static class F  {
+		@RestMethod(name=GET, path="/")
+		public String a(RequestPath path) {
+			return format("a: {0}", path);
+		}
+		@RestMethod(name=GET, path="/*")
+		public String b(RequestPath path) {
+			return format("b: {0}", path);
+		}
+		@RestMethod(name=GET, path="/fc")
+		public String c(RequestPath path) {
+			return format("c: {0}", path);
+		}
+		@RestMethod(name=GET, path="/fd/{c}/{d}")
+		public String d(RequestPath path) {
+			return format("d: {0}", path);
+		}
+		@RestMethod(name=GET, path="/fe/{a}/{b}")
+		public String e(RequestPath path) {
+			return format("e: {0}", path);
+		}
+		@RestMethod(name=GET, path="/ff/{c}/{d}/*")
+		public String f(RequestPath path) {
+			return format("f: {0}", path);
+		}
+		private String format(String msg, Object...args) {
+			return SimpleJson.DEFAULT.format(msg, args);
+		}
+	}
+
+	@Test
+	public void f01_pathVariablesOnClass() throws Exception {
+		RestClient f = MockRestClient.createLax(F.class).servletPath("/f").build();
+		f.get("http://localhost/f/x1/x2")
+			.run()
+			.assertBody().is("a: {a:'x1',b:'x2'}");
+		f.get("http://localhost/f/x1")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f//")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f/x/")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f//x")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f/x1/x2/foo")
+			.run()
+			.assertBody().is("b: {'/*':'foo','/**':'foo',a:'x1',b:'x2'}");
+		f.get("http://localhost/f///foo")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f/x1//foo")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f//x2/foo")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f/x1/x2/fc")
+			.run()
+			.assertBody().is("c: {a:'x1',b:'x2'}");
+		f.get("http://localhost/f///a")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f/x1//a")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f//x2/a")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f/x1/x2/fd/x3/x4")
+			.run()
+			.assertBody().is("d: {a:'x1',b:'x2',c:'x3',d:'x4'}");
+		f.get("http://localhost/f//x2/b/x3/x4")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f/x1//b/x3/x4")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f/x1/x2/b//x4")
+			.run()
+			.assertCode().is(200);
+		f.get("http://localhost/f/x1/x2/b/x3/")
+			.run()
+			.assertCode().is(200);
+		f.get("http://localhost/f///b//")
+			.run()
+			.assertCode().is(404);
+		f.get("http://localhost/f/x1/x2/fe/x3/x4")
+			.run()
+			.assertBody().is("e: {a:'x3',b:'x4'}");
+		f.get("http://localhost/f/x1/x2/ff/x3/x4")
+			.run()
+			.assertBody().is("f: {a:'x1',b:'x2',c:'x3',d:'x4'}");
+		f.get("http://localhost/f/x1/x2/ff/x3/x4/")
+			.run()
+			.assertBody().is("f: {'/*':'','/**':'',a:'x1',b:'x2',c:'x3',d:'x4'}");
+		f.get("http://localhost/f/x1/x2/ff/x3/x4/foo/bar")
+			.run()
+			.assertBody().is("f: {'/*':'foo/bar','/**':'foo/bar',a:'x1',b:'x2',c:'x3',d:'x4'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Path variables on child class.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(children={F.class})
+	public static class G {}
+
+
+	@Test
+	public void g01_pathVariablesOnChildClass() throws Exception {
+		RestClient g = MockRestClient.buildLax(G.class);
+		g.get("http://localhost/f/x1/x2")
+			.run()
+			.assertBody().is("a: {a:'x1',b:'x2'}");
+		g.get("http://localhost/f/x1")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f//")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f/x1/")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f//x2")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f/x1/x2/fc")
+			.run()
+			.assertBody().is("c: {a:'x1',b:'x2'}");
+		g.get("http://localhost/f///a")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f/x1//a")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f//x2/a")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f/x1/x2/fd/x3/x4")
+			.run()
+			.assertBody().is("d: {a:'x1',b:'x2',c:'x3',d:'x4'}");
+		g.get("http://localhost/f//x2/b/x3/x4")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f/x1//b/x3/x4")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f/x1/x2/b//x4")
+			.run()
+			.assertCode().is(200);
+		g.get("http://localhost/f/x1/x2/b/x3/")
+			.run()
+			.assertCode().is(200);
+		g.get("http://localhost/f///b//")
+			.run()
+			.assertCode().is(404);
+		g.get("http://localhost/f/x1/x2/fe/x3/x4")
+			.run()
+			.assertBody().is("e: {a:'x3',b:'x4'}");
+		g.get("http://localhost/f/x1/x2/ff/x3/x4")
+			.run()
+			.assertBody().is("f: {a:'x1',b:'x2',c:'x3',d:'x4'}");
+		g.get("http://localhost/f/x1/x2/ff/x3/x4/")
+			.run()
+			.assertBody().is("f: {'/*':'','/**':'',a:'x1',b:'x2',c:'x3',d:'x4'}");
+		g.get("http://localhost/f/x1/x2/ff/x3/x4/foo/bar")
+			.run()
+			.assertBody().is("f: {'/*':'foo/bar','/**':'foo/bar',a:'x1',b:'x2',c:'x3',d:'x4'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Path variables on parent and child class.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(path="/h/{ha}/{hb}", children={F.class})
+	public static class H {}
+
+	@Test
+	public void h01_pathVariablesOnParentAndChildClass() throws Exception {
+		RestClient h = MockRestClient.createLax(H.class).servletPath("/h").build();
+		h.get("http://localhost/h/ha1/hb1/f/x1/x2")
+			.run()
+			.assertBody().is("a: {a:'x1',b:'x2',ha:'ha1',hb:'hb1'}");
+		// These are 405 instead of 404 because when children don't match, we try to find a matching Java method.
+		h.get("http://localhost/h/ha1/hb1/f/x1")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h//hb1/f/x1/x2")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1//f/x1/x2")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f//x2")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f/x1/")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h///f//")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f/x1/x2/foo")
+			.run()
+			.assertBody().is("b: {'/*':'foo','/**':'foo',a:'x1',b:'x2',ha:'ha1',hb:'hb1'}");
+		h.get("http://localhost/h//hb1/f/x1/x2/foo")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1//f/x1/x2/foo")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f//x2/foo")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f/x1//foo")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h///f///foo")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f/x1/x2/fc")
+			.run()
+			.assertBody().is("c: {a:'x1',b:'x2',ha:'ha1',hb:'hb1'}");
+		h.get("http://localhost/h//hb1/f/x1/x2/a")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1//f/x1/x2/a")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f//x2/a")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f/x1//a")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h///f///a")
+			.run()
+			.assertCode().is(404);
+		h.get("http://localhost/h/ha1/hb1/f/x1/x2/fd/x3/x4")
+			.run()
+			.assertBody().is("d: {a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1'}");
+		h.get("http://localhost/h/ha1/hb1/f/x1/x2/fe/x3/x4")
+			.run()
+			.assertBody().is("e: {a:'x3',b:'x4',ha:'ha1',hb:'hb1'}");
+		h.get("http://localhost/h/ha1/hb1/f/x1/x2/ff/x3/x4")
+			.run()
+			.assertBody().is("f: {a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1'}");
+		h.get("http://localhost/h/ha1/hb1/f/x1/x2/ff/x3/x4/")
+			.run()
+			.assertBody().is("f: {'/*':'','/**':'',a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1'}");
+		h.get("http://localhost/h/ha1/hb1/f/x1/x2/ff/x3/x4/foo/bar")
+			.run()
+			.assertBody().is("f: {'/*':'foo/bar','/**':'foo/bar',a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Path variables on parents and child class.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(path="/i/{ia}/{ib}", children={H.class})
+	public static class I {}
+
+	@Test
+	public void i01_pathVariablesOnParentAndChildClass() throws Exception {
+		RestClient i = MockRestClient.createLax(I.class).servletPath("/i").build();
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2")
+			.run()
+			.assertBody().is("a: {a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1/h/ha1")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1/h")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i//ib1/h/ha1/hb1/f/x1/x2")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1//h/ha1/hb1/f/x1/x2")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1/h//hb1/f/x1/x2")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1/h/ha1//f/x1/x2")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f//x2")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i///h///f//")
+			.run()
+			.assertCode().is(404);
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/foo")
+			.run()
+			.assertBody().is("b: {'/*':'foo','/**':'foo',a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/fc")
+			.run()
+			.assertBody().is("c: {a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/fd/x3/x4")
+			.run()
+			.assertBody().is("d: {a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/fe/x3/x4")
+			.run()
+			.assertBody().is("e: {a:'x3',b:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/ff/x3/x4")
+			.run()
+			.assertBody().is("f: {a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/ff/x3/x4/")
+			.run()
+			.assertBody().is("f: {'/*':'','/**':'',a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/ff/x3/x4/foo/bar")
+			.run()
+			.assertBody().is("f: {'/*':'foo/bar','/**':'foo/bar',a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Optional path parameter.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class)
+	public static class J {
+		@RestMethod(name=GET,path="/a/{f1}")
+		public Object a(@Path("f1") Optional<Integer> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod(name=GET,path="/b/{f1}")
+		public Object b(@Path("f1") Optional<ABean> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod(name=GET,path="/c/{f1}")
+		public Object c(@Path("f1") Optional<List<ABean>> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod(name=GET,path="/d/{f1}")
+		public Object d(@Path("f1") List<Optional<ABean>> f1) throws Exception {
+			return f1;
+		}
+	}
+
+	@Test
+	public void j01_optionalParam() throws Exception {
+		RestClient j = MockRestClient.buildJson(J.class);
+		j.get("/a/123")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("123");
+		j.get("/b/a=1,b=foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("{a:1,b:'foo'}");
+		j.get("/c/@((a=1,b=foo))")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+		j.get("/d/@((a=1,b=foo))")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+	}
+
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Basic tests
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(path="/k1/{k1}",children=K2.class)
+	public static class K1 {}
+
+	@Rest(path="/k2")
+	public static class K2 {
+		@RestMethod(path="/")
+		public String a(@Path(n="k1",r=false) String k1) {
+			return k1 == null ? "nil" : k1;
+		}
+		@RestMethod(path="/foo/{bar}")
+		public String b(@Path(n="k1",r=false) String k1, @Path(n="bar",r=false) String bar) {
+			return (k1 == null ? "nil" : k1) + "," + (bar == null ? "nil" : bar);
+		}
+	}
+
+	@Test
+	public void k01_basic() throws Exception {
+		RestClient k1 = MockRestClient.build(K1.class);
+		RestClient k2 = MockRestClient.build(K2.class);
+
+		k1.get("http://localhost/k1/foo/k2")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo");
+		k1.get("http://localhost/k1/foo/k2/foo/xxx")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo,xxx");
+		k2.get("/")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("nil");
+		k2.get("/foo/xxx")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("nil,xxx");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Multiple paths
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(path="/l1/{l1}",children=L2.class)
+	public static class L1 {}
+
+	@Rest(path="/l2")
+	public static class L2 {
+		@RestMethod(paths={"/","/{foo}"})
+		public String a(@Path(n="l1",r=false) String l1, @Path(n="foo",r=false) String foo) {
+			return "1," + (l1 == null ? "nil" : l1) + "," + (foo == null ? "nil" : foo);
+		}
+		@RestMethod(paths={"/foo","/foo/{foo}"})
+		public String b(@Path(n="l1",r=false) String l1, @Path(n="foo",r=false) String foo) {
+			return "2," + (l1 == null ? "nil" : l1) + "," + (foo == null ? "nil" : foo);
+		}
+	}
+
+	@Test
+	public void l01_multiplePaths() throws Exception {
+		RestClient l1 = MockRestClient.build(L1.class);
+		RestClient l2 = MockRestClient.build(L2.class);
+
+		l1.get("http://localhost/l1/l1foo/l2")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("1,l1foo,nil");
+		l1.get("http://localhost/l1/l1foo/l2/l2foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("1,l1foo,l2foo");
+		l1.get("http://localhost/l1/l1foo/l2/foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("2,l1foo,nil");
+		l1.get("http://localhost/l1/l1foo/l2/foo/l2foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("2,l1foo,l2foo");
+		l2.get("http://localhost/l2")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("1,nil,nil");
+		l2.get("http://localhost/l2/l2foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("1,nil,l2foo");
+		l2.get("http://localhost/l2/foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("2,nil,nil");
+		l2.get("http://localhost/l2/foo/l2foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("2,nil,l2foo");
+	}
+}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java
new file mode 100644
index 0000000..f6e4dce
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Query_Test.java
@@ -0,0 +1,292 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.jsonschema.annotation.Items;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.apache.juneau.testutils.pojos.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Query_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Simple tests
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+		@RestMethod
+		public String a(RestRequest req, @Query(n="p1",aev=true) String p1, @Query(n="p2",aev=true) int p2) throws Exception {
+			RequestQuery q = req.getQuery();
+			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"],p2=["+p2+","+q.getString("p2")+","+q.get("p2", int.class)+"]";
+		}
+		@RestMethod(method=POST)
+		public String b(RestRequest req, @Query(n="p1",aev=true) String p1, @Query(n="p2",aev=true) int p2) throws Exception {
+			RequestQuery q = req.getQuery();
+			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"],p2=["+p2+","+q.getString("p2")+","+q.get("p2", int.class)+"]";
+		}
+	}
+
+	@Test
+	public void a01_basic() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+
+		a.get("/a?p1=p1&p2=2").run().assertBody().is("p1=[p1,p1,p1],p2=[2,2,2]");
+		a.get("/a?p1&p2").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.get("/a?p1=&p2=").run().assertBody().is("p1=[,,],p2=[0,,0]");
+		a.get("/a").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.get("/a?p1").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.get("/a?p1=").run().assertBody().is("p1=[,,],p2=[0,null,0]");
+		a.get("/a?p2").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.get("/a?p2=").run().assertBody().is("p1=[null,null,null],p2=[0,,0]");
+		a.get("/a?p1=foo&p2").run().assertBody().is("p1=[foo,foo,foo],p2=[0,null,0]");
+		a.get("/a?p1&p2=1").run().assertBody().is("p1=[null,null,null],p2=[1,1,1]");
+		String x1 = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
+		a.get("/a?p1="+x1+"&p2=1").run().assertBody().is("p1=[a/b%c=d e,a/b%c=d e,a/b%c=d e],p2=[1,1,1]");
+
+		a.post("/b?p1=p1&p2=2", null).run().assertBody().is("p1=[p1,p1,p1],p2=[2,2,2]");
+		a.post("/b?p1&p2", null).run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.post("/b?p1=&p2=", null).run().assertBody().is("p1=[,,],p2=[0,,0]");
+		a.post("/b", null).run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.post("/b?p1", null).run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.post("/b?p1=", null).run().assertBody().is("p1=[,,],p2=[0,null,0]");
+		a.post("/b?p2", null).run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
+		a.post("/b?p2=", null).run().assertBody().is("p1=[null,null,null],p2=[0,,0]");
+		a.post("/b?p1=foo&p2", null).run().assertBody().is("p1=[foo,foo,foo],p2=[0,null,0]");
+		a.post("/b?p1&p2=1", null).run().assertBody().is("p1=[null,null,null],p2=[1,1,1]");
+		String x2 = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
+		a.post("/b?p1="+x2+"&p2=1", null).run().assertBody().is("p1=[a/b%c=d e,a/b%c=d e,a/b%c=d e],p2=[1,1,1]");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// UON parameters
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class B {
+		@RestMethod
+		public String a(RestRequest req, @Query(n="p1") String p1) throws Exception {
+			RequestQuery q = req.getQuery();
+			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"]";
+		}
+		@RestMethod
+		public String b(RestRequest req, @Query(n="p1",f="uon") String p1) throws Exception {
+			RequestQuery q = req.getQuery();
+			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"]";
+		}
+		@RestMethod(name=POST)
+		public String c(RestRequest req, @Query(n="p1") String p1) throws Exception {
+			RequestQuery q = req.getQuery();
+			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"]";
+		}
+		@RestMethod(name=POST)
+		public String d(RestRequest req, @Query(n="p1",f="uon") String p1) throws Exception {
+			RequestQuery q = req.getQuery();
+			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"]";
+		}
+	}
+
+	@Test
+	public void b01_uonParameters() throws Exception {
+		RestClient b = MockRestClient.build(B.class);
+		b.get("/a?p1=p1").run().assertBody().is("p1=[p1,p1,p1]");
+		b.get("/a?p1='p1'").run().assertBody().is("p1=['p1','p1','p1']");
+		b.get("/b?p1=p1").run().assertBody().is("p1=[p1,p1,p1]");
+		b.get("/b?p1='p1'").run().assertBody().is("p1=[p1,'p1','p1']");
+		b.post("/c?p1=p1", null).run().assertBody().is("p1=[p1,p1,p1]");
+		b.post("/c?p1='p1'", null).run().assertBody().is("p1=['p1','p1','p1']");
+		b.post("/d?p1=p1", null).run().assertBody().is("p1=[p1,p1,p1]");
+		b.post("/d?p1='p1'", null).run().assertBody().is("p1=[p1,'p1','p1']");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Multipart parameters (e.g. &key=val1,&key=val2).
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class)
+	public static class C {
+		public static class C1 {
+			public String a;
+			public int b;
+			public boolean c;
+		}
+
+		@RestMethod
+		public Object a(@Query(n="x",cf="multi") String[] x) {
+			return x;
+		}
+		@RestMethod
+		public Object b(@Query(n="x",cf="multi") int[] x) {
+			return x;
+		}
+		@RestMethod
+		public Object c(@Query(n="x",cf="multi") List<String> x) {
+			return x;
+		}
+		@RestMethod
+		public Object d(@Query(n="x",cf="multi") List<Integer> x) {
+			return x;
+		}
+		@RestMethod
+		public Object e(@Query(n="x",cf="multi",items=@Items(f="uon")) C1[] x) {
+			return x;
+		}
+		@RestMethod
+		public Object f(@Query(n="x",cf="multi",items=@Items(f="uon")) List<C1> x) {
+			return x;
+		}
+	}
+
+	@Test
+	public void c01_multipartParams() throws Exception {
+		RestClient c = MockRestClient.build(C.class);
+		c.get("/a?x=a").run().assertBody().is("['a']");
+		c.get("/a?x=a&x=b").run().assertBody().is("['a','b']");
+		c.get("/b?x=1").run().assertBody().is("[1]");
+		c.get("/b?x=1&x=2").run().assertBody().is("[1,2]");
+		c.get("/c?x=a").run().assertBody().is("['a']");
+		c.get("/c?x=a&x=b").run().assertBody().is("['a','b']");
+		c.get("/d?x=1").run().assertBody().is("[1]");
+		c.get("/d?x=1&x=2").run().assertBody().is("[1,2]");
+		c.get("/e?x=a=1,b=2,c=false").run().assertBody().is("[{a:'1',b:2,c:false}]");
+		c.get("/e?x=a=1,b=2,c=false&x=a=3,b=4,c=true").run().assertBody().is("[{a:'1',b:2,c:false},{a:'3',b:4,c:true}]");
+		c.get("/f?x=a=1,b=2,c=false").run().assertBody().is("[{a:'1',b:2,c:false}]");
+		c.get("/f?x=a=1,b=2,c=false&x=a=3,b=4,c=true").run().assertBody().is("[{a:'1',b:2,c:false},{a:'3',b:4,c:true}]");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Default values.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class D {
+		@RestMethod(defaultQuery={"f1:1","f2=2"," f3 : 3 "})
+		public OMap a(RequestQuery query) {
+			return OMap.of()
+				.a("f1", query.getString("f1"))
+				.a("f2", query.getString("f2"))
+				.a("f3", query.getString("f3"));
+		}
+		@RestMethod
+		public OMap b(@Query("f1") String f1, @Query("f2") String f2, @Query("f3") String f3) {
+			return OMap.of()
+				.a("f1", f1)
+				.a("f2", f2)
+				.a("f3", f3);
+		}
+		@RestMethod
+		public OMap c(@Query(n="f1",df="1") String f1, @Query(n="f2",df="2") String f2, @Query(n="f3",df="3") String f3) {
+			return OMap.of()
+				.a("f1", f1)
+				.a("f2", f2)
+				.a("f3", f3);
+		}
+		@RestMethod(defaultQuery={"f1:1","f2=2"," f3 : 3 "})
+		public OMap d(@Query(n="f1",df="4") String f1, @Query(n="f2",df="5") String f2, @Query(n="f3",df="6") String f3) {
+			return OMap.of()
+				.a("f1", f1)
+				.a("f2", f2)
+				.a("f3", f3);
+		}
+	}
+
+	@Test
+	public void d01_defaultValues() throws Exception {
+		RestClient d = MockRestClient.build(D.class);
+		d.get("/a").run().assertBody().is("{f1:'1',f2:'2',f3:'3'}");
+		d.get("/a").query("f1",4).query("f2",5).query("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
+		d.get("/b").run().assertBody().is("{f1:null,f2:null,f3:null}");
+		d.get("/b").query("f1",4).query("f2",5).query("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
+		d.get("/c").run().assertBody().is("{f1:'1',f2:'2',f3:'3'}");
+		d.get("/c").query("f1",4).query("f2",5).query("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
+		d.get("/d").run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
+		d.get("/d").query("f1",7).query("f2",8).query("f3",9).run().assertBody().is("{f1:'7',f2:'8',f3:'9'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Optional query parameter.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class)
+	public static class E {
+		@RestMethod
+		public Object a(@Query("f1") Optional<Integer> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod
+		public Object b(@Query("f1") Optional<ABean> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod
+		public Object c(@Query("f1") Optional<List<ABean>> f1) throws Exception {
+			assertNotNull(f1);
+			return f1;
+		}
+		@RestMethod
+		public Object d(@Query("f1") List<Optional<ABean>> f1) throws Exception {
+			return f1;
+		}
+	}
+
+	@Test
+	public void e01_optionalParams() throws Exception {
+		RestClient e = MockRestClient.buildJson(E.class);
+		e.get("/a?f1=123")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("123");
+		e.get("/a")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+		e.get("/b?f1=a=1,b=foo")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("{a:1,b:'foo'}");
+		e.get("/b")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+		e.get("/c?f1=@((a=1,b=foo))")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+		e.get("/c")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+		e.get("/d?f1=@((a=1,b=foo))")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[{a:1,b:'foo'}]");
+		e.get("/d")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("null");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseBodyAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseBody_Test.java
similarity index 97%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseBodyAnnotationTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseBody_Test.java
index 6cbbdd4..a73ca36 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseBodyAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseBody_Test.java
@@ -19,6 +19,6 @@
  * Tests the @Response annotation.
  */
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class ResponseBodyAnnotationTest {
+public class ResponseBody_Test {
 
 }
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java
deleted file mode 100644
index 30797e8..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java
+++ /dev/null
@@ -1,279 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.apache.juneau.rest.testutils.TestUtils.*;
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class ResponseHeaderAnnotationTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest
-	public static class A {
-		@RestMethod
-		public void a01(Value<A01> h) {
-			h.set(new A01());
-		}
-		@RestMethod
-		public void a02(@ResponseHeader(name="Foo") Value<String> h) {
-			h.set("foo");
-		}
-		@RestMethod
-		public void a03(@ResponseHeader(name="Bar") Value<A01> h) {
-			h.set(new A01());
-		}
-	}
-
-	@ResponseHeader(name="Foo")
-	public static class A01 {
-		@Override
-		public String toString() {return "foo";}
-	}
-
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01_valueOnParameterPojo() throws Exception {
-		a.get("/a01")
-			.run()
-			.assertCode().is(200)
-			.assertStringHeader("Foo").is("foo");
-	}
-	@Test
-	public void a02_valueOnParameterString() throws Exception {
-		a.get("/a02")
-			.run()
-			.assertCode().is(200)
-			.assertStringHeader("Foo").is("foo");
-	}
-	@Test
-	public void a03_valueOnParameterOverrideName() throws Exception {
-		a.get("/a03")
-			.run()
-			.assertCode().is(200)
-			.assertStringHeader("Bar").is("foo");
-	}
-
-	//=================================================================================================================
-	// @ResponseHeader on POJO
-	//=================================================================================================================
-
-	@Rest
-	public static class SA {
-
-		@ResponseHeader(
-			name="H",
-			description="a",
-			type="string"
-		)
-		public static class SA01 {}
-		@RestMethod
-		public void sa01(Value<SA01> h) {}
-
-		@ResponseHeader(
-			name="H",
-			api={
-				"description:'a',",
-				"type:'string'"
-			}
-		)
-		public static class SA02 {}
-		@RestMethod
-		public void sa02(Value<SA02> h) {}
-
-		@ResponseHeader(
-			name="H",
-			api={
-				"description:'b',",
-				"type:'number'"
-			},
-			description="a",
-			type="string"
-		)
-		public static class SA03 {}
-		@RestMethod
-		public void sa03(Value<SA03> h) {}
-
-		@ResponseHeader(name="H", code=100)
-		public static class SA04 {}
-		@RestMethod
-		public void sa04(Value<SA04> h) {}
-
-		@ResponseHeader(name="H", code={100,101})
-		public static class SA05 {}
-		@RestMethod
-		public void sa05(Value<SA05> h) {}
-
-		@ResponseHeader(name="H", description="a")
-		public static class SA07 {}
-		@RestMethod
-		public void sa07(Value<SA07> h) {}
-
-		@ResponseHeader("H")
-		public static class SA08 {}
-		@RestMethod
-		public void sa08(Value<SA08> h) {}
-	}
-
-	static Swagger sa = getSwagger(SA.class);
-
-	@Test
-	public void sa01_ResponseHeader_onPojo_basic() throws Exception {
-		HeaderInfo x = sa.getResponseInfo("/sa01","get",200).getHeader("H");
-		assertEquals("a", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sa02_ResponseHeader_onPojo_api() throws Exception {
-		HeaderInfo x = sa.getResponseInfo("/sa02","get",200).getHeader("H");
-		assertEquals("a", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sa03_ResponseHeader_onPojo_mixed() throws Exception {
-		HeaderInfo x = sa.getResponseInfo("/sa03","get",200).getHeader("H");
-		assertEquals("a", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sa04_ResponseHeader_onPojo_code() throws Exception {
-		HeaderInfo x = sa.getResponseInfo("/sa04","get",100).getHeader("H");
-		assertNotNull(x);
-	}
-	@Test
-	public void sa05_ResponseHeader_onPojo_codes() throws Exception {
-		Operation x = sa.getOperation("/sa05","get");
-		assertNotNull(x.getResponse(100).getHeader("H"));
-		assertNotNull(x.getResponse(101).getHeader("H"));
-	}
-	@Test
-	public void sa07_ResponseHeader_onPojo_nocode() throws Exception {
-		HeaderInfo x = sa.getResponseInfo("/sa07","get",200).getHeader("H");
-		assertEquals("a", x.getDescription());
-	}
-	@Test
-	public void sa08_ResponseHeader_onPojo_value() throws Exception {
-		HeaderInfo x = sa.getResponseInfo("/sa08","get",200).getHeader("H");
-		assertNotNull(x);
-	}
-
-	//=================================================================================================================
-	// @ResponseHeader on parameter
-	//=================================================================================================================
-
-	@Rest
-	public static class SB {
-
-		public static class SB01 {}
-		@RestMethod
-		public void sb01(
-			@ResponseHeader(
-				name="H",
-				description="a",
-				type="string"
-			) Value<SB01> h) {}
-
-		public static class SB02 {}
-		@RestMethod
-		public void sb02(
-			@ResponseHeader(
-				name="H",
-				api={
-					"description:'a',",
-					"type:'string'"
-				}
-			) Value<SB02> h) {}
-
-		public static class SB03 {}
-		@RestMethod
-		public void sb03(
-			@ResponseHeader(
-				name="H",
-				api={
-					"description:'b',",
-					"type:'number'"
-				},
-				description="a",
-				type="string"
-			) Value<SB03> h) {}
-
-		public static class SB04 {}
-		@RestMethod
-		public void sb04(@ResponseHeader(name="H", code=100) Value<SB04> h) {}
-
-		public static class SB05 {}
-		@RestMethod
-		public void sb05(@ResponseHeader(name="H", code={100,101}) Value<SB05> h) {}
-
-		public static class SB07 {}
-		@RestMethod
-		public void sb07(@ResponseHeader(name="H", description="a") Value<SB07> h) {}
-
-		public static class SB08 {}
-		@RestMethod
-		public void sb08(@ResponseHeader("H") Value<SB08> h) {}
-	}
-
-	static Swagger sb = getSwagger(SB.class);
-
-	@Test
-	public void sb01_ResponseHeader_onPojo_basic() throws Exception {
-		HeaderInfo x = sb.getResponseInfo("/sb01","get",200).getHeader("H");
-		assertEquals("a", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sb02_ResponseHeader_onPojo_api() throws Exception {
-		HeaderInfo x = sb.getResponseInfo("/sb02","get",200).getHeader("H");
-		assertEquals("a", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sb03_ResponseHeader_onPojo_mixed() throws Exception {
-		HeaderInfo x = sb.getResponseInfo("/sb03","get",200).getHeader("H");
-		assertEquals("a", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sb04_ResponseHeader_onPojo_code() throws Exception {
-		HeaderInfo x = sb.getResponseInfo("/sb04","get",100).getHeader("H");
-		assertNotNull(x);
-	}
-	@Test
-	public void sb05_ResponseHeader_onPojo_codes() throws Exception {
-		Operation x = sb.getOperation("/sb05","get");
-		assertNotNull(x.getResponse(100).getHeader("H"));
-		assertNotNull(x.getResponse(101).getHeader("H"));
-	}
-	@Test
-	public void sb07_ResponseHeader_onPojo_nocode() throws Exception {
-		HeaderInfo x = sb.getResponseInfo("/sb07","get",200).getHeader("H");
-		assertEquals("a", x.getDescription());
-	}
-	@Test
-	public void sb08_ResponseHeader_onPojo_value() throws Exception {
-		HeaderInfo x = sb.getResponseInfo("/sb08","get",200).getHeader("H");
-		assertNotNull(x);
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseHeader_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseHeader_Test.java
new file mode 100644
index 0000000..3f43495
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseHeader_Test.java
@@ -0,0 +1,252 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.rest.testutils.TestUtils.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class ResponseHeader_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @ResponseHeader on method parameters
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+		@RestMethod
+		public void a(Value<A1> h) {
+			h.set(new A1());
+		}
+		@RestMethod
+		public void b(@ResponseHeader(name="Foo") Value<String> h) {
+			h.set("foo");
+		}
+		@RestMethod
+		public void c(@ResponseHeader(name="Bar") Value<A1> h) {
+			h.set(new A1());
+		}
+	}
+
+	@ResponseHeader(name="Foo")
+	public static class A1 {
+		@Override
+		public String toString() {return "foo";}
+	}
+
+	@Test
+	public void a01_methodParameters() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/a")
+			.run()
+			.assertCode().is(200)
+			.assertStringHeader("Foo").is("foo");
+		a.get("/b")
+			.run()
+			.assertCode().is(200)
+			.assertStringHeader("Foo").is("foo");
+		a.get("/c")
+			.run()
+			.assertCode().is(200)
+			.assertStringHeader("Bar").is("foo");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @ResponseHeader swagger on POJOs
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class B {
+
+		@ResponseHeader(
+			name="H",
+			description="a",
+			type="string"
+		)
+		public static class B1 {}
+		@RestMethod
+		public void a(Value<B1> h) {}
+
+		@ResponseHeader(
+			name="H",
+			api={
+				"description:'a',",
+				"type:'string'"
+			}
+		)
+		public static class B2 {}
+		@RestMethod
+		public void b(Value<B2> h) {}
+
+		@ResponseHeader(
+			name="H",
+			api={
+				"description:'b',",
+				"type:'number'"
+			},
+			description="a",
+			type="string"
+		)
+		public static class B3 {}
+		@RestMethod
+		public void c(Value<B3> h) {}
+
+		@ResponseHeader(name="H", code=100)
+		public static class B4 {}
+		@RestMethod
+		public void d(Value<B4> h) {}
+
+		@ResponseHeader(name="H", code={100,101})
+		public static class B5 {}
+		@RestMethod
+		public void e(Value<B5> h) {}
+
+		@ResponseHeader(name="H", description="a")
+		public static class B6 {}
+		@RestMethod
+		public void f(Value<B6> h) {}
+
+		@ResponseHeader("H")
+		public static class B7 {}
+		@RestMethod
+		public void g(Value<B7> h) {}
+	}
+
+
+	@Test
+	public void b01_swagger_onPojo() throws Exception {
+		HeaderInfo x;
+		Swagger s = getSwagger(B.class);
+
+		x = s.getResponseInfo("/a","get",200).getHeader("H");
+		assertEquals("a", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getResponseInfo("/b","get",200).getHeader("H");
+		assertEquals("a", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getResponseInfo("/c","get",200).getHeader("H");
+		assertEquals("a", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getResponseInfo("/d","get",100).getHeader("H");
+		assertNotNull(x);
+
+		Operation x2 = s.getOperation("/e","get");
+		assertNotNull(x2.getResponse(100).getHeader("H"));
+		assertNotNull(x2.getResponse(101).getHeader("H"));
+
+		x = s.getResponseInfo("/f","get",200).getHeader("H");
+		assertEquals("a", x.getDescription());
+
+		x = s.getResponseInfo("/g","get",200).getHeader("H");
+		assertNotNull(x);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @ResponseHeader swagger on method parameters
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class C {
+
+		public static class C1 {}
+		@RestMethod
+		public void a(
+			@ResponseHeader(
+				name="H",
+				description="a",
+				type="string"
+			) Value<C1> h) {}
+
+		public static class C2 {}
+		@RestMethod
+		public void b(
+			@ResponseHeader(
+				name="H",
+				api={
+					"description:'a',",
+					"type:'string'"
+				}
+			) Value<C2> h) {}
+
+		public static class C3 {}
+		@RestMethod
+		public void c(
+			@ResponseHeader(
+				name="H",
+				api={
+					"description:'b',",
+					"type:'number'"
+				},
+				description="a",
+				type="string"
+			) Value<C3> h) {}
+
+		public static class C4 {}
+		@RestMethod
+		public void d(@ResponseHeader(name="H", code=100) Value<C4> h) {}
+
+		public static class C5 {}
+		@RestMethod
+		public void e(@ResponseHeader(name="H", code={100,101}) Value<C5> h) {}
+
+		public static class C6 {}
+		@RestMethod
+		public void f(@ResponseHeader(name="H", description="a") Value<C6> h) {}
+
+		public static class C7 {}
+		@RestMethod
+		public void g(@ResponseHeader("H") Value<C7> h) {}
+	}
+
+	@Test
+	public void c01_swagger_onMethodParameters() throws Exception {
+		HeaderInfo x;
+		Swagger sc = getSwagger(C.class);
+
+		x = sc.getResponseInfo("/a","get",200).getHeader("H");
+		assertEquals("a", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = sc.getResponseInfo("/b","get",200).getHeader("H");
+		assertEquals("a", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = sc.getResponseInfo("/c","get",200).getHeader("H");
+		assertEquals("a", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = sc.getResponseInfo("/d","get",100).getHeader("H");
+		assertNotNull(x);
+
+		Operation x2 = sc.getOperation("/e","get");
+		assertNotNull(x2.getResponse(100).getHeader("H"));
+		assertNotNull(x2.getResponse(101).getHeader("H"));
+
+		x = sc.getResponseInfo("/f","get",200).getHeader("H");
+		assertEquals("a", x.getDescription());
+
+		x = sc.getResponseInfo("/g","get",200).getHeader("H");
+		assertNotNull(x);
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseStatus_Test.java
similarity index 79%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseStatus_Test.java
index 2b38e8f..8611e1a 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/ResponseStatus_Test.java
@@ -16,29 +16,25 @@
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.rest.client2.*;
 import org.apache.juneau.rest.mock2.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class ResponseStatusAnnotationTest {
-
-	//=================================================================================================================
-	// Test on parameter
-	//=================================================================================================================
+public class ResponseStatus_Test {
 
 	@Rest
 	public static class A {
 		@RestMethod
-		public void a01(@ResponseStatus Value<Integer> status) {
+		public void a(@ResponseStatus Value<Integer> status) {
 			status.set(202);
 		}
 	}
 
-	static MockRestClient a = MockRestClient.build(A.class);
-
 	@Test
-	public void a01() throws Exception {
-		a.get("/a01")
+	public void a01_onMethodParameter() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/a")
 			.run()
 			.assertCode().is(202);
 	}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Response_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Response_Test.java
new file mode 100644
index 0000000..a399346
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Response_Test.java
@@ -0,0 +1,348 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.collections.*;
+import org.apache.juneau.http.annotation.Response;
+import org.apache.juneau.json.*;
+import org.apache.juneau.jsonschema.annotation.Schema;
+import org.apache.juneau.oapi.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@SuppressWarnings({"serial"})
+@FixMethodOrder(NAME_ASCENDING)
+public class Response_Test {
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// HTTP status code
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+		@RestMethod
+		public A1 a() {
+			return new A1();
+		}
+		@RestMethod
+		public String b() throws A2 {
+			throw new A2();
+		}
+	}
+
+	@Response(code=201)
+	public static class A1 {
+		@Override
+		public String toString() {return "foo";}
+	}
+
+	@Response(code=501)
+	public static class A2 extends Exception {
+		@Override
+		public String toString() {return "foo";}
+	}
+
+	@Test
+	public void a01_httpstatusCodes() throws Exception {
+		RestClient a = MockRestClient.buildLax(A.class);
+		a.get("/a")
+			.run()
+			.assertCode().is(201)
+			.assertBody().is("foo");
+		a.get("/b")
+			.run()
+			.assertCode().is(501);
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// OpenApiSerializer
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=OpenApiSerializer.class,defaultAccept="text/openapi")
+	public static class B {
+		@Response
+		@RestMethod
+		public String a() {
+			return "foo";
+		}
+		@RestMethod
+		public B1 b() {
+			return new B1();
+		}
+		@RestMethod
+		public String c() throws B2 {
+			throw new B2();
+		}
+		@RestMethod
+		public void d(@Response Value<String> value) {
+			value.set("foo");
+		}
+	}
+
+	@Response
+	public static class B1 {
+		@Override
+		public String toString() {return "foo";}
+	}
+
+	@Response
+	public static class B2 extends Exception {
+		@Override
+		public String toString() {return "foo";}
+	}
+
+	@Test
+	public void b01_openApi() throws Exception {
+		RestClient b = MockRestClient.buildLax(B.class);
+		b.get("/a")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo");
+		b.get("/b")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo");
+		b.get("/c")
+			.run()
+			.assertCode().is(500)
+			.assertBody().is("foo");
+		b.get("/d")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo");
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// OpenAPI with schema
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=OpenApiSerializer.class,defaultAccept="text/openapi")
+	public static class D {
+		@Response(schema=@Schema(collectionFormat="pipes"))
+		@RestMethod
+		public String[] a() {
+			return new String[]{"foo","bar"};
+		}
+		@Response(schema=@Schema(type="string",format="byte"))
+		@RestMethod
+		public byte[] b() {
+			return "foo".getBytes();
+		}
+		@RestMethod
+		public D1 c() {
+			return new D1();
+		}
+		@RestMethod
+		public D2 d() {
+			return new D2();
+		}
+		@RestMethod
+		public String e() throws D3 {
+			throw new D3();
+		}
+		@RestMethod
+		public String f() throws D4 {
+			throw new D4();
+		}
+		@RestMethod
+		public void g(@Response(schema=@Schema(collectionFormat="pipes")) Value<String[]> value) {
+			value.set(new String[]{"foo","bar"});
+		}
+		@RestMethod
+		public void h(@Response(schema=@Schema(type="string",format="byte")) Value<byte[]> value) {
+			value.set("foo".getBytes());
+		}
+	}
+
+	@Response(schema=@Schema(type="array",collectionFormat="pipes"))
+	public static class D1 {
+		public String[] toStringArray() {
+			return new String[]{"foo","bar"};
+		}
+	}
+
+	@Response(schema=@Schema(format="byte"))
+	public static class D2 {
+		public byte[] toByteArray() {
+			return "foo".getBytes();
+		}
+	}
+
+	@Response(schema=@Schema(type="array",collectionFormat="pipes"))
+	public static class D3 extends Exception {
+		public String[] toStringArray() {
+			return new String[]{"foo","bar"};
+		}
+	}
+
+	@Response(schema=@Schema(format="byte"))
+	public static class D4 extends Exception {
+		public byte[] toByteArray() {
+			return "foo".getBytes();
+		}
+	}
+
+	@Test
+	public void d01_openApi_withSchema() throws Exception {
+		RestClient d = MockRestClient.buildLax(D.class);
+		d.get("/a")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo|bar");
+		d.get("/b")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("Zm9v");
+		d.get("/c")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo|bar");
+		d.get("/d")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("Zm9v");
+		d.get("/e")
+			.run()
+			.assertCode().is(500)
+			.assertBody().is("foo|bar");
+		d.get("/f")
+			.run()
+			.assertCode().is(500)
+			.assertBody().is("Zm9v");
+		d.get("/g")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo|bar");
+		d.get("/h")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("Zm9v");
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// No serializers
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class E {
+		@RestMethod
+		public void a(@Response Value<E1> body) {
+			body.set(new E1());
+		}
+		@RestMethod
+		public void b(Value<E2> body) {
+			body.set(new E2());
+		}
+		@RestMethod
+		@Response
+		public E1 c() {
+			return new E1();
+		}
+		@RestMethod
+		public E2 d() {
+			return new E2();
+		}
+	}
+
+	public static class E1 {
+		@Override
+		public String toString() {return "foo";}
+	}
+
+	@Response
+	public static class E2 {
+		@Override
+		public String toString() {return "foo";}
+	}
+
+	@Test
+	public void e01_defaultSerialization() throws Exception {
+		RestClient e = MockRestClient.build(E.class);
+		e.get("/a")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo");
+		e.get("/b")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo");
+		e.get("/c")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo");
+		e.get("/d")
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("foo");
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// JSON Accept
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest(serializers=SimpleJsonSerializer.class)
+	public static class G {
+		@RestMethod
+		public void a(@Response Value<List<Integer>> body) {
+			body.set(AList.of(1,2));
+		}
+		@RestMethod
+		public void b(Value<G1> body) {
+			body.set(new G1());
+		}
+		@RestMethod
+		@Response
+		public List<Integer> c() {
+			return AList.of(1,2);
+		}
+		@RestMethod
+		public G1 d() {
+			return new G1();
+		}
+	}
+
+	@Response
+	public static class G1 extends ArrayList<Integer> {
+		public G1() {
+			add(1);
+			add(2);
+		}
+	}
+
+	@Test
+	public void g01_json() throws Exception {
+		RestClient g = MockRestClient.build(G.class);
+		g.get("/a").json()
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[1,2]");
+		g.get("/b").json()
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[1,2]");
+		g.get("/c").json()
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[1,2]");
+		g.get("/d").json()
+			.run()
+			.assertCode().is(200)
+			.assertBody().is("[1,2]");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestHookTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestHook_Test.java
similarity index 71%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestHookTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestHook_Test.java
index cf51a78..53896bc 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestHookTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestHook_Test.java
@@ -10,7 +10,7 @@
 // * "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.rest.annotation2;
+package org.apache.juneau.rest.annotation;
 
 import static org.apache.juneau.http.HttpMethod.*;
 import static org.apache.juneau.rest.annotation.HookEvent.*;
@@ -28,20 +28,22 @@
 import org.apache.juneau.http.header.*;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.RestResponse;
+import org.apache.juneau.rest.client2.*;
 import org.apache.juneau.rest.mock2.*;
 import org.apache.juneau.serializer.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestHookTest {
+public class RestHook_Test {
 
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// @RestHook(PRE_CALL)
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(
-		parsers=A01.class,
+		parsers=A1.class,
 		reqAttrs={
 			"p1:sp1", // Unchanged servlet-level property.
 			"p2:sp2", // Servlet-level property overridden by onPreCall.
@@ -62,27 +64,26 @@
 				req.getHeaders().put("Content-Type", overrideContentType);
 		}
 
-		@RestMethod(name=PUT, path="/propertiesOverriddenByAnnotation",
+		@RestMethod(name=PUT,
 			reqAttrs={
 				"p3:mp3",
 				"p4:mp4"
 			}
 		)
-		public String a01(@Body String in) {
+		public String a(@Body String in) {
 			return in;
 		}
 
-		@RestMethod(name=PUT, path="/propertiesOverriddenProgrammatically")
-		public String a02(RestRequest req, RequestAttributes attrs) throws Exception {
+		@RestMethod(name=PUT)
+		public String b(RestRequest req, RequestAttributes attrs) throws Exception {
 			attrs.put("p3", "pp3");
 			attrs.put("p4", "pp4");
 			return req.getBody().asType(String.class);
 		}
 	}
-	static MockRestClient a = MockRestClient.build(A.class);
 
-	public static class A01 extends ReaderParser {
-		public A01(PropertyStore ps) {
+	public static class A1 extends ReaderParser {
+		public A1(PropertyStore ps) {
 			super(ps, "text/a1", "text/a2", "text/a3");
 		}
 		@Override /* Parser */
@@ -98,23 +99,20 @@
 	}
 
 	@Test
-	public void a01_preCall_propertiesOverriddenByAnnotation() throws Exception {
-		a.put("/propertiesOverriddenByAnnotation", null).contentType("text/a1").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		a.put("/propertiesOverriddenByAnnotation", null).contentType("text/a1").header("Override-Content-Type", "text/a2").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+	public void a01_preCall() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.put("/a", null).contentType("text/a1").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		a.put("/a", null).contentType("text/a1").header("Override-Content-Type", "text/a2").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		a.put("/b", null).contentType("text/a1").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5");
+		a.put("/b", null).contentType("text/a1").header("Override-Content-Type", "text/a2").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5");
 	}
 
-	@Test
-	public void a02_preCall_propertiesOverriddenProgrammatically() throws Exception {
-		a.put("/propertiesOverriddenProgrammatically", null).contentType("text/a1").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5");
-		a.put("/propertiesOverriddenProgrammatically", null).contentType("text/a1").header("Override-Content-Type", "text/a2").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5");
-	}
-
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// @RestHook(POST_CALL)
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(
-		serializers=B01.class,
+		serializers=B1.class,
 		reqAttrs={
 			"p1:sp1", // Unchanged servlet-level property.
 			"p2:sp2", // Servlet-level property overridden by onPostCall.
@@ -138,19 +136,19 @@
 				attrs.put("Override-Content-Type", overrideContentType);
 		}
 
-		@RestMethod(name=PUT, path="/propertiesOverridenByAnnotation",
+		@RestMethod(name=PUT,
 			reqAttrs={
 				"p3:mp3",
 				"p4:mp4"
 			},
 			reqHeaders="Accept: text/s2"
 		)
-		public String b01() {
+		public String a() {
 			return null;
 		}
 
-		@RestMethod(name=PUT, path="/propertiesOverriddenProgramatically")
-		public String b02(RestRequest req, RequestAttributes attrs) throws Exception {
+		@RestMethod(name=PUT)
+		public String b(RestRequest req, RequestAttributes attrs) throws Exception {
 			attrs.put("p3", "pp3");
 			attrs.put("p4", "pp4");
 			String accept = req.getHeader("Accept");
@@ -159,10 +157,9 @@
 			return null;
 		}
 	}
-	static MockRestClient b = MockRestClient.build(B.class);
 
-	public static class B01 extends WriterSerializer {
-		public B01(PropertyStore ps) {
+	public static class B1 extends WriterSerializer {
+		public B1(PropertyStore ps) {
 			super(ps, "test/s1", "text/s1,text/s2,text/s3");
 		}
 		@Override /* Serializer */
@@ -184,37 +181,28 @@
 	}
 
 	@Test
-	public void b01a_postCall_propertiesOverridenByAnnotation() throws Exception {
-		b.put("/propertiesOverridenByAnnotation", null).accept("text/s1").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/propertiesOverridenByAnnotation", null).accept("text/s1").header("Override-Accept", "text/s2").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/propertiesOverridenByAnnotation", null).accept("text/s1").header("Override-Content-Type", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-	}
-	@Test
-	public void b01b_postCall_propertiesOverridenByAnnotation_defaultAccept() throws Exception {
-		b.put("/propertiesOverridenByAnnotation", null).run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/propertiesOverridenByAnnotation", null).header("Override-Accept", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/propertiesOverridenByAnnotation", null).header("Override-Content-Type", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-	}
-	@Test
-	public void b02a_postCall_propertiesOverriddenProgramatically() throws Exception {
-		b.put("/propertiesOverriddenProgramatically", null).accept("text/s1").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-		b.put("/propertiesOverriddenProgramatically", null).accept("text/s1").header("Override-Accept", "text/s2").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-		b.put("/propertiesOverriddenProgramatically", null).accept("text/s1").header("Override-Content-Type", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-	}
-	@Test
-	public void b02b_postCall_propertiesOverriddenProgramatically_defaultAccept() throws Exception {
-		b.put("/propertiesOverriddenProgramatically", null).run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-		b.put("/propertiesOverriddenProgramatically", null).header("Override-Accept", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-		b.put("/propertiesOverriddenProgramatically", null).header("Override-Content-Type", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+	public void b01_postCall() throws Exception {
+		RestClient b = MockRestClient.build(B.class);
+		b.put("/a", null).accept("text/s1").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).accept("text/s1").header("Override-Accept", "text/s2").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).accept("text/s1").header("Override-Content-Type", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).header("Override-Accept", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).header("Override-Content-Type", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/b", null).accept("text/s1").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).accept("text/s1").header("Override-Accept", "text/s2").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).accept("text/s1").header("Override-Content-Type", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).header("Override-Accept", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).header("Override-Content-Type", "text/s3").run().assertBody().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
 	}
 
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// @RestHook(INIT)
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(children={C_Super.class,C_Sub.class})
 	public static class C {}
-	static MockRestClient c = MockRestClient.build(C.class);
 
 	@Rest(path="/super")
 	public static class C_Super {
@@ -279,17 +267,17 @@
 
 	@Test
 	public void c01_init() throws Exception {
+		RestClient c = MockRestClient.build(C.class);
 		c.get("/super/events").run().assertBody().is("['super-1a','super-1b','super-1c','super-2a']");
 		c.get("/sub/events").run().assertBody().is("['sub-1a','sub-1b','sub-1c','super-2a','sub-2b']");
 		c.get("/sub/child/events").run().assertBody().is("['super-1a','super-1b','child-1c','super-2a','child-2b']");
 	}
 
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// @RestHook(POST_INIT)
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	@Rest(children={D_Super.class,D_Sub.class})
 	public static class D {}
-	static MockRestClient d = MockRestClient.build(D.class);
 
 	@Rest(path="/super")
 	public static class D_Super {
@@ -367,18 +355,16 @@
 
 	@Test
 	public void d01_postInit() throws Exception {
+		RestClient d = MockRestClient.build(D.class);
 		d.get("/super/events").run().assertBody().is("['super-1a','super-1b','super-1c','super-2a']");
 		d.get("/sub/events").run().assertBody().is("['sub-1a','sub-1b','sub-1c','super-2a','sub-2b']");
 		d.get("/sub/child/events").run().assertBody().is("['super-1a','super-1b','child-1c','super-2a','child-2b']");
-	}
-	@Test
-	public void d02_postInit_order() throws Exception {
 		d.get("/sub/lastCalled").run().assertBody().is("CHILD");
 	}
 
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// @RestHook(POST_INIT_CHILD_FIRST)
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(
 		children={
@@ -387,7 +373,6 @@
 		}
 	)
 	public static class E {}
-	static MockRestClient e = MockRestClient.build(E.class);
 
 	@Rest(path="/super")
 	public static class E_Super {
@@ -465,18 +450,16 @@
 
 	@Test
 	public void e01_postInitChildFirst() throws Exception {
+		RestClient e = MockRestClient.build(E.class);
 		e.get("/super/postInitChildFirstEvents").run().assertBody().is("['super-1a','super-1b','super-1c','super-2a']");
 		e.get("/sub/postInitChildFirstEvents").run().assertBody().is("['sub-1a','sub-1b','sub-1c','super-2a','sub-2b']");
 		e.get("/sub/child/postInitChildFirstEvents").run().assertBody().is("['super-1a','super-1b','child-1c','super-2a','child-2b']");
-	}
-	@Test
-	public void e02_postInitChildFirst_order() throws Exception {
 		e.get("/sub/lastCalled").run().assertBody().is("PARENT");
 	}
 
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// @RestHook(START_CALL)
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest
 	public static class F extends F_Parent {
@@ -494,7 +477,7 @@
 			res.setHeader("start4-called", "true");
 		}
 		@RestMethod(path="/")
-		public OMap getHeaders(RestRequest req, RestResponse res) {
+		public OMap a(RestRequest req, RestResponse res) {
 			return OMap.of()
 				.a("1", res.getHeader("start1-called"))
 				.a("2", res.getHeader("start2-called"))
@@ -502,7 +485,6 @@
 				.a("4", res.getHeader("start4-called"));
 		}
 	}
-	static MockRestClient f = MockRestClient.build(F.class);
 
 	public static class F_Parent {
 		private boolean start1Called;
@@ -522,12 +504,13 @@
 
 	@Test
 	public void f01_startCall() throws Exception {
+		RestClient f = MockRestClient.build(F.class);
 		f.get("/").run().assertBody().is("{'1':'true','2':'true','3':'true','4':'true'}");
 	}
 
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// @RestHook(PRE_CALL)
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest
 	public static class G extends G_Parent {
@@ -545,7 +528,7 @@
 			res.setHeader("pre4-called", "true");
 		}
 		@RestMethod(path="/")
-		public OMap getHeaders(RestRequest req, RestResponse res) {
+		public OMap a(RestRequest req, RestResponse res) {
 			return OMap.of()
 				.a("1", res.getHeader("pre1-called"))
 				.a("2", res.getHeader("pre2-called"))
@@ -553,7 +536,6 @@
 				.a("4", res.getHeader("pre4-called"));
 		}
 	}
-	static MockRestClient g = MockRestClient.build(G.class);
 
 	public static class G_Parent {
 		private boolean pre1Called;
@@ -573,12 +555,13 @@
 
 	@Test
 	public void g01_preCall() throws Exception {
+		RestClient g = MockRestClient.build(G.class);
 		g.get("/").run().assertBody().is("{'1':'true','2':'true','3':'true','4':'true'}");
 	}
 
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// @RestHook(POST_CALL)
-	//====================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest
 	public static class H extends H_Parent {
@@ -596,11 +579,10 @@
 			res.setHeader("post4-called", "true");
 		}
 		@RestMethod(path="/")
-		public String doGet() {
+		public String a() {
 			return "OK";
 		}
 	}
-	static MockRestClient h = MockRestClient.build(H.class);
 
 	public static class H_Parent {
 		private boolean post1Called;
@@ -620,6 +602,7 @@
 
 	@Test
 	public void h01_postCall() throws Exception {
+		RestClient h = MockRestClient.build(H.class);
 		h.get("/").run()
 			.assertStringHeader("post1-called").is("true")
 			.assertStringHeader("post2-called").is("true")
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodBpiTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodBpiTest.java
deleted file mode 100644
index a015d9b..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodBpiTest.java
+++ /dev/null
@@ -1,533 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.annotation.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class RestMethodBpiTest {
-
-	//=================================================================================================================
-	// BPI on normal bean
-	//=================================================================================================================
-
-	public static class A extends BasicRestServlet {
-		private static final long serialVersionUID = 1L;
-
-		@RestMethod(bpi="MyBeanA: a,_b")
-		public Object a01() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod(bpi="MyBeanA: a")
-		public Object a02() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod(bpi="MyBeanA: _b")
-		public Object a03() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="MyBeanA: a,_b")
-		public Object a04() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="MyBeanA: a")
-		public Object a05() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="MyBeanA: _b")
-		public Object a06() throws Exception {
-			return new MyBeanA().init();
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.get("/a01").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
-		a.get("/a01").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
-		a.get("/a01").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
-		a.get("/a01").uon().run().assertBody().is("(a=1,_b=foo)");
-		a.get("/a01").urlEnc().run().assertBody().is("a=1&_b=foo");
-	}
-	@Test
-	public void a02() throws Exception {
-		a.get("/a02").json().run().assertBody().is("{\"a\":1}");
-		a.get("/a02").xml().run().assertBody().contains("<object><a>1</a></object>");
-		a.get("/a02").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		a.get("/a02").uon().run().assertBody().is("(a=1)");
-		a.get("/a02").urlEnc().run().assertBody().is("a=1");
-	}
-	@Test
-	public void a03() throws Exception {
-		a.get("/a03").json().run().assertBody().is("{\"_b\":\"foo\"}");
-		a.get("/a03").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
-		a.get("/a03").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
-		a.get("/a03").uon().run().assertBody().is("(_b=foo)");
-		a.get("/a03").urlEnc().run().assertBody().is("_b=foo");
-	}
-
-	@Test
-	public void a04() throws Exception {
-		a.get("/a04").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
-		a.get("/a04").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
-		a.get("/a04").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
-		a.get("/a04").uon().run().assertBody().is("(a=1,_b=foo)");
-		a.get("/a04").urlEnc().run().assertBody().is("a=1&_b=foo");
-	}
-	@Test
-	public void a05() throws Exception {
-		a.get("/a05").json().run().assertBody().is("{\"a\":1}");
-		a.get("/a05").xml().run().assertBody().contains("<object><a>1</a></object>");
-		a.get("/a05").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		a.get("/a05").uon().run().assertBody().is("(a=1)");
-		a.get("/a05").urlEnc().run().assertBody().is("a=1");
-	}
-	@Test
-	public void a06() throws Exception {
-		a.get("/a06").json().run().assertBody().is("{\"_b\":\"foo\"}");
-		a.get("/a06").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
-		a.get("/a06").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
-		a.get("/a06").uon().run().assertBody().is("(_b=foo)");
-		a.get("/a06").urlEnc().run().assertBody().is("_b=foo");
-	}
-
-	//=================================================================================================================
-	// BPX on normal bean
-	//=================================================================================================================
-
-	public static class B extends BasicRestServlet {
-		private static final long serialVersionUID = 1L;
-
-		@RestMethod(bpx="MyBeanA: a,_b")
-		public Object b01() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod(bpx="MyBeanA: a")
-		public Object b02() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod(bpx="MyBeanA: _b")
-		public Object b03() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpx="MyBeanA: a,_b")
-		public Object b04() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpx="MyBeanA: a")
-		public Object b05() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpx="MyBeanA: _b")
-		public Object b06() throws Exception {
-			return new MyBeanA().init();
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.get("/b01").json().run().assertBody().is("{}");
-		b.get("/b01").xml().run().assertBody().contains("<object/>");
-		b.get("/b01").html().run().assertBody().contains("<table></table>");
-		b.get("/b01").uon().run().assertBody().is("()");
-		b.get("/b01").urlEnc().run().assertBody().is("");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.get("/b02").json().run().assertBody().is("{\"_b\":\"foo\"}");
-		b.get("/b02").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
-		b.get("/b02").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
-		b.get("/b02").uon().run().assertBody().is("(_b=foo)");
-		b.get("/b02").urlEnc().run().assertBody().is("_b=foo");
-	}
-	@Test
-	public void b03() throws Exception {
-		b.get("/b03").json().run().assertBody().is("{\"a\":1}");
-		b.get("/b03").xml().run().assertBody().contains("<object><a>1</a></object>");
-		b.get("/b03").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		b.get("/b03").uon().run().assertBody().is("(a=1)");
-		b.get("/b03").urlEnc().run().assertBody().is("a=1");
-	}
-	@Test
-	public void b04() throws Exception {
-		b.get("/b04").json().run().assertBody().is("{}");
-		b.get("/b04").xml().run().assertBody().contains("<object/>");
-		b.get("/b04").html().run().assertBody().contains("<table></table>");
-		b.get("/b04").uon().run().assertBody().is("()");
-		b.get("/b04").urlEnc().run().assertBody().is("");
-	}
-	@Test
-	public void b05() throws Exception {
-		b.get("/b05").json().run().assertBody().is("{\"_b\":\"foo\"}");
-		b.get("/b05").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
-		b.get("/b05").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
-		b.get("/b05").uon().run().assertBody().is("(_b=foo)");
-		b.get("/b05").urlEnc().run().assertBody().is("_b=foo");
-	}
-	@Test
-	public void b06() throws Exception {
-		b.get("/b06").json().run().assertBody().is("{\"a\":1}");
-		b.get("/b06").xml().run().assertBody().contains("<object><a>1</a></object>");
-		b.get("/b06").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		b.get("/b06").uon().run().assertBody().is("(a=1)");
-		b.get("/b06").urlEnc().run().assertBody().is("a=1");
-	}
-
-	//=================================================================================================================
-	// BPI on bean using @Bean(properties)
-	//=================================================================================================================
-
-	public static class C extends BasicRestServlet {
-		private static final long serialVersionUID = 1L;
-
-		@RestMethod(bpi="MyBeanB: a,_b")
-		public Object c01() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod(bpi="MyBeanB: a")
-		public Object c02() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod(bpi="MyBeanB: _b")
-		public Object c03() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="MyBeanB: a,_b")
-		public Object c04() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="MyBeanB: a")
-		public Object c05() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="MyBeanB: _b")
-		public Object c06() throws Exception {
-			return new MyBeanB().init();
-		}
-	}
-	static MockRestClient c = MockRestClient.build(C.class);
-
-	@Test
-	public void c01() throws Exception {
-		c.get("/c01").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
-		c.get("/c01").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
-		c.get("/c01").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
-		c.get("/c01").uon().run().assertBody().is("(a=1,_b=foo)");
-		c.get("/c01").urlEnc().run().assertBody().is("a=1&_b=foo");
-	}
-	@Test
-	public void c02() throws Exception {
-		c.get("/c02").json().run().assertBody().is("{\"a\":1}");
-		c.get("/c02").xml().run().assertBody().contains("<object><a>1</a></object>");
-		c.get("/c02").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		c.get("/c02").uon().run().assertBody().is("(a=1)");
-		c.get("/c02").urlEnc().run().assertBody().is("a=1");
-	}
-	@Test
-	public void c03() throws Exception {
-		c.get("/c03").json().run().assertBody().is("{\"_b\":\"foo\"}");
-		c.get("/c03").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
-		c.get("/c03").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
-		c.get("/c03").uon().run().assertBody().is("(_b=foo)");
-		c.get("/c03").urlEnc().run().assertBody().is("_b=foo");
-	}
-	@Test
-	public void c04() throws Exception {
-		c.get("/c04").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
-		c.get("/c04").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
-		c.get("/c04").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
-		c.get("/c04").uon().run().assertBody().is("(a=1,_b=foo)");
-		c.get("/c04").urlEnc().run().assertBody().is("a=1&_b=foo");
-	}
-	@Test
-	public void c05() throws Exception {
-		c.get("/c05").json().run().assertBody().is("{\"a\":1}");
-		c.get("/c05").xml().run().assertBody().contains("<object><a>1</a></object>");
-		c.get("/c05").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		c.get("/c05").uon().run().assertBody().is("(a=1)");
-		c.get("/c05").urlEnc().run().assertBody().is("a=1");
-	}
-	@Test
-	public void c06() throws Exception {
-		c.get("/c06").json().run().assertBody().is("{\"_b\":\"foo\"}");
-		c.get("/c06").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
-		c.get("/c06").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
-		c.get("/c06").uon().run().assertBody().is("(_b=foo)");
-		c.get("/c06").urlEnc().run().assertBody().is("_b=foo");
-	}
-
-	//=================================================================================================================
-	// BPX on bean using @Bean(properties)
-	//=================================================================================================================
-
-	public static class D extends BasicRestServlet {
-		private static final long serialVersionUID = 1L;
-
-		@RestMethod(bpx="MyBeanB: a,_b")
-		public Object d01() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod(bpx="MyBeanB: a")
-		public Object d02() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod(bpx="MyBeanB: _b")
-		public Object d03() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod
-		@BeanConfig(bpx="MyBeanB: a,_b")
-		public Object d04() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod
-		@BeanConfig(bpx="MyBeanB: a")
-		public Object d05() throws Exception {
-			return new MyBeanB().init();
-		}
-		@RestMethod
-		@BeanConfig(bpx="MyBeanB: _b")
-		public Object d06() throws Exception {
-			return new MyBeanB().init();
-		}
-	}
-	static MockRestClient d = MockRestClient.build(D.class);
-
-	@Test
-	public void d01() throws Exception {
-		d.get("/d01").json().run().assertBody().is("{}");
-		d.get("/d01").xml().run().assertBody().contains("<object/>");
-		d.get("/d01").html().run().assertBody().contains("<table></table>");
-		d.get("/d01").uon().run().assertBody().is("()");
-		d.get("/d01").urlEnc().run().assertBody().is("");
-	}
-	@Test
-	public void d02() throws Exception {
-		d.get("/d02").json().run().assertBody().is("{\"_b\":\"foo\"}");
-		d.get("/d02").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
-		d.get("/d02").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
-		d.get("/d02").uon().run().assertBody().is("(_b=foo)");
-		d.get("/d02").urlEnc().run().assertBody().is("_b=foo");
-	}
-	@Test
-	public void d03() throws Exception {
-		d.get("/d03").json().run().assertBody().is("{\"a\":1}");
-		d.get("/d03").xml().run().assertBody().contains("<object><a>1</a></object>");
-		d.get("/d03").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		d.get("/d03").uon().run().assertBody().is("(a=1)");
-		d.get("/d03").urlEnc().run().assertBody().is("a=1");
-	}
-	@Test
-	public void d04() throws Exception {
-		d.get("/d04").json().run().assertBody().is("{}");
-		d.get("/d04").xml().run().assertBody().contains("<object/>");
-		d.get("/d04").html().run().assertBody().contains("<table></table>");
-		d.get("/d04").uon().run().assertBody().is("()");
-		d.get("/d04").urlEnc().run().assertBody().is("");
-	}
-	@Test
-	public void d05() throws Exception {
-		d.get("/d05").json().run().assertBody().is("{\"_b\":\"foo\"}");
-		d.get("/d05").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
-		d.get("/d05").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
-		d.get("/d05").uon().run().assertBody().is("(_b=foo)");
-		d.get("/d05").urlEnc().run().assertBody().is("_b=foo");
-	}
-	@Test
-	public void d06() throws Exception {
-		d.get("/d06").json().run().assertBody().is("{\"a\":1}");
-		d.get("/d06").xml().run().assertBody().contains("<object><a>1</a></object>");
-		d.get("/d06").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		d.get("/d06").uon().run().assertBody().is("(a=1)");
-		d.get("/d06").urlEnc().run().assertBody().is("a=1");
-	}
-
-	//=================================================================================================================
-	// BPI meta-matching
-	//=================================================================================================================
-
-	public static class E extends BasicRestServlet {
-		private static final long serialVersionUID = 1L;
-
-		@RestMethod(bpi="*: a")
-		public Object e01() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="*: a")
-		public Object e02() throws Exception {
-			return new MyBeanA().init();
-		}
-	}
-	static MockRestClient e = MockRestClient.build(E.class);
-
-	@Test
-	public void e01() throws Exception {
-		e.get("/e01").json().run().assertBody().is("{\"a\":1}");
-		e.get("/e01").xml().run().assertBody().contains("<object><a>1</a></object>");
-		e.get("/e01").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		e.get("/e01").uon().run().assertBody().is("(a=1)");
-		e.get("/e01").urlEnc().run().assertBody().is("a=1");
-	}
-	@Test
-	public void e02() throws Exception {
-		e.get("/e02").json().run().assertBody().is("{\"a\":1}");
-		e.get("/e02").xml().run().assertBody().contains("<object><a>1</a></object>");
-		e.get("/e02").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		e.get("/e02").uon().run().assertBody().is("(a=1)");
-		e.get("/e02").urlEnc().run().assertBody().is("a=1");
-	}
-
-	//=================================================================================================================
-	// BPI fully-qualified class name
-	//=================================================================================================================
-
-	public static class F extends BasicRestServlet {
-		private static final long serialVersionUID = 1L;
-
-		@RestMethod(bpi="org.apache.juneau.rest.annotation.RestMethodBpiTest$MyBeanA: a")
-		public Object f01() throws Exception {
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="org.apache.juneau.rest.annotation.RestMethodBpiTest$MyBeanA: a")
-		public Object f02() throws Exception {
-			return new MyBeanA().init();
-		}
-	}
-	static MockRestClient f = MockRestClient.build(F.class);
-
-	@Test
-	public void f01() throws Exception {
-		f.get("/f01").json().run().assertBody().is("{\"a\":1}");
-		f.get("/f01").xml().run().assertBody().contains("<object><a>1</a></object>");
-		f.get("/f01").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		f.get("/f01").uon().run().assertBody().is("(a=1)");
-		f.get("/f01").urlEnc().run().assertBody().is("a=1");
-	}
-	@Test
-	public void f02() throws Exception {
-		f.get("/f02").json().run().assertBody().is("{\"a\":1}");
-		f.get("/f02").xml().run().assertBody().contains("<object><a>1</a></object>");
-		f.get("/f02").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
-		f.get("/f02").uon().run().assertBody().is("(a=1)");
-		f.get("/f02").urlEnc().run().assertBody().is("a=1");
-	}
-
-	//=================================================================================================================
-	// Negative matching
-	//=================================================================================================================
-
-	public static class G extends BasicRestServlet {
-		private static final long serialVersionUID = 1L;
-
-		@RestMethod(bpi="MyBean: a")
-		public Object g01() throws Exception {
-			// Should not match.
-			return new MyBeanA().init();
-		}
-		@RestMethod(bpi="MyBean*: a")
-		public Object g02() throws Exception {
-			// Should not match.  We don't support meta-matches in class names.
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="MyBean: a")
-		public Object g03() throws Exception {
-			// Should not match.
-			return new MyBeanA().init();
-		}
-		@RestMethod
-		@BeanConfig(bpi="MyBean*: a")
-		public Object g04() throws Exception {
-			// Should not match.  We don't support meta-matches in class names.
-			return new MyBeanA().init();
-		}
-	}
-	static MockRestClient g = MockRestClient.build(G.class);
-
-	@Test
-	public void g01() throws Exception {
-		g.get("/g01").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
-		g.get("/g01").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
-		g.get("/g01").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
-		g.get("/g01").uon().run().assertBody().is("(a=1,_b=foo)");
-		g.get("/g01").urlEnc().run().assertBody().is("a=1&_b=foo");
-	}
-	@Test
-	public void g02() throws Exception {
-		g.get("/g02").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
-		g.get("/g02").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
-		g.get("/g02").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
-		g.get("/g02").uon().run().assertBody().is("(a=1,_b=foo)");
-		g.get("/g02").urlEnc().run().assertBody().is("a=1&_b=foo");
-	}
-	@Test
-	public void g03() throws Exception {
-		g.get("/g03").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
-		g.get("/g03").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
-		g.get("/g03").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
-		g.get("/g03").uon().run().assertBody().is("(a=1,_b=foo)");
-		g.get("/g03").urlEnc().run().assertBody().is("a=1&_b=foo");
-	}
-	@Test
-	public void g04() throws Exception {
-		g.get("/g04").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
-		g.get("/g04").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
-		g.get("/g04").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
-		g.get("/g04").uon().run().assertBody().is("(a=1,_b=foo)");
-		g.get("/g04").urlEnc().run().assertBody().is("a=1&_b=foo");
-	}
-
-	//=================================================================================================================
-	// Beans
-	//=================================================================================================================
-
-	public static class MyBeanA {
-		public int a;
-		@Beanp("_b") public String b;
-
-		MyBeanA init() {
-			a = 1;
-			b = "foo";
-			return this;
-		}
-	}
-
-	@Bean(bpi="_b,a")
-	public static class MyBeanB {
-		public int a;
-		@Beanp("_b") public String b;
-
-		MyBeanB init() {
-			a = 1;
-			b = "foo";
-			return this;
-		}
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java
deleted file mode 100644
index af71da4..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-// ***************************************************************************************************************************

-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

-// * with the License.  You may obtain a copy of the License at                                                              *

-// *                                                                                                                         *

-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

-// *                                                                                                                         *

-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

-// * specific language governing permissions and limitations under the License.                                              *

-// ***************************************************************************************************************************

-package org.apache.juneau.rest.annotation;

-

-import static org.apache.juneau.http.HttpMethod.*;

-import static org.junit.runners.MethodSorters.*;

-

-import org.apache.juneau.rest.mock2.*;

-import org.junit.*;

-

-@FixMethodOrder(NAME_ASCENDING)

-public class RestMethodPathTest {

-

-	//=================================================================================================================

-	// Overlapping URL patterns

-	//=================================================================================================================

-

-	@Rest

-	public static class A {

-		@RestMethod(name=GET, path="/")

-		public String a01a() {

-			return "a";

-		}

-		@RestMethod(name=GET, path="/*")

-		public String a01b() {

-			return "b";

-		}

-		@RestMethod(name=GET, path="/foo")

-		public String a01c() {

-			return "c";

-		}

-		@RestMethod(name=GET, path="/foo/*")

-		public String a01d() {

-			return "d";

-		}

-		@RestMethod(name=GET, path="/{id}")

-		public String a01e() {

-			return "e";

-		}

-		@RestMethod(name=GET, path="/{id}/*")

-		public String a01f() {

-			return "f";

-		}

-		@RestMethod(name=GET, path="/{id}/foo")

-		public String a01g() {

-			return "g";

-		}

-		@RestMethod(name=GET, path="/{id}/foo/*")

-		public String a01h() {

-			return "h";

-		}

-	}

-	static MockRestClient a = MockRestClient.build(A.class);

-

-	@Test

-	public void a01_overlappingPaths() throws Exception {

-		// [/] = [test5a]

-		// [/*] = [test5b]   -- Cannot get called.

-		// [/foo] = [test5c]

-		// [/foo/*] = [test5d]

-		// [/{id}] = [test5e]

-		// [/{id}/*] = [test5f]

-		// [/{id}/foo] = [test5g]

-		// [/{id}/foo/*] = [test5h]

-		a.get("/").run().assertBody().is("a");

-		a.get("/foo").run().assertBody().is("c");

-		a.get("/foo/x").run().assertBody().is("d");

-		a.get("/x").run().assertBody().is("e");

-		a.get("/x/x").run().assertBody().is("f");

-		a.get("/x/foo").run().assertBody().is("g");

-		a.get("/x/foo/x").run().assertBody().is("h");

-	}

-

-	//=================================================================================================================

-	// Overridden URL patterns

-	//=================================================================================================================

-

-	@Rest

-	public static class B1 {

-		@RestMethod(name=GET, path="/foo")

-		public String b01a() {

-			return "a";

-		}

-	}

-

-	@Rest

-	public static class B2 extends B1 {

-		@RestMethod(name=GET, path="/foo")

-		public String b02a() {  // Overrides method on parent.

-			return "b";

-		}

-	}

-	static MockRestClient b2 = MockRestClient.build(B2.class);

-

-	@Test

-	public void b01_pathOverriddenByChild() throws Exception {

-		b2.get("/foo").run().assertBody().is("b");

-	}

-}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_BeanConfig_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_BeanConfig_Test.java
new file mode 100644
index 0000000..c476831
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_BeanConfig_Test.java
@@ -0,0 +1,299 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+@SuppressWarnings("serial")
+public class RestMethod_BeanConfig_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @BeanConfig(bpi)
+	//------------------------------------------------------------------------------------------------------------------
+
+	public static class A1 extends BasicRestServlet {
+		@RestMethod
+		@BeanConfig(bpi="X1: a,_b")
+		public Object a() throws Exception {
+			return new X1().init();
+		}
+		@RestMethod
+		@BeanConfig(bpi="X1: a")
+		public Object b() throws Exception {
+			return new X1().init();
+		}
+		@RestMethod
+		@BeanConfig(bpi="X1: _b")
+		public Object c() throws Exception {
+			return new X1().init();
+		}
+	}
+
+	@Test
+	public void a01_bpi() throws Exception {
+		RestClient a1 = MockRestClient.build(A1.class);
+		a1.get("/a").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
+		a1.get("/a").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
+		a1.get("/a").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
+		a1.get("/a").uon().run().assertBody().is("(a=1,_b=foo)");
+		a1.get("/a").urlEnc().run().assertBody().is("a=1&_b=foo");
+		a1.get("/b").json().run().assertBody().is("{\"a\":1}");
+		a1.get("/b").xml().run().assertBody().contains("<object><a>1</a></object>");
+		a1.get("/b").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
+		a1.get("/b").uon().run().assertBody().is("(a=1)");
+		a1.get("/b").urlEnc().run().assertBody().is("a=1");
+		a1.get("/c").json().run().assertBody().is("{\"_b\":\"foo\"}");
+		a1.get("/c").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
+		a1.get("/c").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
+		a1.get("/c").uon().run().assertBody().is("(_b=foo)");
+		a1.get("/c").urlEnc().run().assertBody().is("_b=foo");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @BeanConfig(bpx)
+	//------------------------------------------------------------------------------------------------------------------
+
+	public static class A2 extends BasicRestServlet {
+		@RestMethod
+		@BeanConfig(bpx="X1: a,_b")
+		public Object a() throws Exception {
+			return new X1().init();
+		}
+		@RestMethod
+		@BeanConfig(bpx="X1: a")
+		public Object b() throws Exception {
+			return new X1().init();
+		}
+		@RestMethod
+		@BeanConfig(bpx="X1: _b")
+		public Object c() throws Exception {
+			return new X1().init();
+		}
+	}
+
+	@Test
+	public void a02_bpx() throws Exception {
+		RestClient a2 = MockRestClient.build(A2.class);
+		a2.get("/a").json().run().assertBody().is("{}");
+		a2.get("/a").xml().run().assertBody().contains("<object/>");
+		a2.get("/a").html().run().assertBody().contains("<table></table>");
+		a2.get("/a").uon().run().assertBody().is("()");
+		a2.get("/a").urlEnc().run().assertBody().is("");
+		a2.get("/b").json().run().assertBody().is("{\"_b\":\"foo\"}");
+		a2.get("/b").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
+		a2.get("/b").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
+		a2.get("/b").uon().run().assertBody().is("(_b=foo)");
+		a2.get("/b").urlEnc().run().assertBody().is("_b=foo");
+		a2.get("/c").json().run().assertBody().is("{\"a\":1}");
+		a2.get("/c").xml().run().assertBody().contains("<object><a>1</a></object>");
+		a2.get("/c").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
+		a2.get("/c").uon().run().assertBody().is("(a=1)");
+		a2.get("/c").urlEnc().run().assertBody().is("a=1");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @BeanConfig(bpi) and @Bean(bpi)
+	//------------------------------------------------------------------------------------------------------------------
+
+	public static class A3 extends BasicRestServlet {
+		@RestMethod
+		@BeanConfig(bpi="X2: a,_b")
+		public Object a() throws Exception {
+			return new X2().init();
+		}
+		@RestMethod
+		@BeanConfig(bpi="X2: a")
+		public Object b() throws Exception {
+			return new X2().init();
+		}
+		@RestMethod
+		@BeanConfig(bpi="X2: _b")
+		public Object c() throws Exception {
+			return new X2().init();
+		}
+	}
+
+	@Test
+	public void a03_bpi_overridesClass() throws Exception {
+		RestClient c = MockRestClient.build(A3.class);
+		c.get("/a").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
+		c.get("/a").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
+		c.get("/a").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
+		c.get("/a").uon().run().assertBody().is("(a=1,_b=foo)");
+		c.get("/a").urlEnc().run().assertBody().is("a=1&_b=foo");
+		c.get("/b").json().run().assertBody().is("{\"a\":1}");
+		c.get("/b").xml().run().assertBody().contains("<object><a>1</a></object>");
+		c.get("/b").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
+		c.get("/b").uon().run().assertBody().is("(a=1)");
+		c.get("/b").urlEnc().run().assertBody().is("a=1");
+		c.get("/c").json().run().assertBody().is("{\"_b\":\"foo\"}");
+		c.get("/c").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
+		c.get("/c").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
+		c.get("/c").uon().run().assertBody().is("(_b=foo)");
+		c.get("/c").urlEnc().run().assertBody().is("_b=foo");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @BeanConfig(bpx) and @Bean(bpi)
+	//------------------------------------------------------------------------------------------------------------------
+
+	public static class A4 extends BasicRestServlet {
+		@RestMethod
+		@BeanConfig(bpx="X2: a,_b")
+		public Object a() throws Exception {
+			return new X2().init();
+		}
+		@RestMethod
+		@BeanConfig(bpx="X2: a")
+		public Object b() throws Exception {
+			return new X2().init();
+		}
+		@RestMethod
+		@BeanConfig(bpx="X2: _b")
+		public Object c() throws Exception {
+			return new X2().init();
+		}
+	}
+
+	@Test
+	public void a04_bpx_overridesClass() throws Exception {
+		RestClient a4 = MockRestClient.build(A4.class);
+		a4.get("/a").json().run().assertBody().is("{}");
+		a4.get("/a").xml().run().assertBody().contains("<object/>");
+		a4.get("/a").html().run().assertBody().contains("<table></table>");
+		a4.get("/a").uon().run().assertBody().is("()");
+		a4.get("/a").urlEnc().run().assertBody().is("");
+		a4.get("/b").json().run().assertBody().is("{\"_b\":\"foo\"}");
+		a4.get("/b").xml().run().assertBody().contains("<object><_b>foo</_b></object>");
+		a4.get("/b").html().run().assertBody().contains("<table><tr><td>_b</td><td>foo</td></tr></table>");
+		a4.get("/b").uon().run().assertBody().is("(_b=foo)");
+		a4.get("/b").urlEnc().run().assertBody().is("_b=foo");
+		a4.get("/c").json().run().assertBody().is("{\"a\":1}");
+		a4.get("/c").xml().run().assertBody().contains("<object><a>1</a></object>");
+		a4.get("/c").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
+		a4.get("/c").uon().run().assertBody().is("(a=1)");
+		a4.get("/c").urlEnc().run().assertBody().is("a=1");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @BeanConfig(bpi), meta-matching
+	//------------------------------------------------------------------------------------------------------------------
+
+	public static class A5 extends BasicRestServlet {
+		@RestMethod
+		@BeanConfig(bpi="*: a")
+		public Object a() throws Exception {
+			return new X1().init();
+		}
+	}
+
+	@Test
+	public void a05_bpi_metaMatching() throws Exception {
+		RestClient a5 = MockRestClient.build(A5.class);
+		a5.get("/a").json().run().assertBody().is("{\"a\":1}");
+		a5.get("/a").xml().run().assertBody().contains("<object><a>1</a></object>");
+		a5.get("/a").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
+		a5.get("/a").uon().run().assertBody().is("(a=1)");
+		a5.get("/a").urlEnc().run().assertBody().is("a=1");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @BeanConfig(bpi), fully-qualified class name
+	//------------------------------------------------------------------------------------------------------------------
+
+	public static class A6 extends BasicRestServlet {
+		@RestMethod
+		@BeanConfig(bpi="org.apache.juneau.rest.annotation.RestMethod_BeanConfig_Test$X1: a")
+		public Object a() throws Exception {
+			return new X1().init();
+		}
+	}
+
+	@Test
+	public void a06_bpi_fullyQualifiedClassNames() throws Exception {
+		RestClient a6 = MockRestClient.build(A6.class);
+		a6.get("/a").json().run().assertBody().is("{\"a\":1}");
+		a6.get("/a").xml().run().assertBody().contains("<object><a>1</a></object>");
+		a6.get("/a").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr></table>");
+		a6.get("/a").uon().run().assertBody().is("(a=1)");
+		a6.get("/a").urlEnc().run().assertBody().is("a=1");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @BeanConfig(bpi), negative matching
+	//------------------------------------------------------------------------------------------------------------------
+
+	public static class A7 extends BasicRestServlet {
+		@RestMethod
+		@BeanConfig(bpi="MyBean: a")
+		public Object a() throws Exception {
+			// Should not match.
+			return new X1().init();
+		}
+		@RestMethod
+		@BeanConfig(bpi="MyBean*: a")
+		public Object b() throws Exception {
+			// Should not match.  We don't support meta-matches in class names.
+			return new X1().init();
+		}
+	}
+
+	@Test
+	public void a07_bpi_negativeMatching() throws Exception {
+		RestClient a7 = MockRestClient.build(A7.class);
+		a7.get("/a").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
+		a7.get("/a").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
+		a7.get("/a").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
+		a7.get("/a").uon().run().assertBody().is("(a=1,_b=foo)");
+		a7.get("/a").urlEnc().run().assertBody().is("a=1&_b=foo");
+		a7.get("/b").json().run().assertBody().is("{\"a\":1,\"_b\":\"foo\"}");
+		a7.get("/b").xml().run().assertBody().contains("<object><a>1</a><_b>foo</_b></object>");
+		a7.get("/b").html().run().assertBody().contains("<table><tr><td>a</td><td>1</td></tr><tr><td>_b</td><td>foo</td></tr></table>");
+		a7.get("/b").uon().run().assertBody().is("(a=1,_b=foo)");
+		a7.get("/b").urlEnc().run().assertBody().is("a=1&_b=foo");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Beans
+	//------------------------------------------------------------------------------------------------------------------
+
+	public static class X1 {
+		public int a;
+		@Beanp("_b") public String b;
+
+		X1 init() {
+			a = 1;
+			b = "foo";
+			return this;
+		}
+	}
+
+	@Bean(bpi="_b,a")
+	public static class X2 {
+		public int a;
+		@Beanp("_b") public String b;
+
+		X2 init() {
+			a = 1;
+			b = "foo";
+			return this;
+		}
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ClientVersionTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ClientVersion_Test.java
similarity index 79%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ClientVersionTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ClientVersion_Test.java
index 174ced7..6d2b052 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ClientVersionTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ClientVersion_Test.java
@@ -10,49 +10,49 @@
 // * "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.rest.headers;

+package org.apache.juneau.rest.annotation;

 

 import static org.apache.juneau.http.HttpMethod.*;

 import static org.junit.runners.MethodSorters.*;

 

-import org.apache.juneau.rest.annotation.*;

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class ClientVersionTest {

+public class RestMethod_ClientVersion_Test {

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Basic tests - default X-Client-Version header.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest

 	public static class A {

 		@RestMethod(name=GET, path="/")

-		public String test0() {

+		public String a() {

 			return "no-version";

 		}

 		@RestMethod(name=GET, path="/", clientVersion="[0.0,1.0)")

-		public String test1() {

+		public String b() {

 			return "[0.0,1.0)";

 		}

 		@RestMethod(name=GET, path="/", clientVersion="[1.0,1.0]")

-		public String test2() {

+		public String c() {

 			return "[1.0,1.0]";

 		}

 		@RestMethod(name=GET, path="/", clientVersion="[1.1,2)")

-		public String test3() {

+		public String d() {

 			return "[1.1,2)";

 		}

 		@RestMethod(name=GET, path="/", clientVersion="2")

-		public String test4() {

+		public String e() {

 			return "2";

 		}

 	}

-	static MockRestClient a = MockRestClient.build(A.class);

 

 	@Test

 	public void a01_defaultHeader() throws Exception {

+		RestClient a = MockRestClient.build(A.class);

 		a.get("/").run().assertBody().is("no-version");

 		for (String s : "1, 1.0, 1.0.0, 1.0.1".split("\\s*,\\s*")) {

 			a.get("/").clientVersion(s).run().assertBody().is("[1.0,1.0]");

@@ -65,37 +65,37 @@
 		}

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Basic tests - Custom-Client-Version header.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest(clientVersionHeader="Custom-Client-Version")

 	public static class B {

 		@RestMethod(name=GET, path="/")

-		public String test0() {

+		public String a() {

 			return "no-version";

 		}

 		@RestMethod(name=GET, path="/", clientVersion="[0.0,1.0)")

-		public String test1() {

+		public String b() {

 			return "[0.0,1.0)";

 		}

 		@RestMethod(name=GET, path="/", clientVersion="[1.0,1.0]")

-		public String test2() {

+		public String c() {

 			return "[1.0,1.0]";

 		}

 		@RestMethod(name=GET, path="/", clientVersion="[1.1,2)")

-		public String test3() {

+		public String d() {

 			return "[1.1,2)";

 		}

 		@RestMethod(name=GET, path="/", clientVersion="2")

-		public String test4() {

+		public String e() {

 			return "2";

 		}

 	}

-	static MockRestClient b = MockRestClient.build(B.class);

 

 	@Test

 	public void b01_testCustomHeader() throws Exception {

+		RestClient b = MockRestClient.build(B.class);

 		b.get("/").run().assertBody().is("no-version");

 		for (String s : "0, 0.0, 0.1, .1, .9, .99".split("\\s*,\\s*")) {

 			b.get("/").header("Custom-Client-Version", s).run().assertBody().is("[0.0,1.0)");

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodGuardsTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_Guards_Test.java
similarity index 74%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodGuardsTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_Guards_Test.java
index d3b17e9..dbbe647 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodGuardsTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_Guards_Test.java
@@ -15,67 +15,65 @@
 import static org.junit.runners.MethodSorters.*;

 

 import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.RestRequest;

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class RestMethodGuardsTest {

+public class RestMethod_Guards_Test {

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Overlapping guards

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest

 	public static class A {

-		@RestMethod(guards=Test1Guard.class)

-		public String a01() {

+		@RestMethod(guards=A1.class)

+		public String a() {

 			return "OK1";

 		}

-		@RestMethod(guards={Test1Guard.class,Test2Guard.class})

-		public String a02() {

+		@RestMethod(guards={A1.class,A2.class})

+		public String b() {

 			return "OK2";

 		}

-		public static class Test1Guard extends RestGuard {

+		public static class A1 extends RestGuard {

 			@Override /* RestGuard */

 			public boolean isRequestAllowed(RestRequest req) {

 				return req.getQuery().getString("t1","").equals("1");

 			}

 		}

-		public static class Test2Guard extends RestGuard {

+		public static class A2 extends RestGuard {

 			@Override /* RestGuard */

 			public boolean isRequestAllowed(RestRequest req) {

 				return req.getQuery().getString("t2","").equals("2");

 			}

 		}

 	}

-	static MockRestClient a = MockRestClient.buildLax(A.class);

 

 	@Test

-	public void a01_overlappingOneGuard() throws Exception {

-		a.get("/a01?t1=1")

+	public void a01_basic() throws Exception {

+		RestClient a = MockRestClient.buildLax(A.class);

+		a.get("/a?t1=1")

 			.run()

 			.assertBody().is("OK1");

-		a.get("/a01?noTrace=true")

+		a.get("/a?noTrace=true")

 			.run()

 			.assertCode().is(403)

 			.assertBody().contains("Access denied by guard");

-	}

-

-	@Test

-	public void a02_overlappingTwoGuards() throws Exception {

-		a.get("/a02?noTrace=true")

+		a.get("/b?noTrace=true")

 			.run()

 			.assertCode().is(403)

 			.assertBody().contains("Access denied by guard");

-		a.get("/a02?noTrace=true&t1=1")

+		a.get("/b?noTrace=true&t1=1")

 			.run()

 			.assertCode().is(403)

 			.assertBody().contains("Access denied by guard");

-		a.get("/a02?noTrace=true&t2=2")

+		a.get("/b?noTrace=true&t2=2")

 			.run()

 			.assertCode().is(403)

 			.assertBody().contains("Access denied by guard");

-		a.get("/a02?t1=1&t2=2")

+		a.get("/b?t1=1&t2=2")

 			.run()

 			.assertBody().is("OK2");

 	}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodMatchersTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_Matchers_Test.java
similarity index 76%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodMatchersTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_Matchers_Test.java
index f2583aa..1f8480f 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethodMatchersTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_Matchers_Test.java
@@ -16,62 +16,61 @@
 import static org.junit.runners.MethodSorters.*;

 

 import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.RestRequest;

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class RestMethodMatchersTest {

+public class RestMethod_Matchers_Test {

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Overlapping matchers

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest

 	public static class A {

-		@RestMethod(name=GET, path="/one", matchers=M1.class)

-		public String a01a() {

+		@RestMethod(name=GET, path="/one", matchers=A1.class)

+		public String a() {

 			return "OK-1a";

 		}

-		@RestMethod(name=GET, path="/one", matchers=M2.class)

-		public String a01b() {

+		@RestMethod(name=GET, path="/one", matchers=A2.class)

+		public String b() {

 			return "OK-1b";

 		}

 		@RestMethod(name=GET, path="/one")

-		public String a01c() {

+		public String c() {

 			return "OK-1c";

 		}

 		@RestMethod(name=GET, path="/two")

-		public String a02a() {

+		public String d() {

 			return "OK-2a";

 		}

-		@RestMethod(name=GET, path="/two", matchers={M1.class, M2.class})

-		public String a02b() {

+		@RestMethod(name=GET, path="/two", matchers={A1.class, A2.class})

+		public String e() {

 			return "OK-2b";

 		}

 

-		public static class M1 extends RestMatcher {

+		public static class A1 extends RestMatcher {

 			@Override /* RestMatcher */

 			public boolean matches(RestRequest req) {

 				return req.getQuery().getString("t1","").equals("1");

 			}

 		}

-		public static class M2 extends RestMatcher {

+		public static class A2 extends RestMatcher {

 			@Override /* RestMatcher */

 			public boolean matches(RestRequest req) {

 				return req.getQuery().getString("t2","").equals("2");

 			}

 		}

 	}

-	static MockRestClient a = MockRestClient.build(A.class);

 

 	@Test

-	public void a01() throws Exception {

+	public void a01_overlapping() throws Exception {

+		RestClient a = MockRestClient.build(A.class);

 		a.get("/one?t1=1").run().assertBody().is("OK-1a");

 		a.get("/one?t2=2").run().assertBody().is("OK-1b");

 		a.get("/one").run().assertBody().is("OK-1c");

-	}

-	@Test

-	public void a02() throws Exception {

 		a.get("/two?t1=1").run().assertBody().is("OK-2b");

 		a.get("/two?t2=2").run().assertBody().is("OK-2b");

 		a.get("/two?t1=1&t2=2").run().assertBody().is("OK-2b");

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ReqHeaders_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ReqHeaders_Test.java
new file mode 100644
index 0000000..0cded6d
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestMethod_ReqHeaders_Test.java
@@ -0,0 +1,73 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class RestMethod_ReqHeaders_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Default values - Default request headers
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+		@RestMethod(reqHeaders={"H1:1","H2=2"," H3 : 3 "})
+		public OMap a(RequestHeaders headers) {
+			return OMap.of()
+				.a("h1", headers.getString("H1"))
+				.a("h2", headers.getString("H2"))
+				.a("h3", headers.getString("H3"));
+		}
+	}
+
+	@Test
+	public void a01_reqHeaders() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/a").run().assertBody().is("{h1:'1',h2:'2',h3:'3'}");
+		a.get("/a").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+		a.get("/a").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Default values - Default request headers, case-insensitive matching
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class B {
+		@RestMethod(reqHeaders={"H1:1","H2=2"," H3 : 3 "})
+		public OMap a(RequestHeaders headers) {
+			return OMap.of()
+				.a("h1", headers.getString("h1"))
+				.a("h2", headers.getString("h2"))
+				.a("h3", headers.getString("h3"));
+		}
+	}
+
+	@Test
+	public void b01_reqHeadersCaseInsensitive() throws Exception {
+		RestClient b = MockRestClient.build(B.class);
+		b.get("/a").run().assertBody().is("{h1:'1',h2:'2',h3:'3'}");
+		b.get("/a").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+		b.get("/a").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");
+	}
+
+
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceLoggingTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceLoggingTest.java
deleted file mode 100644
index 8f2351f..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceLoggingTest.java
+++ /dev/null
@@ -1,685 +0,0 @@
-// ***************************************************************************************************************************

-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

-// * with the License.  You may obtain a copy of the License at                                                              *

-// *                                                                                                                         *

-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

-// *                                                                                                                         *

-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

-// * specific language governing permissions and limitations under the License.                                              *

-// ***************************************************************************************************************************

-package org.apache.juneau.rest.annotation;

-

-import static org.junit.runners.MethodSorters.*;

-

-import java.util.*;

-import java.util.stream.*;

-

-import org.apache.juneau.marshall.*;

-import org.apache.juneau.rest.*;

-import org.apache.juneau.rest.mock2.*;

-import org.junit.*;

-

-@FixMethodOrder(NAME_ASCENDING)

-public class RestResourceLoggingTest {

-

-	private static String string(RestCallLoggerConfig config) {

-		return SimpleJson.DEFAULT.toString(config);

-	}

-	private static String string(Collection<RestCallLoggerRule> rules) {

-		return rules.stream().map(x -> x.toString()).collect(Collectors.joining(","));

-	}

-

-	//------------------------------------------------------------------------------------------------------------------

-	// Default logger config

-	//------------------------------------------------------------------------------------------------------------------

-

-	@Rest

-	public static class A  {

-		@RestMethod

-		public String get(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	static MockRestClient a = MockRestClient.build(A.class);

-

-	@Test

-	public void a01_default() throws Exception {

-		a.get("/").run().assertBody().is("{}");

-	}

-

-	//------------------------------------------------------------------------------------------------------------------

-	// Level

-	//------------------------------------------------------------------------------------------------------------------

-

-	@Rest(logging=@Logging(level="WARNING"))

-	public static class B1 {

-		@RestMethod(path="b01")

-		public String b01(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="b02", logging=@Logging(level="SEVERE"))

-		public String b02(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="b07", logging=@Logging(level="SEVERE"))

-		public String b07(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	@Rest

-	public static class B2 {

-		@RestMethod(path="b03")

-		public String getB03(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="b04", logging=@Logging(level="SEVERE"))

-		public String getB04(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	public static class B3 extends B1 {

-		@Override

-		public String b01(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@Override

-		public String b02(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@Override

-		@RestMethod(logging=@Logging(level="OFF"))

-		public String b07(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="b08")

-		public String b08(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="b09", logging=@Logging(level="SEVERE"))

-		public String b09(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	static MockRestClient b1 = MockRestClient.build(B1.class);

-	static MockRestClient b2 = MockRestClient.build(B2.class);

-	static MockRestClient b3 = MockRestClient.build(B3.class);

-

-	@Test

-	public void b01_logging() throws Exception {

-		b1.get("/b01").run().assertBody().is("{level:'WARNING'}");

-	}

-	@Test

-	public void b02_logging() throws Exception {

-		b1.get("/b02").run().assertBody().is("{level:'SEVERE'}");

-	}

-	@Test

-	public void b03_logging() throws Exception {

-		b2.get("/b03").run().assertBody().is("{}");

-	}

-	@Test

-	public void b04_logging() throws Exception {

-		b2.get("/b04").run().assertBody().is("{level:'SEVERE'}");

-	}

-	@Test

-	public void b05_logging() throws Exception {

-		b3.get("/b01").run().assertBody().is("{level:'WARNING'}");

-	}

-	@Test

-	public void b06_logging() throws Exception {

-		b3.get("/b02").run().assertBody().is("{level:'SEVERE'}");

-	}

-	@Test

-	public void b07_logging() throws Exception {

-		b3.get("/b07").run().assertBody().is("{level:'OFF'}");

-	}

-	@Test

-	public void b08_logging() throws Exception {

-		b3.get("/b08").run().assertBody().is("{level:'WARNING'}");

-	}

-	@Test

-	public void b09_logging() throws Exception {

-		b3.get("/b09").run().assertBody().is("{level:'SEVERE'}");

-	}

-

-	//------------------------------------------------------------------------------------------------------------------

-	// useStackTraceHashing

-	//------------------------------------------------------------------------------------------------------------------

-

-	@Rest(logging=@Logging(useStackTraceHashing="true"))

-	public static class C1 {

-		@RestMethod(path="c01")

-		public String c01(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="c02", logging=@Logging(useStackTraceHashing="false"))

-		public String c02(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="c08", logging=@Logging(useStackTraceHashing="false"))

-		public String c08(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	@Rest

-	public static class C2 {

-		@RestMethod(path="c03")

-		public String c03(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="c04", logging=@Logging(useStackTraceHashing="true"))

-		public String c04(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="c05", logging=@Logging(useStackTraceHashing="foo"))

-		public String c05(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	public static class C3 extends C1 {

-		@Override

-		public String c01(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@Override

-		public String c02(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@Override

-		@RestMethod(logging=@Logging(useStackTraceHashing="TRUE"))

-		public String c08(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="c09")

-		public String c09(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="c10", logging=@Logging(useStackTraceHashing="FALSE"))

-		public String c10(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-	@Rest(logging=@Logging(useStackTraceHashing="foo"))

-	public static class C4 {

-		@RestMethod(path="c11")

-		public String c11(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	static MockRestClient c1 = MockRestClient.build(C1.class);

-	static MockRestClient c2 = MockRestClient.build(C2.class);

-	static MockRestClient c3 = MockRestClient.build(C3.class);

-	static MockRestClient c4 = MockRestClient.build(C4.class);

-

-	@Test

-	public void c01_useStackTraceHashing() throws Exception {

-		c1.get("/c01").run().assertBody().is("{useStackTraceHashing:true}");

-	}

-	@Test

-	public void c02_useStackTraceHashing() throws Exception {

-		c1.get("/c02").run().assertBody().is("{}");

-	}

-	@Test

-	public void c03_useStackTraceHashing() throws Exception {

-		c2.get("/c03").run().assertBody().is("{}");

-	}

-	@Test

-	public void c04_useStackTraceHashing() throws Exception {

-		c2.get("/c04").run().assertBody().is("{useStackTraceHashing:true}");

-	}

-	@Test

-	public void c05_useStackTraceHashing() throws Exception {

-		c2.get("/c05").run().assertBody().is("{}");

-	}

-	@Test

-	public void c06_useStackTraceHashing() throws Exception {

-		c3.get("/c01").run().assertBody().is("{useStackTraceHashing:true}");

-	}

-	@Test

-	public void c07_useStackTraceHashing() throws Exception {

-		c3.get("/c02").run().assertBody().is("{}");

-	}

-	@Test

-	public void c08_useStackTraceHashing() throws Exception {

-		c3.get("/c08").run().assertBody().is("{useStackTraceHashing:true}");

-	}

-	@Test

-	public void c09_useStackTraceHashing() throws Exception {

-		c3.get("/c09").run().assertBody().is("{useStackTraceHashing:true}");

-	}

-	@Test

-	public void c10_useStackTraceHashing() throws Exception {

-		c3.get("/c10").run().assertBody().is("{}");

-	}

-	@Test

-	public void c11_useStackTraceHashing() throws Exception {

-		c4.get("/c11").run().assertBody().is("{}");

-	}

-

-	//------------------------------------------------------------------------------------------------------------------

-	// stackTraceHashingTimeout

-	//------------------------------------------------------------------------------------------------------------------

-

-	@Rest(logging=@Logging(stackTraceHashingTimeout="1"))

-	public static class D1 {

-		@RestMethod(path="d01")

-		public String d01(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="d02", logging=@Logging(stackTraceHashingTimeout="2"))

-		public String d02(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="d07", logging=@Logging(stackTraceHashingTimeout="3"))

-		public String d07(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	@Rest

-	public static class D2 {

-		@RestMethod(path="d03")

-		public String d03(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="d04", logging=@Logging(stackTraceHashingTimeout="4"))

-		public String d04(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	public static class D3 extends D1 {

-		@Override

-		public String d01(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@Override

-		public String d02(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@Override

-		@RestMethod(logging=@Logging(stackTraceHashingTimeout="5"))

-		public String d07(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="d08")

-		public String d08(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="d09", logging=@Logging(stackTraceHashingTimeout="6"))

-		public String d09(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	static MockRestClient d1 = MockRestClient.build(D1.class);

-	static MockRestClient d2 = MockRestClient.build(D2.class);

-	static MockRestClient d3 = MockRestClient.build(D3.class);

-

-	@Test

-	public void d01_stackTraceHashingTimeout() throws Exception {

-		d1.get("/d01").run().assertBody().is("{stackTraceHashingTimeout:1}");

-	}

-	@Test

-	public void d02_stackTraceHashingTimeout() throws Exception {

-		d1.get("/d02").run().assertBody().is("{stackTraceHashingTimeout:2}");

-	}

-	@Test

-	public void d03_stackTraceHashingTimeout() throws Exception {

-		d2.get("/d03").run().assertBody().is("{}");

-	}

-	@Test

-	public void d04_stackTraceHashingTimeout() throws Exception {

-		d2.get("/d04").run().assertBody().is("{stackTraceHashingTimeout:4}");

-	}

-	@Test

-	public void d05_stackTraceHashingTimeout() throws Exception {

-		d3.get("/d01").run().assertBody().is("{stackTraceHashingTimeout:1}");

-	}

-	@Test

-	public void d06_stackTraceHashingTimeout() throws Exception {

-		d3.get("/d02").run().assertBody().is("{stackTraceHashingTimeout:2}");

-	}

-	@Test

-	public void d07_stackTraceHashingTimeout() throws Exception {

-		d3.get("/d07").run().assertBody().is("{stackTraceHashingTimeout:5}");

-	}

-	@Test

-	public void d08_stackTraceHashingTimeout() throws Exception {

-		d3.get("/d08").run().assertBody().is("{stackTraceHashingTimeout:1}");

-	}

-	@Test

-	public void d09_stackTraceHashingTimeout() throws Exception {

-		d3.get("/d09").run().assertBody().is("{stackTraceHashingTimeout:6}");

-	}

-

-	//------------------------------------------------------------------------------------------------------------------

-	// noTrace

-	//------------------------------------------------------------------------------------------------------------------

-

-	@Rest(logging=@Logging(disabled="true"))

-	public static class E1 {

-		@RestMethod(path="e01")

-		public String e01(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="e02", logging=@Logging(disabled="per-request"))

-		public String e02(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="e08", logging=@Logging(disabled="per-request"))

-		public String e08(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	@Rest

-	public static class E2 {

-		@RestMethod(path="e03")

-		public String e03(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="e04", logging=@Logging(disabled="true"))

-		public String e04(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="e05", logging=@Logging(disabled="foo"))

-		public String e05(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	public static class E3 extends E1 {

-		@Override

-		public String e01(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@Override

-		public String e02(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@Override

-		@RestMethod(logging=@Logging(disabled="false"))

-		public String e08(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="e09")

-		public String e09(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-		@RestMethod(path="e10", logging=@Logging(disabled="per-request"))

-		public String e10(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-	@Rest(logging=@Logging(disabled="foo"))

-	public static class E4 {

-		@RestMethod(path="e11")

-		public String e11(RestRequest req) {

-			return string(req.getCallLoggerConfig());

-		}

-	}

-

-	static MockRestClient e1 = MockRestClient.build(E1.class);

-	static MockRestClient e2 = MockRestClient.build(E2.class);

-	static MockRestClient e3 = MockRestClient.build(E3.class);

-	static MockRestClient e4 = MockRestClient.build(E4.class);

-

-	@Test

-	public void e01_noTrace() throws Exception {

-		e1.get("/e01").run().assertBody().is("{disabled:'TRUE'}");

-	}

-	@Test

-	public void e02_noTrace() throws Exception {

-		e1.get("/e02").run().assertBody().is("{disabled:'PER_REQUEST'}");

-	}

-	@Test

-	public void e03_noTrace() throws Exception {

-		e2.get("/e03").run().assertBody().is("{}");

-	}

-	@Test

-	public void e04_noTrace() throws Exception {

-		e2.get("/e04").run().assertBody().is("{disabled:'TRUE'}");

-	}

-	@Test

-	public void e05_noTrace() throws Exception {

-		e2.get("/e05").run().assertBody().is("{}");

-	}

-	@Test

-	public void e06_noTrace() throws Exception {

-		e3.get("/e01").run().assertBody().is("{disabled:'TRUE'}");

-	}

-	@Test

-	public void e07_noTrace() throws Exception {

-		e3.get("/e02").run().assertBody().is("{disabled:'PER_REQUEST'}");

-	}

-	@Test

-	public void e08_noTrace() throws Exception {

-		e3.get("/e08").run().assertBody().is("{}");

-	}

-	@Test

-	public void e09_noTrace() throws Exception {

-		e3.get("/e09").run().assertBody().is("{disabled:'TRUE'}");

-	}

-	@Test

-	public void e10_noTrace() throws Exception {

-		e3.get("/e10").run().assertBody().is("{disabled:'PER_REQUEST'}");

-	}

-	@Test

-	public void e11_noTrace() throws Exception {

-		e4.get("/e11").run().assertBody().is("{}");

-	}

-

-	//------------------------------------------------------------------------------------------------------------------

-	// rules

-	//------------------------------------------------------------------------------------------------------------------

-

-	@Rest(logging=@Logging(rules=@LoggingRule(codes="1")))

-	public static class F1 {

-		@RestMethod(path="f01")

-		public String f01(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-		@RestMethod(path="f02", logging=@Logging(rules=@LoggingRule(codes="2")))

-		public String f02(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-		@RestMethod(path="f07", logging=@Logging(rules=@LoggingRule(codes="3")))

-		public String f07(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-	}

-

-	@Rest

-	public static class F2 {

-		@RestMethod(path="f03")

-		public String f03(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-		@RestMethod(path="f04", logging=@Logging(rules=@LoggingRule(codes="4")))

-		public String f04(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-	}

-

-	public static class F3 extends F1 {

-		@Override

-		public String f01(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-		@Override

-		public String f02(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-		@Override

-		@RestMethod(logging=@Logging(rules=@LoggingRule(codes="5")))

-		public String f07(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-		@RestMethod(path="f08")

-		public String f08(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-		@RestMethod(path="f09", logging=@Logging(rules=@LoggingRule(codes="6")))

-		public String f09(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-	}

-

-	static MockRestClient f1 = MockRestClient.build(F1.class);

-	static MockRestClient f2 = MockRestClient.build(F2.class);

-	static MockRestClient f3 = MockRestClient.build(F3.class);

-

-	@Test

-	public void f01_rules() throws Exception {

-		f1.get("/f01").run().assertBody().is("{codes:'1'}");

-	}

-	@Test

-	public void f02_rules() throws Exception {

-		f1.get("/f02").run().assertBody().is("{codes:'2'},{codes:'1'}");

-	}

-	@Test

-	public void f03_rules() throws Exception {

-		f2.get("/f03").run().assertBody().is("");

-	}

-	@Test

-	public void f04_rules() throws Exception {

-		f2.get("/f04").run().assertBody().is("{codes:'4'}");

-	}

-	@Test

-	public void f05_rules() throws Exception {

-		f3.get("/f01").run().assertBody().is("{codes:'1'}");

-	}

-	@Test

-	public void f06_rules() throws Exception {

-		f3.get("/f02").run().assertBody().is("{codes:'2'},{codes:'1'}");

-	}

-	@Test

-	public void f07_rules() throws Exception {

-		f3.get("/f07").run().assertBody().is("{codes:'5'},{codes:'3'},{codes:'1'}");

-	}

-	@Test

-	public void f08_rules() throws Exception {

-		f3.get("/f08").run().assertBody().is("{codes:'1'}");

-	}

-	@Test

-	public void f09_rules() throws Exception {

-		f3.get("/f09").run().assertBody().is("{codes:'6'},{codes:'1'}");

-	}

-

-	//------------------------------------------------------------------------------------------------------------------

-	// rules

-	//------------------------------------------------------------------------------------------------------------------

-

-	@Rest(

-		logging=@Logging(

-			rules=@LoggingRule(

-				exceptions="1",

-				debugOnly="true",

-				level="WARNING",

-				req="MEDIUM",

-				res="LARGE"

-			)

-		)

-	)

-	public static class G1 {

-		@RestMethod(path="g01")

-		public String g01(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-		@RestMethod(path="g02",

-			logging=@Logging(

-				rules=@LoggingRule(

-					exceptions="2",

-					debugOnly="true",

-					level="WARNING",

-					req="MEDIUM",

-					res="LARGE"

-				)

-			)

-		)

-		public String g02(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-	}

-

-	@Rest

-	public static class G2 {

-		@RestMethod(path="g03",

-			logging=@Logging(

-				rules=@LoggingRule(

-					exceptions="3",

-					debugOnly="true",

-					level="WARNING",

-					req="MEDIUM",

-					res="LARGE"

-				)

-			)

-		)

-		public String g03(RestRequest req) {

-			return string(req.getCallLoggerConfig().getRules());

-		}

-	}

-	static MockRestClient g1 = MockRestClient.build(G1.class);

-	static MockRestClient g2 = MockRestClient.build(G2.class);

-

-	@Test

-	public void g01_rules() throws Exception {

-		g1.get("/g01").run().assertBody().is("{exceptions:'1',debugOnly:true,level:'WARNING',req:'MEDIUM'}");

-	}

-	@Test

-	public void g02_rules() throws Exception {

-		g1.get("/g02").run().assertBody().is("{exceptions:'2',debugOnly:true,level:'WARNING',req:'MEDIUM'},{exceptions:'1',debugOnly:true,level:'WARNING',req:'MEDIUM'}");

-	}

-	@Test

-	public void g03_rules() throws Exception {

-		g2.get("/g03").run().assertBody().is("{exceptions:'3',debugOnly:true,level:'WARNING',req:'MEDIUM'}");

-	}

-

-	//------------------------------------------------------------------------------------------------------------------

-	// Examples

-	//------------------------------------------------------------------------------------------------------------------

-

-	@Rest(

-		debug="always",

-		logging=@Logging(

-			useStackTraceHashing="true",

-			rules={

-				@LoggingRule(codes=">=500", level="off", req="short", res="short")

-			}

-		)

-	)

-	public static class MyRestClass {

-

-		@RestMethod(method="POST", path="foo")

-		public String myRestMethod(RestRequest req, RestResponse res) throws Exception {

-			res.setStatus(500);

-			res.setHeader("Foo", "bar");

-			res.setException(new StringIndexOutOfBoundsException());

-			return req.getBody().asString();

-		}

-	}

-

-	static MockRestClient MY_REST = MockRestClient.buildLax(MyRestClass.class);

-

-	@Test

-	public void test() throws Exception {

-		MY_REST.post("/foo?foo=bar", "Foo")

-			.header("Foo", "bar")

-			.run()

-			.assertCode().is(500);

-		MY_REST.post("/foo?foo=bar", "Foo")

-			.header("Foo", "bar")

-			.run()

-			.assertCode().is(500);

-	}

-}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourcePathTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourcePathTest.java
deleted file mode 100644
index ee1ec18..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourcePathTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// ***************************************************************************************************************************

-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

-// * with the License.  You may obtain a copy of the License at                                                              *

-// *                                                                                                                         *

-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

-// *                                                                                                                         *

-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

-// * specific language governing permissions and limitations under the License.                                              *

-// ***************************************************************************************************************************

-package org.apache.juneau.rest.annotation;

-

-import static org.apache.juneau.http.HttpMethod.*;

-import static org.junit.runners.MethodSorters.*;

-

-import org.apache.juneau.rest.*;

-import org.apache.juneau.rest.mock2.*;

-import org.junit.*;

-

-@FixMethodOrder(NAME_ASCENDING)

-public class RestResourcePathTest {

-

-	//=================================================================================================================

-	// Nested children.

-	//=================================================================================================================

-

-	@Rest(path="/p0", children={A01.class})

-	public static class A  {

-		@RestMethod(name=GET, path="/")

-		public String doGet(RestContext c) {

-			return "A-" + c.getPath();

-		}

-	}

-	@Rest(path="/p1", children={A02.class})

-	public static class A01 {

-		@RestMethod(name=GET, path="/")

-		public String doGet(RestContext c) {

-			return "A01-" + c.getPath();

-		}

-	}

-	public static class A02a  {

-		@RestMethod(name=GET, path="/")

-		public String doGet(RestContext c) {

-			return "A02a-" + c.getPath();

-		}

-	}

-	@Rest(path="/p2")

-	public static class A02 extends A02a {}

-

-	static MockRestClient a = MockRestClient.build(A.class);

-

-	@Test

-	public void a01_nestedChildren() throws Exception {

-		// Since we're not running from a servlet container, we access A directly with no path.

-		// However, the path is still reflected in RestContext.getPath().

-		a.get("/").run().assertBody().is("A-p0");

-		a.get("/p1").run().assertBody().is("A01-p0/p1");

-		a.get("/p1/p2").run().assertBody().is("A02a-p0/p1/p2");

-	}

-}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceTest.java
deleted file mode 100644
index ea18b9f..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceTest.java
+++ /dev/null
@@ -1,485 +0,0 @@
-// ***************************************************************************************************************************

-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

-// * with the License.  You may obtain a copy of the License at                                                              *

-// *                                                                                                                         *

-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

-// *                                                                                                                         *

-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

-// * specific language governing permissions and limitations under the License.                                              *

-// ***************************************************************************************************************************

-package org.apache.juneau.rest.annotation;

-

-import static org.junit.runners.MethodSorters.*;

-

-import org.apache.juneau.collections.*;

-import org.apache.juneau.http.annotation.*;

-import org.apache.juneau.rest.*;

-import org.apache.juneau.rest.mock2.*;

-import org.junit.*;

-

-@FixMethodOrder(NAME_ASCENDING)

-public class RestResourceTest {

-

-	//====================================================================================================

-	// @Rest(allowBodyParam)

-	//====================================================================================================

-

-	@Rest(allowBodyParam="true")

-	public static class A1 {

-		@RestMethod

-		public OMap put(@Body OMap body) {

-			return body;

-		}

-	}

-	@Rest(allowBodyParam="false")

-	public static class A2 {

-		@RestMethod

-		public OMap put(@Body OMap body) {

-			return body;

-		}

-	}

-	@Rest(allowBodyParam="false")

-	public static class A3 extends A1 {}

-

-	@Rest(allowBodyParam="true")

-	public static class A4 extends A2 {}

-

-	static MockRestClient a1 = MockRestClient.build(A1.class);

-	static MockRestClient a2 = MockRestClient.build(A2.class);

-	static MockRestClient a3 = MockRestClient.build(A3.class);

-	static MockRestClient a4 = MockRestClient.build(A4.class);

-

-	@Test

-	public void a01_allowBodyParam_true() throws Exception {

-		a1.put("/", "{a:'b'}").run().assertBody().is("{a:'b'}");

-		a1.put("/?body=(c=d)", "{a:'b'}").run().assertBody().is("{c:'d'}");

-	}

-

-	@Test

-	public void a02_allowBodyParam_false() throws Exception {

-		a2.put("/", "{a:'b'}").run().assertBody().is("{a:'b'}");

-		a2.put("/?body=(c=d)", "{a:'b'}").run().assertBody().is("{a:'b'}");

-	}

-

-	@Test

-	public void a03_allowBodyParam_overridden_false() throws Exception {

-		a3.put("/", "{a:'b'}").run().assertBody().is("{a:'b'}");

-		a3.put("/?body=(c=d)", "{a:'b'}").run().assertBody().is("{a:'b'}");

-	}

-

-	@Test

-	public void a04_allowBodyParam_overridden_true() throws Exception {

-		a4.put("/", "{a:'b'}").run().assertBody().is("{a:'b'}");

-		a4.put("/?body=(c=d)", "{a:'b'}").run().assertBody().is("{c:'d'}");

-	}

-

-	//====================================================================================================

-	// @Rest(allowedHeaderParams)

-	//====================================================================================================

-

-	public static class B {

-		@RestMethod

-		public String put(RequestHeaders h) {

-			return "Accept="+h.getAccept().getValue()+",Content-Type=" + h.getContentType().getValue() + ",Custom=" + h.getString("Custom");

-		}

-	}

-

-	@Rest()

-	public static class B1 extends B {}

-

-	@Rest(allowedHeaderParams="Accept, Content-Type")

-	public static class B2 extends B {}

-

-	@Rest(allowedHeaderParams="ACCEPT, CONTENT-TYPE")

-	public static class B3 extends B {}

-

-	@Rest(allowedHeaderParams="Custom")

-	public static class B4 extends B {}

-

-	@Rest(allowedHeaderParams="*")

-	public static class B5 extends B {}

-

-	@Rest(allowedHeaderParams="NONE")

-	public static class B6 extends B {}

-

-	@Rest(allowedHeaderParams="None")

-	public static class B7 extends B {}

-

-	@Rest(allowedHeaderParams="None")

-	public static class B8 extends B5 {}

-

-	static MockRestClient b1 = MockRestClient.build(B1.class);

-	static MockRestClient b2 = MockRestClient.build(B2.class);

-	static MockRestClient b3 = MockRestClient.build(B3.class);

-	static MockRestClient b4 = MockRestClient.build(B4.class);

-	static MockRestClient b5 = MockRestClient.build(B5.class);

-	static MockRestClient b6 = MockRestClient.build(B6.class);

-	static MockRestClient b7 = MockRestClient.build(B7.class);

-	static MockRestClient b8 = MockRestClient.build(B8.class);

-

-	@Test

-	public void b01_allowedHeaderParams_default() throws Exception {

-		b1.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b1.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

-		b1.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

-	}

-

-	@Test

-	public void b02_allowedHeaderParams_defaultExplicit() throws Exception {

-		b2.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b2.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

-		b2.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

-	}

-

-	@Test

-	public void b03_allowedHeaderParams_caseSensitivity() throws Exception {

-		b3.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b3.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

-		b3.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

-	}

-

-	@Test

-	public void b04_allowedHeaderParams_customHeaderOnly() throws Exception {

-		b4.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b4.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=bar3");

-		b4.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=bar3");

-	}

-

-	@Test

-	public void b05_allowedHeaderParams_allHeaders() throws Exception {

-		b5.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b5.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=bar3");

-		b5.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=bar3");

-	}

-

-	@Test

-	public void b06_allowedHeaderParams_none() throws Exception {

-		b6.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b6.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b6.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-	}

-

-	@Test

-	public void b07_allowedHeaderParams_none_caseSensitivity() throws Exception {

-		b7.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b7.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b7.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-	}

-

-	@Test

-	public void b08_allowedHeaderParams_none_overridingParent() throws Exception {

-		b8.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b8.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-		b8.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

-	}

-

-	//====================================================================================================

-	// @Rest(allowedMethodHeaders)

-	//====================================================================================================

-

-	public static class C {

-		@RestMethod

-		public String get() {

-			return "GET";

-		}

-		@RestMethod

-		public String put() {

-			return "PUT";

-		}

-		@RestMethod(name="foo",path="/")

-		public String foo() {

-			return "FOO";

-		}

-	}

-

-	@Rest()

-	public static class C1 extends C {}

-

-	@Rest(allowedMethodHeaders="GET")

-	public static class C2 extends C {}

-

-	@Rest(allowedMethodHeaders="get")

-	public static class C3 extends C {}

-

-	@Rest(allowedMethodHeaders="FOO")

-	public static class C4 extends C {}

-

-	@Rest(allowedMethodHeaders="*")

-	public static class C5 extends C {}

-

-	@Rest(allowedMethodHeaders="NONE")

-	public static class C6 extends C {}

-

-	@Rest(allowedMethodHeaders="None")

-	public static class C7 extends C {}

-

-	@Rest(allowedMethodHeaders="None")

-	public static class C8 extends C5 {}

-

-	static MockRestClient c1 = MockRestClient.build(C1.class);

-	static MockRestClient c2 = MockRestClient.build(C2.class);

-	static MockRestClient c3 = MockRestClient.build(C3.class);

-	static MockRestClient c4 = MockRestClient.build(C4.class);

-	static MockRestClient c5 = MockRestClient.build(C5.class);

-	static MockRestClient c6 = MockRestClient.build(C6.class);

-	static MockRestClient c7 = MockRestClient.build(C7.class);

-	static MockRestClient c8 = MockRestClient.build(C8.class);

-

-	@Test

-	public void c01_allowedMethodHeaders_default() throws Exception {

-		c1.get("/").run().assertBody().is("GET");

-		c1.put("/", "").run().assertBody().is("PUT");

-		c1.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

-		c1.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

-		c1.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void c02_allowedMethodHeaders_GET_only() throws Exception {

-		c2.get("/").run().assertBody().is("GET");

-		c2.put("/", "").run().assertBody().is("PUT");

-		c2.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

-		c2.put("/", "").header("X-Method", "GET").run().assertBody().is("GET");

-		c2.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void c03_allowedMethodHeaders_GET_caseSensitivity() throws Exception {

-		c3.get("/").run().assertBody().is("GET");

-		c3.put("/", "").run().assertBody().is("PUT");

-		c3.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

-		c3.put("/", "").header("X-Method", "GET").run().assertBody().is("GET");

-		c3.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void c04_allowedMethodHeaders_FOO_only() throws Exception {

-		c4.get("/").run().assertBody().is("GET");

-		c4.put("/", "").run().assertBody().is("PUT");

-		c4.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

-		c4.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

-		c4.request("get","/").header("X-Method","FOO").run().assertBody().is("FOO");

-	}

-

-	@Test

-	public void c05_allowedMethodHeaders_allMethods() throws Exception {

-		c5.get("/").run().assertBody().is("GET");

-		c5.put("/", "").run().assertBody().is("PUT");

-		c5.get("/").header("X-Method", "PUT").run().assertBody().is("PUT");

-		c5.put("/", "").header("X-Method", "GET").run().assertBody().is("GET");

-		c5.request("get","/").header("X-Method","FOO").run().assertBody().is("FOO");

-	}

-

-	@Test

-	public void c06_allowedMethodHeaders_none() throws Exception {

-		c6.get("/").run().assertBody().is("GET");

-		c6.put("/", "").run().assertBody().is("PUT");

-		c6.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

-		c6.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

-		c6.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void c07_allowedMethodHeaders_none_caseSensitivity() throws Exception {

-		c7.get("/").run().assertBody().is("GET");

-		c7.put("/", "").run().assertBody().is("PUT");

-		c7.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

-		c7.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

-		c7.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void c08_allowedMethodHeaders_none_overridingParent() throws Exception {

-		c8.get("/").run().assertBody().is("GET");

-		c8.put("/", "").run().assertBody().is("PUT");

-		c8.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

-		c8.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

-		c8.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void c09_allowedMethodHeaders_caseInsensitiveHeaderName() throws Exception {

-		c5.get("/").header("x-method", "PUT").run().assertBody().is("PUT");

-		c5.get("/").header("x-method", "FOO").run().assertBody().is("FOO");

-	}

-

-	@Test

-	public void c10_allowedMethodHeaders_caseInsensitiveHeaderValue() throws Exception {

-		c5.get("/").header("X-Method", "put").run().assertBody().is("PUT");

-		c5.get("/").header("X-Method", "foo").run().assertBody().is("FOO");

-	}

-

-	//====================================================================================================

-	// @Rest(allowedMethodParams)

-	//====================================================================================================

-

-	public static class D {

-		@RestMethod

-		public String get() {

-			return "GET";

-		}

-		@RestMethod

-		public String put() {

-			return "PUT";

-		}

-		@RestMethod

-		public String head() {

-			// Note that HTTP client is going to ignore this body.

-			return "HEAD";

-		}

-		@RestMethod

-		public String options() {

-			return "OPTIONS";

-		}

-		@RestMethod(name="foo",path="/")

-		public String foo() {

-			return "FOO";

-		}

-	}

-

-	@Rest()

-	public static class D1 extends D {}

-

-	@Rest(allowedMethodParams="GET")

-	public static class D2 extends D {}

-

-	@Rest(allowedMethodParams="get")

-	public static class D3 extends D {}

-

-	@Rest(allowedMethodParams="FOO")

-	public static class D4 extends D {}

-

-	@Rest(allowedMethodParams="*")

-	public static class D5 extends D {}

-

-	@Rest(allowedMethodParams="NONE")

-	public static class D6 extends D {}

-

-	@Rest(allowedMethodParams="None")

-	public static class D7 extends D {}

-

-	@Rest(allowedMethodParams="None")

-	public static class D8 extends D5 {}

-

-	static MockRestClient d1 = MockRestClient.build(D1.class);

-	static MockRestClient d2 = MockRestClient.build(D2.class);

-	static MockRestClient d3 = MockRestClient.build(D3.class);

-	static MockRestClient d4 = MockRestClient.build(D4.class);

-	static MockRestClient d5 = MockRestClient.build(D5.class);

-	static MockRestClient d6 = MockRestClient.build(D6.class);

-	static MockRestClient d7 = MockRestClient.build(D7.class);

-	static MockRestClient d8 = MockRestClient.build(D8.class);

-

-	@Test

-	public void d01_allowedMethodHeaders_default() throws Exception {

-		d1.get("/").run().assertBody().is("GET");

-		d1.put("/", "").run().assertBody().is("PUT");

-		d1.head("/").run().assertBody().is("");

-		d1.options("/").run().assertBody().is("OPTIONS");

-		d1.get("/?method=PUT").run().assertBody().is("GET");

-		d1.put("/?method=GET", "").run().assertBody().is("PUT");

-		d1.get("/?method=HEAD").run().assertBody().is("HEAD");

-		d1.get("/?method=OPTIONS").run().assertBody().is("OPTIONS");

-		d1.request("get","/?method=FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void d02_allowedMethodParams_GET_only() throws Exception {

-		d2.get("/").run().assertBody().is("GET");

-		d2.put("/", "").run().assertBody().is("PUT");

-		d2.head("/").run().assertBody().is("");

-		d2.options("/").run().assertBody().is("OPTIONS");

-		d2.get("/?method=PUT").run().assertBody().is("GET");

-		d2.put("/?method=GET", "").run().assertBody().is("GET");

-		d2.get("/?method=HEAD").run().assertBody().is("GET");

-		d2.get("/?method=OPTIONS").run().assertBody().is("GET");

-		d2.request("get","/?method=FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void d03_allowedMethodParams_GET_caseSensitivity() throws Exception {

-		d3.get("/").run().assertBody().is("GET");

-		d3.put("/", "").run().assertBody().is("PUT");

-		d3.head("/").run().assertBody().is("");

-		d3.options("/").run().assertBody().is("OPTIONS");

-		d3.get("/?method=PUT").run().assertBody().is("GET");

-		d3.put("/?method=GET", "").run().assertBody().is("GET");

-		d3.get("/?method=HEAD").run().assertBody().is("GET");

-		d3.get("/?method=OPTIONS").run().assertBody().is("GET");

-		d3.request("get","/?method=FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void d04_allowedMethodParams_FOO_only() throws Exception {

-		d4.get("/").run().assertBody().is("GET");

-		d4.put("/", "").run().assertBody().is("PUT");

-		d4.head("/").run().assertBody().is("");

-		d4.options("/").run().assertBody().is("OPTIONS");

-		d4.get("/?method=PUT").run().assertBody().is("GET");

-		d4.put("/?method=GET", "").run().assertBody().is("PUT");

-		d4.get("/?method=HEAD").run().assertBody().is("GET");

-		d4.get("/?method=OPTIONS").run().assertBody().is("GET");

-		d4.request("get","/?method=FOO").run().assertBody().is("FOO");

-	}

-

-	@Test

-	public void d05_allowedMethodParams_allMethods() throws Exception {

-		d5.get("/").run().assertBody().is("GET");

-		d5.put("/", "").run().assertBody().is("PUT");

-		d5.head("/").run().assertBody().is("");

-		d5.options("/").run().assertBody().is("OPTIONS");

-		d5.get("/?method=PUT").run().assertBody().is("PUT");

-		d5.put("/?method=GET", "").run().assertBody().is("GET");

-		d5.get("/?method=HEAD").run().assertBody().is("HEAD");

-		d5.get("/?method=OPTIONS").run().assertBody().is("OPTIONS");

-		d5.request("get","/?method=FOO").run().assertBody().is("FOO");

-	}

-

-	@Test

-	public void d06_allowedMethodParams_none() throws Exception {

-		d6.get("/").run().assertBody().is("GET");

-		d6.put("/", "").run().assertBody().is("PUT");

-		d6.head("/").run().assertBody().is("");

-		d6.options("/").run().assertBody().is("OPTIONS");

-		d6.get("/?method=PUT").run().assertBody().is("GET");

-		d6.put("/?method=GET", "").run().assertBody().is("PUT");

-		d6.get("/?method=HEAD").run().assertBody().is("GET");

-		d6.get("/?method=OPTIONS").run().assertBody().is("GET");

-		d6.request("get","/?method=FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void d07_allowedMethodParams_none_caseSensitivity() throws Exception {

-		d7.get("/").run().assertBody().is("GET");

-		d7.put("/", "").run().assertBody().is("PUT");

-		d7.head("/").run().assertBody().is("");

-		d7.options("/").run().assertBody().is("OPTIONS");

-		d7.get("/?method=PUT").run().assertBody().is("GET");

-		d7.put("/?method=GET", "").run().assertBody().is("PUT");

-		d7.get("/?method=HEAD").run().assertBody().is("GET");

-		d7.get("/?method=OPTIONS").run().assertBody().is("GET");

-		d7.request("get","/?method=FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void d08_allowedMethodParams_none_overridingParent() throws Exception {

-		d8.get("/").run().assertBody().is("GET");

-		d8.put("/", "").run().assertBody().is("PUT");

-		d8.head("/").run().assertBody().is("");

-		d8.options("/").run().assertBody().is("OPTIONS");

-		d8.get("/?method=PUT").run().assertBody().is("GET");

-		d8.put("/?method=GET", "").run().assertBody().is("PUT");

-		d8.get("/?method=HEAD").run().assertBody().is("GET");

-		d8.get("/?method=OPTIONS").run().assertBody().is("GET");

-		d8.request("get","/?method=FOO").run().assertBody().is("GET");

-	}

-

-	@Test

-	public void d09_allowedMethodHeaders_caseInsensitiveParamValue() throws Exception {

-		d5.get("/?method=Put").run().assertBody().is("PUT");

-		d5.get("/?method=Foo").run().assertBody().is("FOO");

-	}

-}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowBodyParam_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowBodyParam_Test.java
new file mode 100644
index 0000000..52cb067
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowBodyParam_Test.java
@@ -0,0 +1,69 @@
+// ***************************************************************************************************************************

+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

+// * with the License.  You may obtain a copy of the License at                                                              *

+// *                                                                                                                         *

+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

+// *                                                                                                                         *

+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

+// * specific language governing permissions and limitations under the License.                                              *

+// ***************************************************************************************************************************

+package org.apache.juneau.rest.annotation;

+

+import static org.junit.runners.MethodSorters.*;

+

+import org.apache.juneau.collections.*;

+import org.apache.juneau.http.annotation.*;

+import org.apache.juneau.rest.client2.*;

+import org.apache.juneau.rest.mock2.*;

+import org.junit.*;

+

+@FixMethodOrder(NAME_ASCENDING)

+public class Rest_AllowBodyParam_Test {

+

+	//------------------------------------------------------------------------------------------------------------------

+	// @Rest(allowBodyParam)

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(allowBodyParam="true")

+	public static class A1 {

+		@RestMethod

+		public OMap put(@Body OMap body) {

+			return body;

+		}

+	}

+	@Rest(allowBodyParam="false")

+	public static class A2 {

+		@RestMethod

+		public OMap put(@Body OMap body) {

+			return body;

+		}

+	}

+	@Rest(allowBodyParam="false")

+	public static class A3 extends A1 {}

+

+	@Rest(allowBodyParam="true")

+	public static class A4 extends A2 {}

+

+

+	@Test

+	public void a01_basic() throws Exception {

+		RestClient a1 = MockRestClient.build(A1.class);

+		a1.put("/", "{a:'b'}").run().assertBody().is("{a:'b'}");

+		a1.put("/?body=(c=d)", "{a:'b'}").run().assertBody().is("{c:'d'}");

+

+		RestClient a2 = MockRestClient.build(A2.class);

+		a2.put("/", "{a:'b'}").run().assertBody().is("{a:'b'}");

+		a2.put("/?body=(c=d)", "{a:'b'}").run().assertBody().is("{a:'b'}");

+

+		RestClient a3 = MockRestClient.build(A3.class);

+		a3.put("/", "{a:'b'}").run().assertBody().is("{a:'b'}");

+		a3.put("/?body=(c=d)", "{a:'b'}").run().assertBody().is("{a:'b'}");

+

+		RestClient a4 = MockRestClient.build(A4.class);

+		a4.put("/", "{a:'b'}").run().assertBody().is("{a:'b'}");

+		a4.put("/?body=(c=d)", "{a:'b'}").run().assertBody().is("{c:'d'}");

+	}

+}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
new file mode 100644
index 0000000..daf7ffa
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedHeaderParams_Test.java
@@ -0,0 +1,103 @@
+// ***************************************************************************************************************************

+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

+// * with the License.  You may obtain a copy of the License at                                                              *

+// *                                                                                                                         *

+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

+// *                                                                                                                         *

+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

+// * specific language governing permissions and limitations under the License.                                              *

+// ***************************************************************************************************************************

+package org.apache.juneau.rest.annotation;

+

+import static org.junit.runners.MethodSorters.*;

+

+import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.client2.*;

+import org.apache.juneau.rest.mock2.*;

+import org.junit.*;

+

+@FixMethodOrder(NAME_ASCENDING)

+public class Rest_AllowedHeaderParams_Test {

+

+	//------------------------------------------------------------------------------------------------------------------

+	// @Rest(allowedHeaderParams)

+	//------------------------------------------------------------------------------------------------------------------

+

+	public static class A {

+		@RestMethod

+		public String put(RequestHeaders h) {

+			return "Accept="+h.getAccept().getValue()+",Content-Type=" + h.getContentType().getValue() + ",Custom=" + h.getString("Custom");

+		}

+	}

+

+	@Rest()

+	public static class A1 extends A {}

+

+	@Rest(allowedHeaderParams="Accept, Content-Type")

+	public static class A2 extends A {}

+

+	@Rest(allowedHeaderParams="ACCEPT, CONTENT-TYPE")

+	public static class A3 extends A {}

+

+	@Rest(allowedHeaderParams="Custom")

+	public static class A4 extends A {}

+

+	@Rest(allowedHeaderParams="*")

+	public static class A5 extends A {}

+

+	@Rest(allowedHeaderParams="NONE")

+	public static class A6 extends A {}

+

+	@Rest(allowedHeaderParams="None")

+	public static class A7 extends A {}

+

+	@Rest(allowedHeaderParams="None")

+	public static class A8 extends A5 {}

+

+

+	@Test

+	public void a01_basic() throws Exception {

+		RestClient a1 = MockRestClient.build(A1.class);

+		a1.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a1.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

+		a1.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

+

+		RestClient a2 = MockRestClient.build(A2.class);

+		a2.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a2.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

+		a2.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

+

+		RestClient a3 = MockRestClient.build(A3.class);

+		a3.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a3.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

+		a3.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=foo3");

+

+		RestClient a4 = MockRestClient.build(A4.class);

+		a4.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a4.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=bar3");

+		a4.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=bar3");

+

+		RestClient a5 = MockRestClient.build(A5.class);

+		a5.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a5.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=bar3");

+		a5.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+bar1,Content-Type=text/plain+bar2,Custom=bar3");

+

+		RestClient a6 = MockRestClient.build(A6.class);

+		a6.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a6.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a6.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+

+		RestClient a7 = MockRestClient.build(A7.class);

+		a7.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a7.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a7.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+

+		RestClient a8 = MockRestClient.build(A8.class);

+		a8.put("/", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a8.put("/?Accept=text/plain%2Bbar1&Content-Type=text/plain%2Bbar2&Custom=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+		a8.put("/?ACCEPT=text/plain%2Bbar1&CONTENT-TYPE=text/plain%2Bbar2&CUSTOM=bar3", "").accept("text/plain+foo1").contentType("text/plain+foo2").header("Custom", "foo3").run().assertBody().is("Accept=text/plain+foo1,Content-Type=text/plain+foo2,Custom=foo3");

+	}

+}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedMethodHeaders_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedMethodHeaders_Test.java
new file mode 100644
index 0000000..252b3fc
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedMethodHeaders_Test.java
@@ -0,0 +1,128 @@
+// ***************************************************************************************************************************

+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

+// * with the License.  You may obtain a copy of the License at                                                              *

+// *                                                                                                                         *

+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

+// *                                                                                                                         *

+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

+// * specific language governing permissions and limitations under the License.                                              *

+// ***************************************************************************************************************************

+package org.apache.juneau.rest.annotation;

+

+import static org.junit.runners.MethodSorters.*;

+

+import org.apache.juneau.rest.client2.*;

+import org.apache.juneau.rest.mock2.*;

+import org.junit.*;

+

+@FixMethodOrder(NAME_ASCENDING)

+public class Rest_AllowedMethodHeaders_Test {

+	//------------------------------------------------------------------------------------------------------------------

+	// @Rest(allowedMethodHeaders)

+	//------------------------------------------------------------------------------------------------------------------

+

+	public static class A {

+		@RestMethod

+		public String get() {

+			return "GET";

+		}

+		@RestMethod

+		public String put() {

+			return "PUT";

+		}

+		@RestMethod(name="foo",path="/")

+		public String foo() {

+			return "FOO";

+		}

+	}

+

+	@Rest()

+	public static class A1 extends A {}

+

+	@Rest(allowedMethodHeaders="GET")

+	public static class A2 extends A {}

+

+	@Rest(allowedMethodHeaders="get")

+	public static class A3 extends A {}

+

+	@Rest(allowedMethodHeaders="FOO")

+	public static class A4 extends A {}

+

+	@Rest(allowedMethodHeaders="*")

+	public static class A5 extends A {}

+

+	@Rest(allowedMethodHeaders="NONE")

+	public static class A6 extends A {}

+

+	@Rest(allowedMethodHeaders="None")

+	public static class A7 extends A {}

+

+	@Rest(allowedMethodHeaders="None")

+	public static class A8 extends A5 {}

+

+	@Test

+	public void c01_basic() throws Exception {

+		RestClient a1 = MockRestClient.build(A1.class);

+		a1.get("/").run().assertBody().is("GET");

+		a1.put("/", "").run().assertBody().is("PUT");

+		a1.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

+		a1.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

+		a1.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

+

+		RestClient a2 = MockRestClient.build(A2.class);

+		a2.get("/").run().assertBody().is("GET");

+		a2.put("/", "").run().assertBody().is("PUT");

+		a2.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

+		a2.put("/", "").header("X-Method", "GET").run().assertBody().is("GET");

+		a2.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

+

+		RestClient a3 = MockRestClient.build(A3.class);

+		a3.get("/").run().assertBody().is("GET");

+		a3.put("/", "").run().assertBody().is("PUT");

+		a3.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

+		a3.put("/", "").header("X-Method", "GET").run().assertBody().is("GET");

+		a3.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

+

+		RestClient a4 = MockRestClient.build(A4.class);

+		a4.get("/").run().assertBody().is("GET");

+		a4.put("/", "").run().assertBody().is("PUT");

+		a4.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

+		a4.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

+		a4.request("get","/").header("X-Method","FOO").run().assertBody().is("FOO");

+

+		RestClient a5 = MockRestClient.build(A5.class);

+		a5.get("/").run().assertBody().is("GET");

+		a5.put("/", "").run().assertBody().is("PUT");

+		a5.get("/").header("X-Method", "PUT").run().assertBody().is("PUT");

+		a5.put("/", "").header("X-Method", "GET").run().assertBody().is("GET");

+		a5.get("/").header("x-method", "PUT").run().assertBody().is("PUT");

+		a5.get("/").header("x-method", "FOO").run().assertBody().is("FOO");

+		a5.get("/").header("X-Method", "put").run().assertBody().is("PUT");

+		a5.get("/").header("X-Method", "foo").run().assertBody().is("FOO");

+		a5.request("get","/").header("X-Method","FOO").run().assertBody().is("FOO");

+

+		RestClient a6 = MockRestClient.build(A6.class);

+		a6.get("/").run().assertBody().is("GET");

+		a6.put("/", "").run().assertBody().is("PUT");

+		a6.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

+		a6.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

+		a6.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

+

+		RestClient a7 = MockRestClient.build(A7.class);

+		a7.get("/").run().assertBody().is("GET");

+		a7.put("/", "").run().assertBody().is("PUT");

+		a7.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

+		a7.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

+		a7.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

+

+		RestClient a8 = MockRestClient.build(A8.class);

+		a8.get("/").run().assertBody().is("GET");

+		a8.put("/", "").run().assertBody().is("PUT");

+		a8.get("/").header("X-Method", "PUT").run().assertBody().is("GET");

+		a8.put("/", "").header("X-Method", "GET").run().assertBody().is("PUT");

+		a8.request("get","/").header("X-Method","FOO").run().assertBody().is("GET");

+	}

+}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedMethodParams_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedMethodParams_Test.java
new file mode 100644
index 0000000..89ad742
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AllowedMethodParams_Test.java
@@ -0,0 +1,168 @@
+// ***************************************************************************************************************************

+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

+// * with the License.  You may obtain a copy of the License at                                                              *

+// *                                                                                                                         *

+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

+// *                                                                                                                         *

+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

+// * specific language governing permissions and limitations under the License.                                              *

+// ***************************************************************************************************************************

+package org.apache.juneau.rest.annotation;

+

+import static org.junit.runners.MethodSorters.*;

+

+import org.apache.juneau.rest.client2.*;

+import org.apache.juneau.rest.mock2.*;

+import org.junit.*;

+

+@FixMethodOrder(NAME_ASCENDING)

+public class Rest_AllowedMethodParams_Test {

+

+	//------------------------------------------------------------------------------------------------------------------

+	// @Rest(allowedMethodParams)

+	//------------------------------------------------------------------------------------------------------------------

+

+	public static class A {

+		@RestMethod

+		public String get() {

+			return "GET";

+		}

+		@RestMethod

+		public String put() {

+			return "PUT";

+		}

+		@RestMethod

+		public String head() {

+			// Note that HTTP client is going to ignore this body.

+			return "HEAD";

+		}

+		@RestMethod

+		public String options() {

+			return "OPTIONS";

+		}

+		@RestMethod(name="foo",path="/")

+		public String foo() {

+			return "FOO";

+		}

+	}

+

+	@Rest()

+	public static class A1 extends A {}

+

+	@Rest(allowedMethodParams="GET")

+	public static class A2 extends A {}

+

+	@Rest(allowedMethodParams="get")

+	public static class A3 extends A {}

+

+	@Rest(allowedMethodParams="FOO")

+	public static class A4 extends A {}

+

+	@Rest(allowedMethodParams="*")

+	public static class A5 extends A {}

+

+	@Rest(allowedMethodParams="NONE")

+	public static class A6 extends A {}

+

+	@Rest(allowedMethodParams="None")

+	public static class A7 extends A {}

+

+	@Rest(allowedMethodParams="None")

+	public static class A8 extends A5 {}

+

+	@Test

+	public void a01_basic() throws Exception {

+		RestClient a1 = MockRestClient.build(A1.class);

+		a1.get("/").run().assertBody().is("GET");

+		a1.put("/", "").run().assertBody().is("PUT");

+		a1.head("/").run().assertBody().is("");

+		a1.options("/").run().assertBody().is("OPTIONS");

+		a1.get("/?method=PUT").run().assertBody().is("GET");

+		a1.put("/?method=GET", "").run().assertBody().is("PUT");

+		a1.get("/?method=HEAD").run().assertBody().is("HEAD");

+		a1.get("/?method=OPTIONS").run().assertBody().is("OPTIONS");

+		a1.request("get","/?method=FOO").run().assertBody().is("GET");

+

+		RestClient a2 = MockRestClient.build(A2.class);

+		a2.get("/").run().assertBody().is("GET");

+		a2.put("/", "").run().assertBody().is("PUT");

+		a2.head("/").run().assertBody().is("");

+		a2.options("/").run().assertBody().is("OPTIONS");

+		a2.get("/?method=PUT").run().assertBody().is("GET");

+		a2.put("/?method=GET", "").run().assertBody().is("GET");

+		a2.get("/?method=HEAD").run().assertBody().is("GET");

+		a2.get("/?method=OPTIONS").run().assertBody().is("GET");

+		a2.request("get","/?method=FOO").run().assertBody().is("GET");

+

+		RestClient a3 = MockRestClient.build(A3.class);

+		a3.get("/").run().assertBody().is("GET");

+		a3.put("/", "").run().assertBody().is("PUT");

+		a3.head("/").run().assertBody().is("");

+		a3.options("/").run().assertBody().is("OPTIONS");

+		a3.get("/?method=PUT").run().assertBody().is("GET");

+		a3.put("/?method=GET", "").run().assertBody().is("GET");

+		a3.get("/?method=HEAD").run().assertBody().is("GET");

+		a3.get("/?method=OPTIONS").run().assertBody().is("GET");

+		a3.request("get","/?method=FOO").run().assertBody().is("GET");

+

+		RestClient a4 = MockRestClient.build(A4.class);

+		a4.get("/").run().assertBody().is("GET");

+		a4.put("/", "").run().assertBody().is("PUT");

+		a4.head("/").run().assertBody().is("");

+		a4.options("/").run().assertBody().is("OPTIONS");

+		a4.get("/?method=PUT").run().assertBody().is("GET");

+		a4.put("/?method=GET", "").run().assertBody().is("PUT");

+		a4.get("/?method=HEAD").run().assertBody().is("GET");

+		a4.get("/?method=OPTIONS").run().assertBody().is("GET");

+		a4.request("get","/?method=FOO").run().assertBody().is("FOO");

+

+		RestClient a5 = MockRestClient.build(A5.class);

+		a5.get("/").run().assertBody().is("GET");

+		a5.put("/", "").run().assertBody().is("PUT");

+		a5.head("/").run().assertBody().is("");

+		a5.options("/").run().assertBody().is("OPTIONS");

+		a5.get("/?method=PUT").run().assertBody().is("PUT");

+		a5.put("/?method=GET", "").run().assertBody().is("GET");

+		a5.get("/?method=HEAD").run().assertBody().is("HEAD");

+		a5.get("/?method=OPTIONS").run().assertBody().is("OPTIONS");

+		a5.request("get","/?method=FOO").run().assertBody().is("FOO");

+		a5.get("/?method=Put").run().assertBody().is("PUT");

+		a5.get("/?method=Foo").run().assertBody().is("FOO");

+

+		RestClient a6 = MockRestClient.build(A6.class);

+		a6.get("/").run().assertBody().is("GET");

+		a6.put("/", "").run().assertBody().is("PUT");

+		a6.head("/").run().assertBody().is("");

+		a6.options("/").run().assertBody().is("OPTIONS");

+		a6.get("/?method=PUT").run().assertBody().is("GET");

+		a6.put("/?method=GET", "").run().assertBody().is("PUT");

+		a6.get("/?method=HEAD").run().assertBody().is("GET");

+		a6.get("/?method=OPTIONS").run().assertBody().is("GET");

+		a6.request("get","/?method=FOO").run().assertBody().is("GET");

+

+		RestClient a7 = MockRestClient.build(A7.class);

+		a7.get("/").run().assertBody().is("GET");

+		a7.put("/", "").run().assertBody().is("PUT");

+		a7.head("/").run().assertBody().is("");

+		a7.options("/").run().assertBody().is("OPTIONS");

+		a7.get("/?method=PUT").run().assertBody().is("GET");

+		a7.put("/?method=GET", "").run().assertBody().is("PUT");

+		a7.get("/?method=HEAD").run().assertBody().is("GET");

+		a7.get("/?method=OPTIONS").run().assertBody().is("GET");

+		a7.request("get","/?method=FOO").run().assertBody().is("GET");

+

+		RestClient a8 = MockRestClient.build(A8.class);

+		a8.get("/").run().assertBody().is("GET");

+		a8.put("/", "").run().assertBody().is("PUT");

+		a8.head("/").run().assertBody().is("");

+		a8.options("/").run().assertBody().is("OPTIONS");

+		a8.get("/?method=PUT").run().assertBody().is("GET");

+		a8.put("/?method=GET", "").run().assertBody().is("PUT");

+		a8.get("/?method=HEAD").run().assertBody().is("GET");

+		a8.get("/?method=OPTIONS").run().assertBody().is("GET");

+		a8.request("get","/?method=FOO").run().assertBody().is("GET");

+	}

+}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/AnnotationInheritanceTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AnnotationInheritance_Test.java
similarity index 65%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/AnnotationInheritanceTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AnnotationInheritance_Test.java
index 99bb538..ff668e1 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/AnnotationInheritanceTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_AnnotationInheritance_Test.java
@@ -10,7 +10,7 @@
 // * "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.rest.annotation2;
+package org.apache.juneau.rest.annotation;
 
 import static org.apache.juneau.http.HttpMethod.*;
 import static org.junit.runners.MethodSorters.*;
@@ -19,59 +19,47 @@
 import org.apache.juneau.http.annotation.Header;
 import org.apache.juneau.http.annotation.Query;
 import org.apache.juneau.json.*;
-import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
 import org.apache.juneau.rest.mock2.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class AnnotationInheritanceTest {
+public class Rest_AnnotationInheritance_Test {
 
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// @Body on parameter
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class, defaultAccept="text/json")
 	public static interface IA {
-		@RestMethod(name=PUT, path="/a01")
-		public String a01(@Body String b);
-
-		@RestMethod(name=GET, path="/a02")
-		public String a02(@Query("foo") String b);
-
-		@RestMethod(name=GET, path="/a03")
-		public String a03(@Header("foo") String b);
+		@RestMethod(name=PUT)
+		public String a(@Body String b);
+		@RestMethod(name=GET)
+		public String b(@Query("foo") String b);
+		@RestMethod(name=GET)
+		public String c(@Header("foo") String b);
 	}
 
 	public static class A implements IA {
-
 		@Override
-		public String a01(String b) {
+		public String a(String b) {
 			return b;
 		}
-
 		@Override
-		public String a02(String b) {
+		public String b(String b) {
 			return b;
 		}
-
 		@Override
-		public String a03(String b) {
+		public String c(String b) {
 			return b;
 		}
 	}
 
-	private static MockRestClient a = MockRestClient.build(A.class);
-
 	@Test
-	public void a01_inherited_Body() throws Exception {
-		a.put("/a01", "foo").json().run().assertBody().is("'foo'");
-	}
-	@Test
-	public void a02_inherited_Query() throws Exception {
-		a.get("/a02").query("foo", "bar").json().run().assertBody().is("'bar'");
-	}
-	@Test
-	public void a03_inherited_Header() throws Exception {
-		a.get("/a03").header("foo", "bar").json().run().assertBody().is("'bar'");
+	public void a01_inheritedFromInterface() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.put("/a", "foo").json().run().assertBody().is("'foo'");
+		a.get("/b").query("foo", "bar").json().run().assertBody().is("'bar'");
+		a.get("/c").header("foo", "bar").json().run().assertBody().is("'bar'");
 	}
 }
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestContext_context_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
similarity index 78%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestContext_context_Test.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
index 2a4c299..bc08022 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/RestContext_context_Test.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
@@ -10,20 +10,20 @@
 // * "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.rest;
+package org.apache.juneau.rest.annotation;
 
 import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
 
-import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.mock2.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestContext_context_Test {
+public class Rest_Context_Test {
 
-	public static class MyRestContext extends RestContext {
-		public MyRestContext(RestContextBuilder builder) throws Exception {
+	public static class X1 extends RestContext {
+		public X1(RestContextBuilder builder) throws Exception {
 			super(builder);
 		}
 	}
@@ -38,17 +38,17 @@
 
 	@Test
 	public void a01_default() throws Exception {
-		MockRestClient x = client(A1.class);
-		x.get().run().assertBody().is("RestContext");
+		MockRestClient a1 = client(A1.class);
+		a1.get().run().assertBody().is("RestContext");
 	}
 
-	@Rest(context=MyRestContext.class)
+	@Rest(context=X1.class)
 	public static class A2 extends A1 {}
 
 	@Test
 	public void a02_custom() throws Exception {
-		MockRestClient x = client(A2.class);
-		x.get().run().assertBody().is("MyRestContext");
+		MockRestClient a2 = client(A2.class);
+		a2.get().run().assertBody().is("X1");
 	}
 
 	@Rest
@@ -56,32 +56,32 @@
 
 	@Test
 	public void a03_notOverriddenByChild() throws Exception {
-		MockRestClient x = client(A3.class);
-		x.get().run().assertBody().is("MyRestContext");
+		MockRestClient a3 = client(A3.class);
+		a3.get().run().assertBody().is("X1");
 	}
 
 	@Rest
 	public static class A4 extends A1 {
 		 @RestHook(HookEvent.INIT)
 		 public void init(RestContextBuilder builder) throws Exception {
-			 builder.context(MyRestContext.class);
+			 builder.context(X1.class);
 		 }
 	}
 
 	@Test
 	public void a04_definedInBuilder() throws Exception {
-		MockRestClient x = client(A4.class);
-		x.get().run().assertBody().is("MyRestContext");
+		MockRestClient a4 = client(A4.class);
+		a4.get().run().assertBody().is("X1");
 	}
 
 
-	public static class MyBadRestContext extends RestContext {
-		public MyBadRestContext() throws Exception {
+	public static class X2 extends RestContext {
+		public X2() throws Exception {
 			super(null);
 		}
 	}
 
-	@Rest(context=MyBadRestContext.class)
+	@Rest(context=X2.class)
 	public static class A5 {
 		@RestMethod
 		public String get(RestContext context) {
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Debug_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Debug_Test.java
new file mode 100644
index 0000000..d763a70
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Debug_Test.java
@@ -0,0 +1,1198 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.logging.*;
+
+import javax.servlet.http.*;
+
+import org.apache.juneau.internal.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.client2.*;
+import org.apache.juneau.rest.config.*;
+import org.apache.juneau.rest.mock2.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Rest_Debug_Test {
+
+	public static final CaptureCallLogger LOGGER = new CaptureCallLogger();
+
+	public static class CaptureCallLogger extends BasicRestCallLogger {
+
+		private volatile String msg;
+
+		public static CaptureCallLogger create() {
+			return LOGGER;
+		}
+
+		private CaptureCallLogger() {
+			super(null);
+		}
+
+		@Override
+		protected synchronized void log(Level level, String msg, Throwable e) {
+			this.msg = StringUtils.emptyIfNull(msg);
+		}
+
+		synchronized CaptureCallLogger reset() {
+			this.msg = null;
+			return this;
+		}
+
+		synchronized String getMessage() {
+			return msg;
+		}
+
+		public synchronized CaptureCallLogger assertMessageContains(String s) {
+			assertNotNull(msg);
+			if (! msg.contains(s))
+				assertEquals("Substring not found.", s, msg);
+			return this;
+		}
+	}
+
+	private static void assertLogged(boolean b) {
+		assertEquals(b, LOGGER.getMessage() != null);
+		LOGGER.reset();
+	}
+
+	private static void assertLoggedContains(String s) {
+		String msg = LOGGER.getMessage();
+		assertLogged(true);
+		if (! msg.contains(s))
+			assertEquals("Substring not found.", s, msg);
+		LOGGER.reset();
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @Rest(debug=""), various @RestMethod(debug)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(callLogger=CaptureCallLogger.class)
+	public static class A1 implements BasicUniversalRest {
+		@RestMethod
+		public boolean a(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean b(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean c(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean d(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="foo")
+		public boolean e(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean f(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean g(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+	}
+
+	@Test
+	public void a01_debugDefault() throws Exception {
+		RestClient a1 = MockRestClient.buildSimpleJson(A1.class);
+		RestClient a1d = MockRestClient.create(A1.class).simpleJson().header("X-Debug", true).build();
+
+		a1.get("/a").run().assertBody().is("false");
+		assertLogged(false);
+		a1d.get("/a").run().assertBody().is("false");
+		assertLogged(false);
+
+		a1.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+		a1d.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+
+		a1.get("/c").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c");
+		a1d.get("/c").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c");
+
+		a1.get("/d").run().assertBody().is("false");
+		assertLogged(false);
+		a1d.get("/d").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d");
+
+		a1.get("/e").run().assertBody().is("false");
+		assertLogged(false);
+		a1d.get("/e").run().assertBody().is("false");
+		assertLogged(false);
+
+		a1.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+		a1d.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+
+		a1.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+		a1d.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+	}
+
+	@Rest(callLogger=CaptureCallLogger.class)
+	public static class A1a extends BasicRest {
+		@RestMethod
+		public boolean a(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean b(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean c(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean d(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="foo")
+		public boolean e(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean f(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean g(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+	}
+
+	@Test
+	public void a01a_debugDefault() throws Exception {
+		RestClient a1a = MockRestClient.buildSimpleJson(A1a.class);
+		RestClient a1ad = MockRestClient.create(A1a.class).simpleJson().header("X-Debug", true).build();
+
+		a1a.get("/a").run().assertBody().is("false");
+		assertLogged(false);
+		a1ad.get("/a").run().assertBody().is("false");
+		assertLogged(false);
+
+		a1a.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+		a1ad.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+
+		a1a.get("/c").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c");
+		a1ad.get("/c").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c");
+
+		a1a.get("/d").run().assertBody().is("false");
+		assertLogged(false);
+		a1ad.get("/d").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d");
+
+		a1a.get("/e").run().assertBody().is("false");
+		assertLogged(false);
+		a1ad.get("/e").run().assertBody().is("false");
+		assertLogged(false);
+
+		a1a.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+		a1ad.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+
+		a1a.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+		a1ad.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @Rest(debug="true"), various @RestMethod(debug)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(callLogger=CaptureCallLogger.class, debug="true")
+	public static class A2 implements BasicUniversalRest {
+		@RestMethod
+		public boolean a(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean b(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean c(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean d(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="foo")
+		public boolean e(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean f(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean g(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+	}
+
+	@Test
+	public void a02_debugTrue() throws Exception {
+		RestClient a2 = MockRestClient.buildSimpleJson(A2.class);
+		RestClient a2d = MockRestClient.create(A2.class).simpleJson().header("X-Debug", true).build();
+
+		a2.get("/a").run().assertBody().is("true");
+		assertLogged(true);
+		a2d.get("/a").run().assertBody().is("true");
+		assertLogged(true);
+
+		a2.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+		a2d.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+
+		a2.get("/c").run().assertBody().is("true");
+		assertLogged(true);
+		a2d.get("/c").run().assertBody().is("true");
+		assertLogged(true);
+
+		a2.get("/d").run().assertBody().is("false");
+		assertLogged(false);
+		a2d.get("/d").run().assertBody().is("true");
+		assertLogged(true);
+
+		a2.get("/e").run().assertBody().is("true");
+		assertLogged(true);
+		a2d.get("/e").run().assertBody().is("true");
+		assertLogged(true);
+
+		a2.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+		a2d.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+
+		a2.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+		a2d.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @Rest(debug="false"), various @RestMethod(debug)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(callLogger=CaptureCallLogger.class,debug="false")
+	public static class A3 implements BasicUniversalRest {
+		@RestMethod
+		public boolean a(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean b(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean c(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean d(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="foo")
+		public boolean e(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean f(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean g(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+	}
+
+	@Test
+	public void a03_restDebugFalse() throws Exception {
+		RestClient a3 = MockRestClient.buildSimpleJson(A3.class);
+		RestClient a3d = MockRestClient.create(A3.class).simpleJson().header("X-Debug", true).build();
+
+		a3.get("/a").run().assertBody().is("false");
+		assertLogged(false);
+		a3d.get("/a").run().assertBody().is("false");
+		assertLogged(false);
+
+		a3.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+		a3d.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+
+		a3.get("/c").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c");
+		a3d.get("/c").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c");
+
+		a3.get("/d").run().assertBody().is("false");
+		assertLogged(false);
+		a3d.get("/d").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d");
+
+		a3.get("/e").run().assertBody().is("false");
+		assertLogged(false);
+		a3d.get("/e").run().assertBody().is("false");
+		assertLogged(false);
+
+		a3.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+		a3d.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+
+		a3.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+		a3d.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @Rest(debug="per-request"), various @RestMethod(debug)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(callLogger=CaptureCallLogger.class,debug="per-request")
+	public static class A4 implements BasicUniversalRest {
+		@RestMethod
+		public boolean a(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean b(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean c(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean d(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="foo")
+		public boolean e(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean f(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean g(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+	}
+
+	@Test
+	public void a04_debugPerRequest() throws Exception {
+		RestClient a4 = MockRestClient.buildSimpleJson(A4.class);
+		RestClient a4d = MockRestClient.create(A4.class).simpleJson().header("X-Debug", true).build();
+
+		a4.get("/a").run().assertBody().is("false");
+		assertLogged(false);
+		a4d.get("/a").run().assertBody().is("true");
+		assertLogged(true);
+
+		a4.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+		a4d.get("/b").run().assertBody().is("false");
+		assertLogged(false);
+
+		a4.get("/c").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c");
+		a4d.get("/c").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c");
+
+		a4.get("/d").run().assertBody().is("false");
+		assertLogged(false);
+		a4d.get("/d").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d");
+
+		a4.get("/e").run().assertBody().is("false");
+		assertLogged(false);
+		a4d.get("/e").run().assertBody().is("true");
+		assertLogged(true);
+
+		a4.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+		a4d.get("/f").run().assertBody().is("true");
+		assertLogged(true);
+
+		a4.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+		a4d.get("/g").run().assertBody().is("false");
+		assertLogged(false);
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Implement RestCallLogger directly.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class B1 implements BasicUniversalRest, RestCallLogger {
+		@RestMethod
+		public boolean a(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean b(RestRequest req) {
+			return req.isDebug();
+		}
+		@Override
+		public void log(RestCallLoggerConfig config, HttpServletRequest req, HttpServletResponse res) {
+			LOGGER.log(config, req, res);
+		}
+	}
+
+	@Test
+	public void b01_debugDefault() throws Exception {
+		RestClient b1 = MockRestClient.buildSimpleJson(B1.class);
+
+		b1.get("/a").run().assertBody().is("false");
+		assertLogged(false);
+		b1.get("/b").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /b");
+	}
+
+	@Rest
+	public static class B2 extends BasicRest {
+		@RestMethod
+		public boolean a(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean b(RestRequest req) {
+			return req.isDebug();
+		}
+		@Override
+		public void log(RestCallLoggerConfig config, HttpServletRequest req, HttpServletResponse res) {
+			LOGGER.log(config, req, res);
+		}
+	}
+
+	@Test
+	public void b02_debugDefault() throws Exception {
+		RestClient b2 = MockRestClient.buildSimpleJson(B2.class);
+
+		b2.get("/a").run().assertBody().is("false");
+		assertLogged(false);
+		b2.get("/b").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /b");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @Rest(debugOn=""), various @RestMethod(debug)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(
+		callLogger=CaptureCallLogger.class,
+		debugOn=""
+			+ "C1.b1=false,C1.b2=false,C1.b3=FALSE,C1.b4=FALSE,C1.b5=FALSE,C1.b6=FALSE,"
+			+ " C1.c1 , C1.c2 = true , C1.c3 = TRUE , C1.c4 = TRUE , C1.c5 = TRUE , C1.c6 = TRUE , "
+			+ "C1.d1=per-request,C1.d2=per-request,C1.d3=PER-REQUEST,C1.d4=PER-REQUEST,C1.d5=PER-REQUEST,C1.d6=PER-REQUEST,"
+			+ "C1.e1=foo,C1.e2=,C1.e3=foo,C1.e4=foo,C1.e5=foo,C1.e6=foo,"
+	)
+	public static class C1 implements BasicUniversalRest {
+
+		@RestMethod
+		public boolean a1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean a2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean a3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean a4(RestRequest req) {
+			return req.isDebug();
+		}
+
+		// debug=false
+		@RestMethod
+		public boolean b1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean b2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean b3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean b4(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean b5(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean b6(RestRequest req) {
+			return req.isDebug();
+		}
+
+		// debug=true
+		@RestMethod
+		public boolean c1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean c2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean c3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean c4(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean c5(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean c6(RestRequest req) {
+			return req.isDebug();
+		}
+
+		// debug=per-request
+		@RestMethod
+		public boolean d1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean d2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean d3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean d4(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean d5(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean d6(RestRequest req) {
+			return req.isDebug();
+		}
+
+		// debug=foo
+		@RestMethod
+		public boolean e1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean e2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean e3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean e4(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean e5(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean e6(RestRequest req) {
+			return req.isDebug();
+		}
+
+		@RestMethod
+		public boolean f1(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean f2(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean f3(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean f4(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+
+		@RestMethod
+		public boolean g1(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean g2(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean g3(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean g4(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+	}
+
+	@Test
+	public void c01_debugDefault() throws Exception {
+		RestClient c1 = MockRestClient.buildSimpleJson(C1.class);
+		RestClient c1d = MockRestClient.create(C1.class).simpleJson().header("X-Debug", true).build();
+
+		c1.get("/a1").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/a1").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/a2").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/a2").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/a3").run().assertBody().is("true");
+		assertLogged(true);
+		c1d.get("/a3").run().assertBody().is("true");
+		assertLogged(true);
+		c1.get("/a4").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/a4").run().assertBody().is("true");
+		assertLogged(true);
+
+		c1.get("/b1").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/b1").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/b2").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/b2").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/b3").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/b3").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/b4").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/b4").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/b5").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/b5").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/b6").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/b6").run().assertBody().is("false");
+		assertLogged(false);
+
+		c1.get("/c1").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c1");
+		c1d.get("/c1").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c1");
+		c1.get("/c2").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c2");
+		c1d.get("/c2").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c2");
+		c1.get("/c3").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c3");
+		c1d.get("/c3").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c3");
+		c1.get("/c4").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c4");
+		c1d.get("/c4").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c4");
+		c1.get("/c5").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c5");
+		c1d.get("/c5").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c5");
+		c1.get("/c6").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c6");
+		c1d.get("/c6").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c6");
+
+		c1.get("/d1").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/d1").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d1");
+		c1.get("/d2").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/d2").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d2");
+		c1.get("/d3").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/d3").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d3");
+		c1.get("/d4").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/d4").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d4");
+		c1.get("/d5").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/d5").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d5");
+		c1.get("/d6").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/d6").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d6");
+
+		c1.get("/e1").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/e1").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/e2").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/e2").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/e3").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/e3").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/e4").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/e4").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/e5").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/e5").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/e6").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/e6").run().assertBody().is("false");
+		assertLogged(false);
+
+		c1.get("/f1").run().assertBody().is("true");
+		assertLogged(true);
+		c1d.get("/f1").run().assertBody().is("true");
+		assertLogged(true);
+		c1.get("/f2").run().assertBody().is("true");
+		assertLogged(true);
+		c1d.get("/f2").run().assertBody().is("true");
+		assertLogged(true);
+		c1.get("/f3").run().assertBody().is("true");
+		assertLogged(true);
+		c1d.get("/f3").run().assertBody().is("true");
+		assertLogged(true);
+		c1.get("/f4").run().assertBody().is("true");
+		assertLogged(true);
+		c1d.get("/f4").run().assertBody().is("true");
+		assertLogged(true);
+
+		c1.get("/g1").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/g1").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/g2").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/g2").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/g3").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/g3").run().assertBody().is("false");
+		assertLogged(false);
+		c1.get("/g4").run().assertBody().is("false");
+		assertLogged(false);
+		c1d.get("/g4").run().assertBody().is("false");
+		assertLogged(false);
+	}
+
+	static {
+		System.setProperty("C2DebugEnabled", "C2=true");
+	}
+	@Rest(
+		callLogger=CaptureCallLogger.class,
+		debugOn="$S{C2DebugEnabled},"
+			+ "C2.b1=false,C2.b2=false,C2.b3=FALSE,C2.b4=FALSE,C2.b5=FALSE,C2.b6=FALSE,"
+			+ " C2.c1 , C2.c2 = true , C2.c3 = TRUE , C2.c4 = TRUE , C2.c5 = TRUE , C2.c6 = TRUE , "
+			+ "C2.d1=per-request,C2.d2=per-request,C2.d3=PER-REQUEST,C2.d4=PER-REQUEST,C2.d5=PER-REQUEST,C2.d6=PER-REQUEST,"
+			+ "C2.e1=foo,C2.e2=,C2.e3=foo,C2.e4=foo,C2.e5=foo,C2.e6=foo,"
+	)
+	public static class C2 implements BasicUniversalRest {
+
+		@RestMethod
+		public boolean a1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean a2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean a3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean a4(RestRequest req) {
+			return req.isDebug();
+		}
+
+		// debug=false
+		@RestMethod
+		public boolean b1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean b2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean b3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean b4(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean b5(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean b6(RestRequest req) {
+			return req.isDebug();
+		}
+
+		// debug=true
+		@RestMethod
+		public boolean c1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean c2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean c3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean c4(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean c5(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean c6(RestRequest req) {
+			return req.isDebug();
+		}
+
+		// debug=per-request
+		@RestMethod
+		public boolean d1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean d2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean d3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean d4(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean d5(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean d6(RestRequest req) {
+			return req.isDebug();
+		}
+
+		// debug=foo
+		@RestMethod
+		public boolean e1(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean e2(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod
+		public boolean e3(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean e4(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean e5(RestRequest req) {
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean e6(RestRequest req) {
+			return req.isDebug();
+		}
+
+		@RestMethod
+		public boolean f1(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean f2(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean f3(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean f4(RestRequest req) throws Exception {
+			req.setDebug();
+			return req.isDebug();
+		}
+
+		@RestMethod
+		public boolean g1(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+		@RestMethod(debug="false")
+		public boolean g2(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+		@RestMethod(debug="true")
+		public boolean g3(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+		@RestMethod(debug="per-request")
+		public boolean g4(RestRequest req) throws Exception {
+			req.setDebug(false);
+			return req.isDebug();
+		}
+	}
+
+	@Test
+	public void c02_debugTrue() throws Exception {
+		RestClient c2 = MockRestClient.buildSimpleJson(C2.class);
+		RestClient c2d = MockRestClient.create(C2.class).simpleJson().header("X-Debug", true).build();
+
+		c2.get("/a1").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/a1").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/a2").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/a2").run().assertBody().is("false");
+		assertLogged(false);
+		c2.get("/a3").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/a3").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/a4").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/a4").run().assertBody().is("true");
+		assertLogged(true);
+
+		c2.get("/b1").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/b1").run().assertBody().is("false");
+		assertLogged(false);
+		c2.get("/b2").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/b2").run().assertBody().is("false");
+		assertLogged(false);
+		c2.get("/b3").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/b3").run().assertBody().is("false");
+		assertLogged(false);
+		c2.get("/b4").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/b4").run().assertBody().is("false");
+		assertLogged(false);
+		c2.get("/b5").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/b5").run().assertBody().is("false");
+		assertLogged(false);
+		c2.get("/b6").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/b6").run().assertBody().is("false");
+		assertLogged(false);
+
+		c2.get("/c1").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c1");
+		c2d.get("/c1").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c1");
+		c2.get("/c2").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c2");
+		c2d.get("/c2").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c2");
+		c2.get("/c3").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c3");
+		c2d.get("/c3").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c3");
+		c2.get("/c4").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c4");
+		c2d.get("/c4").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c4");
+		c2.get("/c5").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c5");
+		c2d.get("/c5").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c5");
+		c2.get("/c6").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c6");
+		c2d.get("/c6").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /c6");
+
+		c2.get("/d1").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/d1").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d1");
+		c2.get("/d2").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/d2").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d2");
+		c2.get("/d3").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/d3").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d3");
+		c2.get("/d4").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/d4").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d4");
+		c2.get("/d5").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/d5").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d5");
+		c2.get("/d6").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/d6").run().assertBody().is("true");
+		assertLoggedContains("[200] HTTP GET /d6");
+
+		c2.get("/e1").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/d1").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/e2").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/e2").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/e3").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/e3").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/e4").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/e4").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/e5").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/e5").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/e6").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/e6").run().assertBody().is("true");
+		assertLogged(true);
+
+		c2.get("/f1").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/f1").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/f2").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/f2").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/f3").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/f3").run().assertBody().is("true");
+		assertLogged(true);
+		c2.get("/f4").run().assertBody().is("true");
+		assertLogged(true);
+		c2d.get("/f4").run().assertBody().is("true");
+		assertLogged(true);
+
+		c2.get("/g1").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/g1").run().assertBody().is("false");
+		assertLogged(false);
+		c2.get("/g2").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/g2").run().assertBody().is("false");
+		assertLogged(false);
+		c2.get("/g3").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/g3").run().assertBody().is("false");
+		assertLogged(false);
+		c2.get("/g4").run().assertBody().is("false");
+		assertLogged(false);
+		c2d.get("/g4").run().assertBody().is("false");
+		assertLogged(false);
+	}
+
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ContentEncodingTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Encoders_Test.java
similarity index 67%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ContentEncodingTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Encoders_Test.java
index 7c7e012..da5c15e 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ContentEncodingTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Encoders_Test.java
@@ -10,24 +10,23 @@
 // * "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.rest.headers;
+package org.apache.juneau.rest.annotation;
 
-import static org.apache.juneau.http.HttpMethod.*;
 import static org.junit.runners.MethodSorters.*;
 
 import org.apache.juneau.encoders.*;
 import org.apache.juneau.http.annotation.Body;
 import org.apache.juneau.internal.*;
-import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
 import org.apache.juneau.rest.mock2.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class ContentEncodingTest {
+public class Rest_Encoders_Test {
 
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// Setup classes
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	public static class MyEncoder extends GzipEncoder {
 		@Override /* ConfigEncoder */
@@ -36,9 +35,9 @@
 		}
 	}
 
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// Test with no compression enabled.
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest
 	public static class A {
@@ -47,16 +46,13 @@
 			return in;
 		}
 	}
-	static MockRestClient a = MockRestClient.buildLax(A.class);
 
 	@Test
 	public void a01_noCompression() throws Exception {
+		RestClient a = MockRestClient.buildLax(A.class);
 		a.put("/", "foo").run().assertBody().is("foo");
 		a.put("/", "foo").contentEncoding("").run().assertBody().is("foo");
 		a.put("/", "foo").contentEncoding("identity").run().assertBody().is("foo");
-	}
-	@Test
-	public void a02_noCompression_invalid() throws Exception {
 		a.put("?noTrace=true", StringUtils.compress("foo")).contentEncoding("mycoding").run()
 			.assertCode().is(415)
 			.assertBody().contains(
@@ -65,21 +61,21 @@
 			);
 	}
 
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 	// Test with compression enabled.
-	//=================================================================================================================
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest(encoders=MyEncoder.class)
 	public static class B {
-		@RestMethod(name=PUT, path="/")
-		public String test1put(@Body String in) {
+		@RestMethod
+		public String put(@Body String in) {
 			return in;
 		}
 	}
-	static MockRestClient b = MockRestClient.build(B.class);
 
 	@Test
-	public void b01_withCompression_identity() throws Exception {
+	public void b01_withCompression() throws Exception {
+		RestClient b = MockRestClient.build(B.class);
 		b.put("/", "foo")
 			.run()
 			.assertBody().is("foo");
@@ -91,13 +87,9 @@
 			.contentEncoding("identity")
 			.run()
 			.assertBody().is("foo");
-	}
-	@Test
-	@Ignore
-	public void b02_withCompression_gzip() throws Exception {
-		b.put("/", StringUtils.compress("foo"))
-			.contentEncoding("mycoding")
-			.run()
-			.assertBody().is("foo");
+//		b.put("/", StringUtils.compress("foo"))
+//			.contentEncoding("mycoding")
+//			.run()
+//			.assertBody().is("foo");
 	}
 }
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Logging_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Logging_Test.java
new file mode 100644
index 0000000..cc22cd2
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Logging_Test.java
@@ -0,0 +1,557 @@
+// ***************************************************************************************************************************

+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

+// * with the License.  You may obtain a copy of the License at                                                              *

+// *                                                                                                                         *

+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

+// *                                                                                                                         *

+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

+// * specific language governing permissions and limitations under the License.                                              *

+// ***************************************************************************************************************************

+package org.apache.juneau.rest.annotation;

+

+import static org.junit.runners.MethodSorters.*;

+

+import java.util.*;

+import java.util.stream.*;

+

+import org.apache.juneau.marshall.*;

+import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.RestRequest;

+import org.apache.juneau.rest.RestResponse;

+import org.apache.juneau.rest.client2.*;

+import org.apache.juneau.rest.mock2.*;

+import org.junit.*;

+

+@FixMethodOrder(NAME_ASCENDING)

+public class Rest_Logging_Test {

+

+	private static String string(RestCallLoggerConfig config) {

+		return SimpleJson.DEFAULT.toString(config);

+	}

+	private static String string(Collection<RestCallLoggerRule> rules) {

+		return rules.stream().map(x -> x.toString()).collect(Collectors.joining(","));

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Default logger config

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest

+	public static class A  {

+		@RestMethod

+		public String get(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	@Test

+	public void a01_default() throws Exception {

+		RestClient a = MockRestClient.build(A.class);

+		a.get("/").run().assertBody().is("{}");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Level

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(logging=@Logging(level="WARNING"))

+	public static class B1 {

+		@RestMethod

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(level="SEVERE"))

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(level="SEVERE"))

+		public String e(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	@Rest

+	public static class B2 {

+		@RestMethod

+		public String c(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(level="SEVERE"))

+		public String d(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	public static class B3 extends B1 {

+		@Override

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@Override

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@Override

+		@RestMethod(logging=@Logging(level="OFF"))

+		public String e(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod

+		public String f(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(level="SEVERE"))

+		public String g(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	@Test

+	public void b01_logging() throws Exception {

+		RestClient b1 = MockRestClient.build(B1.class);

+		b1.get("/a").run().assertBody().is("{level:'WARNING'}");

+		b1.get("/b").run().assertBody().is("{level:'SEVERE'}");

+

+		RestClient b2 = MockRestClient.build(B2.class);

+		b2.get("/c").run().assertBody().is("{}");

+		b2.get("/d").run().assertBody().is("{level:'SEVERE'}");

+

+		RestClient b3 = MockRestClient.build(B3.class);

+		b3.get("/a").run().assertBody().is("{level:'WARNING'}");

+		b3.get("/b").run().assertBody().is("{level:'SEVERE'}");

+		b3.get("/e").run().assertBody().is("{level:'OFF'}");

+		b3.get("/f").run().assertBody().is("{level:'WARNING'}");

+		b3.get("/g").run().assertBody().is("{level:'SEVERE'}");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// useStackTraceHashing

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(logging=@Logging(useStackTraceHashing="true"))

+	public static class C1 {

+		@RestMethod

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(useStackTraceHashing="false"))

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(useStackTraceHashing="false"))

+		public String f(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	@Rest

+	public static class C2 {

+		@RestMethod

+		public String c(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(useStackTraceHashing="true"))

+		public String d(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(useStackTraceHashing="foo"))

+		public String e(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	public static class C3 extends C1 {

+		@Override

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@Override

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@Override

+		@RestMethod(logging=@Logging(useStackTraceHashing="TRUE"))

+		public String f(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod

+		public String g(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(useStackTraceHashing="FALSE"))

+		public String h(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+	@Rest(logging=@Logging(useStackTraceHashing="foo"))

+	public static class C4 {

+		@RestMethod(path="i")

+		public String i(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	@Test

+	public void c01_useStackTraceHashing() throws Exception {

+		RestClient c1 = MockRestClient.build(C1.class);

+		c1.get("/a").run().assertBody().is("{useStackTraceHashing:true}");

+		c1.get("/b").run().assertBody().is("{}");

+

+		RestClient c2 = MockRestClient.build(C2.class);

+		c2.get("/c").run().assertBody().is("{}");

+		c2.get("/d").run().assertBody().is("{useStackTraceHashing:true}");

+		c2.get("/e").run().assertBody().is("{}");

+

+		RestClient c3 = MockRestClient.build(C3.class);

+		c3.get("/a").run().assertBody().is("{useStackTraceHashing:true}");

+		c3.get("/b").run().assertBody().is("{}");

+		c3.get("/f").run().assertBody().is("{useStackTraceHashing:true}");

+		c3.get("/g").run().assertBody().is("{useStackTraceHashing:true}");

+		c3.get("/h").run().assertBody().is("{}");

+

+		RestClient c4 = MockRestClient.build(C4.class);

+		c4.get("/i").run().assertBody().is("{}");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// stackTraceHashingTimeout

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(logging=@Logging(stackTraceHashingTimeout="1"))

+	public static class D1 {

+		@RestMethod

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(stackTraceHashingTimeout="2"))

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(stackTraceHashingTimeout="3"))

+		public String e(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	@Rest

+	public static class D2 {

+		@RestMethod

+		public String c(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(stackTraceHashingTimeout="4"))

+		public String d(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	public static class D3 extends D1 {

+		@Override

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@Override

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@Override

+		@RestMethod(logging=@Logging(stackTraceHashingTimeout="5"))

+		public String e(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod

+		public String f(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(stackTraceHashingTimeout="6"))

+		public String g(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+

+	@Test

+	public void d01_stackTraceHashingTimeout() throws Exception {

+		RestClient d1 = MockRestClient.build(D1.class);

+		d1.get("/a").run().assertBody().is("{stackTraceHashingTimeout:1}");

+		d1.get("/b").run().assertBody().is("{stackTraceHashingTimeout:2}");

+

+		RestClient d2 = MockRestClient.build(D2.class);

+		d2.get("/c").run().assertBody().is("{}");

+		d2.get("/d").run().assertBody().is("{stackTraceHashingTimeout:4}");

+

+		RestClient d3 = MockRestClient.build(D3.class);

+		d3.get("/a").run().assertBody().is("{stackTraceHashingTimeout:1}");

+		d3.get("/b").run().assertBody().is("{stackTraceHashingTimeout:2}");

+		d3.get("/e").run().assertBody().is("{stackTraceHashingTimeout:5}");

+		d3.get("/f").run().assertBody().is("{stackTraceHashingTimeout:1}");

+		d3.get("/g").run().assertBody().is("{stackTraceHashingTimeout:6}");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// noTrace

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(logging=@Logging(disabled="true"))

+	public static class E1 {

+		@RestMethod

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(disabled="per-request"))

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(disabled="per-request"))

+		public String f(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	@Rest

+	public static class E2 {

+		@RestMethod

+		public String c(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(disabled="true"))

+		public String d(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(disabled="foo"))

+		public String e(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	public static class E3 extends E1 {

+		@Override

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@Override

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@Override

+		@RestMethod(logging=@Logging(disabled="false"))

+		public String f(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod

+		public String g(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+		@RestMethod(logging=@Logging(disabled="per-request"))

+		public String h(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+	@Rest(logging=@Logging(disabled="foo"))

+	public static class E4 {

+		@RestMethod

+		public String i(RestRequest req) {

+			return string(req.getCallLoggerConfig());

+		}

+	}

+

+	@Test

+	public void e01_noTrace() throws Exception {

+		RestClient e1 = MockRestClient.build(E1.class);

+		e1.get("/a").run().assertBody().is("{disabled:'TRUE'}");

+		e1.get("/b").run().assertBody().is("{disabled:'PER_REQUEST'}");

+

+		RestClient e2 = MockRestClient.build(E2.class);

+		e2.get("/c").run().assertBody().is("{}");

+		e2.get("/d").run().assertBody().is("{disabled:'TRUE'}");

+		e2.get("/e").run().assertBody().is("{}");

+

+		RestClient e3 = MockRestClient.build(E3.class);

+		e3.get("/a").run().assertBody().is("{disabled:'TRUE'}");

+		e3.get("/b").run().assertBody().is("{disabled:'PER_REQUEST'}");

+		e3.get("/f").run().assertBody().is("{}");

+		e3.get("/g").run().assertBody().is("{disabled:'TRUE'}");

+		e3.get("/h").run().assertBody().is("{disabled:'PER_REQUEST'}");

+

+		RestClient e4 = MockRestClient.build(E4.class);

+		e4.get("/i").run().assertBody().is("{}");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// rules

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(logging=@Logging(rules=@LoggingRule(codes="1")))

+	public static class F1 {

+		@RestMethod

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+		@RestMethod(logging=@Logging(rules=@LoggingRule(codes="2")))

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+		@RestMethod(logging=@Logging(rules=@LoggingRule(codes="3")))

+		public String e(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+	}

+

+	@Rest

+	public static class F2 {

+		@RestMethod

+		public String c(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+		@RestMethod(logging=@Logging(rules=@LoggingRule(codes="4")))

+		public String d(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+	}

+

+	public static class F3 extends F1 {

+		@Override

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+		@Override

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+		@Override

+		@RestMethod(logging=@Logging(rules=@LoggingRule(codes="5")))

+		public String e(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+		@RestMethod

+		public String f(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+		@RestMethod(logging=@Logging(rules=@LoggingRule(codes="6")))

+		public String g(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+	}

+

+	@Test

+	public void f01_rules() throws Exception {

+		RestClient f1 = MockRestClient.build(F1.class);

+		f1.get("/a").run().assertBody().is("{codes:'1'}");

+		f1.get("/b").run().assertBody().is("{codes:'2'},{codes:'1'}");

+

+		RestClient f2 = MockRestClient.build(F2.class);

+		f2.get("/c").run().assertBody().is("");

+		f2.get("/d").run().assertBody().is("{codes:'4'}");

+

+		RestClient f3 = MockRestClient.build(F3.class);

+		f3.get("/a").run().assertBody().is("{codes:'1'}");

+		f3.get("/b").run().assertBody().is("{codes:'2'},{codes:'1'}");

+		f3.get("/e").run().assertBody().is("{codes:'5'},{codes:'3'},{codes:'1'}");

+		f3.get("/f").run().assertBody().is("{codes:'1'}");

+		f3.get("/g").run().assertBody().is("{codes:'6'},{codes:'1'}");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// rules

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		logging=@Logging(

+			rules=@LoggingRule(

+				exceptions="1",

+				debugOnly="true",

+				level="WARNING",

+				req="MEDIUM",

+				res="LARGE"

+			)

+		)

+	)

+	public static class G1 {

+		@RestMethod

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+		@RestMethod(

+			logging=@Logging(

+				rules=@LoggingRule(

+					exceptions="2",

+					debugOnly="true",

+					level="WARNING",

+					req="MEDIUM",

+					res="LARGE"

+				)

+			)

+		)

+		public String b(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+	}

+

+	@Rest

+	public static class G2 {

+		@RestMethod(

+			logging=@Logging(

+				rules=@LoggingRule(

+					exceptions="3",

+					debugOnly="true",

+					level="WARNING",

+					req="MEDIUM",

+					res="LARGE"

+				)

+			)

+		)

+		public String a(RestRequest req) {

+			return string(req.getCallLoggerConfig().getRules());

+		}

+	}

+

+	@Test

+	public void g01_rules() throws Exception {

+		RestClient g1 = MockRestClient.build(G1.class);

+		g1.get("/b").run().assertBody().is("{exceptions:'2',debugOnly:true,level:'WARNING',req:'MEDIUM'},{exceptions:'1',debugOnly:true,level:'WARNING',req:'MEDIUM'}");

+

+		RestClient g2 = MockRestClient.build(G2.class);

+		g2.get("/a").run().assertBody().is("{exceptions:'3',debugOnly:true,level:'WARNING',req:'MEDIUM'}");

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Examples

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(

+		debug="always",

+		logging=@Logging(

+			useStackTraceHashing="true",

+			rules={

+				@LoggingRule(codes=">=500", level="off", req="short", res="short")

+			}

+		)

+	)

+	public static class H {

+

+		@RestMethod(method="POST", path="foo")

+		public String a(RestRequest req, RestResponse res) throws Exception {

+			res.setStatus(500);

+			res.setHeader("Foo", "bar");

+			res.setException(new StringIndexOutOfBoundsException());

+			return req.getBody().asString();

+		}

+	}

+

+

+	@Test

+	public void h01_examples() throws Exception {

+		RestClient MY_REST = MockRestClient.buildLax(H.class);

+		MY_REST.post("/foo?foo=bar", "Foo")

+			.header("Foo", "bar")

+			.run()

+			.assertCode().is(500);

+		MY_REST.post("/foo?foo=bar", "Foo")

+			.header("Foo", "bar")

+			.run()

+			.assertCode().is(500);

+	}

+}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java
index 2157af2..923cae7 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java
@@ -19,6 +19,7 @@
 import org.apache.juneau.collections.*;

 import org.apache.juneau.cp.*;

 import org.apache.juneau.http.annotation.*;

+import org.apache.juneau.rest.*;

 import org.apache.juneau.rest.mock2.*;

 import org.junit.*;

 

@@ -44,10 +45,10 @@
 			return m.getString(name);

 		}

 	}

-	static MockRestClient a1 = MockRestClient.build(A1.class);

 

 	@Test

 	public void a01_default() throws Exception {

+		MockRestClient a1 = MockRestClient.build(A1.class);

 		a1.get("/a").run().assertBody().is("{'A1.key2':'A1.value2a',key1:'value1a',key2:'A1.value2a'}");

 		a1.get("/b").run().assertBody().is("{'A1.key2':'A1.value2a',key1:'value1a',key2:'A1.value2a'}");

 		a1.get("/c?name=key1").run().assertBody().is("value1a");

@@ -57,10 +58,10 @@
 

 	@Rest

 	public static class A2 extends A1 {}

-	static MockRestClient a2 = MockRestClient.build(A2.class);

 

 	@Test

 	public void a02_subclassed() throws Exception {

+		MockRestClient a2 = MockRestClient.build(A2.class);

 		a2.get("/a").run().assertBody().is("{'A1.key2':'A1.value2a','A2.key3':'A2.value3b',key1:'value1a',key2:'value2b',key3:'A2.value3b'}");

 		a2.get("/b").run().assertBody().is("{'A1.key2':'A1.value2a','A2.key3':'A2.value3b',key1:'value1a',key2:'value2b',key3:'A2.value3b'}");

 		a2.get("/c?name=key1").run().assertBody().is("value1a");

@@ -88,10 +89,10 @@
 			return m.getString(name);

 		}

 	}

-	static MockRestClient b1 = MockRestClient.build(B1.class);

 

 	@Test

 	public void b01_customName() throws Exception {

+		MockRestClient b1 = MockRestClient.build(B1.class);

 		b1.get("/a").run().assertBody().is("{'B1.key2':'B1.value2a',key1:'value1a',key2:'B1.value2a'}");

 		b1.get("/b").run().assertBody().is("{'B1.key2':'B1.value2a',key1:'value1a',key2:'B1.value2a'}");

 		b1.get("/c?name=key1").run().assertBody().is("value1a");

@@ -101,10 +102,10 @@
 

 	@Rest(messages="B2x")

 	public static class B2 extends B1 {}

-	static MockRestClient b2 = MockRestClient.build(B2.class);

 

 	@Test

 	public void b02_subclassed_customName() throws Exception {

+		MockRestClient b2 = MockRestClient.build(B2.class);

 		b2.get("/a").run().assertBody().stderr().is("{'B1.key2':'B1.value2a','B2.key3':'B2.value3b',key1:'value1a',key2:'value2b',key3:'B2.value3b'}");

 		b2.get("/b").run().assertBody().is("{'B1.key2':'B1.value2a','B2.key3':'B2.value3b',key1:'value1a',key2:'value2b',key3:'B2.value3b'}");

 		b2.get("/c?name=key1").run().assertBody().is("value1a");

@@ -113,6 +114,25 @@
 		b2.get("/c?name=key4").run().assertBody().is("{!key4}");

 	}

 

+	public static class B3 extends B1 {

+		 @RestHook(HookEvent.INIT)

+		 public void init(RestContextBuilder builder) throws Exception {

+			 builder.messages("B2x");

+			 builder.messages(B1.class, "B1x");

+		 }

+	}

+

+	@Test

+	public void b03_viaBuilder() throws Exception {

+		MockRestClient b3 = MockRestClient.build(B3.class);

+		b3.get("/a").run().assertBody().stderr().is("{'B1.key2':'B1.value2a','B2.key3':'B2.value3b',key1:'value1a',key2:'value2b'}");

+		b3.get("/b").run().assertBody().is("{'B1.key2':'B1.value2a','B2.key3':'B2.value3b',key1:'value1a',key2:'value2b'}");

+		b3.get("/c?name=key1").run().assertBody().is("value1a");

+		b3.get("/c?name=key2").run().assertBody().is("value2b");

+		b3.get("/c?name=key3").run().assertBody().is("{!key3}");

+		b3.get("/c?name=key4").run().assertBody().is("{!key4}");

+	}

+

 	//------------------------------------------------------------------------------------------------------------------

 	// Helper methods.

 	//------------------------------------------------------------------------------------------------------------------

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourcePropertiesTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_RVars_Test.java
similarity index 84%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourcePropertiesTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_RVars_Test.java
index 88bb227..c16657d 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourcePropertiesTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_RVars_Test.java
@@ -19,17 +19,18 @@
 import java.io.IOException;

 

 import org.apache.juneau.*;

-import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.RestResponse;

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.apache.juneau.serializer.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class RestResourcePropertiesTest {

+public class Rest_RVars_Test {

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Basic tests

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest(

 		path="/p1",

@@ -51,17 +52,17 @@
 

 		@RestMethod(name=GET, path="/p2",

 			reqAttrs={"B1: b1", "B2:b"},

-			serializers=A01.class

+			serializers=A1.class

 		)

-		public void testPropertiesDefinedOnMethod(RestResponse res) {

+		public void a(RestResponse res) {

 			res.attr("A2", "c");

 			res.attr("B2", "c");

 			res.attr("C", "c");

 			res.setOutput(null);

 		}

 

-		public static class A01 extends WriterSerializer {

-			public A01(PropertyStore ps) {

+		public static class A1 extends WriterSerializer {

+			public A1(PropertyStore ps) {

 				super(ps, "text/plain", "*/*");

 			}

 			@Override /* Serializer */

@@ -77,10 +78,10 @@
 			}

 		}

 	}

-	static MockRestClient a = MockRestClient.build(A.class);

 

 	@Test

-	public void a01() throws Exception {

+	public void a01_basic() throws Exception {

+		RestClient a = MockRestClient.build(A.class);

 		a.get("/p2").accept("text/plain").run().assertBody().is("A1=a1,A2=c,B1=b1,B2=c,C=c,R1a=/p1/p2,R1b=/p1,R2=bar,R3=,R4=a1,R5=c,R6=c");

 	}

 }

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceStaticFilesTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_StaticFiles_Test.java
similarity index 75%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceStaticFilesTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_StaticFiles_Test.java
index bfea12e..7bfc744 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceStaticFilesTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_StaticFiles_Test.java
@@ -14,68 +14,38 @@
 

 import static org.junit.runners.MethodSorters.*;

 

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class RestResourceStaticFilesTest {

+public class Rest_StaticFiles_Test {

 

 	//------------------------------------------------------------------------------------------------------------------

 	// Basic tests

 	//------------------------------------------------------------------------------------------------------------------

 

 	@Rest(staticFiles={"xdocs:xdocs","xdocs2:xdocs2:{Foo:'Bar'}"})

-	public static class A1 {

+	public static class A {

 		@RestMethod

-		public String a01() {

+		public String a() {

 			return null;

 		}

 	}

-	static MockRestClient a1 = MockRestClient.buildLax(A1.class);

 

 	@Test

-	public void a01a() throws Exception {

-		a1.get("/xdocs/test.txt")

+	public void a01_basic() throws Exception {

+		RestClient a = MockRestClient.buildLax(A.class);

+		a.get("/xdocs/test.txt")

 			.run()

 			.assertBody().contains("OK-1");

-		a1.get("/xdocs/xsubdocs/test.txt")

+		a.get("/xdocs/xsubdocs/test.txt")

 			.run()

 			.assertBody().contains("OK-2");

-	}

-	@Test

-	public void a01b_preventPathTraversals() throws Exception {

-		a1.get("/xdocs/xsubdocs/../test.txt?noTrace=true")

+		a.get("/xdocs/xsubdocs/../test.txt?noTrace=true")

 			.run()

 			.assertCode().is(404);

-		a1.get("/xdocs/xsubdocs/%2E%2E/test.txt?noTrace=true")

-			.run()

-			.assertCode().is(404);

-	}

-

-	@Rest(staticFiles={"xdocs2:xdocs2:{Foo:'Bar',Baz:'Qux'},xdocs:xdocs"})

-	public static class A2 {

-		@RestMethod

-		public String a02() {

-			return null;

-		}

-	}

-	static MockRestClient a2 = MockRestClient.build(A1.class);

-

-	@Test

-	public void a02a() throws Exception {

-		a1.get("/xdocs/test.txt")

-			.run()

-			.assertBody().contains("OK-1");

-		a1.get("/xdocs/xsubdocs/test.txt")

-			.run()

-			.assertBody().contains("OK-2");

-	}

-	@Test

-	public void a02b_preventPathTraversals() throws Exception {

-		a1.get("/xdocs/xsubdocs/../test.txt?noTrace=true")

-			.run()

-			.assertCode().is(404);

-		a1.get("/xdocs/xsubdocs/%2E%2E/test.txt?noTrace=true")

+		a.get("/xdocs/xsubdocs/%2E%2E/test.txt?noTrace=true")

 			.run()

 			.assertCode().is(404);

 	}

@@ -87,14 +57,14 @@
 	@Rest(staticFiles={"xdocs:xdocs:{Foo:'Bar',Baz:'Qux'}"})

 	public static class B {

 		@RestMethod

-		public String b01() {

+		public String a() {

 			return null;

 		}

 	}

-	static MockRestClient b = MockRestClient.build(B.class);

 

 	@Test

-	public void b01() throws Exception {

+	public void b01_withResponseHeaders() throws Exception {

+		RestClient b = MockRestClient.build(B.class);

 		b.get("/xdocs/test.txt")

 			.run()

 			.assertStringHeader("Foo").is("Bar")

@@ -109,7 +79,7 @@
 	@Rest(staticFiles={"xdocs:xdocs"})

 	public static class C1 {

 		@RestMethod

-		public String c01() {

+		public String a() {

 			return null;

 		}

 	}

@@ -117,16 +87,14 @@
 	@Rest(staticFiles={"xdocs:/xdocs"})

 	public static class C2 extends C1 {

 		@RestMethod

-		public String c02() {

+		public String b() {

 			return null;

 		}

 	}

 

-	static MockRestClient c1 = MockRestClient.build(C1.class);

-	static MockRestClient c2 = MockRestClient.build(C2.class);

-

 	@Test

-	public void c01() throws Exception {

+	public void c01_classHierarchy() throws Exception {

+		RestClient c1 = MockRestClient.build(C1.class);

 		// Should resolve to relative xdocs folder.

 		c1.get("/xdocs/test.txt")

 			.run()

@@ -136,6 +104,7 @@
 			.assertBody().contains("OK-2");

 

 		// Should be overridden to absolute xdocs folder.

+		RestClient c2 = MockRestClient.build(C2.class);

 		c2.get("/xdocs/test.txt")

 			.run()

 			.assertBody().contains("OK-3");

@@ -165,15 +134,15 @@
 	@Rest(staticFiles={"xdocs:/xdocs,xdocs:xdocs"})

 	public static class D {

 		@RestMethod

-		public String d01() {

+		public String a() {

 			return null;

 		}

 	}

 

-	static MockRestClient d = MockRestClient.build(D.class);

-

 	@Test

-	public void d01() throws Exception {

+	public void d01_overriddenPatterns() throws Exception {

+		RestClient d = MockRestClient.build(D.class);

+

 		// Should be overridden to absolute xdocs folder.

 		d.get("/xdocs/test.txt")

 			.run()

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Parsers_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Parsers_Test.java
new file mode 100644
index 0000000..9a52407
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Parsers_Test.java
@@ -0,0 +1,246 @@
+// ***************************************************************************************************************************

+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

+// * with the License.  You may obtain a copy of the License at                                                              *

+// *                                                                                                                         *

+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

+// *                                                                                                                         *

+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

+// * specific language governing permissions and limitations under the License.                                              *

+// ***************************************************************************************************************************

+package org.apache.juneau.rest.annotation;

+

+import static org.apache.juneau.http.HttpMethod.*;

+import static org.apache.juneau.internal.IOUtils.*;

+import static org.junit.runners.MethodSorters.*;

+

+import java.io.IOException;

+

+import org.apache.juneau.*;

+import org.apache.juneau.collections.*;

+import org.apache.juneau.http.annotation.Body;

+import org.apache.juneau.parser.*;

+import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.RestRequest;

+import org.apache.juneau.rest.client2.*;

+import org.apache.juneau.rest.mock2.*;

+import org.junit.*;

+

+@FixMethodOrder(NAME_ASCENDING)

+public class Restx_Parsers_Test {

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Setup

+	//------------------------------------------------------------------------------------------------------------------

+

+	public static class PA extends ReaderParser {

+		public PA(PropertyStore ps) {

+			super(ps, "text/a");

+		}

+		@Override /* Parser */

+		public ReaderParserSession createSession(ParserSessionArgs args) {

+			return new ReaderParserSession(args) {

+				@Override /* ParserSession */

+				@SuppressWarnings("unchecked")

+				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

+					return (T)("text/a - " + read(pipe.getReader()).trim());

+				}

+			};

+		}

+	}

+

+	public static class PB extends ReaderParser {

+		public PB(PropertyStore ps) {

+			super(ps, "text/b");

+		}

+		@Override /* Parser */

+		public ReaderParserSession createSession(ParserSessionArgs args) {

+			return new ReaderParserSession(args) {

+				@Override /* ParserSession */

+				@SuppressWarnings("unchecked")

+				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

+					return (T)("text/b - " + read(pipe.getReader()).trim());

+				}

+			};

+		}

+	}

+

+	public static class PC extends ReaderParser {

+		public PC(PropertyStore ps) {

+			super(ps, "text/c");

+		}

+		@Override /* Parser */

+		public ReaderParserSession createSession(ParserSessionArgs args) {

+			return new ReaderParserSession(args) {

+				@Override /* ParserSession */

+				@SuppressWarnings("unchecked")

+				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

+					return (T)("text/c - " + read(pipe.getReader()).trim());

+				}

+			};

+		}

+	}

+

+	public static class PD extends ReaderParser {

+		public PD(PropertyStore ps) {

+			super(ps, "text/d");

+		}

+		@Override /* Parser */

+		public ReaderParserSession createSession(ParserSessionArgs args) {

+			return new ReaderParserSession(args) {

+				@Override /* ParserSession */

+				@SuppressWarnings("unchecked")

+				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

+					return (T)("text/d - " + read(pipe.getReader()).trim());

+				}

+			};

+		}

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Basic tests

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(parsers=PA.class)

+	public static class A {

+		@RestMethod(name=PUT)

+		public String a(@Body String in) {

+			return in;

+		}

+		@RestMethod(name=PUT, parsers=PB.class)

+		public String b(@Body String in) {

+			return in;

+		}

+		@RestMethod(name=PUT, parsers={Inherit.class, PB.class,PC.class})

+		public String c(@Body String in) {

+			return in;

+		}

+		@RestMethod(name=PUT, parsers={Inherit.class, PD.class})

+		public String d(@Body String in) {

+			return in;

+		}

+		@RestMethod(name=PUT)

+		public String e(@Body String in) {

+			return in;

+		}

+	}

+

+	@Test

+	public void a01_basic() throws Exception {

+		MockRestClient a = MockRestClient.buildLax(A.class);

+

+		a.put("/a", "test1")

+			.contentType("text/a")

+			.run()

+			.assertBody().is("text/a - test1");

+		a.put("/a?noTrace=true", "test1")

+			.contentType("text/b")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Content-Type': 'text/b'",

+				"Supported media-types: ['text/a"

+			);

+

+		a.put("/b", "test2")

+			.contentType("text/b")

+			.run()

+			.assertBody().is("text/b - test2");

+		a.put("/b?noTrace=true", "test2")

+			.contentType("text/a")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Content-Type': 'text/a'",

+				"Supported media-types: ['text/b']"

+			);

+

+		a.put("/c", "test3")

+			.contentType("text/a")

+			.run()

+			.assertBody().is("text/a - test3");

+		a.put("/c", "test3")

+			.contentType("text/b")

+			.run()

+			.assertBody().is("text/b - test3");

+

+		a.put("/d", "test4")

+			.contentType("text/a")

+			.run()

+			.assertBody().is("text/a - test4");

+		a.put("/d", "test4")

+			.contentType("text/d")

+			.run()

+			.assertBody().is("text/d - test4");

+

+		a.put("/e?noTrace=true", "test1")

+			.contentType("text/bad")

+			.run()

+			.assertCode().is(415)

+			.assertBody().contains(

+				"Unsupported media-type in request header 'Content-Type': 'text/bad'",

+				"Supported media-types: ['text/a"

+			);

+	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test parser inheritance.

+	//------------------------------------------------------------------------------------------------------------------

+

+	public static class DummyParser extends ReaderParser {

+		public DummyParser(String...consumes) {

+			super(PropertyStore.DEFAULT, consumes);

+		}

+		@Override /* Parser */

+		public ReaderParserSession createSession(ParserSessionArgs args) {

+			return new ReaderParserSession(args) {

+				@Override /* ParserSession */

+				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

+					return null;

+				}

+			};

+		}

+	}

+

+	public static class P1 extends DummyParser{ public P1(PropertyStore ps) {super("text/p1");} }

+	public static class P2 extends DummyParser{ public P2(PropertyStore ps) {super("text/p2");} }

+	public static class P3 extends DummyParser{ public P3(PropertyStore ps) {super("text/p3");} }

+	public static class P4 extends DummyParser{ public P4(PropertyStore ps) {super("text/p4");} }

+	public static class P5 extends DummyParser{ public P5(PropertyStore ps) {super("text/p5");} }

+

+	@Rest(parsers={P1.class,P2.class})

+	public static class B {}

+

+	@Rest(parsers={P3.class,P4.class,Inherit.class})

+	public static class B1 extends B {}

+

+	@Rest

+	public static class B2 extends B1 {

+		@RestMethod

+		public OList a(RestRequest req) {

+			// Should show ['text/p3','text/p4','text/p1','text/p2']

+			return OList.ofAll(req.getConsumes());

+		}

+		@RestMethod(parsers=P5.class)

+		public OList b(RestRequest req) {

+			// Should show ['text/p5']

+			return OList.ofAll(req.getConsumes());

+		}

+		@RestMethod(parsers={P5.class,Inherit.class})

+		public OList c(RestRequest req) {

+			// Should show ['text/p5','text/p3','text/p4','text/p1','text/p2']

+			return OList.ofAll(req.getConsumes());

+		}

+	}

+

+	@Test

+	public void b01_inheritence() throws Exception {

+		RestClient b = MockRestClient.build(B2.class);

+		b.get("/a").run().assertBody().is("['text/p3','text/p4','text/p1','text/p2']");

+		b.get("/b").run().assertBody().is("['text/p5']");

+		b.get("/c").run().assertBody().is("['text/p5','text/p3','text/p4','text/p1','text/p2']");

+	}

+

+}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Path_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Path_Test.java
new file mode 100644
index 0000000..28c55b7
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Path_Test.java
@@ -0,0 +1,147 @@
+// ***************************************************************************************************************************

+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

+// * with the License.  You may obtain a copy of the License at                                                              *

+// *                                                                                                                         *

+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

+// *                                                                                                                         *

+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

+// * specific language governing permissions and limitations under the License.                                              *

+// ***************************************************************************************************************************

+package org.apache.juneau.rest.annotation;

+

+import static org.junit.runners.MethodSorters.*;

+

+import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.client2.*;

+import org.apache.juneau.rest.mock2.*;

+import org.junit.*;

+

+@FixMethodOrder(NAME_ASCENDING)

+public class Restx_Path_Test {

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Nested children.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(path="/p0", children={A1.class})

+	public static class A  {

+		@RestMethod(path="/")

+		public String a(RestContext c) {

+			return "A-" + c.getPath();

+		}

+	}

+	@Rest(path="/p1", children={A2.class})

+	public static class A1 {

+		@RestMethod(path="/")

+		public String a(RestContext c) {

+			return "A01-" + c.getPath();

+		}

+	}

+	public static class A2a  {

+		@RestMethod(path="/")

+		public String a(RestContext c) {

+			return "A02a-" + c.getPath();

+		}

+	}

+	@Rest(path="/p2")

+	public static class A2 extends A2a {}

+

+	@Test

+	public void a01_nestedChildren() throws Exception {

+		RestClient a = MockRestClient.build(A.class);

+		// Since we're not running from a servlet container, we access A directly with no path.

+		// However, the path is still reflected in RestContext.getPath().

+		a.get("/").run().assertBody().is("A-p0");

+		a.get("/p1").run().assertBody().is("A01-p0/p1");

+		a.get("/p1/p2").run().assertBody().is("A02a-p0/p1/p2");

+	}

+

+	//-----------------------------------------------------------------------------------------------------------------

+	// Overlapping URL patterns

+	//-----------------------------------------------------------------------------------------------------------------

+

+	@Rest

+	public static class B {

+		@RestMethod(path="/")

+		public String a() {

+			return "a";

+		}

+		@RestMethod(path="/*")

+		public String b() {

+			return "b";

+		}

+		@RestMethod(path="/foo")

+		public String c() {

+			return "c";

+		}

+		@RestMethod(path="/foo/*")

+		public String d() {

+			return "d";

+		}

+		@RestMethod(path="/{id}")

+		public String e() {

+			return "e";

+		}

+		@RestMethod(path="/{id}/*")

+		public String f() {

+			return "f";

+		}

+		@RestMethod(path="/{id}/foo")

+		public String g() {

+			return "g";

+		}

+		@RestMethod(path="/{id}/foo/*")

+		public String h() {

+			return "h";

+		}

+	}

+

+	@Test

+	public void b01_overlappingPaths() throws Exception {

+		RestClient b = MockRestClient.build(B.class);

+		// [/] = [test5a]

+		// [/*] = [test5b]   -- Cannot get called.

+		// [/foo] = [test5c]

+		// [/foo/*] = [test5d]

+		// [/{id}] = [test5e]

+		// [/{id}/*] = [test5f]

+		// [/{id}/foo] = [test5g]

+		// [/{id}/foo/*] = [test5h]

+		b.get("/").run().assertBody().is("a");

+		b.get("/foo").run().assertBody().is("c");

+		b.get("/foo/x").run().assertBody().is("d");

+		b.get("/x").run().assertBody().is("e");

+		b.get("/x/x").run().assertBody().is("f");

+		b.get("/x/foo").run().assertBody().is("g");

+		b.get("/x/foo/x").run().assertBody().is("h");

+	}

+

+	//-----------------------------------------------------------------------------------------------------------------

+	// Overridden URL patterns

+	//-----------------------------------------------------------------------------------------------------------------

+

+	@Rest

+	public static class C1 {

+		@RestMethod(path="/foo")

+		public String a() {

+			return "a";

+		}

+	}

+

+	@Rest

+	public static class C2 extends C1 {

+		@RestMethod(path="/foo")

+		public String b() {  // Overrides method on parent.

+			return "b";

+		}

+	}

+

+	@Test

+	public void c01_pathOverriddenByChild() throws Exception {

+		RestClient c2 = MockRestClient.build(C2.class);

+		c2.get("/foo").run().assertBody().is("b");

+	}

+}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_ReqAttrs_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_ReqAttrs_Test.java
new file mode 100644
index 0000000..b2bb1f9
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_ReqAttrs_Test.java
@@ -0,0 +1,77 @@
+// ***************************************************************************************************************************

+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

+// * with the License.  You may obtain a copy of the License at                                                              *

+// *                                                                                                                         *

+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

+// *                                                                                                                         *

+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

+// * specific language governing permissions and limitations under the License.                                              *

+// ***************************************************************************************************************************

+package org.apache.juneau.rest.annotation;

+

+import static org.junit.runners.MethodSorters.*;

+

+import java.util.*;

+

+import org.apache.juneau.collections.*;

+import org.apache.juneau.http.annotation.HasQuery;

+import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.client2.*;

+import org.apache.juneau.rest.mock2.*;

+import org.junit.*;

+

+@FixMethodOrder(NAME_ASCENDING)

+public class Restx_ReqAttrs_Test {

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test properties inheritance.

+	//------------------------------------------------------------------------------------------------------------------

+

+	@Rest(reqAttrs={"p1:v1","p2:v2"})

+	public static class A {}

+

+	@Rest(reqAttrs={"p2:v2a","p3:v3","p4:v4"})

+	public static class A1 extends A {}

+

+	@Rest

+	public static class A2 extends A1 {

+		@RestMethod

+		public OMap a(RequestAttributes attrs) {

+			// Should show {p1:'v1',p2:'v2a',p3:'v3',p4:'v4'}

+			return transform(attrs);

+		}

+		@RestMethod(reqAttrs={"p4:v4a","p5:v5"})

+		public OMap b(RequestAttributes attrs, @HasQuery("override") boolean override) {

+			// Should show {p1:'v1',p2:'v2a',p3:'v3',p4:'v4a',p5:'v5'} when override is false.

+			// Should show {p1:'x',p2:'x',p3:'x',p4:'x',p5:'x'} when override is true.

+			if (override) {

+				attrs.put("p1", "x");

+				attrs.put("p2", "x");

+				attrs.put("p3", "x");

+				attrs.put("p4", "x");

+				attrs.put("p5", "x");

+			}

+			return transform(attrs);

+		}

+

+		private OMap transform(RequestAttributes attrs) {

+			OMap m = new OMap();

+			for (Map.Entry<String,Object> e : attrs.entrySet()) {

+				if (e.getKey().startsWith("p"))

+					m.put(e.getKey(), e.getValue());

+			}

+			return m;

+		}

+	}

+

+	@Test

+	public void a01_basic() throws Exception {

+		RestClient a = MockRestClient.build(A2.class);

+		a.get("/a").run().assertBody().is("{p1:'v1',p2:'v2a',p3:'v3',p4:'v4'}");

+		a.get("/b").run().assertBody().is("{p1:'v1',p2:'v2a',p3:'v3',p4:'v4a',p5:'v5'}");

+		a.get("/b?override").run().assertBody().is("{p1:'x',p2:'x',p3:'x',p4:'x',p5:'x'}");

+	}

+}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RoleGuardTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_RoleGuard_Test.java
similarity index 68%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RoleGuardTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_RoleGuard_Test.java
index ac7a12e..bbf0349 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RoleGuardTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_RoleGuard_Test.java
@@ -10,16 +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.rest.annotation2;
+package org.apache.juneau.rest.annotation;
 
 import static org.junit.runners.MethodSorters.*;
 
-import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.mock2.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RoleGuardTest {
+public class Restx_RoleGuard_Test {
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Simple guard on class
@@ -32,17 +31,13 @@
 			return "OK";
 		}
 	}
-	static MockRestClient a1 = MockRestClient.buildLax(A1.class);
 
 	@Test
-	public void a01a_onClass_simple_pass() throws Exception {
+	public void a01a_onClass_simple() throws Exception {
+		MockRestClient a1 = MockRestClient.buildLax(A1.class);
 		a1.get().roles("foo").run().assertCode().is(200);
 		a1.get().roles("foo","bar").run().assertCode().is(200);
 		a1.get().roles("bar","foo").run().assertCode().is(200);
-	}
-
-	@Test
-	public void a01b_onClass_simple_fail() throws Exception {
 		a1.get().run().assertCode().is(403);
 		a1.get().roles("foo2").run().assertCode().is(403);
 		a1.get().roles("foo2","bar").run().assertCode().is(403);
@@ -59,17 +54,13 @@
 			return "OK";
 		}
 	}
-	static MockRestClient a2 = MockRestClient.buildLax(A2.class);
 
 	@Test
-	public void a02a_onMethod_simple_pass() throws Exception {
+	public void a02a_onMethod_simple() throws Exception {
+		MockRestClient a2 = MockRestClient.buildLax(A2.class);
 		a2.get().roles("foo").run().assertCode().is(200);
 		a2.get().roles("foo","bar").run().assertCode().is(200);
 		a2.get().roles("bar","foo").run().assertCode().is(200);
-	}
-
-	@Test
-	public void a02b_onMethod_simple_fail() throws Exception {
 		a2.get().run().assertCode().is(403);
 		a2.get().roles("foo2").run().assertCode().is(403);
 		a2.get().roles("foo2","bar").run().assertCode().is(403);
@@ -86,17 +77,13 @@
 			return "OK";
 		}
 	}
-	static MockRestClient a3 = MockRestClient.buildLax(A3.class);
 
 	@Test
-	public void a03a_onBoth_simple_pass() throws Exception {
+	public void a03a_onBoth_simple() throws Exception {
+		MockRestClient a3 = MockRestClient.buildLax(A3.class);
 		a3.get().roles("foo","bar").run().assertCode().is(200);
 		a3.get().roles("bar","foo").run().assertCode().is(200);
 		a3.get().roles("bar","foo","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void a03b_onBoth_simple_fail() throws Exception {
 		a3.get().run().assertCode().is(403);
 		a3.get().roles("foo").run().assertCode().is(403);
 		a3.get().roles("bar").run().assertCode().is(403);
@@ -125,21 +112,11 @@
 		}
 	}
 
-	static MockRestClient a4 = MockRestClient.buildLax(A4b.class);
-
 	@Test
-	public void a04a_inheritence_simple_pass() throws Exception {
+	public void a04a_inheritence_simple() throws Exception {
+		MockRestClient a4 = MockRestClient.buildLax(A4b.class);
 		a4.get().roles("foo","bar","baz","qux").run().assertCode().is(200);
 		a4.get().roles("foo","bar","baz","qux","quux").run().assertCode().is(200);
-	}
-
-	@Test
-	public void a04b_inheritence_simple_fail() throws Exception {
-		a3.get().run().assertCode().is(403);
-		a3.get().roles("foo").run().assertCode().is(403);
-		a3.get().roles("bar").run().assertCode().is(403);
-		a3.get().roles("baz").run().assertCode().is(403);
-		a3.get().roles("qux").run().assertCode().is(403);
 		a4.get().roles("foo","bar","baz").run().assertCode().is(403);
 		a4.get().roles("foo","bar","qux").run().assertCode().is(403);
 		a4.get().roles("foo","baz","qux").run().assertCode().is(403);
@@ -161,160 +138,111 @@
 	@Rest(roleGuard="foo,bar")
 	public static class B1a extends B1 {}
 
-	@Rest(roleGuard="foo | bar")
-	public static class B1b extends B1 {}
-
-	@Rest(roleGuard="foo || bar")
-	public static class B1c extends B1 {}
-
-	@Rest(roleGuard="foo & bar")
-	public static class B1d extends B1 {}
-
-	@Rest(roleGuard="foo && bar")
-	public static class B1e extends B1 {}
-
-	@Rest(roleGuard="(foo) && (bar)")
-	public static class B1f extends B1 {}
-
-	@Rest(roleGuard="foo && (bar || baz)")
-	public static class B1g extends B1 {}
-
-	@Rest(roleGuard="foo || (bar && baz)")
-	public static class B1h extends B1 {}
-
-	static MockRestClient b1a = MockRestClient.buildLax(B1a.class);
-	static MockRestClient b1b = MockRestClient.buildLax(B1b.class);
-	static MockRestClient b1c = MockRestClient.buildLax(B1c.class);
-	static MockRestClient b1d = MockRestClient.buildLax(B1d.class);
-	static MockRestClient b1e = MockRestClient.buildLax(B1e.class);
-	static MockRestClient b1f = MockRestClient.buildLax(B1f.class);
-	static MockRestClient b1g = MockRestClient.buildLax(B1g.class);
-	static MockRestClient b1h = MockRestClient.buildLax(B1h.class);
-
 	@Test
 	public void b01a_orsWithComma_pass() throws Exception {
-		// @Rest(roleGuard="foo,bar")
+		MockRestClient b1a = MockRestClient.buildLax(B1a.class);
 		b1a.get().roles("foo").run().assertCode().is(200);
 		b1a.get().roles("bar").run().assertCode().is(200);
 		b1a.get().roles("foo","bar").run().assertCode().is(200);
 		b1a.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b01b_orsWithComma_fail() throws Exception {
-		// @Rest(roleGuard="foo,bar")
 		b1a.get().roles().run().assertCode().is(403);
 		b1a.get().roles("baz").run().assertCode().is(403);
 	}
 
+	@Rest(roleGuard="foo | bar")
+	public static class B1b extends B1 {}
+
 	@Test
-	public void b01c_orsWithSinglePipe_pass() throws Exception {
-		// @Rest(roleGuard="foo | bar")
+	public void b01b_orsWithSinglePipe_pass() throws Exception {
+		MockRestClient b1b = MockRestClient.buildLax(B1b.class);
 		b1b.get().roles("foo").run().assertCode().is(200);
 		b1b.get().roles("bar").run().assertCode().is(200);
 		b1b.get().roles("foo","bar").run().assertCode().is(200);
 		b1b.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b01d_orsWithSinglePipe_fail() throws Exception {
-		// @Rest(roleGuard="foo | bar")
 		b1b.get().roles().run().assertCode().is(403);
 		b1b.get().roles("baz").run().assertCode().is(403);
 	}
 
+	@Rest(roleGuard="foo || bar")
+	public static class B1c extends B1 {}
+
 	@Test
-	public void b01e_orsWithDoublePipe_pass() throws Exception {
-		// @Rest(roleGuard="foo || bar")
+	public void b01c_orsWithDoublePipe_pass() throws Exception {
+		MockRestClient b1c = MockRestClient.buildLax(B1c.class);
 		b1c.get().roles("foo").run().assertCode().is(200);
 		b1c.get().roles("bar").run().assertCode().is(200);
 		b1c.get().roles("foo","bar").run().assertCode().is(200);
 		b1c.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b01f_orsWithDoublePipe_fail() throws Exception {
-		// @Rest(roleGuard="foo || bar")
 		b1c.get().roles().run().assertCode().is(403);
 		b1c.get().roles("baz").run().assertCode().is(403);
 	}
 
-	@Test
-	public void b01g_andsWithSingleAmp_pass() throws Exception {
-		// @Rest(roleGuard="foo & bar")
-		b1d.get().roles("foo","bar").run().assertCode().is(200);
-		b1d.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
+	@Rest(roleGuard="foo & bar")
+	public static class B1d extends B1 {}
 
 	@Test
-	public void b01h_andsWithSingleAmp_fail() throws Exception {
-		// @Rest(roleGuard="foo & bar")
+	public void b01d_andsWithSingleAmp_pass() throws Exception {
+		MockRestClient b1d = MockRestClient.buildLax(B1d.class);
+		b1d.get().roles("foo","bar").run().assertCode().is(200);
+		b1d.get().roles("foo","bar","baz").run().assertCode().is(200);
 		b1d.get().roles().run().assertCode().is(403);
 		b1d.get().roles("foo").run().assertCode().is(403);
 		b1d.get().roles("bar").run().assertCode().is(403);
 		b1d.get().roles("baz").run().assertCode().is(403);
 	}
 
-	@Test
-	public void b01i_andsWithDoubleAmp_pass() throws Exception {
-		// @Rest(roleGuard="foo && bar")
-		b1e.get().roles("foo","bar").run().assertCode().is(200);
-		b1e.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
+	@Rest(roleGuard="foo && bar")
+	public static class B1e extends B1 {}
 
 	@Test
-	public void b01j_andsWithDoubleAmp_fail() throws Exception {
-		// @Rest(roleGuard="foo && bar")
+	public void b01e_andsWithDoubleAmp_pass() throws Exception {
+		MockRestClient b1e = MockRestClient.buildLax(B1e.class);
+		b1e.get().roles("foo","bar").run().assertCode().is(200);
+		b1e.get().roles("foo","bar","baz").run().assertCode().is(200);
 		b1e.get().roles().run().assertCode().is(403);
 		b1e.get().roles("foo").run().assertCode().is(403);
 		b1e.get().roles("bar").run().assertCode().is(403);
 		b1e.get().roles("baz").run().assertCode().is(403);
 	}
 
-	@Test
-	public void b01k_andsWithDoubleAmpAndParens_pass() throws Exception {
-		// @Rest(roleGuard="(foo) && (bar)")
-		b1f.get().roles("foo","bar").run().assertCode().is(200);
-		b1f.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
+	@Rest(roleGuard="(foo) && (bar)")
+	public static class B1f extends B1 {}
 
 	@Test
-	public void b01l_andsWithDoubleAmpAndParens_fail() throws Exception {
-		// @Rest(roleGuard="(foo) && (bar)")
+	public void b01f_andsWithDoubleAmpAndParens_pass() throws Exception {
+		MockRestClient b1f = MockRestClient.buildLax(B1f.class);
+		b1f.get().roles("foo","bar").run().assertCode().is(200);
+		b1f.get().roles("foo","bar","baz").run().assertCode().is(200);
 		b1f.get().roles().run().assertCode().is(403);
 		b1f.get().roles("foo").run().assertCode().is(403);
 		b1f.get().roles("bar").run().assertCode().is(403);
 		b1f.get().roles("baz").run().assertCode().is(403);
 	}
 
+	@Rest(roleGuard="foo && (bar || baz)")
+	public static class B1g extends B1 {}
+
 	@Test
-	public void b01m_complex_pass() throws Exception {
-		// @Rest(roleGuard="foo && (bar || baz)")
+	public void b01g_complex_pass() throws Exception {
+		MockRestClient b1g = MockRestClient.buildLax(B1g.class);
 		b1g.get().roles("foo","bar").run().assertCode().is(200);
 		b1g.get().roles("foo","baz").run().assertCode().is(200);
 		b1g.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b01n_complex_fail() throws Exception {
-		// @Rest(roleGuard="foo && (bar || baz)")
 		b1g.get().roles().run().assertCode().is(403);
 		b1g.get().roles("foo").run().assertCode().is(403);
 		b1g.get().roles("bar","baz").run().assertCode().is(403);
 		b1g.get().roles("baz").run().assertCode().is(403);
 	}
 
+	@Rest(roleGuard="foo || (bar && baz)")
+	public static class B1h extends B1 {}
+
 	@Test
-	public void b01o_complex_pass() throws Exception {
-		// @Rest(roleGuard="foo || (bar && baz)")
+	public void b01h_complex_pass() throws Exception {
+		MockRestClient b1h = MockRestClient.buildLax(B1h.class);
 		b1h.get().roles("foo").run().assertCode().is(200);
 		b1h.get().roles("bar","baz").run().assertCode().is(200);
 		b1h.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b01p_complex_fail() throws Exception {
-		// @Rest(roleGuard="foo || (bar && baz)")
 		b1h.get().roles().run().assertCode().is(403);
 		b1h.get().roles("bar").run().assertCode().is(403);
 		b1h.get().roles("baz").run().assertCode().is(403);
@@ -332,6 +260,17 @@
 		}
 	}
 
+	@Test
+	public void b02a_orsWithComma_pass() throws Exception {
+		MockRestClient b2a = MockRestClient.buildLax(B2a.class);
+		b2a.get().roles("foo").run().assertCode().is(200);
+		b2a.get().roles("bar").run().assertCode().is(200);
+		b2a.get().roles("foo","bar").run().assertCode().is(200);
+		b2a.get().roles("foo","bar","baz").run().assertCode().is(200);
+		b2a.get().roles().run().assertCode().is(403);
+		b2a.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class B2b {
 		@RestMethod(roleGuard="foo | bar")
@@ -340,6 +279,17 @@
 		}
 	}
 
+	@Test
+	public void b02b_orsWithSinglePipe_pass() throws Exception {
+		MockRestClient b2b = MockRestClient.buildLax(B2b.class);
+		b2b.get().roles("foo").run().assertCode().is(200);
+		b2b.get().roles("bar").run().assertCode().is(200);
+		b2b.get().roles("foo","bar").run().assertCode().is(200);
+		b2b.get().roles("foo","bar","baz").run().assertCode().is(200);
+		b2b.get().roles().run().assertCode().is(403);
+		b2b.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class B2c {
 		@RestMethod(roleGuard="foo || bar")
@@ -348,6 +298,17 @@
 		}
 	}
 
+	@Test
+	public void b02c_orsWithDoublePipe_pass() throws Exception {
+		MockRestClient b2c = MockRestClient.buildLax(B2c.class);
+		b2c.get().roles("foo").run().assertCode().is(200);
+		b2c.get().roles("bar").run().assertCode().is(200);
+		b2c.get().roles("foo","bar").run().assertCode().is(200);
+		b2c.get().roles("foo","bar","baz").run().assertCode().is(200);
+		b2c.get().roles().run().assertCode().is(403);
+		b2c.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class B2d {
 		@RestMethod(roleGuard="foo & bar")
@@ -356,6 +317,17 @@
 		}
 	}
 
+	@Test
+	public void b02d_andsWithSingleAmp_pass() throws Exception {
+		MockRestClient b2d = MockRestClient.buildLax(B2d.class);
+		b2d.get().roles("foo","bar").run().assertCode().is(200);
+		b2d.get().roles("foo","bar","baz").run().assertCode().is(200);
+		b2d.get().roles().run().assertCode().is(403);
+		b2d.get().roles("foo").run().assertCode().is(403);
+		b2d.get().roles("bar").run().assertCode().is(403);
+		b2d.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class B2e {
 		@RestMethod(roleGuard="foo && bar")
@@ -364,6 +336,17 @@
 		}
 	}
 
+	@Test
+	public void b02e_andsWithDoubleAmp_pass() throws Exception {
+		MockRestClient b2e = MockRestClient.buildLax(B2e.class);
+		b2e.get().roles("foo","bar").run().assertCode().is(200);
+		b2e.get().roles("foo","bar","baz").run().assertCode().is(200);
+		b2e.get().roles().run().assertCode().is(403);
+		b2e.get().roles("foo").run().assertCode().is(403);
+		b2e.get().roles("bar").run().assertCode().is(403);
+		b2e.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class B2f {
 		@RestMethod(roleGuard="(foo) && (bar)")
@@ -372,6 +355,17 @@
 		}
 	}
 
+	@Test
+	public void b02f_andsWithDoubleAmpAndParens_pass() throws Exception {
+		MockRestClient b2f = MockRestClient.buildLax(B2f.class);
+		b2f.get().roles("foo","bar").run().assertCode().is(200);
+		b2f.get().roles("foo","bar","baz").run().assertCode().is(200);
+		b2f.get().roles().run().assertCode().is(403);
+		b2f.get().roles("foo").run().assertCode().is(403);
+		b2f.get().roles("bar").run().assertCode().is(403);
+		b2f.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class B2g {
 		@RestMethod(roleGuard="foo && (bar || baz)")
@@ -380,6 +374,18 @@
 		}
 	}
 
+	@Test
+	public void b02g_complex_pass() throws Exception {
+		MockRestClient b2g = MockRestClient.buildLax(B2g.class);
+		b2g.get().roles("foo","bar").run().assertCode().is(200);
+		b2g.get().roles("foo","baz").run().assertCode().is(200);
+		b2g.get().roles("foo","bar","baz").run().assertCode().is(200);
+		b2g.get().roles().run().assertCode().is(403);
+		b2g.get().roles("foo").run().assertCode().is(403);
+		b2g.get().roles("bar","baz").run().assertCode().is(403);
+		b2g.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class B2h {
 		@RestMethod(roleGuard="foo || (bar && baz)")
@@ -388,139 +394,12 @@
 		}
 	}
 
-	static MockRestClient b2a = MockRestClient.buildLax(B2a.class);
-	static MockRestClient b2b = MockRestClient.buildLax(B2b.class);
-	static MockRestClient b2c = MockRestClient.buildLax(B2c.class);
-	static MockRestClient b2d = MockRestClient.buildLax(B2d.class);
-	static MockRestClient b2e = MockRestClient.buildLax(B2e.class);
-	static MockRestClient b2f = MockRestClient.buildLax(B2f.class);
-	static MockRestClient b2g = MockRestClient.buildLax(B2g.class);
-	static MockRestClient b2h = MockRestClient.buildLax(B2h.class);
-
 	@Test
-	public void b02a_orsWithComma_pass() throws Exception {
-		// @RestMethod(roleGuard="foo,bar")
-		b2a.get().roles("foo").run().assertCode().is(200);
-		b2a.get().roles("bar").run().assertCode().is(200);
-		b2a.get().roles("foo","bar").run().assertCode().is(200);
-		b2a.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b02b_orsWithComma_fail() throws Exception {
-		// @RestMethod(roleGuard="foo,bar")
-		b2a.get().roles().run().assertCode().is(403);
-		b2a.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void b02c_orsWithSinglePipe_pass() throws Exception {
-		// @RestMethod(roleGuard="foo | bar")
-		b2b.get().roles("foo").run().assertCode().is(200);
-		b2b.get().roles("bar").run().assertCode().is(200);
-		b2b.get().roles("foo","bar").run().assertCode().is(200);
-		b2b.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b02d_orsWithSinglePipe_fail() throws Exception {
-		// @RestMethod(roleGuard="foo | bar")
-		b2b.get().roles().run().assertCode().is(403);
-		b2b.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void b02e_orsWithDoublePipe_pass() throws Exception {
-		// @RestMethod(roleGuard="foo || bar")
-		b2c.get().roles("foo").run().assertCode().is(200);
-		b2c.get().roles("bar").run().assertCode().is(200);
-		b2c.get().roles("foo","bar").run().assertCode().is(200);
-		b2c.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b02f_orsWithDoublePipe_fail() throws Exception {
-		// @RestMethod(roleGuard="foo || bar")
-		b2c.get().roles().run().assertCode().is(403);
-		b2c.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void b02g_andsWithSingleAmp_pass() throws Exception {
-		// @RestMethod(roleGuard="foo & bar")
-		b2d.get().roles("foo","bar").run().assertCode().is(200);
-		b2d.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b02h_andsWithSingleAmp_fail() throws Exception {
-		// @RestMethod(roleGuard="foo & bar")
-		b2d.get().roles().run().assertCode().is(403);
-		b2d.get().roles("foo").run().assertCode().is(403);
-		b2d.get().roles("bar").run().assertCode().is(403);
-		b2d.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void b02i_andsWithDoubleAmp_pass() throws Exception {
-		// @RestMethod(roleGuard="foo && bar")
-		b2e.get().roles("foo","bar").run().assertCode().is(200);
-		b2e.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b02j_andsWithDoubleAmp_fail() throws Exception {
-		// @RestMethod(roleGuard="foo && bar")
-		b2e.get().roles().run().assertCode().is(403);
-		b2e.get().roles("foo").run().assertCode().is(403);
-		b2e.get().roles("bar").run().assertCode().is(403);
-		b2e.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void b02k_andsWithDoubleAmpAndParens_pass() throws Exception {
-		// @RestMethod(roleGuard="(foo) && (bar)")
-		b2f.get().roles("foo","bar").run().assertCode().is(200);
-		b2f.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b02l_andsWithDoubleAmpAndParens_fail() throws Exception {
-		// @RestMethod(roleGuard="(foo) && (bar)")
-		b2f.get().roles().run().assertCode().is(403);
-		b2f.get().roles("foo").run().assertCode().is(403);
-		b2f.get().roles("bar").run().assertCode().is(403);
-		b2f.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void b02m_complex_pass() throws Exception {
-		// @RestMethod(roleGuard="foo && (bar || baz)")
-		b2g.get().roles("foo","bar").run().assertCode().is(200);
-		b2g.get().roles("foo","baz").run().assertCode().is(200);
-		b2g.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b02n_complex_fail() throws Exception {
-		// @RestMethod(roleGuard="foo && (bar || baz)")
-		b2g.get().roles().run().assertCode().is(403);
-		b2g.get().roles("foo").run().assertCode().is(403);
-		b2g.get().roles("bar","baz").run().assertCode().is(403);
-		b2g.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void b02o_complex_pass() throws Exception {
-		// @RestMethod(roleGuard="foo || (bar && baz)")
+	public void b02h_complex_pass() throws Exception {
+		MockRestClient b2h = MockRestClient.buildLax(B2h.class);
 		b2h.get().roles("foo").run().assertCode().is(200);
 		b2h.get().roles("bar","baz").run().assertCode().is(200);
 		b2h.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void b02p_complex_fail() throws Exception {
-		// @RestMethod(roleGuard="foo || (bar && baz)")
 		b2h.get().roles().run().assertCode().is(403);
 		b2h.get().roles("bar").run().assertCode().is(403);
 		b2h.get().roles("baz").run().assertCode().is(403);
@@ -541,160 +420,111 @@
 	@Rest(roleGuard="fo*,*ar")
 	public static class C1a extends C1 {}
 
-	@Rest(roleGuard="fo* | *ar")
-	public static class C1b extends C1 {}
-
-	@Rest(roleGuard="fo* || *ar")
-	public static class C1c extends C1 {}
-
-	@Rest(roleGuard="fo* & *ar")
-	public static class C1d extends C1 {}
-
-	@Rest(roleGuard="fo* && *ar")
-	public static class C1e extends C1 {}
-
-	@Rest(roleGuard="(fo*) && (*ar)")
-	public static class C1f extends C1 {}
-
-	@Rest(roleGuard="fo* && (*ar || *az)")
-	public static class C1g extends C1 {}
-
-	@Rest(roleGuard="fo* || (*ar && *az)")
-	public static class C1h extends C1 {}
-
-	static MockRestClient c1a = MockRestClient.buildLax(C1a.class);
-	static MockRestClient c1b = MockRestClient.buildLax(C1b.class);
-	static MockRestClient c1c = MockRestClient.buildLax(C1c.class);
-	static MockRestClient c1d = MockRestClient.buildLax(C1d.class);
-	static MockRestClient c1e = MockRestClient.buildLax(C1e.class);
-	static MockRestClient c1f = MockRestClient.buildLax(C1f.class);
-	static MockRestClient c1g = MockRestClient.buildLax(C1g.class);
-	static MockRestClient c1h = MockRestClient.buildLax(C1h.class);
-
 	@Test
 	public void c01a_orPatternsWithComma_pass() throws Exception {
-		// @Rest(roleGuard="fo*,*ar")
+		MockRestClient c1a = MockRestClient.buildLax(C1a.class);
 		c1a.get().roles("foo").run().assertCode().is(200);
 		c1a.get().roles("bar").run().assertCode().is(200);
 		c1a.get().roles("foo","bar").run().assertCode().is(200);
 		c1a.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c01b_orPatternsWithComma_fail() throws Exception {
-		// @Rest(roleGuard="fo*,*ar")
 		c1a.get().roles().run().assertCode().is(403);
 		c1a.get().roles("baz").run().assertCode().is(403);
 	}
 
+	@Rest(roleGuard="fo* | *ar")
+	public static class C1b extends C1 {}
+
 	@Test
-	public void c01c_orPatternsWithSinglePipe_pass() throws Exception {
-		// @Rest(roleGuard="fo* | *ar")
+	public void c01b_orPatternsWithSinglePipe_pass() throws Exception {
+		MockRestClient c1b = MockRestClient.buildLax(C1b.class);
 		c1b.get().roles("foo").run().assertCode().is(200);
 		c1b.get().roles("bar").run().assertCode().is(200);
 		c1b.get().roles("foo","bar").run().assertCode().is(200);
 		c1b.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c01d_orPatternsWithSinglePipe_fail() throws Exception {
-		// @Rest(roleGuard="fo* | *ar")
 		c1b.get().roles().run().assertCode().is(403);
 		c1b.get().roles("baz").run().assertCode().is(403);
 	}
 
+	@Rest(roleGuard="fo* || *ar")
+	public static class C1c extends C1 {}
+
 	@Test
-	public void c01e_orPatternsWithDoublePipe_pass() throws Exception {
-		// @Rest(roleGuard="fo* || *ar")
+	public void c01c_orPatternsWithDoublePipe_pass() throws Exception {
+		MockRestClient c1c = MockRestClient.buildLax(C1c.class);
 		c1c.get().roles("foo").run().assertCode().is(200);
 		c1c.get().roles("bar").run().assertCode().is(200);
 		c1c.get().roles("foo","bar").run().assertCode().is(200);
 		c1c.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c01f_orPatternsWithDoublePipe_fail() throws Exception {
-		// @Rest(roleGuard="fo* || *ar")
 		c1c.get().roles().run().assertCode().is(403);
 		c1c.get().roles("baz").run().assertCode().is(403);
 	}
 
-	@Test
-	public void c01g_andPatternsWithSingleAmp_pass() throws Exception {
-		// @Rest(roleGuard="fo* & *ar")
-		c1d.get().roles("foo","bar").run().assertCode().is(200);
-		c1d.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
+	@Rest(roleGuard="fo* & *ar")
+	public static class C1d extends C1 {}
 
 	@Test
-	public void c01h_andPatternsWithSingleAmp_fail() throws Exception {
-		// @Rest(roleGuard="fo* & *ar")
+	public void c01d_andPatternsWithSingleAmp_pass() throws Exception {
+		MockRestClient c1d = MockRestClient.buildLax(C1d.class);
+		c1d.get().roles("foo","bar").run().assertCode().is(200);
+		c1d.get().roles("foo","bar","baz").run().assertCode().is(200);
 		c1d.get().roles().run().assertCode().is(403);
 		c1d.get().roles("foo").run().assertCode().is(403);
 		c1d.get().roles("bar").run().assertCode().is(403);
 		c1d.get().roles("baz").run().assertCode().is(403);
 	}
 
-	@Test
-	public void c01i_andPatternsWithDoubleAmp_pass() throws Exception {
-		// @Rest(roleGuard="fo* && *ar")
-		c1e.get().roles("foo","bar").run().assertCode().is(200);
-		c1e.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
+	@Rest(roleGuard="fo* && *ar")
+	public static class C1e extends C1 {}
 
 	@Test
-	public void c01j_andPatternsWithDoubleAmp_fail() throws Exception {
-		// @Rest(roleGuard="fo* && *ar")
+	public void c01e_andPatternsWithDoubleAmp_pass() throws Exception {
+		MockRestClient c1e = MockRestClient.buildLax(C1e.class);
+		c1e.get().roles("foo","bar").run().assertCode().is(200);
+		c1e.get().roles("foo","bar","baz").run().assertCode().is(200);
 		c1e.get().roles().run().assertCode().is(403);
 		c1e.get().roles("foo").run().assertCode().is(403);
 		c1e.get().roles("bar").run().assertCode().is(403);
 		c1e.get().roles("baz").run().assertCode().is(403);
 	}
 
-	@Test
-	public void c01k_andPatternsWithDoubleAmpAndParens_pass() throws Exception {
-		// @Rest(roleGuard="(fo*) && (*ar)")
-		c1f.get().roles("foo","bar").run().assertCode().is(200);
-		c1f.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
+	@Rest(roleGuard="(fo*) && (*ar)")
+	public static class C1f extends C1 {}
 
 	@Test
-	public void c01l_andPatternsWithDoubleAmpAndParens_fail() throws Exception {
-		// @Rest(roleGuard="(fo*) && (*ar)")
+	public void c01f_andPatternsWithDoubleAmpAndParens_pass() throws Exception {
+		MockRestClient c1f = MockRestClient.buildLax(C1f.class);
+		c1f.get().roles("foo","bar").run().assertCode().is(200);
+		c1f.get().roles("foo","bar","baz").run().assertCode().is(200);
 		c1f.get().roles().run().assertCode().is(403);
 		c1f.get().roles("foo").run().assertCode().is(403);
 		c1f.get().roles("bar").run().assertCode().is(403);
 		c1f.get().roles("baz").run().assertCode().is(403);
 	}
 
+	@Rest(roleGuard="fo* && (*ar || *az)")
+	public static class C1g extends C1 {}
+
 	@Test
-	public void c01m_complexPatterns_pass() throws Exception {
-		// @Rest(roleGuard="fo* && (*ar || *az)")
+	public void c01g_complexPatterns_pass() throws Exception {
+		MockRestClient c1g = MockRestClient.buildLax(C1g.class);
 		c1g.get().roles("foo","bar").run().assertCode().is(200);
 		c1g.get().roles("foo","baz").run().assertCode().is(200);
 		c1g.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c01n_complexPatterns_fail() throws Exception {
-		// @Rest(roleGuard="fo* && (*ar || *az)")
 		c1g.get().roles().run().assertCode().is(403);
 		c1g.get().roles("foo").run().assertCode().is(403);
 		c1g.get().roles("bar","baz").run().assertCode().is(403);
 		c1g.get().roles("baz").run().assertCode().is(403);
 	}
 
+	@Rest(roleGuard="fo* || (*ar && *az)")
+	public static class C1h extends C1 {}
+
 	@Test
-	public void c01o_complexPatterns_pass() throws Exception {
-		// @Rest(roleGuard="fo* || (*ar && *az)")
+	public void c01h_complexPatterns_pass() throws Exception {
+		MockRestClient c1h = MockRestClient.buildLax(C1h.class);
 		c1h.get().roles("foo").run().assertCode().is(200);
 		c1h.get().roles("bar","baz").run().assertCode().is(200);
 		c1h.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c01p_complexPatterns_fail() throws Exception {
-		// @Rest(roleGuard="fo* || (*ar && *az)")
 		c1h.get().roles().run().assertCode().is(403);
 		c1h.get().roles("bar").run().assertCode().is(403);
 		c1h.get().roles("baz").run().assertCode().is(403);
@@ -712,6 +542,17 @@
 		}
 	}
 
+	@Test
+	public void c02a_orPatternsWithComma_pass() throws Exception {
+		MockRestClient c2a = MockRestClient.buildLax(C2a.class);
+		c2a.get().roles("foo").run().assertCode().is(200);
+		c2a.get().roles("bar").run().assertCode().is(200);
+		c2a.get().roles("foo","bar").run().assertCode().is(200);
+		c2a.get().roles("foo","bar","baz").run().assertCode().is(200);
+		c2a.get().roles().run().assertCode().is(403);
+		c2a.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class C2b {
 		@RestMethod(roleGuard="fo* | *ar",rolesDeclared="foo,bar,baz")
@@ -720,6 +561,17 @@
 		}
 	}
 
+	@Test
+	public void c02b_orPatternsWithSinglePipe_pass() throws Exception {
+		MockRestClient c2b = MockRestClient.buildLax(C2b.class);
+		c2b.get().roles("foo").run().assertCode().is(200);
+		c2b.get().roles("bar").run().assertCode().is(200);
+		c2b.get().roles("foo","bar").run().assertCode().is(200);
+		c2b.get().roles("foo","bar","baz").run().assertCode().is(200);
+		c2b.get().roles().run().assertCode().is(403);
+		c2b.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class C2c {
 		@RestMethod(roleGuard="fo* || *ar",rolesDeclared="foo,bar,baz")
@@ -728,6 +580,17 @@
 		}
 	}
 
+	@Test
+	public void c02c_orPatternsWithDoublePipe_pass() throws Exception {
+		MockRestClient c2c = MockRestClient.buildLax(C2c.class);
+		c2c.get().roles("foo").run().assertCode().is(200);
+		c2c.get().roles("bar").run().assertCode().is(200);
+		c2c.get().roles("foo","bar").run().assertCode().is(200);
+		c2c.get().roles("foo","bar","baz").run().assertCode().is(200);
+		c2c.get().roles().run().assertCode().is(403);
+		c2c.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class C2d {
 		@RestMethod(roleGuard="fo* & *ar",rolesDeclared="foo,bar,baz")
@@ -736,6 +599,17 @@
 		}
 	}
 
+	@Test
+	public void c02d_andPatternsWithSingleAmp_pass() throws Exception {
+		MockRestClient c2d = MockRestClient.buildLax(C2d.class);
+		c2d.get().roles("foo","bar").run().assertCode().is(200);
+		c2d.get().roles("foo","bar","baz").run().assertCode().is(200);
+		c2d.get().roles().run().assertCode().is(403);
+		c2d.get().roles("foo").run().assertCode().is(403);
+		c2d.get().roles("bar").run().assertCode().is(403);
+		c2d.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class C2e {
 		@RestMethod(roleGuard="fo* && *ar",rolesDeclared="foo,bar,baz")
@@ -744,6 +618,17 @@
 		}
 	}
 
+	@Test
+	public void c02e_andPatternsWithDoubleAmp_pass() throws Exception {
+		MockRestClient c2e = MockRestClient.buildLax(C2e.class);
+		c2e.get().roles("foo","bar").run().assertCode().is(200);
+		c2e.get().roles("foo","bar","baz").run().assertCode().is(200);
+		c2e.get().roles().run().assertCode().is(403);
+		c2e.get().roles("foo").run().assertCode().is(403);
+		c2e.get().roles("bar").run().assertCode().is(403);
+		c2e.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class C2f {
 		@RestMethod(roleGuard="(fo*) && (*ar)",rolesDeclared="foo,bar,baz")
@@ -752,6 +637,17 @@
 		}
 	}
 
+	@Test
+	public void c02f_andPatternsWithDoubleAmpAndParens_pass() throws Exception {
+		MockRestClient c2f = MockRestClient.buildLax(C2f.class);
+		c2f.get().roles("foo","bar").run().assertCode().is(200);
+		c2f.get().roles("foo","bar","baz").run().assertCode().is(200);
+		c2f.get().roles().run().assertCode().is(403);
+		c2f.get().roles("foo").run().assertCode().is(403);
+		c2f.get().roles("bar").run().assertCode().is(403);
+		c2f.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class C2g {
 		@RestMethod(roleGuard="fo* && (*ar || *az)",rolesDeclared="foo,bar,baz")
@@ -760,6 +656,18 @@
 		}
 	}
 
+	@Test
+	public void c02g_complexPatterns_pass() throws Exception {
+		MockRestClient c2g = MockRestClient.buildLax(C2g.class);
+		c2g.get().roles("foo","bar").run().assertCode().is(200);
+		c2g.get().roles("foo","baz").run().assertCode().is(200);
+		c2g.get().roles("foo","bar","baz").run().assertCode().is(200);
+		c2g.get().roles().run().assertCode().is(403);
+		c2g.get().roles("foo").run().assertCode().is(403);
+		c2g.get().roles("bar","baz").run().assertCode().is(403);
+		c2g.get().roles("baz").run().assertCode().is(403);
+	}
+
 	@Rest
 	public static class C2h {
 		@RestMethod(roleGuard="fo* || (*ar && *az)",rolesDeclared="foo,bar,baz")
@@ -768,139 +676,12 @@
 		}
 	}
 
-	static MockRestClient c2a = MockRestClient.buildLax(C2a.class);
-	static MockRestClient c2b = MockRestClient.buildLax(C2b.class);
-	static MockRestClient c2c = MockRestClient.buildLax(C2c.class);
-	static MockRestClient c2d = MockRestClient.buildLax(C2d.class);
-	static MockRestClient c2e = MockRestClient.buildLax(C2e.class);
-	static MockRestClient c2f = MockRestClient.buildLax(C2f.class);
-	static MockRestClient c2g = MockRestClient.buildLax(C2g.class);
-	static MockRestClient c2h = MockRestClient.buildLax(C2h.class);
-
 	@Test
-	public void c02a_orPatternsWithComma_pass() throws Exception {
-		// @RestMethod(roleGuard="fo*,*ar")
-		c2a.get().roles("foo").run().assertCode().is(200);
-		c2a.get().roles("bar").run().assertCode().is(200);
-		c2a.get().roles("foo","bar").run().assertCode().is(200);
-		c2a.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c02b_orPatternsWithComma_fail() throws Exception {
-		// @RestMethod(roleGuard="fo*,*ar")
-		c2a.get().roles().run().assertCode().is(403);
-		c2a.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void c02c_orPatternsWithSinglePipe_pass() throws Exception {
-		// @RestMethod(roleGuard="fo* | *ar")
-		c2b.get().roles("foo").run().assertCode().is(200);
-		c2b.get().roles("bar").run().assertCode().is(200);
-		c2b.get().roles("foo","bar").run().assertCode().is(200);
-		c2b.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c02d_orPatternsWithSinglePipe_fail() throws Exception {
-		// @RestMethod(roleGuard="fo* | *ar")
-		c2b.get().roles().run().assertCode().is(403);
-		c2b.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void c02e_orPatternsWithDoublePipe_pass() throws Exception {
-		// @RestMethod(roleGuard="fo* || *ar")
-		c2c.get().roles("foo").run().assertCode().is(200);
-		c2c.get().roles("bar").run().assertCode().is(200);
-		c2c.get().roles("foo","bar").run().assertCode().is(200);
-		c2c.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c02f_orPatternsWithDoublePipe_fail() throws Exception {
-		// @RestMethod(roleGuard="foo || bar")
-		c2c.get().roles().run().assertCode().is(403);
-		c2c.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void c02g_andPatternsWithSingleAmp_pass() throws Exception {
-		// @RestMethod(roleGuard="fo* & *ar")
-		c2d.get().roles("foo","bar").run().assertCode().is(200);
-		c2d.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c02h_andPatternsWithSingleAmp_fail() throws Exception {
-		// @RestMethod(roleGuard="fo* & *ar")
-		c2d.get().roles().run().assertCode().is(403);
-		c2d.get().roles("foo").run().assertCode().is(403);
-		c2d.get().roles("bar").run().assertCode().is(403);
-		c2d.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void c02i_andPatternsWithDoubleAmp_pass() throws Exception {
-		// @RestMethod(roleGuard="fo* && *ar")
-		c2e.get().roles("foo","bar").run().assertCode().is(200);
-		c2e.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c02j_andPatternsWithDoubleAmp_fail() throws Exception {
-		// @RestMethod(roleGuard="fo* && *ar")
-		c2e.get().roles().run().assertCode().is(403);
-		c2e.get().roles("foo").run().assertCode().is(403);
-		c2e.get().roles("bar").run().assertCode().is(403);
-		c2e.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void c02k_andPatternsWithDoubleAmpAndParens_pass() throws Exception {
-		// @RestMethod(roleGuard="(fo*) && (*ar)")
-		c2f.get().roles("foo","bar").run().assertCode().is(200);
-		c2f.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c02l_andPatternsWithDoubleAmpAndParens_fail() throws Exception {
-		// @RestMethod(roleGuard="(fo*) && (*ar)")
-		c2f.get().roles().run().assertCode().is(403);
-		c2f.get().roles("foo").run().assertCode().is(403);
-		c2f.get().roles("bar").run().assertCode().is(403);
-		c2f.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void c02m_complexPatterns_pass() throws Exception {
-		// @RestMethod(roleGuard="fo* && (*ar || *az)")
-		c2g.get().roles("foo","bar").run().assertCode().is(200);
-		c2g.get().roles("foo","baz").run().assertCode().is(200);
-		c2g.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c02n_complexPatterns_fail() throws Exception {
-		// @RestMethod(roleGuard="fo* && (*ar || *az)")
-		c2g.get().roles().run().assertCode().is(403);
-		c2g.get().roles("foo").run().assertCode().is(403);
-		c2g.get().roles("bar","baz").run().assertCode().is(403);
-		c2g.get().roles("baz").run().assertCode().is(403);
-	}
-
-	@Test
-	public void c02o_complexPatterns_pass() throws Exception {
-		// @RestMethod(roleGuard="fo* || (*ar && *az)")
+	public void c02h_complexPatterns_pass() throws Exception {
+		MockRestClient c2h = MockRestClient.buildLax(C2h.class);
 		c2h.get().roles("foo").run().assertCode().is(200);
 		c2h.get().roles("bar","baz").run().assertCode().is(200);
 		c2h.get().roles("foo","bar","baz").run().assertCode().is(200);
-	}
-
-	@Test
-	public void c02p_complexPatterns_fail() throws Exception {
-		// @RestMethod(roleGuard="fo* || (*ar && *az)")
 		c2h.get().roles().run().assertCode().is(403);
 		c2h.get().roles("bar").run().assertCode().is(403);
 		c2h.get().roles("baz").run().assertCode().is(403);
@@ -918,11 +699,9 @@
 		}
 	}
 
-	static MockRestClient d = MockRestClient.buildLax(D.class);
-
 	@Test
-	public void d01_patternsWithoutRoles_fail() throws Exception {
-		// @RestMethod(roleGuard="fo*,*bar")
+	public void d01_patternsWithoutRoles() throws Exception {
+		MockRestClient d = MockRestClient.buildLax(D.class);
 		d.get().roles().run().assertCode().is(403);
 		d.get().roles("foo").run().assertCode().is(403);
 		d.get().roles("bar").run().assertCode().is(403);
@@ -942,20 +721,13 @@
 		}
 	}
 
-	static MockRestClient e = MockRestClient.buildLax(E.class);
-
 	@Test
 	public void e01_anyRole_pass() throws Exception {
-		// @RestMethod(roleGuard="*")
+		MockRestClient e = MockRestClient.buildLax(E.class);
 		e.get().roles("foo").run().assertCode().is(200);
 		e.get().roles("bar").run().assertCode().is(200);
 		e.get().roles("baz").run().assertCode().is(200);
 		e.get().roles("foo","bar").run().assertCode().is(200);
-	}
-
-	@Test
-	public void e02_anyRole_fail() throws Exception {
-		// @RestMethod(roleGuard="*")
 		e.get().roles().run().assertCode().is(403);
 	}
 }
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceSerializersTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Serializers_Test.java
similarity index 62%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceSerializersTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Serializers_Test.java
index af78759..c9d9fc1 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/RestResourceSerializersTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Restx_Serializers_Test.java
@@ -17,17 +17,20 @@
 import java.io.IOException;

 

 import org.apache.juneau.*;

+import org.apache.juneau.collections.*;

 import org.apache.juneau.rest.*;

+import org.apache.juneau.rest.RestResponse;

+import org.apache.juneau.rest.client2.*;

 import org.apache.juneau.rest.mock2.*;

 import org.apache.juneau.serializer.*;

 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class RestResourceSerializersTest {

+public class Restx_Serializers_Test {

 

-	//=================================================================================================================

-	// Setup

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

+	// Basic tests

+	//------------------------------------------------------------------------------------------------------------------

 

 	public static class SA extends WriterSerializer {

 		public SA(PropertyStore ps) {

@@ -90,42 +93,38 @@
 		}

 	}

 

-	//=================================================================================================================

-	// Basic tests

-	//=================================================================================================================

-

 	@Rest(serializers=SA.class)

 	public static class A {

 		@RestMethod

-		public String a01() {

+		public String a() {

 			return "test1";

 		}

 		@RestMethod(serializers=SB.class)

-		public String a02() {

+		public String b() {

 			return "test2";

 		}

 		@RestMethod(serializers={SB.class,SC.class,Inherit.class})

-		public String a03() {

+		public String c() {

 			return "test3";

 		}

 		@RestMethod(serializers={SD.class,Inherit.class})

-		public String a04() {

+		public String d() {

 			return "test4";

 		}

 		@RestMethod

-		public String a05() {

+		public String e() {

 			return "test406";

 		}

 	}

-	static MockRestClient a = MockRestClient.buildLax(A.class);

 

 	@Test

-	public void a01_serializerOnClass() throws Exception {

-		a.get("/a01")

+	public void a01_basic() throws Exception {

+		RestClient a = MockRestClient.buildLax(A.class);

+		a.get("/a")

 			.accept("text/a")

 			.run()

 			.assertBody().is("text/a - test1");

-		a.get("/a01?noTrace=true")

+		a.get("/a?noTrace=true")

 			.accept("text/b")

 			.run()

 			.assertCode().is(406)

@@ -133,10 +132,7 @@
 				"Unsupported media-type in request header 'Accept': 'text/b'",

 				"Supported media-types: ['text/a'"

 			);

-	}

-	@Test

-	public void a02_serializerOnMethod() throws Exception {

-		a.get("/a02?noTrace=true")

+		a.get("/b?noTrace=true")

 			.accept("text/a")

 			.run()

 			.assertCode().is(406)

@@ -144,32 +140,23 @@
 				"Unsupported media-type in request header 'Accept': 'text/a'",

 				"Supported media-types: ['text/b']"

 			);

-	}

-	@Test

-	public void a03_serializerOverriddenOnMethod() throws Exception {

-		a.get("/a03")

+		a.get("/c")

 			.accept("text/a")

 			.run()

 			.assertBody().is("text/c - test3");

-		a.get("/a03")

+		a.get("/c")

 			.accept("text/b")

 			.run()

 			.assertBody().is("text/b - test3");

-	}

-	@Test

-	public void a04_serializerWithDifferentMediaTypes() throws Exception {

-		a.get("/a04")

+		a.get("/d")

 			.accept("text/a")

 			.run()

 			.assertBody().is("text/d - test4");

-		a.get("/a04")

+		a.get("/d")

 			.accept("text/d")

 			.run()

 			.assertBody().is("text/d - test4");

-	}

-	@Test

-	public void a05_validErrorResponse() throws Exception {

-		a.get("/a05?noTrace=true")

+		a.get("/e?noTrace=true")

 			.accept("text/bad")

 			.run()

 			.assertCode().is(406)

@@ -178,4 +165,62 @@
 				"Supported media-types: ['text/a"

 			);

 	}

+

+	//------------------------------------------------------------------------------------------------------------------

+	// Test serializer inheritance.

+	//------------------------------------------------------------------------------------------------------------------

+

+	public static class DummySerializer extends WriterSerializer {

+		public DummySerializer(String produces) {

+			super(PropertyStore.DEFAULT, produces, null);

+		}

+		@Override /* Serializer */

+		public WriterSerializerSession createSession(SerializerSessionArgs args) {

+			return new WriterSerializerSession(args) {

+				@Override /* SerializerSession */

+				protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException {

+					out.getWriter().write(o.toString());

+				}

+			};

+		}

+	}

+

+	public static class S1 extends DummySerializer{ public S1(PropertyStore ps) {super("text/s1");} }

+	public static class S2 extends DummySerializer{ public S2(PropertyStore ps) {super("text/s2");} }

+	public static class S3 extends DummySerializer{ public S3(PropertyStore ps) {super("text/s3");} }

+	public static class S4 extends DummySerializer{ public S4(PropertyStore ps) {super("text/s4");} }

+	public static class S5 extends DummySerializer{ public S5(PropertyStore ps) {super("text/s5");} }

+

+	@Rest(serializers={S1.class,S2.class})

+	public static class B {}

+

+	@Rest(serializers={S3.class,S4.class,Inherit.class})

+	public static class B1 extends B {}

+

+	@Rest

+	public static class B2 extends B1 {

+		@RestMethod

+		public OList a(RestResponse res) {

+			// Should show ['text/s3','text/s4','text/s1','text/s2']

+			return OList.ofAll(res.getSupportedMediaTypes());

+		}

+		@RestMethod(serializers=S5.class)

+		public OList b(RestResponse res) {

+			// Should show ['text/s5']

+			return OList.ofAll(res.getSupportedMediaTypes());

+		}

+		@RestMethod(serializers={S5.class,Inherit.class})

+		public OList c(RestResponse res) {

+			// Should show ['text/s5','text/s3','text/s4','text/s1','text/s2']

+			return OList.ofAll(res.getSupportedMediaTypes());

+		}

+	}

+

+	@Test

+	public void b01_inheritence() throws Exception {

+		RestClient b = MockRestClient.build(B2.class);

+		b.get("/a").run().assertBody().is("['text/s3','text/s4','text/s1','text/s2']");

+		b.get("/b").run().assertBody().is("['text/s5']");

+		b.get("/c").run().assertBody().is("['text/s5','text/s3','text/s4','text/s1','text/s2']");

+	}

 }

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Body_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Body_Test.java
new file mode 100644
index 0000000..df864bf
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Body_Test.java
@@ -0,0 +1,345 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.rest.testutils.TestUtils.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.annotation.Body;
+import org.apache.juneau.jsonschema.annotation.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Swagger_Body_Test {
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Swagger
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+
+		@Body(
+			d={"a","b"},
+			r=true,
+			schema=@Schema(type="string"),
+			ex=" 'a' ",
+			exs="{foo:'bar'}"
+		)
+		public static class A1 {
+			public A1(String x) {}
+		}
+		@RestMethod
+		public void a(A1 h) {}
+
+		@Body({
+			"description:'a\nb',",
+			"required:true,",
+			"schema:{type:'string'},",
+			"x-example:'\\'a\\'',",
+			"x-examples:{foo:'bar'}"
+		})
+		public static class A2 {
+			public A2(String x) {}
+		}
+		@RestMethod
+		public void b(A2 h) {}
+
+		@Body(
+			value={
+				"description:'a\nb',",
+				"required:true,",
+				"schema:{type:'string'},",
+				"x-example:'\\'a\\'',",
+				"x-examples:{foo:'bar'}"
+			},
+			d={"b","c"},
+			schema=@Schema(type="string"),
+			ex="'b'",
+			exs="{foo:'baz'}"
+		)
+		public static class A3 {
+			public A3(String x) {}
+		}
+		@RestMethod
+		public void c(A3 h) {}
+	}
+
+	@Test
+	public void a01_fromPojo() throws Exception {
+		Swagger s = getSwagger(A.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","body",null);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getRequired()).json().is("true");
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertEquals("'a'", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'bar'}");
+
+		x = s.getParameterInfo("/b","get","body",null);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getRequired()).json().is("true");
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertEquals("'a'", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'bar'}");
+
+		x = s.getParameterInfo("/c","get","body",null);
+		assertEquals("b\nc", x.getDescription());
+		assertObject(x.getRequired()).json().is("true");
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertEquals("'b'", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'baz'}");
+	}
+
+	@Rest
+	public static class B {
+
+		@Body(schema=@Schema(" type:'b' "))
+		public static class B1 {}
+		@RestMethod
+		public void a(B1 h) {}
+
+		@Body
+		public static class B2 {
+			public String f1;
+		}
+		@RestMethod
+		public void b(B2 b) {}
+
+		@Body
+		public static class B3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod
+		public void c(B3 b) {}
+
+		@Body
+		public static class B4 {}
+		@RestMethod
+		public void d(B4 b) {}
+	}
+
+	@Test
+	public void b01_schemaFromPojo() throws Exception {
+		Swagger s = getSwagger(B.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","body",null);
+		assertObject(x.getSchema()).json().is("{type:'b'}");
+
+		x = s.getParameterInfo("/b","get","body",null);
+		assertObject(x.getSchema()).json().is("{type:'object',properties:{f1:{type:'string'}}}");
+
+		x = s.getParameterInfo("/c","get","body",null);
+		assertObject(x.getSchema()).json().is("{type:'array',items:{type:'string'}}");
+
+		x = s.getParameterInfo("/d","get","body",null);
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+	}
+
+	@Rest
+	public static class C {
+		@Body(ex=" {f1:'b'} ")
+		public static class C1 {
+			public String f1;
+		}
+		@RestMethod
+		public void a(C1 h) {}
+
+		@Body(exs={" foo:'bar' "})
+		public static class C2 {}
+		@RestMethod
+		public void b(C2 h) {}
+	}
+
+	@Test
+	public void c01_exampleFromPojo() throws Exception {
+		Swagger s = getSwagger(C.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","body",null);
+		assertEquals("{f1:'b'}", x.getExample());
+
+		x = s.getParameterInfo("/b","get","body",null);
+		assertObject(x.getExamples()).json().is("{foo:'bar'}");
+	}
+
+	@Rest
+	public static class D {
+
+		public static class D1 {
+			public D1(String x) {}
+		}
+
+		@RestMethod
+		public void a(
+			@Body(
+				d= {"a","b"},
+				r=true,
+				schema=@Schema(type="string"),
+				ex="a",
+				exs=" {foo:'bar'} "
+			) D1 b) {}
+
+		public static class D2 {
+			public D2(String x) {}
+		}
+
+		@RestMethod
+		public void b(
+			@Body({
+				"description:'a\nb',",
+				"required:true,",
+				"schema:{type:'string'},",
+				"x-example:'a',",
+				"x-examples:{foo:'bar'}"
+			}) D2 b) {}
+
+		public static class D3 {
+			public D3(String x) {}
+		}
+
+		@RestMethod
+		public void c(
+			@Body(
+				value= {
+					"description:'a\nb',",
+					"required:true,",
+					"schema:{type:'string'},",
+					"x-example:'a',",
+					"x-examples:{foo:'bar'}"
+				},
+				d= {"b","c"},
+				schema=@Schema(type="string"),
+				ex="b",
+				exs=" {foo:'baz'} "
+			) D3 b) {}
+	}
+
+	@Test
+	public void d01_fromParameter() throws Exception {
+		Swagger s = getSwagger(D.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","body",null);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getRequired()).json().is("true");
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertEquals("a", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'bar'}");
+
+		x = s.getParameterInfo("/b","get","body",null);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getRequired()).json().is("true");
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertEquals("a", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'bar'}");
+
+		x = s.getParameterInfo("/c","get","body",null);
+		assertEquals("b\nc", x.getDescription());
+		assertObject(x.getRequired()).json().is("true");
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertEquals("b", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'baz'}");
+	}
+
+	@Rest
+	public static class E {
+
+		public static class E1 {}
+		@RestMethod
+		public void a(@Body(schema=@Schema(" { type:'b' } ")) E1 b) {}
+
+		public static class E2 {
+			public String f1;
+		}
+		@RestMethod
+		public void b(@Body E2 b) {}
+
+		public static class E3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod
+		public void c(@Body E3 b) {}
+
+		public static class E4 {}
+		@RestMethod
+		public void d(@Body E4 b) {}
+
+		@RestMethod
+		public void e(@Body Integer b) {}
+
+		@RestMethod
+		public void f(@Body Boolean b) {}
+	}
+
+	@Test
+	public void e01_schemaFromParameter() throws Exception {
+		Swagger s = getSwagger(E.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","body",null);
+		assertObject(x.getSchema()).json().is("{type:'b'}");
+
+		x = s.getParameterInfo("/b","get","body",null);
+		assertObject(x.getSchema()).json().is("{type:'object',properties:{f1:{type:'string'}}}");
+
+		x = s.getParameterInfo("/c","get","body",null);
+		assertObject(x.getSchema()).json().is("{type:'array',items:{type:'string'}}");
+
+		x = s.getParameterInfo("/d","get","body",null);
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+
+		x = s.getParameterInfo("/e","get","body",null);
+		assertObject(x.getSchema()).json().is("{format:'int32',type:'integer'}");
+
+		x = s.getParameterInfo("/f","get","body",null);
+		assertObject(x.getSchema()).json().is("{type:'boolean'}");
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Examples
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class F {
+
+		public static class F1 {
+			public String f1;
+		}
+		@RestMethod
+		public void a(@Body(ex="{f1:'b'}") F1 b) {}
+
+		public static class F2 {}
+		@RestMethod
+		public void b(@Body(exs={" foo:'bar' "}) F2 b) {}
+	}
+
+	@Test
+	public void f01_exampleFromParameter() throws Exception {
+		Swagger s = getSwagger(F.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","body",null);
+		assertEquals("{f1:'b'}", x.getExample());
+
+		x = s.getParameterInfo("/b","get","body",null);
+		assertObject(x.getExamples()).json().is("{foo:'bar'}");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_FormData_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_FormData_Test.java
new file mode 100644
index 0000000..5573e2f
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_FormData_Test.java
@@ -0,0 +1,301 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.rest.testutils.TestUtils.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.annotation.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Swagger_FormData_Test {
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Swagger
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+
+		@FormData(
+			name="F",
+			description= {"a","b"},
+			type="string"
+		)
+		public static class A1 {
+			public A1(String x) {}
+		}
+		@RestMethod
+		public void a(A1 f) {}
+
+		@FormData(
+			name="F",
+			api={
+				"description:'a\nb',",
+				"type:'string'"
+			}
+		)
+		public static class A2 {
+			public A2(String x) {}
+		}
+		@RestMethod
+		public void b(A2 f) {}
+
+		@FormData(
+			name="F",
+			api={
+				"description:'b\nc',",
+				"type:'string'"
+			},
+			description= {"a","b"},
+			type="string"
+		)
+		public static class A3 {
+			public A3(String x) {}
+		}
+		@RestMethod
+		public void c(A3 f) {}
+
+		@FormData("F")
+		public static class A4 {}
+		@RestMethod
+		public void d(A4 f) {}
+	}
+
+	@Test
+	public void a01_fromPojo() throws Exception {
+		Swagger s = getSwagger(A.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","formData","F");
+		assertEquals("F", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/b","get","formData","F");
+		assertEquals("F", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/c","get","formData","F");
+		assertEquals("F", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/d","get","formData","F");
+		assertEquals("F", x.getName());
+	}
+
+	@Rest
+	public static class B {
+
+		@FormData(name="F")
+		public static class B1 {}
+		@RestMethod
+		public void a(B1 f) {}
+
+		@FormData("F")
+		public static class B2 {
+			public String f1;
+		}
+		@RestMethod
+		public void b(B2 f) {}
+
+		@FormData("F")
+		public static class B3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod
+		public void c(B3 f) {}
+
+		@FormData("F")
+		public static class B4 {}
+		@RestMethod
+		public void d(B4 f) {}
+	}
+
+	@Test
+	public void b01_schemaFromPojo() throws Exception {
+		Swagger s = getSwagger(B.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'string'}");
+
+		x = s.getParameterInfo("/b","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'object',schema:{properties:{f1:{type:'string'}}}}");
+
+		x = s.getParameterInfo("/c","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'array',items:{type:'string'}}");
+
+		x = s.getParameterInfo("/d","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'string'}");
+	}
+
+	@Rest
+	public static class C {
+
+		@FormData(name="F", example={"{f1:'a'}"})
+		public static class C1 {
+			public String f1;
+		}
+		@RestMethod
+		public void a(C1 f) {}
+	}
+
+	@Test
+	public void c01_exampleFromPojo() throws Exception {
+		Swagger s = getSwagger(C.class);
+
+		ParameterInfo x = s.getParameterInfo("/a","get","formData","F");
+		assertEquals("{f1:'a'}", x.getExample());
+	}
+
+	@Rest
+	public static class D {
+
+		@RestMethod
+		public void a(
+			@FormData(
+				name="F",
+				description={"a","b"},
+				type="string"
+			) String f) {}
+
+		@RestMethod
+		public void b(
+			@FormData(
+				name="F",
+				api={
+					"description:'a\nb',",
+					"type:'string'",
+				}
+			) String f) {}
+
+		@RestMethod
+		public void c(
+			@FormData(
+				name="F",
+				api={
+					"description:'b\nc',",
+					"type:'string'",
+				},
+				description={"a","b"},
+				type="string"
+			) String f) {}
+
+		@RestMethod
+		public void d(@FormData("F") String f) {}
+	}
+
+	@Test
+	public void d01_fromParameter() throws Exception {
+		Swagger s = getSwagger(D.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","formData","F");
+		assertEquals("F", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/b","get","formData","F");
+		assertEquals("F", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/c","get","formData","F");
+		assertEquals("F", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/d","get","formData","F");
+		assertEquals("F", x.getName());
+	}
+
+	@Rest
+	public static class E {
+
+		@RestMethod
+		public void a(@FormData(name="F") String f) {}
+
+		public static class E2 {
+			public String f1;
+		}
+		@RestMethod
+		public void b(@FormData("F") E2 b) {}
+
+		public static class E3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod
+		public void c(@FormData("F") E3 b) {}
+
+		public static class E4 {}
+		@RestMethod
+		public void d(@FormData("F") E4 b) {}
+
+		@RestMethod
+		public void e(@FormData("F") Integer b) {}
+
+		@RestMethod
+		public void f(@FormData("F") Boolean b) {}
+	}
+
+	@Test
+	public void e01_schemaFromParameter() throws Exception {
+		Swagger s = getSwagger(E.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'string'}");
+
+		x = s.getParameterInfo("/b","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'object',schema:{properties:{f1:{type:'string'}}}}");
+
+		x = s.getParameterInfo("/c","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'array',items:{type:'string'}}");
+
+		x = s.getParameterInfo("/d","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'string'}");
+
+		x = s.getParameterInfo("/e","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'integer',format:'int32'}");
+
+		x = s.getParameterInfo("/f","get","formData","F");
+		assertObject(x).json().is("{'in':'formData',name:'F',type:'boolean'}");
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Examples
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class F {
+		@RestMethod
+		public void a(@FormData(name="F", example="{f1:'a'}") String f) {}
+	}
+
+	@Test
+	public void f01_exampleFromParameter() throws Exception {
+		Swagger s = getSwagger(F.class);
+
+		ParameterInfo x = s.getParameterInfo("/a","get","formData","F");
+		assertEquals("{f1:'a'}", x.getExample());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Header_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Header_Test.java
new file mode 100644
index 0000000..5c5d0d6
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Header_Test.java
@@ -0,0 +1,295 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.rest.testutils.TestUtils.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.annotation.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Swagger_Header_Test {
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Swagger tests
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+
+		@Header(
+			name="H",
+			description={"a","b"},
+			type="string"
+		)
+		public static class A1 {
+			public A1(String x) {}
+		}
+		@RestMethod
+		public void a(A1 h) {}
+
+		@Header(
+			name="H",
+			api={
+				"description:'a\nb',",
+				"type:'string'"
+			}
+		)
+		public static class A2 {
+			public A2(String x) {}
+		}
+		@RestMethod
+		public void b(A2 h) {}
+
+		@Header(
+			name="H",
+			api={
+				"description:'b\nc',",
+				"type:'string'"
+			},
+			description={"a","b"},
+			type="string"
+		)
+		public static class A3 {
+			public A3(String x) {}
+		}
+		@RestMethod
+		public void c(A3 h) {}
+	}
+
+	@Test
+	public void a01_fromPojo() throws Exception {
+		Swagger s = getSwagger(A.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","header","H");
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getType()).json().is("'string'");
+
+		x = s.getParameterInfo("/b","get","header","H");
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getType()).json().is("'string'");
+
+		x = s.getParameterInfo("/c","get","header","H");
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getType()).json().is("'string'");
+	}
+
+	@Rest
+	public static class B {
+
+		@Header(name="H")
+		public static class B1 {}
+		@RestMethod
+		public void a(B1 h) {}
+
+		@Header(name="H")
+		public static class B2 {
+			public String f1;
+		}
+		@RestMethod
+		public void b(B2 b) {}
+
+		@Header(name="H")
+		public static class B3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod
+		public void c(B3 b) {}
+
+		@Header(name="H")
+		public static class B4 {}
+		@RestMethod
+		public void d(B4 b) {}
+	}
+
+	@Test
+	public void b01_schemaFromPojo() throws Exception {
+		Swagger s = getSwagger(B.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'string'}");
+
+		x = s.getParameterInfo("/b","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'object',schema:{properties:{f1:{type:'string'}}}}");
+
+		x = s.getParameterInfo("/c","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'array',items:{type:'string'}}");
+
+		x = s.getParameterInfo("/d","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'string'}");
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Examples
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class C {
+
+		@Header(name="H", example="{f1:'a'}")
+		public static class C1 {
+			public String f1;
+		}
+		@RestMethod
+		public void a(C1 h) {}
+	}
+
+	@Test
+	public void c01_exampleFromPojo() throws Exception {
+		Swagger s = getSwagger(C.class);
+
+		ParameterInfo x = s.getParameterInfo("/a","get","header","H");
+		assertEquals("{f1:'a'}", x.getExample());
+	}
+
+	@Rest
+	public static class D {
+
+		@RestMethod
+		public void a(
+			@Header(
+				name="H",
+				description={"a","b"},
+				type="string"
+			) String h) {}
+
+		@RestMethod
+		public void b(
+			@Header(
+				name="H",
+				api={
+					"description:'a\nb',",
+					"type:'string'",
+				}
+			) String h) {}
+
+		@RestMethod
+		public void c(
+			@Header(
+				name="H",
+				api={
+					"description:'b\nc',",
+					"type:'string'",
+				},
+				description={"a","b"},
+				type="string"
+			) String h) {}
+
+		@RestMethod
+		public void d(@Header("H") String h) {}
+	}
+
+	@Test
+	public void d01_fromParameter() throws Exception {
+		Swagger s = getSwagger(D.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","header","H");
+		assertEquals("H", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/b","get","header","H");
+		assertEquals("H", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/c","get","header","H");
+		assertEquals("H", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/d","get","header","H");
+		assertEquals("H", x.getName());
+	}
+
+	@Rest
+	public static class E {
+
+		@RestMethod
+		public void a(@Header(name="H") String h) {}
+
+		public static class E2 {
+			public String f1;
+		}
+		@RestMethod
+		public void b(@Header("H") E2 b) {}
+
+		public static class E3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod
+		public void c(@Header("H") E3 b) {}
+
+		public static class E4 {}
+		@RestMethod
+		public void d(@Header("H") E4 b) {}
+
+		@RestMethod
+		public void e(@Header("H") Integer b) {}
+
+		@RestMethod
+		public void f(@Header("H") Boolean b) {}
+	}
+
+	@Test
+	public void e01_schemaFromParameter() throws Exception {
+		Swagger s = getSwagger(E.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'string'}");
+
+		x = s.getParameterInfo("/b","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'object',schema:{properties:{f1:{type:'string'}}}}");
+
+		x = s.getParameterInfo("/c","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'array',items:{type:'string'}}");
+
+		x = s.getParameterInfo("/d","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'string'}");
+
+		x = s.getParameterInfo("/e","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'integer',format:'int32'}");
+
+		x = s.getParameterInfo("/f","get","header","H");
+		assertObject(x).json().is("{'in':'header',name:'H',type:'boolean'}");
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Examples
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class F {
+
+		@RestMethod
+		public void a(@Header(name="H", example={"a","b"}) String h) {}
+	}
+
+	@Test
+	public void f01_exampleFromParameter() throws Exception {
+		Swagger s = getSwagger(F.class);
+
+		ParameterInfo x = s.getParameterInfo("/a","get","header","H");
+		assertEquals("a\nb", x.getExample());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Path_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Path_Test.java
new file mode 100644
index 0000000..3a9a7fd
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Path_Test.java
@@ -0,0 +1,349 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.http.HttpMethod.*;
+import static org.apache.juneau.rest.testutils.TestUtils.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.annotation.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Swagger_Path_Test {
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Swagger tests
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+
+		@Path(
+			n="P",
+			d={"a","b"},
+			t="string",
+			e="a,b",
+			ex="a"
+		)
+		public static class A1 {
+			public A1(String x) {}
+			@Override
+			public String toString() {
+				return "a";
+			}
+		}
+		@RestMethod(name=GET,path="/a/{P}")
+		public void a(A1 f) {}
+
+		@Path(
+			n="P",
+			api={
+				"description:'a\nb',",
+				"type:'string',",
+				"enum:['a','b'],",
+				"x-example:'a'"
+			}
+		)
+		public static class A2 {
+			public A2(String x) {}
+			@Override
+			public String toString() {
+				return "b";
+			}
+		}
+		@RestMethod(name=GET,path="/b/{P}")
+		public void b(A2 f) {}
+
+		@Path(
+			n="P",
+			api={
+				"description:'b\nc',",
+				"type:'string',",
+				"enum:['b','c'],",
+				"x-example:'b'"
+			},
+			d={"a","b"},
+			t="string",
+			e="a,b",
+			ex="a"
+		)
+		public static class A3 {
+			public A3(String x) {}
+			@Override
+			public String toString() {
+				return "c";
+			}
+		}
+		@RestMethod(name=GET,path="/c/{P}")
+		public void c(A3 f) {}
+
+
+		@Path("P")
+		public static class A4 {
+			@Override
+			public String toString() {
+				return "d";
+			}
+		}
+		@RestMethod(name=GET,path="/d/{P}")
+		public void d(A4 f) {}
+
+		@Path(n="P",e={" ['a','b'] "})
+		public static class A5 {
+			@Override
+			public String toString() {
+				return "e";
+			}
+		}
+		@RestMethod(name=GET,path="/e/{P}")
+		public void e(A5 f) {}
+	}
+
+	@Test
+	public void a01_fromPojo() throws Exception {
+		Swagger s = getSwagger(A.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a/{P}","get","path","P");
+		assertEquals("P", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+		assertObject(x.getEnum()).json().is("['a','b']");
+		assertEquals("a", x.getExample());
+		assertObject(x).json().is("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/a/a'}}");
+
+		x = s.getParameterInfo("/b/{P}","get","path","P");
+		assertEquals("P", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+		assertObject(x.getEnum()).json().is("['a','b']");
+		assertEquals("a", x.getExample());
+		assertObject(x).json().is("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/b/a'}}");
+
+		x = s.getParameterInfo("/c/{P}","get","path","P");
+		assertEquals("P", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+		assertObject(x.getEnum()).json().is("['a','b']");
+		assertEquals("a", x.getExample());
+		assertObject(x).json().is("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/c/a'}}");
+
+		x = s.getParameterInfo("/d/{P}","get","path","P");
+		assertEquals("P", x.getName());
+		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
+
+		x = s.getParameterInfo("/e/{P}","get","path","P");
+		assertObject(x.getEnum()).json().is("['a','b']");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true,'enum':['a','b']}");
+	}
+
+	@Rest
+	public static class B {
+
+		@Path(n="P")
+		public static class B1 {}
+		@RestMethod(name=GET,path="/a/{P}")
+		public void a(B1 f) {}
+
+		@Path("P")
+		public static class B2 {
+			public String f1;
+		}
+		@RestMethod(name=GET,path="/b/{P}")
+		public void b(B2 b) {}
+
+		@Path("P")
+		public static class B3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod(name=GET,path="/c/{P}")
+		public void c(B3 b) {}
+
+		@Path("P")
+		public static class B4 {}
+		@RestMethod(name=GET,path="/d/{P}")
+		public void d(B4 b) {}
+	}
+
+	@Test
+	public void b01_schemaFromPojo() throws Exception {
+		Swagger s = getSwagger(B.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
+
+		x = s.getParameterInfo("/b/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'object',required:true,schema:{properties:{f1:{type:'string'}}}}");
+
+		x = s.getParameterInfo("/c/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'array',required:true,items:{type:'string'}}");
+
+		x = s.getParameterInfo("/d/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
+	}
+
+	@Rest
+	public static class C {
+
+		@Path(n="P",ex={" {f1:'a'} "})
+		public static class C1 {
+			public String f1;
+		}
+		@RestMethod(name=GET,path="/a/{P}")
+		public void a(C1 f) {}
+	}
+
+	@Test
+	public void c01_exampleFromPojo() throws Exception {
+		Swagger s = getSwagger(C.class);
+
+		ParameterInfo x = s.getParameterInfo("/a/{P}","get","path","P");
+		assertEquals("{f1:'a'}", x.getExample());
+	}
+
+	@Rest
+	public static class D {
+
+		@RestMethod(name=GET,path="/a/{P}")
+		public void a(@Path(
+			n="P",
+			d="a",
+			t="string"
+		) String h) {}
+
+		@RestMethod(name=GET,path="/b/{P}")
+		public void b(@Path(
+			n="P",
+			api={
+				"description:'a',",
+				"type:'string'"
+			}
+		) String h) {}
+
+		@RestMethod(name=GET,path="/c/{P}")
+		public void c(@Path(
+			n="P",
+			api={
+				"description:'b',",
+				"type:'string'"
+			},
+			d="a",
+			t="string"
+		) String h) {}
+
+		@RestMethod(name=GET,path="/d/{P}")
+		public void d(@Path("P") String h) {}
+
+		@RestMethod(name=GET,path="/e/{P}")
+		public void e(@Path(n="P",e={" ['a','b'] "}) String h) {}
+	}
+
+	@Test
+	public void d01_fromParameter() throws Exception {
+		Swagger s = getSwagger(D.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a/{P}","get","path","P");
+		assertEquals("a", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/b/{P}","get","path","P");
+		assertEquals("a", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/c/{P}","get","path","P");
+		assertEquals("a", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/d/{P}","get","path","P");
+		assertEquals("P", x.getName());
+
+		x = s.getParameterInfo("/e/{P}","get","path","P");
+		assertObject(x.getEnum()).json().is("['a','b']");
+	}
+
+	@Rest
+	public static class E {
+
+		@RestMethod(name=GET,path="/a/{P}")
+		public void a(@Path("P") String h) {}
+
+		public static class E2 {
+			public String f1;
+		}
+		@RestMethod(name=GET,path="/b/{P}")
+		public void b(@Path("P") E2 b) {}
+
+		public static class E3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod(name=GET,path="/c/{P}")
+		public void c(@Path("P") E3 b) {}
+
+		public static class E4 {}
+		@RestMethod(name=GET,path="/d/{P}")
+		public void d(@Path("P") E4 b) {}
+
+		@RestMethod(name=GET,path="/e/{P}")
+		public void e(@Path("P") Integer b) {}
+
+		@RestMethod(name=GET,path="/f/{P}")
+		public void f(@Path("P") Boolean b) {}
+	}
+
+	@Test
+	public void d01_schemaFromParameter() throws Exception {
+		Swagger s = getSwagger(E.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
+
+		x = s.getParameterInfo("/b/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'object',required:true,schema:{properties:{f1:{type:'string'}}}}");
+
+		x = s.getParameterInfo("/c/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'array',required:true,items:{type:'string'}}");
+
+		x = s.getParameterInfo("/d/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
+
+		x = s.getParameterInfo("/e/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'integer',required:true,format:'int32'}");
+
+		x = s.getParameterInfo("/f/{P}","get","path","P");
+		assertObject(x).json().is("{'in':'path',name:'P',type:'boolean',required:true}");
+	}
+
+	@Rest
+	public static class F {
+
+		@RestMethod(name=GET,path="/a/{P}")
+		public void a(@Path(n="P",ex="{f1:'b'}") String h) {}
+	}
+
+	@Test
+	public void f01_exampleFromParameter() throws Exception {
+		Swagger s = getSwagger(F.class);
+
+		ParameterInfo x = s.getParameterInfo("/a/{P}","get","path","P");
+		assertEquals("{f1:'b'}", x.getExample());
+	}
+}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Query_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Query_Test.java
new file mode 100644
index 0000000..79e69f6
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Query_Test.java
@@ -0,0 +1,271 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.rest.testutils.TestUtils.*;
+import static org.junit.Assert.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.annotation.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Swagger_Query_Test {
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Swagger tests
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+
+		@Query(
+			n="Q",
+			d= {"a","b"},
+			t="string"
+		)
+		public static class A1 {
+			public A1(String x) {}
+		}
+		@RestMethod
+		public void a(A1 q) {}
+
+		@Query(
+			n="Q",
+			api={
+				"description: 'a\nb',",
+				"type:'string'"
+			}
+		)
+		public static class A2 {
+			public A2(String x) {}
+		}
+		@RestMethod
+		public void b(A2 q) {}
+
+		@Query(
+			n="Q",
+			api={
+				"description: 'b\nc',",
+				"type:'string'"
+			},
+			d={"a","b"},
+			t="string"
+		)
+		public static class A3 {
+			public A3(String x) {}
+		}
+		@RestMethod
+		public void c(A3 q) {}
+
+		@Query("Q")
+		public static class A4 {}
+		@RestMethod
+		public void d(A4 q) {}
+	}
+
+	@Test
+	public void a01_fromPojo() throws Exception {
+		Swagger s = getSwagger(A.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","query","Q");
+		assertEquals("Q", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/b","get","query","Q");
+		assertEquals("Q", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/c","get","query","Q");
+		assertEquals("Q", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/d","get","query","Q");
+		assertEquals("Q", x.getName());
+	}
+
+	@Rest
+	public static class B {
+
+		@Query(n="Q")
+		public static class B1 {}
+		@RestMethod
+		public void a(B1 q) {}
+
+		@Query("Q")
+		public static class B2 {
+			public String f1;
+		}
+		@RestMethod
+		public void b(B2 q) {}
+
+		@Query("Q")
+		public static class B3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod
+		public void c(B3 q) {}
+
+		@Query("Q")
+		public static class B4 {}
+		@RestMethod
+		public void d(B4 q) {}
+	}
+
+	@Test
+	public void b01_schemaFromPojo() throws Exception {
+		Swagger s = getSwagger(B.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","query","Q");
+		assertObject(x).json().is("{'in':'query',name:'Q',type:'string'}");
+
+		x = s.getParameterInfo("/b","get","query","Q");
+		assertObject(x).json().is("{'in':'query',name:'Q',type:'object',schema:{properties:{f1:{type:'string'}}}}");
+
+		x = s.getParameterInfo("/c","get","query","Q");
+		assertObject(x).json().is("{'in':'query',name:'Q',type:'array',items:{type:'string'}}");
+
+		x = s.getParameterInfo("/d","get","query","Q");
+		assertObject(x).json().is("{'in':'query',name:'Q',type:'string'}");
+	}
+
+	@Rest
+	public static class C {
+
+		@Query(n="Q", ex={"{f1:'a'}"})
+		public static class C1 {
+			public String f1;
+		}
+		@RestMethod
+		public void a(C1 q) {}
+	}
+
+	@Test
+	public void c01_exampleFromPojo() throws Exception {
+		Swagger s = getSwagger(C.class);
+
+		ParameterInfo x = s.getParameterInfo("/a","get","query","Q");
+		assertEquals("{f1:'a'}", x.getExample());
+	}
+
+	@Rest
+	public static class D {
+
+		@RestMethod
+		public void a(
+			@Query(
+				n="Q",
+				d= {"a","b"},
+				t="string"
+			)
+			String q) {}
+
+		@RestMethod
+		public void b(
+			@Query(
+				n="Q",
+				api={
+					"description: 'a\nb',",
+					"type:'string'"
+				}
+			)
+			String q) {}
+
+		@RestMethod
+		public void c(
+			@Query(
+				n="Q",
+				api={
+					"description: 'b\nc',",
+					"type:'string'"
+				},
+				d= {"a","b"},
+				t="string"
+			)
+			String q) {}
+
+		@RestMethod
+		public void d(@Query("Q") String q) {}
+	}
+
+	@Test
+	public void d01_fromParameter() throws Exception {
+		Swagger s = getSwagger(D.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/a","get","query","Q");
+		assertEquals("Q", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/b","get","query","Q");
+		assertEquals("Q", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/c","get","query","Q");
+		assertEquals("Q", x.getName());
+		assertEquals("a\nb", x.getDescription());
+		assertEquals("string", x.getType());
+
+		x = s.getParameterInfo("/d","get","query","Q");
+		assertEquals("Q", x.getName());
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Schema
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class E {
+
+		@RestMethod
+		public void a(@Query("Q") String q) {}
+	}
+
+	@Test
+	public void e01_schemaFromParameter() throws Exception {
+		Swagger s = getSwagger(E.class);
+
+		ParameterInfo x = s.getParameterInfo("/a","get","query","Q");
+		assertObject(x).json().is("{'in':'query',name:'Q',type:'string'}");
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Examples
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class F {
+
+		@RestMethod
+		public void a(@Query(n="Q",ex={"a","b"}) String q) {}
+	}
+
+	@Test
+	public void f01_exampleFromParameter() throws Exception {
+		Swagger s = getSwagger(F.class);
+
+		ParameterInfo x = s.getParameterInfo("/a","get","query","Q");
+		assertEquals("a\nb", x.getExample());
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Response_Test.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Response_Test.java
new file mode 100644
index 0000000..ad6725e
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_Response_Test.java
@@ -0,0 +1,431 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.rest.testutils.TestUtils.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.http.annotation.Response;
+import org.apache.juneau.jsonschema.annotation.Schema;
+import org.junit.*;
+
+@SuppressWarnings({"serial"})
+@FixMethodOrder(NAME_ASCENDING)
+public class Swagger_Response_Test {
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Swagger tests
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+
+		@Response(
+			description={"a","b"},
+			schema=@Schema(type="string"),
+			headers=@ResponseHeader(name="foo",type="string"),
+			example="'a'",
+			examples=" {foo:'a'} "
+		)
+		public static class A1 {
+			public A1(String x){}
+		}
+		@RestMethod
+		public void a(Value<A1> r) {}
+		@RestMethod
+		public A1 b() {return null;}
+
+		@Response(
+			api={
+				"description:'a\nb',",
+				"schema:{type:'string'},",
+				"headers:{foo:{type:'string'}},",
+				"example:'a',",
+				"examples:{foo:'a'}"
+			}
+		)
+		public static class A2 {
+			public A2(String x){}
+		}
+		@RestMethod
+		public void c(Value<A2> r) {}
+		@RestMethod
+		public A2 d() {return null;}
+
+		@Response(
+			api={
+				"description:'b',",
+				"schema:{type:'number'},",
+				"headers:{bar:{type:'number'}},",
+				"example:'b',",
+				"examples:{bar:'b'}"
+			},
+			description={"a","b"},
+			schema=@Schema(type="string"),
+			headers=@ResponseHeader(name="foo",type="string"),
+			example="'a'",
+			examples=" {foo:'a'} "
+		)
+		public static class A3 {
+			public A3(String x){}
+		}
+		@RestMethod
+		public void e(Value<A3> r) {}
+		@RestMethod
+		public A3 f() {return null;}
+
+		@Response(code=100)
+		public static class A4 {}
+		@RestMethod
+		public void g(Value<A4> r) {}
+		@RestMethod
+		public A4 h() {return null;}
+
+		@Response(100)
+		public static class A5 {}
+		@RestMethod
+		public void i(Value<A5> r) {}
+		@RestMethod
+		public A5 j() {return null;}
+
+		@Response(headers=@ResponseHeader(name="foo",api=" type:'b' "))
+		public static class A6 {}
+		@RestMethod
+		public void k(Value<A6> r) {}
+		@RestMethod
+		public A6 l() {return null;}
+	}
+
+	@Test
+	public void a01_fromPojo() throws Exception {
+		Swagger s = getSwagger(A.class);
+		ResponseInfo x;
+
+		x = s.getResponseInfo("/a","get",200);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
+		assertEquals("'a'", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'a'}");
+
+		x = s.getResponseInfo("/b","get",200);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
+		assertEquals("'a'", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'a'}");
+
+		x = s.getResponseInfo("/c","get",200);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
+		assertEquals("a", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'a'}");
+
+		x = s.getResponseInfo("/d","get",200);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
+		assertEquals("a", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'a'}");
+
+		x = s.getResponseInfo("/e","get",200);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertObject(x.getHeaders()).json().is("{bar:{type:'number'},foo:{type:'string'}}");
+		assertEquals("'a'", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'a'}");
+
+		x = s.getResponseInfo("/f","get",200);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertObject(x.getHeaders()).json().is("{bar:{type:'number'},foo:{type:'string'}}");
+		assertEquals("'a'", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'a'}");
+
+		x = s.getResponseInfo("/g","get",100);
+		assertEquals("Continue", x.getDescription());
+
+		x = s.getResponseInfo("/h","get",100);
+		assertEquals("Continue", x.getDescription());
+
+		x = s.getResponseInfo("/i","get",100);
+		assertEquals("Continue", x.getDescription());
+
+		x = s.getResponseInfo("/j","get",100);
+		assertEquals("Continue", x.getDescription());
+
+		x = s.getResponseInfo("/k","get",200);
+		assertObject(x.getHeaders()).json().is("{foo:{type:'b'}}");
+
+		x = s.getResponseInfo("/l","get",200);
+		assertObject(x.getHeaders()).json().is("{foo:{type:'b'}}");
+	}
+
+	@Rest
+	public static class B {
+
+		@Response(schema=@Schema(" type:'number' "))
+		public static class B1 {}
+		@RestMethod
+		public void a(Value<B1> r) {}
+		@RestMethod
+		public B1 b() {return null;}
+
+		@Response
+		public static class B2 {
+			public String f1;
+		}
+		@RestMethod
+		public void c(Value<B2> b) {}
+		@RestMethod
+		public B2 d() {return null;}
+
+		@Response
+		public static class B3 extends LinkedList<String> {
+			private static final long serialVersionUID = 1L;
+		}
+		@RestMethod
+		public void e(Value<B3> b) {}
+		@RestMethod
+		public B3 f() {return null;}
+
+		@Response
+		public static class B4 {}
+		@RestMethod
+		public void g(Value<B4> b) {}
+		@RestMethod
+		public B4 h() {return null;}
+	}
+
+	@Test
+	public void b01_schemaFromPojo() throws Exception {
+		Swagger s = getSwagger(B.class);
+		ResponseInfo x;
+
+		x = s.getResponseInfo("/a","get",200);
+		assertObject(x.getSchema()).json().is("{type:'number'}");
+
+		x = s.getResponseInfo("/b","get",200);
+		assertObject(x.getSchema()).json().is("{type:'number'}");
+
+		x = s.getResponseInfo("/c","get",200);
+		assertObject(x.getSchema()).json().is("{type:'object',properties:{f1:{type:'string'}}}");
+
+		x = s.getResponseInfo("/d","get",200);
+		assertObject(x.getSchema()).json().is("{type:'object',properties:{f1:{type:'string'}}}");
+
+		x = s.getResponseInfo("/e","get",200);
+		assertObject(x.getSchema()).json().is("{type:'array',items:{type:'string'}}");
+
+		x = s.getResponseInfo("/f","get",200);
+		assertObject(x.getSchema()).json().is("{type:'array',items:{type:'string'}}");
+
+		x = s.getResponseInfo("/g","get",200);
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+
+		x = s.getResponseInfo("/h","get",200);
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+	}
+
+	@Rest
+	public static class C {
+
+		@Response(example="{f1:'a'}")
+		public static class C1 {
+			public String f1;
+		}
+		@RestMethod
+		public void a(Value<C1> r) {}
+		@RestMethod
+		public C1 b() {return null;}
+
+		@Response(examples={" foo:'b' "})
+		public static class C2 {
+			public C2(String x){}
+		}
+		@RestMethod
+		public void c(Value<C2> r) {}
+		@RestMethod
+		public C2 d() {return null;}
+	}
+
+	@Test
+	public void c01_exampleFromPojo() throws Exception {
+		Swagger sc = getSwagger(C.class);
+		ResponseInfo x;
+
+		x = sc.getResponseInfo("/a","get",200);
+		assertEquals("{f1:'a'}", x.getExample());
+
+		x = sc.getResponseInfo("/b","get",200);
+		assertEquals("{f1:'a'}", x.getExample());
+
+		x = sc.getResponseInfo("/c","get",200);
+		assertObject(x.getExamples()).json().is("{foo:'b'}");
+
+		x = sc.getResponseInfo("/d","get",200);
+		assertObject(x.getExamples()).json().is("{foo:'b'}");
+	}
+
+	@Rest
+	public static class D {
+
+		@Response(
+			description= {"a","b"},
+			schema=@Schema(type="string"),
+			headers=@ResponseHeader(name="foo",type="string"),
+			example=" 'a' ",
+			examples=" {foo:'a'} "
+		)
+		public static class D1 extends Throwable {}
+		@RestMethod
+		public void a() throws D1 {}
+
+		@Response(
+			api={
+				"description:'a\nb',",
+				"schema:{type:'string'},",
+				"headers:{foo:{type:'string'}},",
+				"example:'a',",
+				"examples:{foo:'a'}"
+			}
+		)
+		public static class D2 extends Throwable {}
+		@RestMethod
+		public void b() throws D2 {}
+
+		@Response(
+			api={
+				"description:'b',",
+				"schema:{type:'number'},",
+				"headers:{bar:{type:'number'}},",
+				"example:'b',",
+				"examples:{bar:'b'}"
+			},
+			description= {"a","b"},
+			schema=@Schema(type="string"),
+			headers=@ResponseHeader(name="foo",type="string"),
+			example=" 'a' ",
+			examples=" {foo:'a'} "
+		)
+		public static class D3 extends Throwable {}
+		@RestMethod
+		public void c() throws D3 {}
+
+		@Response(code=100)
+		public static class D4 extends Throwable {}
+		@RestMethod
+		public void d() throws D4 {}
+
+		@Response(code=100)
+		public static class D5 extends Throwable {}
+		@RestMethod
+		public void e() throws D5 {}
+
+		@Response(headers=@ResponseHeader(name="foo", api=" {type:'number'} "))
+		public static class D6 extends Throwable {}
+		@RestMethod
+		public void f() throws D6 {}
+	}
+
+	@Test
+	public void d01_fromThrowable() throws Exception {
+		Swagger s = getSwagger(D.class);
+		ResponseInfo x;
+
+		x = s.getResponseInfo("/a","get",500);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
+		assertEquals("'a'", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'a'}");
+
+		x = s.getResponseInfo("/b","get",500);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
+		assertObject(x.getExample()).json().is("'a'");
+		assertObject(x.getExamples()).json().is("{foo:'a'}");
+
+		x = s.getResponseInfo("/c","get",500);
+		assertEquals("a\nb", x.getDescription());
+		assertObject(x.getSchema()).json().is("{type:'string'}");
+		assertObject(x.getHeaders()).json().is("{bar:{type:'number'},foo:{type:'string'}}");
+		assertEquals("'a'", x.getExample());
+		assertObject(x.getExamples()).json().is("{foo:'a'}");
+
+		x = s.getResponseInfo("/d","get",100);
+		assertEquals("Continue", x.getDescription());
+
+		x = s.getResponseInfo("/e","get",100);
+		assertEquals("Continue", x.getDescription());
+
+		x = s.getResponseInfo("/f","get",500);
+		assertObject(x.getHeaders()).json().is("{foo:{type:'number'}}");
+	}
+
+	@Rest
+	public static class E {
+
+		@Response(schema=@Schema(" type:'number' "))
+		public static class E1 extends Throwable {}
+		@RestMethod
+		public void a() throws E1 {}
+	}
+
+	@Test
+	public void e01_schemaFromThrowable() throws Exception {
+		Swagger s = getSwagger(E.class);
+
+		ResponseInfo x = s.getResponseInfo("/a","get",500);
+		assertObject(x.getSchema()).json().is("{type:'number'}");
+	}
+
+	//-----------------------------------------------------------------------------------------------------------------
+	// Examples
+	//-----------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class F {
+
+		@Response(example={" {f1:'b'} "})
+		public static class F1 extends Throwable {}
+		@RestMethod
+		public void a() throws F1 {}
+
+		@Response(examples={" foo:'b' "})
+		public static class F2 extends Throwable {}
+		@RestMethod
+		public void b() throws F2 {}
+	}
+
+	@Test
+	public void f01_exampeFromThrowable() throws Exception {
+		Swagger s = getSwagger(F.class);
+		ResponseInfo x;
+
+		x = s.getResponseInfo("/a","get",500);
+		assertEquals("{f1:'b'}", x.getExample());
+
+		x = s.getResponseInfo("/b","get",500);
+		assertObject(x.getExamples()).json().is("{foo:'b'}");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_RestMethod_Parameters.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_RestMethod_Parameters.java
new file mode 100644
index 0000000..c963702
--- /dev/null
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation/Swagger_RestMethod_Parameters.java
@@ -0,0 +1,229 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.apache.juneau.assertions.Assertions.*;
+import static org.apache.juneau.rest.testutils.TestUtils.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.juneau.dto.swagger.*;
+import org.apache.juneau.http.header.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Swagger_RestMethod_Parameters {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// Swagger on default headers.
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest
+	public static class A {
+
+		@RestMethod
+		public String accept(Accept accept) {
+			return accept.getValue();
+		}
+		@RestMethod
+		public String acceptCharset(AcceptCharset acceptCharset) {
+			return acceptCharset.getValue();
+		}
+		@RestMethod
+		public String acceptEncoding(AcceptEncoding acceptEncoding) {
+			return acceptEncoding.getValue();
+		}
+		@RestMethod
+		public String acceptLanguage(AcceptLanguage acceptLanguage) {
+			return acceptLanguage.getValue();
+		}
+		@RestMethod
+		public String authorization(Authorization authorization) {
+			return authorization.getValue();
+		}
+		@RestMethod
+		public String cacheControl(CacheControl cacheControl) {
+			return cacheControl.getValue();
+		}
+		@RestMethod
+		public String connection(Connection connection) {
+			return connection.getValue();
+		}
+		@RestMethod
+		public String contentLength(ContentLength contentLength) {
+			return contentLength.getValue();
+		}
+		@RestMethod
+		public String contentType(ContentType contentType) {
+			return contentType.getValue();
+		}
+		@RestMethod
+		public String date(org.apache.juneau.http.header.Date date) {
+			return date.getValue();
+		}
+		@RestMethod
+		public String expect(Expect expect) {
+			return expect.getValue();
+		}
+		@RestMethod
+		public String from(From from) {
+			return from.getValue();
+		}
+		@RestMethod
+		public String host(Host host) {
+			return host.getValue();
+		}
+		@RestMethod
+		public String ifMatch(IfMatch ifMatch) {
+			return ifMatch.getValue();
+		}
+		@RestMethod
+		public String ifModifiedSince(IfModifiedSince ifModifiedSince) {
+			return ifModifiedSince.getValue();
+		}
+		@RestMethod
+		public String ifNoneMatch(IfNoneMatch ifNoneMatch) {
+			return ifNoneMatch.getValue();
+		}
+		@RestMethod
+		public String ifRange(IfRange ifRange) {
+			return ifRange.getValue();
+		}
+		@RestMethod
+		public String ifUnmodifiedSince(IfUnmodifiedSince ifUnmodifiedSince) {
+			return ifUnmodifiedSince.getValue();
+		}
+		@RestMethod
+		public String maxForwards(MaxForwards maxForwards) {
+			return maxForwards.getValue();
+		}
+		@RestMethod
+		public String pragma(Pragma pragma) {
+			return pragma.getValue();
+		}
+		@RestMethod
+		public String proxyAuthorization(ProxyAuthorization proxyAuthorization) {
+			return proxyAuthorization.getValue();
+		}
+		@RestMethod
+		public String range(Range range) {
+			return range.getValue();
+		}
+		@RestMethod
+		public String referer(Referer referer) {
+			return referer.getValue();
+		}
+		@RestMethod
+		public String te(TE te) {
+			return te.getValue();
+		}
+		@RestMethod
+		public String upgrade(Upgrade upgrade) {
+			return upgrade.getValue();
+		}
+		@RestMethod
+		public String userAgent(UserAgent userAgent) {
+			return userAgent.getValue();
+		}
+		@RestMethod
+		public String warning(Warning warning) {
+			return warning.getValue();
+		}
+	}
+
+	@Test
+	public void a01_headerParameters() throws Exception {
+		Swagger s = getSwagger(A.class);
+		ParameterInfo x;
+
+		x = s.getParameterInfo("/accept","get","header","Accept");
+		assertObject(x).json().is("{'in':'header',name:'Accept',type:'string'}");
+
+		x = s.getParameterInfo("/acceptCharset","get","header","Accept-Charset");
+		assertObject(x).json().is("{'in':'header',name:'Accept-Charset',type:'string'}");
+
+		x = s.getParameterInfo("/acceptEncoding","get","header","Accept-Encoding");
+		assertObject(x).json().is("{'in':'header',name:'Accept-Encoding',type:'string'}");
+
+		x = s.getParameterInfo("/acceptLanguage","get","header","Accept-Language");
+		assertObject(x).json().is("{'in':'header',name:'Accept-Language',type:'string'}");
+
+		x = s.getParameterInfo("/authorization","get","header","Authorization");
+		assertObject(x).json().is("{'in':'header',name:'Authorization',type:'string'}");
+
+		x = s.getParameterInfo("/cacheControl","get","header","Cache-Control");
+		assertObject(x).json().is("{'in':'header',name:'Cache-Control',type:'string'}");
+
+		x = s.getParameterInfo("/connection","get","header","Connection");
+		assertObject(x).json().is("{'in':'header',name:'Connection',type:'string'}");
+
+		x = s.getParameterInfo("/contentLength","get","header","Content-Length");
+		assertObject(x).json().is("{'in':'header',name:'Content-Length',type:'integer',format:'int64'}");
+
+		x = s.getParameterInfo("/contentType","get","header","Content-Type");
+		assertObject(x).json().is("{'in':'header',name:'Content-Type',type:'string'}");
+
+		x = s.getParameterInfo("/date","get","header","Date");
+		assertObject(x).json().is("{'in':'header',name:'Date',type:'string'}");
+
+		x = s.getParameterInfo("/expect","get","header","Expect");
+		assertObject(x).json().is("{'in':'header',name:'Expect',type:'string'}");
+
+		x = s.getParameterInfo("/from","get","header","From");
+		assertObject(x).json().is("{'in':'header',name:'From',type:'string'}");
+
+		x = s.getParameterInfo("/host","get","header","Host");
+		assertObject(x).json().is("{'in':'header',name:'Host',type:'string'}");
+
+		x = s.getParameterInfo("/ifMatch","get","header","If-Match");
+		assertObject(x).json().is("{'in':'header',name:'If-Match',type:'string'}");
+
+		x = s.getParameterInfo("/ifModifiedSince","get","header","If-Modified-Since");
+		assertObject(x).json().is("{'in':'header',name:'If-Modified-Since',type:'string'}");
+
+		x = s.getParameterInfo("/ifNoneMatch","get","header","If-None-Match");
+		assertObject(x).json().is("{'in':'header',name:'If-None-Match',type:'string'}");
+
+		x = s.getParameterInfo("/ifRange","get","header","If-Range");
+		assertObject(x).json().is("{'in':'header',name:'If-Range',type:'string'}");
+
+		x = s.getParameterInfo("/ifUnmodifiedSince","get","header","If-Unmodified-Since");
+		assertObject(x).json().is("{'in':'header',name:'If-Unmodified-Since',type:'string'}");
+
+		x = s.getParameterInfo("/maxForwards","get","header","Max-Forwards");
+		assertObject(x).json().is("{'in':'header',name:'Max-Forwards',type:'integer',format:'int32'}");
+
+		x = s.getParameterInfo("/pragma","get","header","Pragma");
+		assertObject(x).json().is("{'in':'header',name:'Pragma',type:'string'}");
+
+		x = s.getParameterInfo("/proxyAuthorization","get","header","Proxy-Authorization");
+		assertObject(x).json().is("{'in':'header',name:'Proxy-Authorization',type:'string'}");
+
+		x = s.getParameterInfo("/range","get","header","Range");
+		assertObject(x).json().is("{'in':'header',name:'Range',type:'string'}");
+
+		x = s.getParameterInfo("/referer","get","header","Referer");
+		assertObject(x).json().is("{'in':'header',name:'Referer',type:'string'}");
+
+		x = s.getParameterInfo("/te","get","header","TE");
+		assertObject(x).json().is("{'in':'header',name:'TE',type:'string'}");
+
+		x = s.getParameterInfo("/upgrade","get","header","Upgrade");
+		assertObject(x).json().is("{'in':'header',name:'Upgrade',type:'string'}");
+
+		x = s.getParameterInfo("/userAgent","get","header","User-Agent");
+		assertObject(x).json().is("{'in':'header',name:'User-Agent',type:'string'}");
+
+		x = s.getParameterInfo("/warning","get","header","Warning");
+		assertObject(x).json().is("{'in':'header',name:'Warning',type:'string'}");
+	}
+}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/BodyAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/BodyAnnotationTest.java
deleted file mode 100644
index bd8e88e..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/BodyAnnotationTest.java
+++ /dev/null
@@ -1,1590 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation2;
-
-import static org.apache.juneau.assertions.Assertions.*;
-import static org.apache.juneau.http.HttpMethod.*;
-import static org.apache.juneau.rest.testutils.TestUtils.*;
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.io.*;
-import java.util.*;
-
-import org.apache.juneau.annotation.*;
-import org.apache.juneau.collections.*;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.annotation.Body;
-import org.apache.juneau.http.annotation.HasQuery;
-import org.apache.juneau.http.annotation.Query;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.jsonschema.annotation.*;
-import org.apache.juneau.marshall.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.apache.juneau.testutils.pojos.*;
-import org.apache.juneau.uon.*;
-import org.apache.juneau.urlencoding.*;
-import org.apache.juneau.urlencoding.annotation.*;
-import org.apache.juneau.urlencoding.annotation.UrlEncoding;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class BodyAnnotationTest {
-
-	//=================================================================================================================
-	// @Body on parameter
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class, defaultAccept="text/json")
-	public static class A {
-		@RestMethod(name=PUT, path="/String")
-		public String a01(@Body String b) {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/Integer")
-		public Integer a02(@Body Integer b) {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/int")
-		public Integer a03(@Body int b) {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/Boolean")
-		public Boolean a04(@Body Boolean b) {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/boolean")
-		public Boolean a05(@Body boolean b) {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/float")
-		public float a06(@Body float f) {
-			return f;
-		}
-		@RestMethod(name=PUT, path="/Float")
-		public Float a07(@Body Float f) {
-			return f;
-		}
-		@RestMethod(name=PUT, path="/Map")
-		public TreeMap<String,Integer> a08(@Body TreeMap<String,Integer> m) {
-			return m;
-		}
-		@RestMethod(name=PUT, path="/enum")
-		public TestEnum a09(@Body TestEnum e) {
-			return e;
-		}
-		public static class A11 {
-			public String f1;
-		}
-		@RestMethod(name=PUT, path="/Bean")
-		public A11 a11(@Body A11 b) {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/InputStream")
-		public String a12(@Body InputStream b) throws Exception {
-			return IOUtils.read(b);
-		}
-		@RestMethod(name=PUT, path="/Reader")
-		public String a13(@Body Reader b) throws Exception {
-			return IOUtils.read(b);
-		}
-		@RestMethod(name=PUT, path="/InputStreamTransform")
-		public A14 a14(@Body A14 b) throws Exception {
-			return b;
-		}
-		public static class A14 {
-			String s;
-			public A14(InputStream in) throws Exception { this.s = IOUtils.read(in); }
-			@Override public String toString() { return s; }
-		}
-		@RestMethod(name=PUT, path="/ReaderTransform")
-		public A15 a15(@Body A15 b) throws Exception {
-			return b;
-		}
-		public static class A15 {
-			private String s;
-			public A15(Reader in) throws Exception { this.s = IOUtils.read(in); }
-			@Override public String toString() { return s; }
-		}
-		@RestMethod(name=PUT, path="/StringTransform")
-		public A16 a16(@Body A16 b) throws Exception { return b; }
-		public static class A16 {
-			private String s;
-			public A16(String s) throws Exception { this.s = s; }
-			@Override public String toString() { return s; }
-		}
-	}
-	private static MockRestClient a = MockRestClient.buildLax(A.class);
-
-	@Test
-	public void a01a_onParameter_String() throws Exception {
-		a.put("/String", "foo")
-			.json()
-			.run()
-			.assertBody().is("'foo'");
-	}
-	@Test
-	public void a01b_onParameter_String_noContentType() throws Exception {
-		// If no Content-Type specified, should be treated as plain-text.
-		a.put("/String", "'foo'")
-			.run()
-			.assertBody().is("'\\'foo\\''");
-	}
-	@Test
-	public void a01c_onParameter_String_noContentType_other() throws Exception {
-		// If Content-Type not matched, should be treated as plain-text.
-		a.put("/String", "'foo'").contentType("")
-			.run()
-			.assertBody().is("'\\'foo\\''");
-		a.put("/String", "'foo'").contentType("text/plain")
-			.run()
-			.assertBody().is("'\\'foo\\''");
-	}
-	@Test
-	public void a02a_onParameter_Integer() throws Exception {
-		a.put("/Integer", "123").json()
-			.run()
-			.assertBody().is("123");
-	}
-	@Test
-	public void a02b_onParameter_Integer_noContentType() throws Exception {
-		// Integer takes in a String arg, so it can be parsed without Content-Type.
-		a.put("/Integer", "123")
-			.run()
-			.assertBody().is("123");
-	}
-	@Test
-	public void a03a_onParameter_int() throws Exception {
-		a.put("/int", "123").json()
-			.run()
-			.assertBody().is("123");
-	}
-	@Test
-	public void a03b_onParameter_int_noContentType() throws Exception {
-		a.put("/int", "123")
-			.run()
-			.assertBody().is("123"); // Uses part parser.
-	}
-	@Test
-	public void a04a_onParameter_Boolean() throws Exception {
-		a.put("/Boolean", "true").json()
-			.run()
-			.assertBody().is("true");
-	}
-	@Test
-	public void a04b_onParameter_Boolean_noContentType() throws Exception {
-		// Boolean takes in a String arg, so it can be parsed without Content-Type.
-		a.put("/Boolean", "true")
-			.run()
-			.assertBody().is("true");
-	}
-	@Test
-	public void a05a_onParameter_boolean() throws Exception {
-		a.put("/boolean", "true").json()
-			.run()
-			.assertBody().is("true");
-	}
-	@Test
-	public void a05b_onParameter_boolean_noContentType() throws Exception {
-		a.put("/boolean", "true")
-			.run()
-			.assertBody().is("true"); // Uses part parser.
-	}
-	@Test
-	public void a06a_onParameter_float() throws Exception {
-		a.put("/float", "1.23").json()
-			.run()
-			.assertBody().is("1.23");
-	}
-	@Test
-	public void a06b_onParameter_float_noContentType() throws Exception {
-		a.put("/float", "1.23")
-			.run()
-			.assertBody().is("1.23");  // Uses part parser.
-	}
-	@Test
-	public void a07a_onParameter_Float() throws Exception {
-		a.put("/Float", "1.23").json()
-			.run()
-			.assertBody().is("1.23");
-	}
-	@Test
-	public void a07b_onParameter_Float_noContentType() throws Exception {
-		// Float takes in a String arg, so it can be parsed without Content-Type.
-		a.put("/Float", "1.23")
-			.run()
-			.assertBody().is("1.23");
-	}
-	@Test
-	public void a08a_onParameter_Map() throws Exception {
-		a.put("/Map", "{foo:123}", "application/json")
-			.run()
-			.assertBody().is("{foo:123}");
-	}
-	@Test
-	public void a08b_onParameter_Map_noContentType() throws Exception {
-		a.put("/Map", "(foo=123)", "text/openapi")
-			.run()
-			.assertCode().is(415);
-	}
-	@Test
-	public void a09a_onParameter_enum() throws Exception {
-		a.put("/enum", "'ONE'", "application/json")
-			.run()
-			.assertBody().is("'ONE'");
-	}
-	@Test
-	public void a09b_onParameter_enum_noContentType() throws Exception {
-		a.put("/enum", "ONE")
-			.run()
-			.assertBody().is("'ONE'");
-	}
-	@Test
-	public void a11a_onParameter_Bean() throws Exception {
-		a.put("/Bean", "{f1:'a'}", "application/json")
-			.run()
-			.assertBody().is("{f1:'a'}");
-	}
-	@Test
-	public void a11b_onParameter_Bean_noContentType() throws Exception {
-		a.put("/Bean", "(f1=a)", "text/openapi")
-			.run()
-			.assertCode().is(415);
-	}
-	@Test
-	public void a12a_onParameter_InputStream() throws Exception {
-		// Content-Type should always be ignored.
-		a.put("/InputStream", "'a'", "application/json")
-			.run()
-			.assertBody().is("'\\'a\\''");
-	}
-	@Test
-	public void a12b_onParameter_InputStream_noContentType() throws Exception {
-		a.put("/InputStream", "'a'")
-			.run()
-			.assertBody().is("'\\'a\\''");
-	}
-	@Test
-	public void a13a_onParameter_Reader() throws Exception {
-		// Content-Type should always be ignored.
-		a.put("/Reader", "'a'", "application/json")
-			.run()
-			.assertBody().is("'\\'a\\''");
-	}
-	@Test
-	public void a13b_onParameter_Reader_noContentType() throws Exception {
-		a.put("/Reader", "'a'")
-			.run()
-			.assertBody().is("'\\'a\\''");
-	}
-	@Test
-	public void a14a_onParameter_InputStreamTransform() throws Exception {
-		// Input stream transform requests must not specify Content-Type or else gets resolved as POJO.
-		a.put("/InputStreamTransform?noTrace=true", "'a'", "application/json")
-			.run()
-			.assertBody().contains("Bad Request");
-	}
-	@Test
-	public void a14b_onParameter_InputStreamTransform_noContentType() throws Exception {
-		a.put("/InputStreamTransform", "'a'")
-			.run()
-			.assertBody().is("'\\'a\\''");
-	}
-	@Test
-	public void a15a_onParameter_ReaderTransform() throws Exception {
-		// Reader transform requests must not specify Content-Type or else gets resolved as POJO.
-		a.put("/ReaderTransform?noTrace=true", "'a'", "application/json")
-			.run()
-			.assertBody().contains("Bad Request");
-	}
-	@Test
-	public void a15b_onParameter_ReaderTransform_noContentType() throws Exception {
-		a.put("/ReaderTransform", "'a'")
-			.run()
-			.assertBody().is("'\\'a\\''");
-	}
-	@Test
-	public void a16a_onParameter_StringTransform() throws Exception {
-		// When Content-Type specified and matched, treated as a parsed POJO.
-		a.put("/StringTransform", "'a'", "application/json")
-			.run()
-			.assertBody().is("'a'");
-	}
-	@Test
-	public void a16b_onParameter_StringTransform_noContentType() throws Exception {
-		// When Content-Type not matched, treated as plain text.
-		a.put("/StringTransform", "'a'")
-			.run()
-			.assertBody().is("'\\'a\\''");
-	}
-
-	//=================================================================================================================
-	// @Body on POJO
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class, defaultAccept="application/json")
-	public static class B {
-		@RestMethod(name=PUT, path="/StringTransform")
-		public B01 b01(B01 b) {
-			return b;
-		}
-		@Body
-		public static class B01 {
-			private String val;
-			public B01(String val) { this.val = val; }
-			@Override public String toString() { return val; }
-		}
-		@RestMethod(name=PUT, path="/Bean")
-		public B02 b02(B02 b) {
-			return b;
-		}
-		@Body
-		public static class B02 {
-			public String f1;
-		}
-		@RestMethod(name=PUT, path="/BeanList")
-		public B03 b03(B03 b) {
-			return b;
-		}
-		@SuppressWarnings("serial")
-		@Body
-		public static class B03 extends LinkedList<B02> {}
-		@RestMethod(name=PUT, path="/InputStreamTransform")
-		public B04 b04(B04 b) throws Exception {
-			return b;
-		}
-		@Body
-		public static class B04 {
-			String s;
-			public B04(InputStream in) throws Exception { this.s = IOUtils.read(in); }
-			@Override public String toString() { return s; }
-		}
-		@RestMethod(name=PUT, path="/ReaderTransform")
-		public B05 b05(B05 b) throws Exception {
-			return b;
-		}
-		@Body
-		public static class B05 {
-			private String s;
-			public B05(Reader in) throws Exception { this.s = IOUtils.read(in); }
-			@Override public String toString() { return s; }
-		}
-	}
-	private static MockRestClient b = MockRestClient.buildLax(B.class);
-
-	@Test
-	public void b01a_onPojo_StringTransform() throws Exception {
-		b.put("/StringTransform", "'foo'", "application/json")
-			.run()
-			.assertBody().is("'foo'");
-	}
-	@Test
-	public void b01b_onPojo_StringTransform_noContentType() throws Exception {
-		// When Content-Type not matched, treated as plain text.
-		b.put("/StringTransform", "'foo'")
-			.run()
-			.assertBody().is("'\\'foo\\''");
-	}
-	@Test
-	public void b02a_onPojo_Bean() throws Exception {
-		b.put("/Bean", "{f1:'a'}", "application/json")
-			.run()
-			.assertBody().is("{f1:'a'}");
-	}
-	@Test
-	public void b02b_onPojo_Bean_noContentType() throws Exception {
-		b.put("/Bean", "(f1=a)", "text/openapi")
-			.run()
-			.assertCode().is(415);
-	}
-	@Test
-	public void b03a_onPojo_BeanList() throws Exception {
-		b.put("/BeanList", "[{f1:'a'}]", "application/json")
-			.run()
-			.assertBody().is("[{f1:'a'}]");
-	}
-	@Test
-	public void b03b_onPojo_BeanList_noContentType() throws Exception {
-		b.put("/BeanList", "(f1=a)", "text/openapi")
-			.run()
-			.assertCode().is(415);
-	}
-	@Test
-	public void b04a_onPojo_InputStreamTransform() throws Exception {
-		b.put("/InputStreamTransform", "a")
-			.run()
-			.assertBody().is("'a'");
-	}
-	@Test
-	public void b04b_onPojo_InputStreamTransform_withContentType() throws Exception {
-		// When Content-Type matched, treated as parsed POJO.
-		b.put("/InputStreamTransform?noTrace=true", "a", "application/json")
-			.run()
-			.assertBody().contains("Bad Request");
-	}
-	@Test
-	public void b05a_onPojo_ReaderTransform() throws Exception {
-		b.put("/ReaderTransform", "a")
-			.run()
-			.assertBody().is("'a'");
-	}
-	@Test
-	public void b05b_onPojo_ReaderTransform_withContentType() throws Exception {
-		// When Content-Type matched, treated as parsed POJO.
-		b.put("/ReaderTransform?noTrace=true", "a", "application/json")
-			.run()
-			.assertBody().contains("Bad Request");
-	}
-
-	//=================================================================================================================
-	// Basic tests using @Body parameter
-	//=================================================================================================================
-
-	public void c01_bodyParam_String() throws Exception {
-		a.put("/String?body=foo", null)
-			.run()
-			.assertBody().is("'foo'");
-		a.put("/String?body=null", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/String?body=", null)
-			.run()
-			.assertBody().is("''");
-	}
-	@Test
-	public void c02_bodyParam_Integer() throws Exception {
-		a.put("/Integer?body=123", null)
-			.run()
-			.assertBody().is("123");
-		a.put("/Integer?body=-123", null)
-			.run()
-			.assertBody().is("-123");
-		a.put("/Integer?body=null", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Integer?body=", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Integer?body=bad&noTrace=true", null)
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c03_bodyParam_int() throws Exception {
-		a.put("/int?body=123", null)
-			.run()
-			.assertBody().is("123");
-		a.put("/int?body=-123", null)
-			.run()
-			.assertBody().is("-123");
-		a.put("/int?body=null", null)
-			.run()
-			.assertBody().is("0");
-		a.put("/int?body=", null)
-			.run()
-			.assertBody().is("0");
-		a.put("/int?body=bad&noTrace=true", null)
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c04_bodyParam_Boolean() throws Exception {
-		a.put("/Boolean?body=true", null)
-			.run()
-			.assertBody().is("true");
-		a.put("/Boolean?body=false", null)
-			.run()
-			.assertBody().is("false");
-		a.put("/Boolean?body=null", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Boolean?body=", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Boolean?body=bad&noTrace=true", null)
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c05_bodyParam_boolean() throws Exception {
-		a.put("/boolean?body=true", null)
-			.run()
-			.assertBody().is("true");
-		a.put("/boolean?body=false", null)
-			.run()
-			.assertBody().is("false");
-		a.put("/boolean?body=null", null)
-			.run()
-			.assertBody().is("false");
-		a.put("/boolean?body=", null)
-			.run()
-			.assertBody().is("false");
-		a.put("/boolean?body=bad&noTrace=true", null)
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c06_bodyParam_Float() throws Exception {
-		a.put("/Float?body=1.23", null)
-			.run()
-			.assertBody().is("1.23");
-		a.put("/Float?body=-1.23", null)
-			.run()
-			.assertBody().is("-1.23");
-		a.put("/Float?body=null", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Float?body=", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Float?body=bad&noTrace=true", null)
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c07_bodyParam_float() throws Exception {
-		a.put("/float?body=1.23", null)
-			.run()
-			.assertBody().is("1.23");
-		a.put("/float?body=-1.23", null)
-			.run()
-			.assertBody().is("-1.23");
-		a.put("/float?body=null", null)
-			.run()
-			.assertBody().is("0.0");
-		a.put("/float?body=", null)
-			.run()
-			.assertBody().is("0.0");
-		a.put("/float?body=bad&noTrace=true", null)
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c08_bodyParam_Map() throws Exception {
-		a.put("/Map?body=(foo=123)", null)
-			.run()
-			.assertBody().is("{foo:123}");
-		a.put("/Map?body=()", null)
-			.run()
-			.assertBody().is("{}");
-		a.put("/Map?body=null", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Map?body=", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Map?body=bad&noTrace=true", null)
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c09_bodyParam_enum() throws Exception {
-		a.put("/enum?body=ONE", null)
-			.run()
-			.assertBody().is("'ONE'");
-		a.put("/enum?body=TWO", null)
-			.run()
-			.assertBody().is("'TWO'");
-		a.put("/enum?body=null", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/enum?body=", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/enum?body=bad&noTrace=true", null)
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c11_bodyParam_Bean() throws Exception {
-		a.put("/Bean?body=(f1=a)", null)
-			.run()
-			.assertBody().is("{f1:'a'}");
-		a.put("/Bean?body=()", null)
-			.run()
-			.assertBody().is("{}");
-		a.put("/Bean?body=null", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Bean?body=", null)
-			.run()
-			.assertBody().is("null");
-		a.put("/Bean?body=bad&noTrace=true", null)
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c12_bodyParam_InputStream() throws Exception {
-		a.put("/InputStream?body=a", null)
-			.run()
-			.assertBody().is("'a'");
-		a.put("/InputStream?body=null", null)
-			.run()
-			.assertBody().is("'null'");
-		a.put("/InputStream?body=", null)
-			.run()
-			.assertBody().is("''");
-	}
-	@Test
-	public void c13_bodyParam_Reader() throws Exception {
-		a.put("/Reader?body=a", null)
-			.run()
-			.assertBody().is("'a'");
-		a.put("/Reader?body=null", null)
-			.run()
-			.assertBody().is("'null'");
-		a.put("/Reader?body=", null)
-			.run()
-			.assertBody().is("''");
-	}
-
-	// It's not currently possible to pass in a &body parameter for InputStream/Reader transforms.
-
-	//=================================================================================================================
-	// No serializers or parsers needed when using only streams and readers.
-	//=================================================================================================================
-
-	@Rest
-	public static class D {
-		@RestMethod(name=PUT, path="/String")
-		public Reader d01(@Body Reader b) throws Exception {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/InputStream")
-		public InputStream d02(@Body InputStream b) throws Exception {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/Reader")
-		public Reader d03(@Body Reader b) throws Exception {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/StringTransform")
-		public Reader d04(@Body D04 b) throws Exception {
-			return new StringReader(b.toString());
-		}
-		public static class D04 {
-			private String s;
-			public D04(String in) throws Exception { this.s = in; }
-			@Override public String toString() { return s; }
-		}
-		@RestMethod(name=PUT, path="/InputStreamTransform")
-		public Reader d05(@Body D05 b) throws Exception {
-			return new StringReader(b.toString());
-		}
-		public static class D05 {
-			String s;
-			public D05(InputStream in) throws Exception { this.s = IOUtils.read(in); }
-			@Override public String toString() { return s; }
-		}
-		@RestMethod(name=PUT, path="/ReaderTransform")
-		public Reader d06(@Body D06 b) throws Exception {
-			return new StringReader(b.toString());
-		}
-		public static class D06 {
-			private String s;
-			public D06(Reader in) throws Exception{ this.s = IOUtils.read(in); }
-			@Override public String toString() { return s; }
-		}
-		@RestMethod(name=PUT, path="/StringTransformBodyOnPojo")
-		public Reader d07(D07 b) throws Exception {
-			return new StringReader(b.toString());
-		}
-		@Body
-		public static class D07 {
-			private String s;
-			public D07(String in) throws Exception { this.s = in; }
-			@Override public String toString() { return s; }
-		}
-		@RestMethod(name=PUT, path="/InputStreamTransformBodyOnPojo")
-		public Reader d08(D08 b) throws Exception {
-			return new StringReader(b.toString());
-		}
-		@Body
-		public static class D08 {
-			String s;
-			public D08(InputStream in) throws Exception { this.s = IOUtils.read(in); }
-			@Override public String toString() { return s; }
-		}
-
-		@RestMethod(name=PUT, path="/ReaderTransformBodyOnPojo")
-		public Reader d09(D09 b) throws Exception {
-			return new StringReader(b.toString());
-		}
-		@Body
-		public static class D09 {
-			private String s;
-			public D09(Reader in) throws Exception{ this.s = IOUtils.read(in); }
-			@Override public String toString() { return s; }
-		}
-	}
-	private static MockRestClient d = MockRestClient.buildLax(D.class);
-
-	@Test
-	public void d01a_noMediaTypes_String() throws Exception {
-		d.put("/String", "a")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d01b_noMediaTypes_String_withContentType() throws Exception {
-		d.put("/String", "a", "application/json")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d02a_noMediaTypes_InputStream() throws Exception {
-		d.put("/InputStream", "a")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d02b_noMediaTypes_InputStream_withContentType() throws Exception {
-		d.put("/InputStream", "a", "application/json")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d03a_noMediaTypes_Reader() throws Exception {
-		d.put("/Reader", "a")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d03b_noMediaTypes_Reader_withContentType() throws Exception {
-		d.put("/Reader", "a", "application/json")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d04a_noMediaTypes_StringTransform() throws Exception {
-		d.put("/StringTransform", "a")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d04b_noMediaTypes_StringTransform_withContentType() throws Exception {
-		d.put("/StringTransform?noTrace=true", "a", "application/json")
-			.run()
-			.assertCode().is(415);
-	}
-	@Test
-	public void d05a_noMediaTypes_InputStreamTransform() throws Exception {
-		d.put("/InputStreamTransform", "a")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d05b_noMediaTypes_InputStreamTransform_withContentType() throws Exception {
-		d.put("/InputStreamTransform", "a", "application/json")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d06a_noMediaTypes_ReaderTransform() throws Exception {
-		d.put("/ReaderTransform", "a")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d06b_noMediaTypes_ReaderTransform_withContentType() throws Exception {
-		d.put("/ReaderTransform", "a", "application/json")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d07a_noMediaTypes_StringTransformBodyOnPojo() throws Exception {
-		d.put("/StringTransformBodyOnPojo", "a")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d07b_noMediaTypes_StringTransformBodyOnPojo_withContentType() throws Exception {
-		d.put("/StringTransformBodyOnPojo?noTrace=true", "a", "application/json")
-			.run()
-			.assertCode().is(415);
-	}
-	@Test
-	public void d08a_noMediaTypes_InputStreamTransformBodyOnPojo() throws Exception {
-		d.put("/InputStreamTransformBodyOnPojo", "a")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d08b_noMediaTypes_InputStreamTransformBodyOnPojo_withContentType() throws Exception {
-		d.put("/InputStreamTransformBodyOnPojo", "a", "application/json")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d09a_noMediaTypes_ReaderTransformBodyOnPojo() throws Exception {
-		d.put("/ReaderTransformBodyOnPojo", "a")
-			.run()
-			.assertBody().is("a");
-	}
-	@Test
-	public void d09b_noMediaTypes_ReaderTransformBodyOnPojo_withContentType() throws Exception {
-		d.put("/ReaderTransformBodyOnPojo", "a", "application/json")
-			.run()
-			.assertBody().is("a");
-	}
-
-	//=================================================================================================================
-	// Complex POJOs
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class, defaultAccept="application/json")
-	public static class E {
-		@RestMethod(name=PUT, path="/B")
-		public XBeans.XB testPojo1(@Body XBeans.XB b) {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/C")
-		public XBeans.XC testPojo2(@Body XBeans.XC c) {
-			return c;
-		}
-	}
-	private static MockRestClient e = MockRestClient.build(E.class);
-
-	@Test
-	public void e01_complexPojos_B_body() throws Exception {
-		String expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
-		e.put("/B", SimpleJsonSerializer.DEFAULT.toString(XBeans.XB.INSTANCE), "application/json")
-			.run()
-			.assertBody().is(expected);
-	}
-	@Test
-	public void e02_complexPojos_B_bodyParam() throws Exception {
-		String expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
-		e.put("/B?body=" + UonSerializer.DEFAULT.serialize(XBeans.XB.INSTANCE), "a")
-			.run()
-			.assertBody().is(expected);
-	}
-	@Test
-	public void e03_complexPojos_C_body() throws Exception {
-		String expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
-		e.put("/C", SimpleJsonSerializer.DEFAULT.toString(XBeans.XB.INSTANCE), "application/json")
-			.run()
-			.assertBody().is(expected);
-	}
-	@Test
-	public void e04_complexPojos_C_bodyParam() throws Exception {
-		String expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
-		e.put("/C?body=" + UonSerializer.DEFAULT.serialize(XBeans.XB.INSTANCE), "a")
-			.run()
-			.assertBody().is(expected);
-	}
-
-	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class, defaultAccept="application/json")
-	@BeanConfig(applyBean={@Bean(on="A,B,C",sort=true)})
-	@UrlEncodingConfig(applyUrlEncoding={@UrlEncoding(on="C",expandedParams=true)})
-	public static class E2 {
-		@RestMethod(name=PUT, path="/B")
-		public XBeans.XE testPojo1(@Body XBeans.XE b) {
-			return b;
-		}
-		@RestMethod(name=PUT, path="/C")
-		public XBeans.XF testPojo2(@Body XBeans.XF c) {
-			return c;
-		}
-	}
-	private static MockRestClient e2 = MockRestClient.build(E2.class);
-
-	@Test
-	public void e05_complexPojos_B_body() throws Exception {
-		String expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
-		e2.put("/B", SimpleJsonSerializer.DEFAULT.builder().applyAnnotations(XBeans.Annotations.class).build().toString(XBeans.XE.INSTANCE), "application/json")
-			.run()
-			.assertBody().is(expected);
-	}
-	@Test
-	public void e06_complexPojos_B_bodyParam() throws Exception {
-		String expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
-		e2.put("/B?body=" + UonSerializer.DEFAULT.builder().applyAnnotations(XBeans.Annotations.class).build().serialize(XBeans.XE.INSTANCE), "a")
-			.run()
-			.assertBody().is(expected);
-	}
-	@Test
-	public void e07_complexPojos_C_body() throws Exception {
-		String expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
-		e2.put("/C", SimpleJsonSerializer.DEFAULT.builder().applyAnnotations(XBeans.Annotations.class).build().toString(XBeans.XE.INSTANCE), "application/json")
-			.run()
-			.assertBody().is(expected);
-	}
-	@Test
-	public void e08_complexPojos_C_bodyParam() throws Exception {
-		String expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
-		e2.put("/C?body=" + UonSerializer.DEFAULT.builder().applyAnnotations(XBeans.Annotations.class).build().serialize(XBeans.XE.INSTANCE), "a")
-			.run()
-			.assertBody().is(expected);
-	}
-
-	//=================================================================================================================
-	// Form POSTS with @Body parameter
-	//=================================================================================================================
-
-	@Rest(serializers=JsonSerializer.class,parsers=JsonParser.class)
-	public static class F {
-		@RestMethod(name=POST, path="/*")
-		public Reader formPostAsContent(
-				@Body F01 bean,
-				@HasQuery("p1") boolean hqp1, @HasQuery("p2") boolean hqp2,
-				@Query("p1") String qp1, @Query("p2") int qp2) throws Exception {
-			return new StringReader("bean=["+SimpleJsonSerializer.DEFAULT.toString(bean)+"],qp1=["+qp1+"],qp2=["+qp2+"],hqp1=["+hqp1+"],hqp2=["+hqp2+"]");
-		}
-		public static class F01 {
-			public String p1;
-			public int p2;
-		}
-	}
-	static MockRestClient f = MockRestClient.build(F.class);
-
-	@Test
-	public void f01_formPostAsContent() throws Exception {
-		f.post("/", "{p1:'p1',p2:2}", "application/json")
-			.run()
-			.assertBody().is("bean=[{p1:'p1',p2:2}],qp1=[null],qp2=[0],hqp1=[false],hqp2=[false]");
-		f.post("/", "{}", "application/json")
-			.run()
-			.assertBody().is("bean=[{p2:0}],qp1=[null],qp2=[0],hqp1=[false],hqp2=[false]");
-		f.post("?p1=p3&p2=4", "{p1:'p1',p2:2}", "application/json")
-			.run()
-			.assertBody().is("bean=[{p1:'p1',p2:2}],qp1=[p3],qp2=[4],hqp1=[true],hqp2=[true]");
-		f.post("?p1=p3&p2=4", "{}", "application/json")
-			.run()
-			.assertBody().is("bean=[{p2:0}],qp1=[p3],qp2=[4],hqp1=[true],hqp2=[true]");
-	}
-
-	//=================================================================================================================
-	// Test multi-part parameter keys on bean properties of type array/Collection (i.e. &key=val1,&key=val2)
-	// using @UrlEncoding(expandedParams=true) annotation on bean.
-	// A simple round-trip test to verify that both serializing and parsing works.
-	//=================================================================================================================
-
-	@Rest(serializers=UrlEncodingSerializer.class,parsers=UrlEncodingParser.class)
-	public static class G {
-		@RestMethod(name=POST,path="/")
-		public XBeans.XC g(@Body XBeans.XC content) throws Exception {
-			return content;
-		}
-	}
-	static MockRestClient g = MockRestClient.build(G.class);
-
-	@Test
-	public void g01() throws Exception {
-		String in = ""
-			+ "f01=a&f01=b"
-			+ "&f02=c&f02=d"
-			+ "&f03=1&f03=2"
-			+ "&f04=3&f04=4"
-			+ "&f05=@(e,f)&f05=@(g,h)"
-			+ "&f06=@(i,j)&f06=@(k,l)"
-			+ "&f07=(a=a,b=1,c=true)&f07=(a=b,b=2,c=false)"
-			+ "&f08=(a=a,b=1,c=true)&f08=(a=b,b=2,c=false)"
-			+ "&f09=@((a=a,b=1,c=true))&f09=@((a=b,b=2,c=false))"
-			+ "&f10=@((a=a,b=1,c=true))&f10=@((a=b,b=2,c=false))"
-			+ "&f11=a&f11=b"
-			+ "&f12=c&f12=d"
-			+ "&f13=1&f13=2"
-			+ "&f14=3&f14=4"
-			+ "&f15=@(e,f)&f15=@(g,h)"
-			+ "&f16=@(i,j)&f16=@(k,l)"
-			+ "&f17=(a=a,b=1,c=true)&f17=(a=b,b=2,c=false)"
-			+ "&f18=(a=a,b=1,c=true)&f18=(a=b,b=2,c=false)"
-			+ "&f19=@((a=a,b=1,c=true))&f19=@((a=b,b=2,c=false))"
-			+ "&f20=@((a=a,b=1,c=true))&f20=@((a=b,b=2,c=false))";
-		g.post("/", in, "application/x-www-form-urlencoded")
-			.run()
-			.assertBody().is(in);
-	}
-
-	//=================================================================================================================
-	// Test multi-part parameter keys on bean properties of type array/Collection (i.e. &key=val1,&key=val2)
-	// using URLENC_expandedParams property.
-	// A simple round-trip test to verify that both serializing and parsing works.
-	//=================================================================================================================
-
-	@Rest(serializers=UrlEncodingSerializer.class,parsers=UrlEncodingParser.class)
-	public static class H {
-		@RestMethod(name=POST,path="/",
-			properties={
-				@Property(name=UrlEncodingSerializer.URLENC_expandedParams, value="true"),
-				@Property(name=UrlEncodingParser.URLENC_expandedParams, value="true")
-			}
-		)
-		public XBeans.XB g(@Body XBeans.XB content) throws Exception {
-			return content;
-		}
-	}
-	static MockRestClient h = MockRestClient.build(H.class);
-
-	@Test
-	public void h01() throws Exception {
-		String in = ""
-			+ "f01=a&f01=b"
-			+ "&f02=c&f02=d"
-			+ "&f03=1&f03=2"
-			+ "&f04=3&f04=4"
-			+ "&f05=@(e,f)&f05=@(g,h)"
-			+ "&f06=@(i,j)&f06=@(k,l)"
-			+ "&f07=(a=a,b=1,c=true)&f07=(a=b,b=2,c=false)"
-			+ "&f08=(a=a,b=1,c=true)&f08=(a=b,b=2,c=false)"
-			+ "&f09=@((a=a,b=1,c=true))&f09=@((a=b,b=2,c=false))"
-			+ "&f10=@((a=a,b=1,c=true))&f10=@((a=b,b=2,c=false))"
-			+ "&f11=a&f11=b"
-			+ "&f12=c&f12=d"
-			+ "&f13=1&f13=2"
-			+ "&f14=3&f14=4"
-			+ "&f15=@(e,f)&f15=@(g,h)"
-			+ "&f16=@(i,j)&f16=@(k,l)"
-			+ "&f17=(a=a,b=1,c=true)&f17=(a=b,b=2,c=false)"
-			+ "&f18=(a=a,b=1,c=true)&f18=(a=b,b=2,c=false)"
-			+ "&f19=@((a=a,b=1,c=true))&f19=@((a=b,b=2,c=false))"
-			+ "&f20=@((a=a,b=1,c=true))&f20=@((a=b,b=2,c=false))";
-		h.post("/", in, "application/x-www-form-urlencoded")
-			.run()
-			.assertBody().is(in);
-	}
-
-	@Rest(serializers=UrlEncodingSerializer.class,parsers=UrlEncodingParser.class)
-	@BeanConfig(applyBean={@Bean(on="A,B,C",sort=true)})
-	@UrlEncodingConfig(applyUrlEncoding={@UrlEncoding(on="C",expandedParams=true)})
-	public static class H2 {
-		@RestMethod(name=POST,path="/",
-			properties={
-				@Property(name=UrlEncodingSerializer.URLENC_expandedParams, value="true"),
-				@Property(name=UrlEncodingParser.URLENC_expandedParams, value="true")
-			}
-		)
-		public XBeans.XE g(@Body XBeans.XE content) throws Exception {
-			return content;
-		}
-	}
-	static MockRestClient h2 = MockRestClient.build(H2.class);
-
-	@Test
-	public void h02() throws Exception {
-		String in = ""
-			+ "f01=a&f01=b"
-			+ "&f02=c&f02=d"
-			+ "&f03=1&f03=2"
-			+ "&f04=3&f04=4"
-			+ "&f05=@(e,f)&f05=@(g,h)"
-			+ "&f06=@(i,j)&f06=@(k,l)"
-			+ "&f07=(a=a,b=1,c=true)&f07=(a=b,b=2,c=false)"
-			+ "&f08=(a=a,b=1,c=true)&f08=(a=b,b=2,c=false)"
-			+ "&f09=@((a=a,b=1,c=true))&f09=@((a=b,b=2,c=false))"
-			+ "&f10=@((a=a,b=1,c=true))&f10=@((a=b,b=2,c=false))"
-			+ "&f11=a&f11=b"
-			+ "&f12=c&f12=d"
-			+ "&f13=1&f13=2"
-			+ "&f14=3&f14=4"
-			+ "&f15=@(e,f)&f15=@(g,h)"
-			+ "&f16=@(i,j)&f16=@(k,l)"
-			+ "&f17=(a=a,b=1,c=true)&f17=(a=b,b=2,c=false)"
-			+ "&f18=(a=a,b=1,c=true)&f18=(a=b,b=2,c=false)"
-			+ "&f19=@((a=a,b=1,c=true))&f19=@((a=b,b=2,c=false))"
-			+ "&f20=@((a=a,b=1,c=true))&f20=@((a=b,b=2,c=false))";
-		h2.post("/", in, "application/x-www-form-urlencoded")
-			.run()
-			.assertBody().is(in);
-	}
-
-	//=================================================================================================================
-	// Test behavior of @Body(required=true).
-	//=================================================================================================================
-
-	@Rest(serializers=JsonSerializer.class,parsers=JsonParser.class)
-	public static class I {
-		@RestMethod(name=POST,path="/")
-		public XBeans.XB g(@Body(r=true) XBeans.XB content) throws Exception {
-			return content;
-		}
-	}
-	static MockRestClient i = MockRestClient.buildLax(I.class);
-
-	@Test
-	public void i01() throws Exception {
-		i.post("/", "", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains("Required value not provided.");
-		i.post("/", "{}", "application/json")
-			.run()
-			.assertCode().is(200);
-	}
-
-	@Rest(serializers=JsonSerializer.class,parsers=JsonParser.class)
-	public static class I2 {
-		@RestMethod(name=POST,path="/")
-		@BeanConfig(applyBean={@Bean(on="A,B,C",sort=true)})
-		@UrlEncodingConfig(applyUrlEncoding={@UrlEncoding(on="C",expandedParams=true)})
-		public XBeans.XE g(@Body(r=true) XBeans.XE content) throws Exception {
-			return content;
-		}
-	}
-	static MockRestClient i2 = MockRestClient.buildLax(I2.class);
-
-	@Test
-	public void i02() throws Exception {
-		i2.post("/", "", "application/json")
-			.run()
-			.assertCode().is(400)
-			.assertBody().contains("Required value not provided.");
-		i2.post("/", "{}", "application/json")
-			.run()
-			.assertCode().is(200);
-	}
-
-	//=================================================================================================================
-	// Optional body parameter.
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class,parsers=JsonParser.class)
-	public static class J {
-		@RestMethod(name=POST,path="/a")
-		public Object a(@Body Optional<Integer> body) throws Exception {
-			assertNotNull(body);
-			return body;
-		}
-		@RestMethod(name=POST,path="/b")
-		public Object b(@Body Optional<ABean> body) throws Exception {
-			assertNotNull(body);
-			return body;
-		}
-		@RestMethod(name=POST,path="/c")
-		public Object c(@Body Optional<List<ABean>> body) throws Exception {
-			assertNotNull(body);
-			return body;
-		}
-		@RestMethod(name=POST,path="/d")
-		public Object d(@Body List<Optional<ABean>> body) throws Exception {
-			return body;
-		}
-	}
-	static MockRestClient j = MockRestClient.buildJson(J.class);
-
-	@Test
-	public void j01_optionalParam_integer() throws Exception {
-		j.post("/a", 123)
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("123");
-		j.post("/a", null)
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void j02_optionalParam_bean() throws Exception {
-		j.post("/b", ABean.get())
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("{a:1,b:'foo'}");
-		j.post("/b", null)
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void j03_optionalParam_listOfBeans() throws Exception {
-		String body = SimpleJson.DEFAULT.toString(AList.of(ABean.get()));
-		j.post("/c", body, "application/json")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-		j.post("/c", null)
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void j04_optionalParam_listOfOptionals() throws Exception {
-		String body = SimpleJson.DEFAULT.toString(AList.of(Optional.of(ABean.get())));
-		j.post("/d", body, "application/json")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-		j.post("/d", null)
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	//=================================================================================================================
-	// Swagger - @Body on POJO
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SA {
-
-		@Body(
-			d={"a","b"},
-			r=true,
-			schema=@Schema(type="string"),
-			ex=" 'a' ",
-			exs="{foo:'bar'}"
-		)
-		public static class SA01 {
-			public SA01(String x) {}
-		}
-		@RestMethod
-		public void sa01(SA01 h) {}
-
-		@Body({
-			"description:'a\nb',",
-			"required:true,",
-			"schema:{type:'string'},",
-			"x-example:'\\'a\\'',",
-			"x-examples:{foo:'bar'}"
-		})
-		public static class SA02 {
-			public SA02(String x) {}
-		}
-		@RestMethod
-		public void sa02(SA02 h) {}
-
-		@Body(
-			value={
-				"description:'a\nb',",
-				"required:true,",
-				"schema:{type:'string'},",
-				"x-example:'\\'a\\'',",
-				"x-examples:{foo:'bar'}"
-			},
-			d={"b","c"},
-			schema=@Schema(type="string"),
-			ex="'b'",
-			exs="{foo:'baz'}"
-		)
-		public static class SA03 {
-			public SA03(String x) {}
-		}
-		@RestMethod
-		public void sa03(SA03 h) {}
-	}
-
-	static Swagger sa = getSwagger(SA.class);
-
-	@Test
-	public void sa01_Body_onPojo_basic() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa01","get","body",null);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getRequired()).json().is("true");
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertEquals("'a'", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'bar'}");
-	}
-	@Test
-	public void sa02_Body_onPojo_api() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa02","get","body",null);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getRequired()).json().is("true");
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertEquals("'a'", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'bar'}");
-	}
-	@Test
-	public void sa03_Body_onPojo_mixed() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa03","get","body",null);
-		assertEquals("b\nc", x.getDescription());
-		assertObject(x.getRequired()).json().is("true");
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertEquals("'b'", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'baz'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SB {
-
-		@Body(schema=@Schema(" type:'b' "))
-		public static class SB01 {}
-		@RestMethod
-		public void sb01(SB01 h) {}
-
-		@Body
-		public static class SB02 {
-			public String f1;
-		}
-		@RestMethod
-		public void sb02(SB02 b) {}
-
-		@Body
-		public static class SB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod
-		public void sb03(SB03 b) {}
-
-		@Body
-		public static class SB04 {}
-		@RestMethod
-		public void sb04(SB04 b) {}
-	}
-
-	static Swagger sb = getSwagger(SB.class);
-
-	@Test
-	public void sb01_Body_onPojo_schemaValue() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb01","get","body",null);
-		assertObject(x.getSchema()).json().is("{type:'b'}");
-	}
-	@Test
-	public void sb02_Body_onPojo_autoDetectBean() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb02","get","body",null);
-		assertObject(x.getSchema()).json().is("{type:'object',properties:{f1:{type:'string'}}}");
-	}
-	@Test
-	public void sb03_Body_onPojo_autoDetectList() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb03","get","body",null);
-		assertObject(x.getSchema()).json().is("{type:'array',items:{type:'string'}}");
-	}
-	@Test
-	public void sb04_Body_onPojo_autoDetectStringObject() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb04","get","body",null);
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SC {
-
-		@Body(ex=" {f1:'b'} ")
-		public static class SC01 {
-			public String f1;
-		}
-		@RestMethod
-		public void sc01(SC01 h) {}
-
-		@Body(exs={" foo:'bar' "})
-		public static class SC02 {}
-		@RestMethod
-		public void sc02(SC02 h) {}
-	}
-
-	static Swagger sc = getSwagger(SC.class);
-
-	@Test
-	public void sc01_Body_onPojo_example() throws Exception {
-		ParameterInfo x = sc.getParameterInfo("/sc01","get","body",null);
-		assertEquals("{f1:'b'}", x.getExample());
-	}
-	@Test
-	public void sc02_Body_onPojo_examples() throws Exception {
-		ParameterInfo x = sc.getParameterInfo("/sc02","get","body",null);
-		assertObject(x.getExamples()).json().is("{foo:'bar'}");
-	}
-
-	//=================================================================================================================
-	// @Body on parameter
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TA {
-
-		public static class TA01 {
-			public TA01(String x) {}
-		}
-
-		@RestMethod
-		public void ta01(
-			@Body(
-				d= {"a","b"},
-				r=true,
-				schema=@Schema(type="string"),
-				ex="a",
-				exs=" {foo:'bar'} "
-			) TA01 b) {}
-
-		public static class TA02 {
-			public TA02(String x) {}
-		}
-
-		@RestMethod
-		public void ta02(
-			@Body({
-				"description:'a\nb',",
-				"required:true,",
-				"schema:{type:'string'},",
-				"x-example:'a',",
-				"x-examples:{foo:'bar'}"
-			}) TA02 b) {}
-
-		public static class TA03 {
-			public TA03(String x) {}
-		}
-
-		@RestMethod
-		public void ta03(
-			@Body(
-				value= {
-					"description:'a\nb',",
-					"required:true,",
-					"schema:{type:'string'},",
-					"x-example:'a',",
-					"x-examples:{foo:'bar'}"
-				},
-				d= {"b","c"},
-				schema=@Schema(type="string"),
-				ex="b",
-				exs=" {foo:'baz'} "
-			) TA03 b) {}
-	}
-
-	static Swagger ta = getSwagger(TA.class);
-
-	@Test
-	public void ta01_Body_onParameter_basic() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta01","get","body",null);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getRequired()).json().is("true");
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertEquals("a", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'bar'}");
-	}
-	@Test
-	public void ta02_Body_onParameter_api() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta02","get","body",null);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getRequired()).json().is("true");
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertEquals("a", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'bar'}");
-	}
-	@Test
-	public void ta03_Body_onParameter_mixed() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta03","get","body",null);
-		assertEquals("b\nc", x.getDescription());
-		assertObject(x.getRequired()).json().is("true");
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertEquals("b", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'baz'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TB {
-
-		public static class TB01 {}
-		@RestMethod
-		public void tb01(@Body(schema=@Schema(" { type:'b' } ")) TB01 b) {}
-
-		public static class TB02 {
-			public String f1;
-		}
-		@RestMethod
-		public void tb02(@Body TB02 b) {}
-
-		public static class TB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod
-		public void tb03(@Body TB03 b) {}
-
-		public static class TB04 {}
-		@RestMethod
-		public void tb04(@Body TB04 b) {}
-
-		@RestMethod
-		public void tb05(@Body Integer b) {}
-
-		@RestMethod
-		public void tb06(@Body Boolean b) {}
-	}
-
-	static Swagger tb = getSwagger(TB.class);
-
-	@Test
-	public void tb01_Body_onParameter_schemaValue() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb01","get","body",null);
-		assertObject(x.getSchema()).json().is("{type:'b'}");
-	}
-	@Test
-	public void tb02_Body_onParameter_autoDetectBean() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb02","get","body",null);
-		assertObject(x.getSchema()).json().is("{type:'object',properties:{f1:{type:'string'}}}");
-	}
-	@Test
-	public void tb03_Body_onParameter_autoDetectList() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb03","get","body",null);
-		assertObject(x.getSchema()).json().is("{type:'array',items:{type:'string'}}");
-	}
-	@Test
-	public void tb04_Body_onParameter_autoDetectStringObject() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb04","get","body",null);
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-	}
-	@Test
-	public void tb05_Body_onParameter_autoDetectInteger() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb05","get","body",null);
-		assertObject(x.getSchema()).json().is("{format:'int32',type:'integer'}");
-	}
-	@Test
-	public void tb06_Body_onParameter_autoDetectBoolean() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb06","get","body",null);
-		assertObject(x.getSchema()).json().is("{type:'boolean'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TC {
-
-		public static class TC01 {
-			public String f1;
-		}
-		@RestMethod
-		public void tc01(@Body(ex="{f1:'b'}") TC01 b) {}
-
-		public static class TC02 {}
-		@RestMethod
-		public void tc02(@Body(exs={" foo:'bar' "}) TC02 b) {}
-	}
-
-	static Swagger tc = getSwagger(TC.class);
-
-	@Test
-	public void tc01_Body_onParameter_example() throws Exception {
-		ParameterInfo x = tc.getParameterInfo("/tc01","get","body",null);
-		assertEquals("{f1:'b'}", x.getExample());
-	}
-	@Test
-	public void tc02_Body_onParameter_examples() throws Exception {
-		ParameterInfo x = tc.getParameterInfo("/tc02","get","body",null);
-		assertObject(x.getExamples()).json().is("{foo:'bar'}");
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/FormDataAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/FormDataAnnotationTest.java
deleted file mode 100644
index f367410..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/FormDataAnnotationTest.java
+++ /dev/null
@@ -1,556 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation2;
-
-import static org.apache.juneau.assertions.Assertions.*;
-import static org.apache.juneau.http.HttpMethod.*;
-import static org.apache.juneau.rest.testutils.TestUtils.*;
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.util.*;
-
-import org.apache.juneau.collections.*;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.apache.juneau.testutils.pojos.*;
-import org.apache.juneau.urlencoding.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class FormDataAnnotationTest {
-
-	//=================================================================================================================
-	// Simple tests
-	//=================================================================================================================
-
-	@Rest(parsers=UrlEncodingParser.class)
-	public static class A {
-		@RestMethod
-		public String post(RestRequest req, @FormData(name="p1",allowEmptyValue=true) String p1, @FormData(name="p2",allowEmptyValue=true) int p2) throws Exception {
-			RequestFormData f = req.getFormData();
-			return "p1=["+p1+","+req.getFormData().getString("p1")+","+f.get("p1", String.class)+"],p2=["+p2+","+req.getFormData().getString("p2")+","+f.get("p2", int.class)+"]";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01() throws Exception {
-		a.post("", "p1=p1&p2=2").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[p1,p1,p1],p2=[2,2,2]");
-		a.post("", "p1&p2").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.post("", "p1=&p2=").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[,,],p2=[0,,0]");
-		a.post("", "").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.post("", "p1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.post("", "p1=").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[,,],p2=[0,null,0]");
-		a.post("", "p2").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.post("", "p2=").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[0,,0]");
-		a.post("", "p1=foo&p2").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[foo,foo,foo],p2=[0,null,0]");
-		a.post("", "p1&p2=1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[null,null,null],p2=[1,1,1]");
-		String x = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
-		a.post("", "p1="+x+"&p2=1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[a/b%c=d e,a/b%c=d e,a/b%c=d e],p2=[1,1,1]");
-	}
-
-	//=================================================================================================================
-	// UON parameters
-	//=================================================================================================================
-
-	@Rest
-	public static class B {
-		@RestMethod(name=POST,path="/post1")
-		public String post1(RestRequest req, @FormData(value="p1") String p1) throws Exception {
-			RequestFormData f = req.getFormData();
-			return "p1=["+p1+","+req.getFormData().getString("p1")+","+f.get("p1", String.class)+"]";
-		}
-		@RestMethod(name=POST,path="/post2")
-		public String post2(RestRequest req, @FormData(value="p1",format="uon") String p1) throws Exception {
-			RequestFormData f = req.getFormData();
-			return "p1=["+p1+","+req.getFormData().getString("p1")+","+f.get("p1", String.class)+"]";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01() throws Exception {
-		b.post("/post1", "p1=p1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[p1,p1,p1]");
-		b.post("/post1", "p1='p1'").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=['p1','p1','p1']");
-	}
-	@Test
-	public void b02() throws Exception {
-		b.post("/post2", "p1=p1").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[p1,p1,p1]");
-		b.post("/post2", "p1='p1'").contentType("application/x-www-form-urlencoded").run().assertBody().is("p1=[p1,'p1','p1']");
-	}
-
-	//=================================================================================================================
-	// Default values.
-	//=================================================================================================================
-
-	@Rest
-	public static class C {
-		@RestMethod(name=POST, path="/defaultFormData", defaultFormData={"f1:1","f2=2"," f3 : 3 "})
-		public OMap c01(RequestFormData formData) {
-			return OMap.of()
-				.a("f1", formData.getString("f1"))
-				.a("f2", formData.getString("f2"))
-				.a("f3", formData.getString("f3"));
-		}
-		@RestMethod(name=POST, path="/annotatedFormData")
-		public OMap c02(@FormData("f1") String f1, @FormData("f2") String f2, @FormData("f3") String f3) {
-			return OMap.of()
-				.a("f1", f1)
-				.a("f2", f2)
-				.a("f3", f3);
-		}
-		@RestMethod(name=POST, path="/annotatedFormDataDefault")
-		public OMap c03(@FormData(value="f1",_default="1") String f1, @FormData(value="f2",_default="2") String f2, @FormData(value="f3",_default="3") String f3) {
-			return OMap.of()
-				.a("f1", f1)
-				.a("f2", f2)
-				.a("f3", f3);
-		}
-		@RestMethod(name=POST, path="/annotatedAndDefaultFormData", defaultFormData={"f1:1","f2=2"," f3 : 3 "})
-		public OMap c04(@FormData(value="f1",_default="4") String f1, @FormData(value="f2",_default="5") String f2, @FormData(value="f3",_default="6") String f3) {
-			return OMap.of()
-				.a("f1", f1)
-				.a("f2", f2)
-				.a("f3", f3);
-		}
-	}
-	static MockRestClient c = MockRestClient.build(C.class);
-
-	@Test
-	public void c01_defaultFormData() throws Exception {
-		c.post("/defaultFormData", null).contentType("application/x-www-form-urlencoded").run().assertBody().is("{f1:'1',f2:'2',f3:'3'}");
-		c.post("/defaultFormData", null).contentType("application/x-www-form-urlencoded").formData("f1",4).formData("f2",5).formData("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
-	}
-
-	@Test
-	public void c02_annotatedFormData() throws Exception {
-		c.post("/annotatedFormData", null).contentType("application/x-www-form-urlencoded").run().assertBody().is("{f1:null,f2:null,f3:null}");
-		c.post("/annotatedFormData", null).contentType("application/x-www-form-urlencoded").formData("f1",4).formData("f2",5).formData("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
-	}
-
-	@Test
-	public void c03_annotatedFormDataDefault() throws Exception {
-		c.post("/annotatedFormDataDefault", null).contentType("application/x-www-form-urlencoded").run().assertBody().is("{f1:'1',f2:'2',f3:'3'}");
-		c.post("/annotatedFormDataDefault", null).contentType("application/x-www-form-urlencoded").formData("f1",4).formData("f2",5).formData("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
-	}
-
-	@Test
-	public void c04_annotatedAndDefaultFormData() throws Exception {
-		c.post("/annotatedAndDefaultFormData", null).contentType("application/x-www-form-urlencoded").run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
-		c.post("/annotatedAndDefaultFormData", null).contentType("application/x-www-form-urlencoded").formData("f1",7).formData("f2",8).formData("f3",9).run().assertBody().is("{f1:'7',f2:'8',f3:'9'}");
-	}
-
-	//=================================================================================================================
-	// Optional form data parameter.
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class)
-	public static class D {
-		@RestMethod(name=POST,path="/a")
-		public Object a(@FormData("f1") Optional<Integer> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=POST,path="/b")
-		public Object b(@FormData("f1") Optional<ABean> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=POST,path="/c")
-		public Object c(@FormData("f1") Optional<List<ABean>> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=POST,path="/d")
-		public Object d(@FormData("f1") List<Optional<ABean>> f1) throws Exception {
-			return f1;
-		}
-	}
-	static MockRestClient d = MockRestClient.create(D.class).accept("application/json").contentType("application/x-www-form-urlencoded").build();
-
-	@Test
-	public void d01_optionalParam_integer() throws Exception {
-		d.post("/a", "f1=123")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("123");
-		d.post("/a", "null")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void d02_optionalParam_bean() throws Exception {
-		d.post("/b", "f1=a=1,b=foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("{a:1,b:'foo'}");
-		d.post("/b", "null")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void d03_optionalParam_listOfBeans() throws Exception {
-		d.post("/c", "f1=@((a=1,b=foo))")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-		d.post("/c", "null")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void d04_optionalParam_listOfOptionals() throws Exception {
-		d.post("/d", "f1=@((a=1,b=foo))")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-		d.post("/d", "null")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-
-	//=================================================================================================================
-	// @FormData on POJO
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SA {
-
-		@FormData(
-			name="F",
-			description= {"a","b"},
-			type="string"
-		)
-		public static class SA01 {
-			public SA01(String x) {}
-		}
-		@RestMethod
-		public void sa01(SA01 f) {}
-
-		@FormData(
-			name="F",
-			api={
-				"description:'a\nb',",
-				"type:'string'"
-			}
-		)
-		public static class SA02 {
-			public SA02(String x) {}
-		}
-		@RestMethod
-		public void sa02(SA02 f) {}
-
-		@FormData(
-			name="F",
-			api={
-				"description:'b\nc',",
-				"type:'string'"
-			},
-			description= {"a","b"},
-			type="string"
-		)
-		public static class SA03 {
-			public SA03(String x) {}
-		}
-		@RestMethod
-		public void sa03(SA03 f) {}
-
-		@FormData("F")
-		public static class SA04 {}
-		@RestMethod
-		public void sa04(SA04 f) {}
-	}
-
-	static Swagger sa = getSwagger(SA.class);
-
-	@Test
-	public void sa01_FormData_onPojo_basic() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa01","get","formData","F");
-		assertEquals("F", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sa02_FormData_onPojo_api() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa02","get","formData","F");
-		assertEquals("F", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sa03_FormData_onPojo_mixed() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa03","get","formData","F");
-		assertEquals("F", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sa04_FormData_onPojo_value() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa04","get","formData","F");
-		assertEquals("F", x.getName());
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SB {
-
-		@FormData(name="F")
-		public static class SB01 {}
-		@RestMethod
-		public void sb01(SB01 f) {}
-
-		@FormData("F")
-		public static class SB02 {
-			public String f1;
-		}
-		@RestMethod
-		public void sb02(SB02 f) {}
-
-		@FormData("F")
-		public static class SB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod
-		public void sb03(SB03 f) {}
-
-		@FormData("F")
-		public static class SB04 {}
-		@RestMethod
-		public void sb04(SB04 f) {}
-	}
-
-	static Swagger sb = getSwagger(SB.class);
-
-	@Test
-	public void sb01_FormData_onPojo_value() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb01","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'string'}");
-	}
-	@Test
-	public void sb02_FormData_onPojo_autoDetectBean() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb02","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'object',schema:{properties:{f1:{type:'string'}}}}");
-	}
-	@Test
-	public void sb03_FormData_onPojo_autoDetectList() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb03","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'array',items:{type:'string'}}");
-	}
-	@Test
-	public void sb04_FormData_onPojo_autoDetectStringObject() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb04","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'string'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SC {
-
-		@FormData(name="F", example={"{f1:'a'}"})
-		public static class SC01 {
-			public String f1;
-		}
-		@RestMethod
-		public void sc01(SC01 f) {}
-	}
-
-	static Swagger sc = getSwagger(SC.class);
-
-	@Test
-	public void sc01_FormData_onPojo_example() throws Exception {
-		ParameterInfo x = sc.getParameterInfo("/sc01","get","formData","F");
-		assertEquals("{f1:'a'}", x.getExample());
-	}
-
-	//=================================================================================================================
-	// @FormData on parameter
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TA {
-
-		@RestMethod
-		public void ta01(
-			@FormData(
-				name="F",
-				description={"a","b"},
-				type="string"
-			) String f) {}
-
-		@RestMethod
-		public void ta02(
-			@FormData(
-				name="F",
-				api={
-					"description:'a\nb',",
-					"type:'string'",
-				}
-			) String f) {}
-
-		@RestMethod
-		public void ta03(
-			@FormData(
-				name="F",
-				api={
-					"description:'b\nc',",
-					"type:'string'",
-				},
-				description={"a","b"},
-				type="string"
-			) String f) {}
-
-		@RestMethod
-		public void ta04(@FormData("F") String f) {}
-	}
-
-	static Swagger ta = getSwagger(TA.class);
-
-	@Test
-	public void ta01_FormData_onParameter_basic() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta01","get","formData","F");
-		assertEquals("F", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta02_FormData_onParameter_api() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta02","get","formData","F");
-		assertEquals("F", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta03_FormData_onParameter_mixed() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta03","get","formData","F");
-		assertEquals("F", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta04_FormData_onParameter_value() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta04","get","formData","F");
-		assertEquals("F", x.getName());
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TB {
-
-		@RestMethod
-		public void tb01(@FormData(name="F") String f) {}
-
-		public static class TB02 {
-			public String f1;
-		}
-		@RestMethod
-		public void tb02(@FormData("F") TB02 b) {}
-
-		public static class TB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod
-		public void tb03(@FormData("F") TB03 b) {}
-
-		public static class TB04 {}
-		@RestMethod
-		public void tb04(@FormData("F") TB04 b) {}
-
-		@RestMethod
-		public void tb05(@FormData("F") Integer b) {}
-
-		@RestMethod
-		public void tb06(@FormData("F") Boolean b) {}
-	}
-
-	static Swagger tb = getSwagger(TB.class);
-
-	@Test
-	public void tb01_FormData_onParameter_schemaValue() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb01","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'string'}");
-	}
-	@Test
-	public void tb02_FormData_onParameter_autoDetectBean() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb02","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'object',schema:{properties:{f1:{type:'string'}}}}");
-	}
-	@Test
-	public void tb03_FormData_onParameter_autoDetectList() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb03","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'array',items:{type:'string'}}");
-	}
-	@Test
-	public void tb04_FormData_onParameter_autoDetectStringObject() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb04","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'string'}");
-	}
-	@Test
-	public void tb05_FormData_onParameter_autoDetectInteger() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb05","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'integer',format:'int32'}");
-	}
-	@Test
-	public void tb06_FormData_onParameter_autoDetectBoolean() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb06","get","formData","F");
-		assertObject(x).json().is("{'in':'formData',name:'F',type:'boolean'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TC {
-
-		@RestMethod
-		public void tc01(@FormData(name="F", example="{f1:'a'}") String f) {}
-	}
-
-	static Swagger tc = getSwagger(TC.class);
-
-	@Test
-	public void tc01_FormData_onParameter_example() throws Exception {
-		ParameterInfo x = tc.getParameterInfo("/tc01","get","formData","F");
-		assertEquals("{f1:'a'}", x.getExample());
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/HasFormDataAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/HasFormDataAnnotationTest.java
deleted file mode 100644
index 0f1faa0..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/HasFormDataAnnotationTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation2;
-
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.http.annotation.HasFormData;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class HasFormDataAnnotationTest {
-
-	//=================================================================================================================
-	// Simple tests
-	//=================================================================================================================
-
-	@Rest
-	public static class A {
-		@RestMethod
-		public String post(RestRequest req, @HasFormData("p1") boolean p1, @HasFormData("p2") Boolean p2) throws Exception {
-			RequestFormData f = req.getFormData();
-			return "p1=["+p1+","+f.containsKey("p1")+"],p2=["+p2+","+f.containsKey("p2")+"]";
-		}
-
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01_post() throws Exception {
-		a.post("", "p1=p1&p2=2").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.post("", "p1&p2").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.post("", "p1=&p2=").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.post("", null).run().assertBody().is("p1=[false,false],p2=[false,false]");
-		a.post("", "p1").run().assertBody().is("p1=[true,true],p2=[false,false]");
-		a.post("", "p1=").run().assertBody().is("p1=[true,true],p2=[false,false]");
-		a.post("", "p2").run().assertBody().is("p1=[false,false],p2=[true,true]");
-		a.post("", "p2=").run().assertBody().is("p1=[false,false],p2=[true,true]");
-		a.post("", "p1=foo&p2").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.post("", "p1&p2=1").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		String x = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
-		a.post("", "p1="+x+"&p2=1").run().assertBody().is("p1=[true,true],p2=[true,true]");
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/HasQueryAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/HasQueryAnnotationTest.java
deleted file mode 100644
index 5db8449..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/HasQueryAnnotationTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation2;
-
-import static org.apache.juneau.http.HttpMethod.*;
-import static org.junit.runners.MethodSorters.*;
-
-import org.apache.juneau.http.annotation.HasQuery;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class HasQueryAnnotationTest {
-
-	//=================================================================================================================
-	// Simple tests
-	//=================================================================================================================
-
-	@Rest
-	public static class A {
-		@RestMethod(name=GET,path="/")
-		public String get(RestRequest req, @HasQuery("p1") boolean p1, @HasQuery("p2") Boolean p2) throws Exception {
-			RequestQuery q = req.getQuery();
-			return "p1=["+p1+","+q.containsKey("p1")+"],p2=["+p2+","+q.containsKey("p2")+"]";
-		}
-		@RestMethod(name=POST,path="/")
-		public String post(RestRequest req, @HasQuery("p1") boolean p1, @HasQuery("p2") Boolean p2) throws Exception {
-			RequestQuery q = req.getQuery();
-			return "p1=["+p1+","+q.containsKey("p1")+"],p2=["+p2+","+q.containsKey("p2")+"]";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01_get() throws Exception {
-		a.get("?p1=p1&p2=2").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.get("?p1&p2").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.get("?p1=&p2=").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.get("/").run().assertBody().is("p1=[false,false],p2=[false,false]");
-		a.get("?p1").run().assertBody().is("p1=[true,true],p2=[false,false]");
-		a.get("?p1=").run().assertBody().is("p1=[true,true],p2=[false,false]");
-		a.get("?p2").run().assertBody().is("p1=[false,false],p2=[true,true]");
-		a.get("?p2=").run().assertBody().is("p1=[false,false],p2=[true,true]");
-		a.get("?p1=foo&p2").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.get("?p1&p2=1").run().assertBody().is("p1=[true,true],p2=[true,true]");
-		String x = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
-		a.get("?p1="+x+"&p2=1").run().assertBody().is("p1=[true,true],p2=[true,true]");
-	}
-	@Test
-	public void a02_post() throws Exception {
-		a.post("?p1=p1&p2=2", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.post("?p1&p2", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.post("?p1=&p2=", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.post("/", null).run().assertBody().is("p1=[false,false],p2=[false,false]");
-		a.post("?p1", null).run().assertBody().is("p1=[true,true],p2=[false,false]");
-		a.post("?p1=", null).run().assertBody().is("p1=[true,true],p2=[false,false]");
-		a.post("?p2", null).run().assertBody().is("p1=[false,false],p2=[true,true]");
-		a.post("?p2=", null).run().assertBody().is("p1=[false,false],p2=[true,true]");
-		a.post("?p1=foo&p2", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
-		a.post("?p1&p2=1", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
-		String x = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
-		a.post("?p1="+x+"&p2=1", null).run().assertBody().is("p1=[true,true],p2=[true,true]");
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/HeaderAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/HeaderAnnotationTest.java
deleted file mode 100644
index 3f4b5cf..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/HeaderAnnotationTest.java
+++ /dev/null
@@ -1,422 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation2;
-
-import static org.apache.juneau.assertions.Assertions.*;
-import static org.apache.juneau.http.HttpMethod.*;
-import static org.apache.juneau.rest.testutils.TestUtils.*;
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.util.*;
-
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.apache.juneau.testutils.pojos.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class HeaderAnnotationTest {
-
-	//=================================================================================================================
-	// Optional header parameter.
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class)
-	public static class A {
-		@RestMethod(name=GET,path="/a")
-		public Object a(@Header("f1") Optional<Integer> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=GET,path="/b")
-		public Object b(@Header("f1") Optional<ABean> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=GET,path="/c")
-		public Object c(@Header("f1") Optional<List<ABean>> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=GET,path="/d")
-		public Object d(@Header("f1") List<Optional<ABean>> f1) throws Exception {
-			return f1;
-		}
-	}
-	static MockRestClient a = MockRestClient.buildJson(A.class);
-
-	@Test
-	public void a01_optionalParam_integer() throws Exception {
-		a.get("/a").header("f1", 123)
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("123");
-		a.get("/a")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void a02_optionalParam_bean() throws Exception {
-		a.get("/b")
-			.header("f1", "a=1,b=foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("{a:1,b:'foo'}");
-		a.get("/b")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void a03_optionalParam_listOfBeans() throws Exception {
-		a.get("/c")
-			.header("f1", "@((a=1,b=foo))")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-		a.get("/c")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void a04_optionalParam_listOfOptionals() throws Exception {
-		a.get("/d")
-			.header("f1", "@((a=1,b=foo))")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-		a.get("/d")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-
-	//=================================================================================================================
-	// @Header on POJO
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SA {
-
-		@Header(
-			name="H",
-			description={"a","b"},
-			type="string"
-		)
-		public static class SA01 {
-			public SA01(String x) {}
-		}
-		@RestMethod
-		public void sa01(SA01 h) {}
-
-		@Header(
-			name="H",
-			api={
-				"description:'a\nb',",
-				"type:'string'"
-			}
-		)
-		public static class SA02 {
-			public SA02(String x) {}
-		}
-		@RestMethod
-		public void sa02(SA02 h) {}
-
-		@Header(
-			name="H",
-			api={
-				"description:'b\nc',",
-				"type:'string'"
-			},
-			description={"a","b"},
-			type="string"
-		)
-		public static class SA03 {
-			public SA03(String x) {}
-		}
-		@RestMethod
-		public void sa03(SA03 h) {}
-	}
-
-	static Swagger sa = getSwagger(SA.class);
-
-	@Test
-	public void sa01_Header_onPojo_basic() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa01","get","header","H");
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getType()).json().is("'string'");
-	}
-	@Test
-	public void sa02_Header_onPojo_api() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa02","get","header","H");
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getType()).json().is("'string'");
-	}
-	@Test
-	public void sa03_Header_onPojo_mixed() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa03","get","header","H");
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getType()).json().is("'string'");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SB {
-
-		@Header(name="H")
-		public static class SB01 {}
-		@RestMethod
-		public void sb01(SB01 h) {}
-
-		@Header(name="H")
-		public static class SB02 {
-			public String f1;
-		}
-		@RestMethod
-		public void sb02(SB02 b) {}
-
-		@Header(name="H")
-		public static class SB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod
-		public void sb03(SB03 b) {}
-
-		@Header(name="H")
-		public static class SB04 {}
-		@RestMethod
-		public void sb04(SB04 b) {}
-	}
-
-	static Swagger sb = getSwagger(SB.class);
-
-	@Test
-	public void sb01_Header_onPojo_schemaValue() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb01","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'string'}");
-	}
-	@Test
-	public void sb02_Header_onPojo_autoDetectBean() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb02","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'object',schema:{properties:{f1:{type:'string'}}}}");
-	}
-	@Test
-	public void sb03_Header_onPojo_autoDetectList() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb03","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'array',items:{type:'string'}}");
-	}
-	@Test
-	public void sb04_Header_onPojo_autoDetectStringObject() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb04","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'string'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SC {
-
-		@Header(name="H", example="{f1:'a'}")
-		public static class SC01 {
-			public String f1;
-		}
-		@RestMethod
-		public void sc01(SC01 h) {}
-	}
-
-	static Swagger sc = getSwagger(SC.class);
-
-	@Test
-	public void sc01_Header_onPojo_example() throws Exception {
-		ParameterInfo x = sc.getParameterInfo("/sc01","get","header","H");
-		assertEquals("{f1:'a'}", x.getExample());
-	}
-
-	//=================================================================================================================
-	// @Header on parameter
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TA {
-
-		@RestMethod
-		public void ta01(
-			@Header(
-				name="H",
-				description={"a","b"},
-				type="string"
-			) String h) {}
-
-		@RestMethod
-		public void ta02(
-			@Header(
-				name="H",
-				api={
-					"description:'a\nb',",
-					"type:'string'",
-				}
-			) String h) {}
-
-		@RestMethod
-		public void ta03(
-			@Header(
-				name="H",
-				api={
-					"description:'b\nc',",
-					"type:'string'",
-				},
-				description={"a","b"},
-				type="string"
-			) String h) {}
-
-		@RestMethod
-		public void ta04(@Header("H") String h) {}
-	}
-
-	static Swagger ta = getSwagger(TA.class);
-
-	@Test
-	public void ta01_Header_onParameter_basic() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta01","get","header","H");
-		assertEquals("H", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta02_Header_onParameter_api() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta02","get","header","H");
-		assertEquals("H", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta03_Header_onParameter_mixed() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta03","get","header","H");
-		assertEquals("H", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta04_Header_onParameter_value() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta04","get","header","H");
-		assertEquals("H", x.getName());
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TB {
-
-		@RestMethod
-		public void tb01(@Header(name="H") String h) {}
-
-		public static class TB02 {
-			public String f1;
-		}
-		@RestMethod
-		public void tb02(@Header("H") TB02 b) {}
-
-		public static class TB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod
-		public void tb03(@Header("H") TB03 b) {}
-
-		public static class TB04 {}
-		@RestMethod
-		public void tb04(@Header("H") TB04 b) {}
-
-		@RestMethod
-		public void tb05(@Header("H") Integer b) {}
-
-		@RestMethod
-		public void tb06(@Header("H") Boolean b) {}
-	}
-
-	static Swagger tb = getSwagger(TB.class);
-
-	@Test
-	public void tb01_Header_onParameter_string() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb01","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'string'}");
-	}
-	@Test
-	public void tb02_Header_onParameter_bean() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb02","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'object',schema:{properties:{f1:{type:'string'}}}}");
-	}
-	@Test
-	public void tb03_Header_onParameter_array() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb03","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'array',items:{type:'string'}}");
-	}
-	@Test
-	public void tb04_Header_onParameter_beanAsString() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb04","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'string'}");
-	}
-	@Test
-	public void tb05_Header_onParameter_Integer() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb05","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'integer',format:'int32'}");
-	}
-	@Test
-	public void tb06_Header_onParameter_Boolean() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb06","get","header","H");
-		assertObject(x).json().is("{'in':'header',name:'H',type:'boolean'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TC {
-
-		@RestMethod
-		public void tc01(@Header(name="H", example={"a","b"}) String h) {}
-	}
-
-	static Swagger tc = getSwagger(TC.class);
-
-	@Test
-	public void tc01_Header_onParameter_example() throws Exception {
-		ParameterInfo x = tc.getParameterInfo("/tc01","get","header","H");
-		assertEquals("a\nb", x.getExample());
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
deleted file mode 100644
index c280a14..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
+++ /dev/null
@@ -1,1500 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation2;
-
-import static org.apache.juneau.assertions.Assertions.*;
-import static org.apache.juneau.http.HttpMethod.*;
-import static org.apache.juneau.rest.testutils.TestUtils.*;
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.util.*;
-
-import org.apache.juneau.collections.*;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.marshall.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.apache.juneau.testutils.pojos.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class PathAnnotationTest {
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest
-	public static class A  {
-		@RestMethod(name=GET, path="/")
-		public void noPath(RestResponse res) {
-			res.setOutput(GET);
-		}
-		@RestMethod(name=GET, path="/a")
-		public String simplePath() {
-			return "GET /a";
-		}
-		@RestMethod(name=GET, path="/a/{foo}")
-		public String simplePathOneVar(RestResponse res, @Path("foo") String foo) {
-			return "GET /a " + foo;
-		}
-		@RestMethod(name=GET, path="/a/{foo}/{bar}")
-		public String simplePathTwoVars(RestResponse res, @Path("foo") String foo, @Path("bar") String bar) {
-			return "GET /a " + foo + "," + bar;
-		}
-		@RestMethod(name=GET, path="/a/{foo}/{bar}/*")
-		public String simplePathWithRemainder(@Path("foo") String foo, @Path("bar") int bar, @Path("/*") String remainder) {
-			return "GET /a "+foo+","+bar+",r="+remainder;
-		}
-	}
-	static MockRestClient a = MockRestClient.buildLax(A.class);
-
-	@Test
-	public void a00_nonExistentPath() throws Exception {
-		a.get("/bad?noTrace=true")
-			.run()
-			.assertCode().is(404);
-	}
-	@Test
-	public void a01_noPath() throws Exception {
-		a.get(null)
-			.run()
-			.assertBody().is("GET");
-		a.get()
-			.run()
-			.assertBody().is("GET");
-	}
-	@Test
-	public void a02_simplePath() throws Exception {
-		a.get("/a")
-			.run()
-			.assertBody().is("GET /a");
-	}
-	@Test
-	public void a03_simplePathOneVar() throws Exception {
-		a.get("/a/foo")
-			.run()
-			.assertBody().is("GET /a foo");
-	}
-	@Test
-	public void a04_simplePathTwoVars() throws Exception {
-		a.get("/a/foo/bar")
-			.run()
-			.assertBody().is("GET /a foo,bar");
-	}
-	@Test
-	public void a05_simplePathWithRemainder() throws Exception {
-		a.get("/a/foo/123/baz")
-			.run()
-			.assertBody().is("GET /a foo,123,r=baz");
-	}
-	@Test
-	public void a06_urlEncodedPathPart() throws Exception {
-		// URL-encoded part should not get decoded before finding method to invoke.
-		// This should match /get1/{foo} and not /get1/{foo}/{bar}
-		// NOTE:  When testing on Tomcat, must specify the following system property:
-		// -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
-		a.get("/a/x%2Fy")
-			.run()
-			.assertBody().is("GET /a x/y");
-		a.get("/a/x%2Fy/x%2Fy")
-			.run()
-			.assertBody().is("GET /a x/y,x/y");
-	}
-
-	//=================================================================================================================
-	// Primitives
-	//=================================================================================================================
-
-	@Rest
-	public static class B  {
-		@RestMethod(name=GET, path="/int/{x}/foo")
-		public String b01(@Path("x") int x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/short/{x}/foo")
-		public String b02(@Path("x") short x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/long/{x}/foo")
-		public String b03(@Path("x") long x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/char/{x}/foo")
-		public String b04(@Path("x") char x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/float/{x}/foo")
-		public String b05(@Path("x") float x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/double/{x}/foo")
-		public String b06(@Path("x") double x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/byte/{x}/foo")
-		public String b07(@Path("x") byte x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/boolean/{x}/foo")
-		public String b08(@Path("x") boolean x) {
-			return String.valueOf(x);
-		}
-	}
-	static MockRestClient b = MockRestClient.buildLax(B.class);
-
-	@Test
-	public void b01_int() throws Exception {
-		b.get("/int/123/foo")
-			.run()
-			.assertBody().is("123");
-		b.get("/int/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void b02_short() throws Exception {
-		b.get("/short/123/foo")
-			.run()
-			.assertBody().is("123");
-		b.get("/short/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void b03_long() throws Exception {
-		b.get("/long/123/foo")
-			.run()
-			.assertBody().is("123");
-		b.get("/long/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void b04_char() throws Exception {
-		b.get("/char/c/foo")
-			.run()
-			.assertBody().is("c");
-		b.get("/char/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void b05_float() throws Exception {
-		b.get("/float/1.23/foo")
-			.run()
-			.assertBody().is("1.23");
-		b.get("/float/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void b06_double() throws Exception {
-		b.get("/double/1.23/foo")
-			.run()
-			.assertBody().is("1.23");
-		b.get("/double/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void b07_byte() throws Exception {
-		b.get("/byte/123/foo")
-			.run()
-			.assertBody().is("123");
-		b.get("/byte/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void b08_boolean() throws Exception {
-		b.get("/boolean/true/foo")
-			.run()
-			.assertBody().is("true");
-		b.get("/boolean/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-
-	//=================================================================================================================
-	// Primitive objects
-	//=================================================================================================================
-
-	@Rest
-	public static class C  {
-		@RestMethod(name=GET, path="/Integer/{x}/foo")
-		public String c01(@Path("x") Integer x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/Short/{x}/foo")
-		public String c02(@Path("x") Short x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/Long/{x}/foo")
-		public String c03(@Path("x") Long x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/Character/{x}/foo")
-		public String c04(@Path("x") Character x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/Float/{x}/foo")
-		public String c05(@Path("x") Float x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/Double/{x}/foo")
-		public String c06(@Path("x") Double x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/Byte/{x}/foo")
-		public String c07(@Path("x") Byte x) {
-			return String.valueOf(x);
-		}
-		@RestMethod(name=GET, path="/Boolean/{x}/foo")
-		public String c08(@Path("x") Boolean x) {
-			return String.valueOf(x);
-		}
-	}
-	static MockRestClient c = MockRestClient.buildLax(C.class);
-
-	@Test
-	public void c01_Integer() throws Exception {
-		c.get("/Integer/123/foo")
-			.run()
-			.assertBody().is("123");
-		c.get("/Integer/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c02_Short() throws Exception {
-		c.get("/Short/123/foo")
-			.run()
-			.assertBody().is("123");
-		c.get("/Short/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c03_Long() throws Exception {
-		c.get("/Long/123/foo")
-			.run()
-			.assertBody().is("123");
-		c.get("/Long/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c04_Char() throws Exception {
-		c.get("/Character/c/foo")
-			.run()
-			.assertBody().is("c");
-		c.get("/Character/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c05_Float() throws Exception {
-		c.get("/Float/1.23/foo")
-			.run()
-			.assertBody().is("1.23");
-		c.get("/Float/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c06_Double() throws Exception {
-		c.get("/Double/1.23/foo")
-			.run()
-			.assertBody().is("1.23");
-		c.get("/Double/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c07_Byte() throws Exception {
-		c.get("/Byte/123/foo")
-			.run()
-			.assertBody().is("123");
-		c.get("/Byte/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-	@Test
-	public void c08_Boolean() throws Exception {
-		c.get("/Boolean/true/foo")
-			.run()
-			.assertBody().is("true");
-		c.get("/Boolean/bad/foo?noTrace=true")
-			.run()
-			.assertCode().is(400);
-	}
-
-	//=================================================================================================================
-	// POJOs convertible from strings
-	//=================================================================================================================
-
-	@Rest
-	public static class D {
-		// Object with forString(String) method
-		@RestMethod(name=GET, path="/uuid/{uuid}")
-		public UUID uuid(RestResponse res, @Path("uuid") UUID uuid) {
-			return uuid;
-		}
-	}
-	static MockRestClient d = MockRestClient.build(D.class);
-
-	@Test
-	public void d01_uuid() throws Exception {
-		UUID uuid = UUID.randomUUID();
-		d.get("/uuid/" + uuid)
-			.run()
-			.assertBody().is(uuid.toString());
-	}
-
-	//=================================================================================================================
-	// @Path annotation without name.
-	//=================================================================================================================
-
-	@Rest
-	public static class E  {
-		@RestMethod(name=GET, path="/x/{foo}/{bar}")
-		public Object normal1(@Path String foo, @Path String bar) {
-			return OMap.of("m", "normal1", "foo", foo, "bar", bar);
-		}
-		@RestMethod(name=GET, path="/x/{foo}/x/{bar}/x")
-		public Object normal2(@Path String foo, @Path String bar) {
-			return OMap.of("m", "normal2", "foo", foo, "bar", bar);
-		}
-		@RestMethod(name=GET, path="/y/{0}/{1}")
-		public Object numbers1(@Path String foo, @Path String bar) {
-			return OMap.of("m", "numbers1", "0", foo, "1", bar);
-		}
-		@RestMethod(name=GET, path="/y/{0}/y/{1}/y")
-		public Object numbers2(@Path String foo, @Path String bar) {
-			return OMap.of("m", "numbers2", "0", foo, "1", bar);
-		}
-		@RestMethod(name=GET, path="/z/{1}/z/{0}/z")
-		public Object numbers3(@Path String foo, @Path String bar) {
-			return OMap.of("m", "numbers3", "0", foo, "1", bar);
-		}
-	}
-	static MockRestClient e = MockRestClient.build(E.class);
-
-	@Test
-	public void e01_normal1() throws Exception {
-		e.get("/x/x1/x2")
-			.run()
-			.assertBody().is("{m:'normal1',foo:'x1',bar:'x2'}");
-	}
-	@Test
-	public void e02_normal2() throws Exception {
-		e.get("/x/x1/x/x2/x")
-			.run()
-			.assertBody().is("{m:'normal2',foo:'x1',bar:'x2'}");
-	}
-	@Test
-	public void e03_numbers1() throws Exception {
-		e.get("/y/y1/y2")
-			.run()
-			.assertBody().is("{m:'numbers1','0':'y1','1':'y2'}");
-	}
-	@Test
-	public void e04_numbers2() throws Exception {
-		e.get("/y/y1/y/y2/y")
-			.run()
-			.assertBody().is("{m:'numbers2','0':'y1','1':'y2'}");
-	}
-	@Test
-	public void e05_numbers3() throws Exception {
-		e.get("/z/z1/z/z2/z")
-			.run()
-			.assertBody().is("{m:'numbers3','0':'z2','1':'z1'}");
-	}
-
-	//=================================================================================================================
-	// Path variables on class.
-	//=================================================================================================================
-
-	@Rest(path="/f/{a}/{b}")
-	public static class F  {
-		@RestMethod(name=GET, path="/")
-		public String noPath(RequestPath path) {
-			return format("noPath: {0}", path);
-		}
-		@RestMethod(name=GET, path="/*")
-		public String noPath2(RequestPath path) {
-			return format("noPath2: {0}", path);
-		}
-		@RestMethod(name=GET, path="/a")
-		public String noVars(RequestPath path) {
-			return format("noVars: {0}", path);
-		}
-		@RestMethod(name=GET, path="/b/{c}/{d}")
-		public String twoVars(RequestPath path) {
-			return format("twoVars: {0}", path);
-		}
-		@RestMethod(name=GET, path="/c/{a}/{b}")
-		public String twoVarsOverlapping(RequestPath path) {
-			return format("twoVarsOverlapping: {0}", path);
-		}
-		@RestMethod(name=GET, path="/d/{c}/{d}/*")
-		public String withRemainder(RequestPath path) {
-			return format("withRemainder: {0}", path);
-		}
-		private String format(String msg, Object...args) {
-			return SimpleJson.DEFAULT.format(msg, args);
-		}
-	}
-	static MockRestClient f = MockRestClient.createLax(F.class).servletPath("/f").build();
-
-	@Test
-	public void f01a_noPath() throws Exception {
-		f.get("http://localhost/f/x1/x2")
-			.run()
-			.assertBody().is("noPath: {a:'x1',b:'x2'}");
-	}
-
-	@Test
-	public void f01b_incompletePath() throws Exception {
-		f.get("http://localhost/f/x1")
-			.run()
-			.assertCode().is(404);
-		f.get("http://localhost/f")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void f01c_noPath_blanks() throws Exception {
-		f.get("http://localhost/f//")
-			.run()
-			.assertCode().is(404);
-		f.get("http://localhost/f/x/")
-			.run()
-			.assertCode().is(404);
-		f.get("http://localhost/f//x")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void f02a_noPath2() throws Exception {
-		f.get("http://localhost/f/x1/x2/foo")
-			.run()
-			.assertBody().is("noPath2: {'/*':'foo','/**':'foo',a:'x1',b:'x2'}");
-	}
-
-	@Test
-	public void f02b_noPath2_blanks() throws Exception {
-		f.get("http://localhost/f///foo")
-			.run()
-			.assertCode().is(404);
-		f.get("http://localhost/f/x1//foo")
-			.run()
-			.assertCode().is(404);
-		f.get("http://localhost/f//x2/foo")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void f03a_noVars() throws Exception {
-		f.get("http://localhost/f/x1/x2/a")
-			.run()
-			.assertBody().is("noVars: {a:'x1',b:'x2'}");
-	}
-
-	@Test
-	public void f03b_noVars_blanks() throws Exception {
-		f.get("http://localhost/f///a")
-			.run()
-			.assertCode().is(404);
-		f.get("http://localhost/f/x1//a")
-			.run()
-			.assertCode().is(404);
-		f.get("http://localhost/f//x2/a")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void f04a_twoVars() throws Exception {
-		f.get("http://localhost/f/x1/x2/b/x3/x4")
-			.run()
-			.assertBody().is("twoVars: {a:'x1',b:'x2',c:'x3',d:'x4'}");
-	}
-
-	@Test
-	public void f04b_twoVars_blanks() throws Exception {
-		f.get("http://localhost/f//x2/b/x3/x4")
-			.run()
-			.assertCode().is(404);
-		f.get("http://localhost/f/x1//b/x3/x4")
-			.run()
-			.assertCode().is(404);
-		f.get("http://localhost/f/x1/x2/b//x4")
-			.run()
-			.assertCode().is(200);
-		f.get("http://localhost/f/x1/x2/b/x3/")
-			.run()
-			.assertCode().is(200);
-		f.get("http://localhost/f///b//")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void f05_twoVarsOverlapping() throws Exception {
-		f.get("http://localhost/f/x1/x2/c/x3/x4")
-			.run()
-			.assertBody().is("twoVarsOverlapping: {a:'x3',b:'x4'}");
-	}
-
-	@Test
-	public void f06a_withRemainder() throws Exception {
-		f.get("http://localhost/f/x1/x2/d/x3/x4")
-			.run()
-			.assertBody().is("withRemainder: {a:'x1',b:'x2',c:'x3',d:'x4'}");
-	}
-
-	@Test
-	public void f06b_withRemainder_lank() throws Exception {
-		f.get("http://localhost/f/x1/x2/d/x3/x4/")
-			.run()
-			.assertBody().is("withRemainder: {'/*':'','/**':'',a:'x1',b:'x2',c:'x3',d:'x4'}");
-	}
-
-	@Test
-	public void f06c_withRemainderWithStuff() throws Exception {
-		f.get("http://localhost/f/x1/x2/d/x3/x4/foo/bar")
-			.run()
-			.assertBody().is("withRemainder: {'/*':'foo/bar','/**':'foo/bar',a:'x1',b:'x2',c:'x3',d:'x4'}");
-	}
-
-	//=================================================================================================================
-	// Path variables on child class.
-	//=================================================================================================================
-
-	@Rest(children={F.class})
-	public static class G {}
-
-	static MockRestClient g = MockRestClient.buildLax(G.class);
-
-	@Test
-	public void g01a_noPath() throws Exception {
-		g.get("http://localhost/f/x1/x2")
-			.run()
-			.assertBody().is("noPath: {a:'x1',b:'x2'}");
-	}
-
-	@Test
-	public void g01b_incompletePath() throws Exception {
-		g.get("http://localhost/f/x1")
-			.run()
-			.assertCode().is(404);
-		g.get("http://localhost/f")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void g01c_noPath_blanks() throws Exception {
-		g.get("http://localhost/f//")
-			.run()
-			.assertCode().is(404);
-		g.get("http://localhost/f/x1/")
-			.run()
-			.assertCode().is(404);
-		g.get("http://localhost/f//x2")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void g02a_noVars() throws Exception {
-		g.get("http://localhost/f/x1/x2/a")
-			.run()
-			.assertBody().is("noVars: {a:'x1',b:'x2'}");
-	}
-
-	@Test
-	public void g02b_noVars_blanks() throws Exception {
-		g.get("http://localhost/f///a")
-			.run()
-			.assertCode().is(404);
-		g.get("http://localhost/f/x1//a")
-			.run()
-			.assertCode().is(404);
-		g.get("http://localhost/f//x2/a")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void g03a_twoVars() throws Exception {
-		g.get("http://localhost/f/x1/x2/b/x3/x4")
-			.run()
-			.assertBody().is("twoVars: {a:'x1',b:'x2',c:'x3',d:'x4'}");
-	}
-
-	@Test
-	public void g03b_twoVars_blanks() throws Exception {
-		g.get("http://localhost/f//x2/b/x3/x4")
-			.run()
-			.assertCode().is(404);
-		g.get("http://localhost/f/x1//b/x3/x4")
-			.run()
-			.assertCode().is(404);
-		g.get("http://localhost/f/x1/x2/b//x4")
-			.run()
-			.assertCode().is(200);
-		g.get("http://localhost/f/x1/x2/b/x3/")
-			.run()
-			.assertCode().is(200);
-		g.get("http://localhost/f///b//")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void g04_twoVarsOverlapping() throws Exception {
-		g.get("http://localhost/f/x1/x2/c/x3/x4")
-			.run()
-			.assertBody().is("twoVarsOverlapping: {a:'x3',b:'x4'}");
-	}
-
-	@Test
-	public void g05a_withRemainder() throws Exception {
-		g.get("http://localhost/f/x1/x2/d/x3/x4")
-			.run()
-			.assertBody().is("withRemainder: {a:'x1',b:'x2',c:'x3',d:'x4'}");
-	}
-
-	@Test
-	public void g05b_withRemainderBlank() throws Exception {
-		g.get("http://localhost/f/x1/x2/d/x3/x4/")
-			.run()
-			.assertBody().is("withRemainder: {'/*':'','/**':'',a:'x1',b:'x2',c:'x3',d:'x4'}");
-	}
-
-	@Test
-	public void g05c_withRemainderWithStuff() throws Exception {
-		g.get("http://localhost/f/x1/x2/d/x3/x4/foo/bar")
-			.run()
-			.assertBody().is("withRemainder: {'/*':'foo/bar','/**':'foo/bar',a:'x1',b:'x2',c:'x3',d:'x4'}");
-	}
-
-	//=================================================================================================================
-	// Path variables on parent and child class.
-	//=================================================================================================================
-
-	@Rest(path="/h/{ha}/{hb}", children={F.class})
-	public static class H {}
-
-	static MockRestClient h = MockRestClient.createLax(H.class).servletPath("/h").build();
-
-	@Test
-	public void h01a_noPath() throws Exception {
-		h.get("http://localhost/h/ha1/hb1/f/x1/x2")
-			.run()
-			.assertBody().is("noPath: {a:'x1',b:'x2',ha:'ha1',hb:'hb1'}");
-	}
-
-	@Test
-	public void h01b_incompletePath() throws Exception {
-		// These are 405 instead of 404 because when children don't match, we try to find a matching Java method.
-		h.get("http://localhost/h/ha1/hb1/f/x1")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1/hb1/f")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1/hb1")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void h01c_noPath_blanks() throws Exception {
-		h.get("http://localhost/h//hb1/f/x1/x2")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1//f/x1/x2")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1/hb1/f//x2")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1/hb1/f/x1/")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h///f//")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void h02a_noPath2() throws Exception {
-		h.get("http://localhost/h/ha1/hb1/f/x1/x2/foo")
-			.run()
-			.assertBody().is("noPath2: {'/*':'foo','/**':'foo',a:'x1',b:'x2',ha:'ha1',hb:'hb1'}");
-	}
-
-	@Test
-	public void h02b_noPath2_blanks() throws Exception {
-		h.get("http://localhost/h//hb1/f/x1/x2/foo")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1//f/x1/x2/foo")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1/hb1/f//x2/foo")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1/hb1/f/x1//foo")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h///f///foo")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void h03a_noVars() throws Exception {
-		h.get("http://localhost/h/ha1/hb1/f/x1/x2/a")
-			.run()
-			.assertBody().is("noVars: {a:'x1',b:'x2',ha:'ha1',hb:'hb1'}");
-	}
-
-	@Test
-	public void h03b_noVars_blanks() throws Exception {
-		h.get("http://localhost/h//hb1/f/x1/x2/a")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1//f/x1/x2/a")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1/hb1/f//x2/a")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h/ha1/hb1/f/x1//a")
-			.run()
-			.assertCode().is(404);
-		h.get("http://localhost/h///f///a")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void h04_twoVars() throws Exception {
-		h.get("http://localhost/h/ha1/hb1/f/x1/x2/b/x3/x4")
-			.run()
-			.assertBody().is("twoVars: {a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1'}");
-	}
-
-	@Test
-	public void h05_twoVarsOverlapping() throws Exception {
-		h.get("http://localhost/h/ha1/hb1/f/x1/x2/c/x3/x4")
-			.run()
-			.assertBody().is("twoVarsOverlapping: {a:'x3',b:'x4',ha:'ha1',hb:'hb1'}");
-	}
-
-	@Test
-	public void h06a_withRemainder() throws Exception {
-		h.get("http://localhost/h/ha1/hb1/f/x1/x2/d/x3/x4")
-			.run()
-			.assertBody().is("withRemainder: {a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1'}");
-	}
-
-	@Test
-	public void h06b_withRemainderBlank() throws Exception {
-		h.get("http://localhost/h/ha1/hb1/f/x1/x2/d/x3/x4/")
-			.run()
-			.assertBody().is("withRemainder: {'/*':'','/**':'',a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1'}");
-	}
-
-	@Test
-	public void h06c_withRemainderWithStuff() throws Exception {
-		h.get("http://localhost/h/ha1/hb1/f/x1/x2/d/x3/x4/foo/bar")
-			.run()
-			.assertBody().is("withRemainder: {'/*':'foo/bar','/**':'foo/bar',a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1'}");
-	}
-
-	//=================================================================================================================
-	// Path variables on parents and child class.
-	//=================================================================================================================
-
-	@Rest(path="/i/{ia}/{ib}", children={H.class})
-	public static class I {}
-
-	static MockRestClient i = MockRestClient.createLax(I.class).servletPath("/i").build();
-
-	@Test
-	public void i01a_noPath() throws Exception {
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2")
-			.run()
-			.assertBody().is("noPath: {a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
-	}
-
-	@Test
-	public void i01b_incompletePath() throws Exception {
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1/ib1/h/ha1")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1/ib1/h")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1/ib1")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void i01c_noPath_blanks() throws Exception {
-		i.get("http://localhost/i//ib1/h/ha1/hb1/f/x1/x2")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1//h/ha1/hb1/f/x1/x2")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1/ib1/h//hb1/f/x1/x2")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1/ib1/h/ha1//f/x1/x2")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f//x2")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/")
-			.run()
-			.assertCode().is(404);
-		i.get("http://localhost/i///h///f//")
-			.run()
-			.assertCode().is(404);
-	}
-
-	@Test
-	public void i02_noPath2() throws Exception {
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/foo")
-			.run()
-			.assertBody().is("noPath2: {'/*':'foo','/**':'foo',a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
-	}
-
-	@Test
-	public void i03_noVars() throws Exception {
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/a")
-			.run()
-			.assertBody().is("noVars: {a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
-	}
-
-	@Test
-	public void i04_twoVars() throws Exception {
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/b/x3/x4")
-			.run()
-			.assertBody().is("twoVars: {a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
-	}
-
-	@Test
-	public void i05_twoVarsOverlapping() throws Exception {
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/c/x3/x4")
-			.run()
-			.assertBody().is("twoVarsOverlapping: {a:'x3',b:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
-	}
-
-	@Test
-	public void i06a_withRemainder() throws Exception {
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/d/x3/x4")
-			.run()
-			.assertBody().is("withRemainder: {a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
-	}
-
-	@Test
-	public void i06b_withRemainderBlank() throws Exception {
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/d/x3/x4/")
-			.run()
-			.assertBody().is("withRemainder: {'/*':'','/**':'',a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
-	}
-
-	@Test
-	public void i06c_withRemainderWithStuff() throws Exception {
-		i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/d/x3/x4/foo/bar")
-			.run()
-			.assertBody().is("withRemainder: {'/*':'foo/bar','/**':'foo/bar',a:'x1',b:'x2',c:'x3',d:'x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
-	}
-
-	//=================================================================================================================
-	// Optional path parameter.
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class)
-	public static class J {
-		@RestMethod(name=GET,path="/a/{f1}")
-		public Object a(@Path("f1") Optional<Integer> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=GET,path="/b/{f1}")
-		public Object b(@Path("f1") Optional<ABean> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=GET,path="/c/{f1}")
-		public Object c(@Path("f1") Optional<List<ABean>> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=GET,path="/d/{f1}")
-		public Object d(@Path("f1") List<Optional<ABean>> f1) throws Exception {
-			return f1;
-		}
-	}
-	static MockRestClient j = MockRestClient.buildJson(J.class);
-
-	@Test
-	public void j01_optionalParam_integer() throws Exception {
-		j.get("/a/123")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("123");
-	}
-
-	@Test
-	public void j02_optionalParam_bean() throws Exception {
-		j.get("/b/a=1,b=foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("{a:1,b:'foo'}");
-	}
-
-	@Test
-	public void j03_optionalParam_listOfBeans() throws Exception {
-		j.get("/c/@((a=1,b=foo))")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-	}
-
-	@Test
-	public void j04_optionalParam_listOfOptionals() throws Exception {
-		j.get("/d/@((a=1,b=foo))")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-	}
-
-
-	//=================================================================================================================
-	// @Path on POJO
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SA {
-
-		@Path(
-			n="P",
-			d={"a","b"},
-			t="string",
-			e="a,b",
-			ex="a"
-		)
-		public static class SA01 {
-			public SA01(String x) {}
-			@Override
-			public String toString() {
-				return "sa01";
-			}
-		}
-		@RestMethod(name=GET,path="/basic/{P}")
-		public void sa01(SA01 f) {}
-
-		@Path(
-			n="P",
-			api={
-				"description:'a\nb',",
-				"type:'string',",
-				"enum:['a','b'],",
-				"x-example:'a'"
-			}
-		)
-		public static class SA02 {
-			public SA02(String x) {}
-			@Override
-			public String toString() {
-				return "sa02";
-			}
-		}
-		@RestMethod(name=GET,path="/api/{P}")
-		public void sa02(SA02 f) {}
-
-		@Path(
-			n="P",
-			api={
-				"description:'b\nc',",
-				"type:'string',",
-				"enum:['b','c'],",
-				"x-example:'b'"
-			},
-			d={"a","b"},
-			t="string",
-			e="a,b",
-			ex="a"
-		)
-		public static class SA03 {
-			public SA03(String x) {}
-			@Override
-			public String toString() {
-				return "sa03";
-			}
-		}
-		@RestMethod(name=GET,path="/mixed/{P}")
-		public void sa03(SA03 f) {}
-
-
-		@Path("P")
-		public static class SA04 {
-			@Override
-			public String toString() {
-				return "sa04";
-			}
-		}
-		@RestMethod(name=GET,path="/value/{P}")
-		public void sa04(SA04 f) {}
-
-		@Path(n="P",e={" ['a','b'] "})
-		public static class SA19 {
-			@Override
-			public String toString() {
-				return "sa19";
-			}
-		}
-		@RestMethod(name=GET,path="/enum/{P}")
-		public void sa19(SA19 f) {}
-	}
-
-	static Swagger sa = getSwagger(SA.class);
-
-	@Test
-	public void sa01_Path_onPojo_basic() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/basic/{P}","get","path","P");
-		assertEquals("P", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-		assertObject(x.getEnum()).json().is("['a','b']");
-		assertEquals("a", x.getExample());
-		assertObject(x).json().is("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/basic/a'}}");
-	}
-	@Test
-	public void sa02_Path_onPojo_api() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/api/{P}","get","path","P");
-		assertEquals("P", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-		assertObject(x.getEnum()).json().is("['a','b']");
-		assertEquals("a", x.getExample());
-		assertObject(x).json().is("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/api/a'}}");
-	}
-	@Test
-	public void sa03_Path_onPojo_mixed() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/mixed/{P}","get","path","P");
-		assertEquals("P", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-		assertObject(x.getEnum()).json().is("['a','b']");
-		assertEquals("a", x.getExample());
-		assertObject(x).json().is("{'in':'path',name:'P',type:'string',description:'a\\nb',required:true,'enum':['a','b'],'x-example':'a','x-examples':{example:'/mixed/a'}}");
-	}
-	@Test
-	public void sa04_Path_onPojo_value() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/value/{P}","get","path","P");
-		assertEquals("P", x.getName());
-		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
-	}
-	@Test
-	public void sa05_Path_onPojo_enum() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/enum/{P}","get","path","P");
-		assertObject(x.getEnum()).json().is("['a','b']");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true,'enum':['a','b']}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SB {
-
-		@Path(n="P")
-		public static class SB01 {}
-		@RestMethod(name=GET,path="/schemaValue/{P}")
-		public void sb01(SB01 f) {}
-
-		@Path("P")
-		public static class SB02 {
-			public String f1;
-		}
-		@RestMethod(name=GET,path="/autoDetectBean/{P}")
-		public void sb02(SB02 b) {}
-
-		@Path("P")
-		public static class SB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod(name=GET,path="/autoDetectList/{P}")
-		public void sb03(SB03 b) {}
-
-		@Path("P")
-		public static class SB04 {}
-		@RestMethod(name=GET,path="/autoDetectStringObject/{P}")
-		public void sb04(SB04 b) {}
-	}
-
-	static Swagger sb = getSwagger(SB.class);
-
-	@Test
-	public void sb01_Path_onPojo_schemaValue() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/schemaValue/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
-	}
-	@Test
-	public void sb02_Path_onPojo_autoDetectBean() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/autoDetectBean/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'object',required:true,schema:{properties:{f1:{type:'string'}}}}");
-	}
-	@Test
-	public void sb03_Path_onPojo_autoDetectList() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/autoDetectList/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'array',required:true,items:{type:'string'}}");
-	}
-	@Test
-	public void sb04_Path_onPojo_autoDetectStringObject() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/autoDetectStringObject/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SC {
-
-		@Path(n="P",ex={" {f1:'a'} "})
-		public static class SC01 {
-			public String f1;
-		}
-		@RestMethod(name=GET,path="/example/{P}")
-		public void sc01(SC01 f) {}
-	}
-
-
-	static Swagger sc = getSwagger(SC.class);
-
-	@Test
-	public void sc01_Path_onPojo_example() throws Exception {
-		ParameterInfo x = sc.getParameterInfo("/example/{P}","get","path","P");
-		assertEquals("{f1:'a'}", x.getExample());
-	}
-
-	//=================================================================================================================
-	// @Path on parameter
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TA {
-
-		@RestMethod(name=GET,path="/basic/{P}")
-		public void ta01(@Path(
-			n="P",
-			d="a",
-			t="string"
-		) String h) {}
-
-		@RestMethod(name=GET,path="/api/{P}")
-		public void ta02(@Path(
-			n="P",
-			api={
-				"description:'a',",
-				"type:'string'"
-			}
-		) String h) {}
-
-		@RestMethod(name=GET,path="/mixed/{P}")
-		public void ta03(@Path(
-			n="P",
-			api={
-				"description:'b',",
-				"type:'string'"
-			},
-			d="a",
-			t="string"
-		) String h) {}
-
-		@RestMethod(name=GET,path="/value/{P}")
-		public void ta04(@Path("P") String h) {}
-
-		@RestMethod(name=GET,path="/enum/{P}")
-		public void ta05(@Path(n="P",e={" ['a','b'] "}) String h) {}
-	}
-
-	static Swagger ta = getSwagger(TA.class);
-
-	@Test
-	public void ta01_Path_onParameter_basic() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/basic/{P}","get","path","P");
-		assertEquals("a", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta02_Path_onParameter_api() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/api/{P}","get","path","P");
-		assertEquals("a", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta03_Path_onParameter_mixed() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/mixed/{P}","get","path","P");
-		assertEquals("a", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta04_Path_onParameter_value() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/value/{P}","get","path","P");
-		assertEquals("P", x.getName());
-	}
-	@Test
-	public void ta05_Path_onParameter_enum() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/enum/{P}","get","path","P");
-		assertObject(x.getEnum()).json().is("['a','b']");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TB {
-
-		@RestMethod(name=GET,path="/schemaValue/{P}")
-		public void tb01(@Path("P") String h) {}
-
-		public static class TB02 {
-			public String f1;
-		}
-		@RestMethod(name=GET,path="/autoDetectBean/{P}")
-		public void tb02(@Path("P") TB02 b) {}
-
-		public static class TB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod(name=GET,path="/autoDetectList/{P}")
-		public void tb03(@Path("P") TB03 b) {}
-
-		public static class TB04 {}
-		@RestMethod(name=GET,path="/autoDetectStringObject/{P}")
-		public void tb04(@Path("P") TB04 b) {}
-
-		@RestMethod(name=GET,path="/autoDetectInteger/{P}")
-		public void tb05(@Path("P") Integer b) {}
-
-		@RestMethod(name=GET,path="/autoDetectBoolean/{P}")
-		public void tb06(@Path("P") Boolean b) {}
-	}
-
-	static Swagger tb = getSwagger(TB.class);
-
-	@Test
-	public void tb01_Path_onParameter_schemaValue() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/schemaValue/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
-	}
-	@Test
-	public void tb02_Path_onParameter_autoDetectBean() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/autoDetectBean/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'object',required:true,schema:{properties:{f1:{type:'string'}}}}");
-	}
-	@Test
-	public void tb03_Path_onParameter_autoDetectList() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/autoDetectList/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'array',required:true,items:{type:'string'}}");
-	}
-	@Test
-	public void tb04_Path_onParameter_autoDetectStringObject() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/autoDetectStringObject/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'string',required:true}");
-	}
-	@Test
-	public void tb05_Path_onParameter_autoDetectInteger() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/autoDetectInteger/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'integer',required:true,format:'int32'}");
-	}
-	@Test
-	public void tb06_Path_onParameter_autoDetectBoolean() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/autoDetectBoolean/{P}","get","path","P");
-		assertObject(x).json().is("{'in':'path',name:'P',type:'boolean',required:true}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TC {
-
-		@RestMethod(name=GET,path="/example/{P}")
-		public void ta21(@Path(n="P",ex="{f1:'b'}") String h) {}
-	}
-
-	static Swagger tc = getSwagger(TC.class);
-
-	@Test
-	public void tc01_Path_onParameter_example2() throws Exception {
-		ParameterInfo x = tc.getParameterInfo("/example/{P}","get","path","P");
-		assertEquals("{f1:'b'}", x.getExample());
-	}
-
-
-	//=================================================================================================================
-	// Basic tests
-	//=================================================================================================================
-
-	@Rest(path="/u1/{u1}",children=U2.class)
-	public static class U1 {
-	}
-	@Rest(path="/u2")
-	public static class U2 {
-		@RestMethod(path="/")
-		public String doGet(@Path(n="u1",r=false) String u1) {
-			return u1 == null ? "nil" : u1;
-		}
-		@RestMethod(path="/foo/{bar}")
-		public String doGetFoo(@Path(n="u1",r=false) String u1, @Path(n="bar",r=false) String bar) {
-			return (u1 == null ? "nil" : u1) + "," + (bar == null ? "nil" : bar);
-		}
-	}
-
-	static MockRestClient u1 = MockRestClient.build(U1.class);
-	static MockRestClient u2 = MockRestClient.build(U2.class);
-
-	@Test
-	public void u01_nonRequiredPath() throws Exception {
-		u1.get("http://localhost/u1/foo/u2")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo");
-		u1.get("http://localhost/u1/foo/u2/foo/xxx")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo,xxx");
-		u2.get("/")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("nil");
-		u2.get("/foo/xxx")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("nil,xxx");
-	}
-
-	//=================================================================================================================
-	// Multiple paths
-	//=================================================================================================================
-
-	@Rest(path="/v1/{v1}",children=V2.class)
-	public static class V1 {
-	}
-	@Rest(path="/v2")
-	public static class V2 {
-		@RestMethod(paths={"/","/{foo}"})
-		public String doGet(@Path(n="v1",r=false) String v1, @Path(n="foo",r=false) String foo) {
-			return "1," + (v1 == null ? "nil" : v1) + "," + (foo == null ? "nil" : foo);
-		}
-		@RestMethod(paths={"/foo","/foo/{foo}"})
-		public String doGet2(@Path(n="v1",r=false) String v1, @Path(n="foo",r=false) String foo) {
-			return "2," + (v1 == null ? "nil" : v1) + "," + (foo == null ? "nil" : foo);
-		}
-	}
-
-	static MockRestClient v1 = MockRestClient.build(V1.class);
-	static MockRestClient v2 = MockRestClient.build(V2.class);
-
-	@Test
-	public void v01_multiplePaths() throws Exception {
-		v1.get("http://localhost/v1/v1foo/v2")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("1,v1foo,nil");
-		v1.get("http://localhost/v1/v1foo/v2/v2foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("1,v1foo,v2foo");
-		v1.get("http://localhost/v1/v1foo/v2/foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("2,v1foo,nil");
-		v1.get("http://localhost/v1/v1foo/v2/foo/v2foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("2,v1foo,v2foo");
-		v2.get("http://localhost/v2")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("1,nil,nil");
-		v2.get("http://localhost/v2/v2foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("1,nil,v2foo");
-		v2.get("http://localhost/v2/foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("2,nil,nil");
-		v2.get("http://localhost/v2/foo/v2foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("2,nil,v2foo");
-	}
-}
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/QueryAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/QueryAnnotationTest.java
deleted file mode 100644
index 23dd016..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/QueryAnnotationTest.java
+++ /dev/null
@@ -1,622 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation2;
-
-import static org.apache.juneau.assertions.Assertions.*;
-import static org.apache.juneau.http.HttpMethod.*;
-import static org.apache.juneau.rest.testutils.TestUtils.*;
-import static org.junit.Assert.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.util.*;
-
-import org.apache.juneau.collections.*;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.jsonschema.annotation.Items;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.apache.juneau.testutils.pojos.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class QueryAnnotationTest {
-
-	//=================================================================================================================
-	// Simple tests
-	//=================================================================================================================
-
-	@Rest
-	public static class A {
-		@RestMethod
-		public String get(RestRequest req, @Query(n="p1",aev=true) String p1, @Query(n="p2",aev=true) int p2) throws Exception {
-			RequestQuery q = req.getQuery();
-			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"],p2=["+p2+","+q.getString("p2")+","+q.get("p2", int.class)+"]";
-		}
-		@RestMethod
-		public String post(RestRequest req, @Query(n="p1",aev=true) String p1, @Query(n="p2",aev=true) int p2) throws Exception {
-			RequestQuery q = req.getQuery();
-			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"],p2=["+p2+","+q.getString("p2")+","+q.get("p2", int.class)+"]";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01_get() throws Exception {
-		a.get("?p1=p1&p2=2").run().assertBody().is("p1=[p1,p1,p1],p2=[2,2,2]");
-		a.get("?p1&p2").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.get("?p1=&p2=").run().assertBody().is("p1=[,,],p2=[0,,0]");
-		a.get("/").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.get("?p1").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.get("?p1=").run().assertBody().is("p1=[,,],p2=[0,null,0]");
-		a.get("?p2").run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.get("?p2=").run().assertBody().is("p1=[null,null,null],p2=[0,,0]");
-		a.get("?p1=foo&p2").run().assertBody().is("p1=[foo,foo,foo],p2=[0,null,0]");
-		a.get("?p1&p2=1").run().assertBody().is("p1=[null,null,null],p2=[1,1,1]");
-		String x = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
-		a.get("?p1="+x+"&p2=1").run().assertBody().is("p1=[a/b%c=d e,a/b%c=d e,a/b%c=d e],p2=[1,1,1]");
-	}
-	@Test
-	public void a02_post() throws Exception {
-		a.post("?p1=p1&p2=2", null).run().assertBody().is("p1=[p1,p1,p1],p2=[2,2,2]");
-		a.post("?p1&p2", null).run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.post("?p1=&p2=", null).run().assertBody().is("p1=[,,],p2=[0,,0]");
-		a.post("/", null).run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.post("?p1", null).run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.post("?p1=", null).run().assertBody().is("p1=[,,],p2=[0,null,0]");
-		a.post("?p2", null).run().assertBody().is("p1=[null,null,null],p2=[0,null,0]");
-		a.post("?p2=", null).run().assertBody().is("p1=[null,null,null],p2=[0,,0]");
-		a.post("?p1=foo&p2", null).run().assertBody().is("p1=[foo,foo,foo],p2=[0,null,0]");
-		a.post("?p1&p2=1", null).run().assertBody().is("p1=[null,null,null],p2=[1,1,1]");
-		String x = "a%2Fb%25c%3Dd+e"; // [x/y%z=a+b]
-		a.post("?p1="+x+"&p2=1", null).run().assertBody().is("p1=[a/b%c=d e,a/b%c=d e,a/b%c=d e],p2=[1,1,1]");
-	}
-
-	//=================================================================================================================
-	// UON parameters
-	//=================================================================================================================
-
-	@Rest
-	public static class B {
-		@RestMethod(name=GET,path="/get1")
-		public String get1(RestRequest req, @Query(n="p1") String p1) throws Exception {
-			RequestQuery q = req.getQuery();
-			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"]";
-		}
-		@RestMethod(name=GET,path="/get2")
-		public String get2(RestRequest req, @Query(n="p1",f="uon") String p1) throws Exception {
-			RequestQuery q = req.getQuery();
-			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"]";
-		}
-		@RestMethod(name=POST,path="/post1")
-		public String post1(RestRequest req, @Query(n="p1") String p1) throws Exception {
-			RequestQuery q = req.getQuery();
-			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"]";
-		}
-		@RestMethod(name=POST,path="/post2")
-		public String post2(RestRequest req, @Query(n="p1",f="uon") String p1) throws Exception {
-			RequestQuery q = req.getQuery();
-			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"]";
-		}
-	}
-	static MockRestClient b = MockRestClient.build(B.class);
-
-	@Test
-	public void b01_get1() throws Exception {
-		b.get("/get1?p1=p1").run().assertBody().is("p1=[p1,p1,p1]");
-		b.get("/get1?p1='p1'").run().assertBody().is("p1=['p1','p1','p1']");
-	}
-	@Test
-	public void b02_get2() throws Exception {
-		b.get("/get2?p1=p1").run().assertBody().is("p1=[p1,p1,p1]");
-		b.get("/get2?p1='p1'").run().assertBody().is("p1=[p1,'p1','p1']");
-	}
-	@Test
-	public void b03_post1() throws Exception {
-		b.post("/post1?p1=p1", null).run().assertBody().is("p1=[p1,p1,p1]");
-		b.post("/post1?p1='p1'", null).run().assertBody().is("p1=['p1','p1','p1']");
-	}
-	@Test
-	public void b04_post2() throws Exception {
-		b.post("/post2?p1=p1", null).run().assertBody().is("p1=[p1,p1,p1]");
-		b.post("/post2?p1='p1'", null).run().assertBody().is("p1=[p1,'p1','p1']");
-	}
-
-	//=================================================================================================================
-	// Multipart parameters (e.g. &key=val1,&key=val2).
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class)
-	public static class C {
-		public static class C01 {
-			public String a;
-			public int b;
-			public boolean c;
-		}
-
-		@RestMethod
-		public Object c01(@Query(n="x",cf="multi") String[] x) {
-			return x;
-		}
-		@RestMethod
-		public Object c02(@Query(n="x",cf="multi") int[] x) {
-			return x;
-		}
-		@RestMethod
-		public Object c03(@Query(n="x",cf="multi") List<String> x) {
-			return x;
-		}
-		@RestMethod
-		public Object c04(@Query(n="x",cf="multi") List<Integer> x) {
-			return x;
-		}
-		@RestMethod
-		public Object c05(@Query(n="x",cf="multi",items=@Items(f="uon")) C01[] x) {
-			return x;
-		}
-		@RestMethod
-		public Object c06(@Query(n="x",cf="multi",items=@Items(f="uon")) List<C01> x) {
-			return x;
-		}
-	}
-	static MockRestClient c = MockRestClient.build(C.class);
-
-	@Test
-	public void c01_StringArray() throws Exception {
-		c.get("/c01?x=a").run().assertBody().is("['a']");
-		c.get("/c01?x=a&x=b").run().assertBody().is("['a','b']");
-	}
-	@Test
-	public void c02_intArray() throws Exception {
-		c.get("/c02?x=1").run().assertBody().is("[1]");
-		c.get("/c02?x=1&x=2").run().assertBody().is("[1,2]");
-	}
-	@Test
-	public void c03_ListOfStrings() throws Exception {
-		c.get("/c03?x=a").run().assertBody().is("['a']");
-		c.get("/c03?x=a&x=b").run().assertBody().is("['a','b']");
-	}
-	@Test
-	public void c04_ListOfIntegers() throws Exception {
-		c.get("/c04?x=1").run().assertBody().is("[1]");
-		c.get("/c04?x=1&x=2").run().assertBody().is("[1,2]");
-	}
-	@Test
-	public void c05_BeanArray() throws Exception {
-		c.get("/c05?x=a=1,b=2,c=false").run().assertBody().is("[{a:'1',b:2,c:false}]");
-		c.get("/c05?x=a=1,b=2,c=false&x=a=3,b=4,c=true").run().assertBody().is("[{a:'1',b:2,c:false},{a:'3',b:4,c:true}]");
-	}
-	@Test
-	public void c06_ListOfBeans() throws Exception {
-		c.get("/c06?x=a=1,b=2,c=false").run().assertBody().is("[{a:'1',b:2,c:false}]");
-		c.get("/c06?x=a=1,b=2,c=false&x=a=3,b=4,c=true").run().assertBody().is("[{a:'1',b:2,c:false},{a:'3',b:4,c:true}]");
-	}
-
-	//=================================================================================================================
-	// Default values.
-	//=================================================================================================================
-
-	@Rest
-	public static class D {
-		@RestMethod(defaultQuery={"f1:1","f2=2"," f3 : 3 "})
-		public OMap d01(RequestQuery query) {
-			return OMap.of()
-				.a("f1", query.getString("f1"))
-				.a("f2", query.getString("f2"))
-				.a("f3", query.getString("f3"));
-		}
-		@RestMethod
-		public OMap d02(@Query("f1") String f1, @Query("f2") String f2, @Query("f3") String f3) {
-			return OMap.of()
-				.a("f1", f1)
-				.a("f2", f2)
-				.a("f3", f3);
-		}
-		@RestMethod
-		public OMap d03(@Query(n="f1",df="1") String f1, @Query(n="f2",df="2") String f2, @Query(n="f3",df="3") String f3) {
-			return OMap.of()
-				.a("f1", f1)
-				.a("f2", f2)
-				.a("f3", f3);
-		}
-		@RestMethod(defaultQuery={"f1:1","f2=2"," f3 : 3 "})
-		public OMap d04(@Query(n="f1",df="4") String f1, @Query(n="f2",df="5") String f2, @Query(n="f3",df="6") String f3) {
-			return OMap.of()
-				.a("f1", f1)
-				.a("f2", f2)
-				.a("f3", f3);
-		}
-	}
-	static MockRestClient d = MockRestClient.build(D.class);
-
-	@Test
-	public void d01_defaultQuery() throws Exception {
-		d.get("/d01").run().assertBody().is("{f1:'1',f2:'2',f3:'3'}");
-		d.get("/d01").query("f1",4).query("f2",5).query("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
-	}
-
-	@Test
-	public void d02_annotatedQuery() throws Exception {
-		d.get("/d02").run().assertBody().is("{f1:null,f2:null,f3:null}");
-		d.get("/d02").query("f1",4).query("f2",5).query("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
-	}
-
-	@Test
-	public void d03_annotatedQueryDefault() throws Exception {
-		d.get("/d03").run().assertBody().is("{f1:'1',f2:'2',f3:'3'}");
-		d.get("/d03").query("f1",4).query("f2",5).query("f3",6).run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
-	}
-
-	@Test
-	public void d04_annotatedAndDefaultQuery() throws Exception {
-		d.get("/d04").run().assertBody().is("{f1:'4',f2:'5',f3:'6'}");
-		d.get("/d04").query("f1",7).query("f2",8).query("f3",9).run().assertBody().is("{f1:'7',f2:'8',f3:'9'}");
-	}
-
-	//=================================================================================================================
-	// Optional query parameter.
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class)
-	public static class E {
-		@RestMethod(name=GET,path="/a")
-		public Object a(@Query("f1") Optional<Integer> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=GET,path="/b")
-		public Object b(@Query("f1") Optional<ABean> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=GET,path="/c")
-		public Object c(@Query("f1") Optional<List<ABean>> f1) throws Exception {
-			assertNotNull(f1);
-			return f1;
-		}
-		@RestMethod(name=GET,path="/d")
-		public Object d(@Query("f1") List<Optional<ABean>> f1) throws Exception {
-			return f1;
-		}
-	}
-	static MockRestClient e = MockRestClient.buildJson(E.class);
-
-	@Test
-	public void e01_optionalParam_integer() throws Exception {
-		e.get("/a?f1=123")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("123");
-		e.get("/a")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void e02_optionalParam_bean() throws Exception {
-		e.get("/b?f1=a=1,b=foo")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("{a:1,b:'foo'}");
-		e.get("/b")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void e03_optionalParam_listOfBeans() throws Exception {
-		e.get("/c?f1=@((a=1,b=foo))")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-		e.get("/c")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-	@Test
-	public void e04_optionalParam_listOfOptionals() throws Exception {
-		e.get("/d?f1=@((a=1,b=foo))")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[{a:1,b:'foo'}]");
-		e.get("/d")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("null");
-	}
-
-
-	//=================================================================================================================
-	// @Query on POJO
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SA {
-
-		@Query(
-			n="Q",
-			d= {"a","b"},
-			t="string"
-		)
-		public static class SA01 {
-			public SA01(String x) {}
-		}
-		@RestMethod
-		public void sa01(SA01 q) {}
-
-		@Query(
-			n="Q",
-			api={
-				"description: 'a\nb',",
-				"type:'string'"
-			}
-		)
-		public static class SA02 {
-			public SA02(String x) {}
-		}
-		@RestMethod
-		public void sa02(SA02 q) {}
-
-		@Query(
-			n="Q",
-			api={
-				"description: 'b\nc',",
-				"type:'string'"
-			},
-			d={"a","b"},
-			t="string"
-		)
-		public static class SA03 {
-			public SA03(String x) {}
-		}
-		@RestMethod
-		public void sa03(SA03 q) {}
-
-		@Query("Q")
-		public static class SA04 {}
-		@RestMethod
-		public void sa04(SA04 q) {}
-	}
-
-	static Swagger sa = getSwagger(SA.class);
-
-	@Test
-	public void sa01_Query_onPojo_basic() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa01","get","query","Q");
-		assertEquals("Q", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sa02_Query_onPojo_api() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa02","get","query","Q");
-		assertEquals("Q", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sa03_Query_onPojo_mixed() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa03","get","query","Q");
-		assertEquals("Q", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void sa04_Query_onPojo_value() throws Exception {
-		ParameterInfo x = sa.getParameterInfo("/sa04","get","query","Q");
-		assertEquals("Q", x.getName());
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SB {
-
-		@Query(n="Q")
-		public static class SB01 {}
-		@RestMethod
-		public void sb01(SB01 q) {}
-
-		@Query("Q")
-		public static class SB02 {
-			public String f1;
-		}
-		@RestMethod
-		public void sb02(SB02 q) {}
-
-		@Query("Q")
-		public static class SB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod
-		public void sb03(SB03 q) {}
-
-		@Query("Q")
-		public static class SB04 {}
-		@RestMethod
-		public void sb04(SB04 q) {}
-	}
-
-	static Swagger sb = getSwagger(SB.class);
-
-	@Test
-	public void sb01_Query_onPojo_schemaValue() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb01","get","query","Q");
-		assertObject(x).json().is("{'in':'query',name:'Q',type:'string'}");
-	}
-	@Test
-	public void sb02_Query_onPojo_autoDetectBean() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb02","get","query","Q");
-		assertObject(x).json().is("{'in':'query',name:'Q',type:'object',schema:{properties:{f1:{type:'string'}}}}");
-	}
-	@Test
-	public void sb03_Query_onPojo_autoDetectList() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb03","get","query","Q");
-		assertObject(x).json().is("{'in':'query',name:'Q',type:'array',items:{type:'string'}}");
-	}
-	@Test
-	public void sb04_Query_onPojo_autoDetectStringObject() throws Exception {
-		ParameterInfo x = sb.getParameterInfo("/sb04","get","query","Q");
-		assertObject(x).json().is("{'in':'query',name:'Q',type:'string'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SC {
-
-		@Query(n="Q", ex={"{f1:'a'}"})
-		public static class SC01 {
-			public String f1;
-		}
-		@RestMethod
-		public void sc01(SC01 q) {}
-	}
-
-	static Swagger sc = getSwagger(SC.class);
-
-	@Test
-	public void sc01_Query_onPojo_example() throws Exception {
-		ParameterInfo x = sc.getParameterInfo("/sc01","get","query","Q");
-		assertEquals("{f1:'a'}", x.getExample());
-	}
-
-	//=================================================================================================================
-	// @Query on parameter
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TA {
-
-		@RestMethod
-		public void ta01(
-			@Query(
-				n="Q",
-				d= {"a","b"},
-				t="string"
-			)
-			String q) {}
-
-		@RestMethod
-		public void ta02(
-			@Query(
-				n="Q",
-				api={
-					"description: 'a\nb',",
-					"type:'string'"
-				}
-			)
-			String q) {}
-
-		@RestMethod
-		public void ta03(
-			@Query(
-				n="Q",
-				api={
-					"description: 'b\nc',",
-					"type:'string'"
-				},
-				d= {"a","b"},
-				t="string"
-			)
-			String q) {}
-
-		@RestMethod
-		public void ta04(@Query("Q") String q) {}
-	}
-
-	static Swagger ta = getSwagger(TA.class);
-
-	@Test
-	public void ta01_Query_onParameter_basic() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta01","get","query","Q");
-		assertEquals("Q", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta02_Query_onParameter_api() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta02","get","query","Q");
-		assertEquals("Q", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta03_Query_onParameter_mixed() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta03","get","query","Q");
-		assertEquals("Q", x.getName());
-		assertEquals("a\nb", x.getDescription());
-		assertEquals("string", x.getType());
-	}
-	@Test
-	public void ta04_Query_onParameter_value() throws Exception {
-		ParameterInfo x = ta.getParameterInfo("/ta04","get","query","Q");
-		assertEquals("Q", x.getName());
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TB {
-
-		@RestMethod
-		public void tb01(@Query("Q") String q) {}
-	}
-
-	static Swagger tb = getSwagger(TB.class);
-
-	@Test
-	public void tb01_Query_onParameter_schemaValue() throws Exception {
-		ParameterInfo x = tb.getParameterInfo("/tb01","get","query","Q");
-		assertObject(x).json().is("{'in':'query',name:'Q',type:'string'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class TC {
-
-		@RestMethod
-		public void tc01(@Query(n="Q",ex={"a","b"}) String q) {}
-	}
-
-	static Swagger tc = getSwagger(TC.class);
-
-	@Test
-	public void tc01_Query_onParameter_example() throws Exception {
-		ParameterInfo x = tc.getParameterInfo("/tc01","get","query","Q");
-		assertEquals("a\nb", x.getExample());
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
deleted file mode 100644
index f84bd00..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
+++ /dev/null
@@ -1,1028 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation2;
-
-import static org.apache.juneau.assertions.Assertions.*;
-import static org.apache.juneau.rest.testutils.TestUtils.*;
-import static org.junit.Assert.assertEquals;
-import static org.junit.runners.MethodSorters.*;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.collections.*;
-import org.apache.juneau.dto.swagger.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.http.annotation.Body;
-import org.apache.juneau.http.annotation.Response;
-import org.apache.juneau.json.*;
-import org.apache.juneau.jsonschema.annotation.Schema;
-import org.apache.juneau.oapi.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@SuppressWarnings({"serial"})
-@FixMethodOrder(NAME_ASCENDING)
-public class ResponseAnnotationTest {
-
-	//=================================================================================================================
-	// Status codes
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// HTTP status code
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class A {
-		@RestMethod
-		public A01 a01() {
-			return new A01();
-		}
-		@RestMethod
-		public String a02() throws A02 {
-			throw new A02();
-		}
-	}
-
-	@Response(code=201)
-	public static class A01 {
-		@Override
-		public String toString() {return "foo";}
-	}
-
-	@Response(code=501)
-	public static class A02 extends Exception {
-		@Override
-		public String toString() {return "foo";}
-	}
-
-	static MockRestClient a = MockRestClient.buildLax(A.class);
-
-	@Test
-	public void a01_codeOnClass() throws Exception {
-		a.get("/a01")
-			.run()
-			.assertCode().is(201)
-			.assertBody().is("foo");
-	}
-	@Test
-	public void a02_codeOnThrown() throws Exception {
-		a.get("/a02")
-			.run()
-			.assertCode().is(501);
-	}
-
-	//=================================================================================================================
-	// PartSerializers
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// @Response(usePartSerializer)
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest(serializers=OpenApiSerializer.class,defaultAccept="text/openapi")
-	public static class B {
-
-		@Response
-		@RestMethod
-		public String b01() {
-			return "foo";
-		}
-		@RestMethod
-		public B03 b03() {
-			return new B03();
-		}
-		@RestMethod
-		public String b05() throws B05 {
-			throw new B05();
-		}
-		@RestMethod
-		public void b07(@Response Value<String> value) {
-			value.set("foo");
-		}
-	}
-
-	@Response
-	public static class B03 {
-		@Override
-		public String toString() {return "foo";}
-	}
-
-	@Response
-	public static class B05 extends Exception {
-		@Override
-		public String toString() {return "foo";}
-	}
-
-	static MockRestClient b = MockRestClient.buildLax(B.class);
-
-	@Test
-	public void b01_useOnMethod() throws Exception {
-		b.get("/b01")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo");
-	}
-	@Test
-	public void b03_useOnClass() throws Exception {
-		b.get("/b03")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo");
-	}
-	@Test
-	public void b05_useOnThrown() throws Exception {
-		b.get("/b05")
-			.run()
-			.assertCode().is(500)
-			.assertBody().is("foo");
-	}
-	@Test
-	public void b07_useOnParameter() throws Exception {
-		b.get("/b07")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo");
-	}
-
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// @Response(partSerializer) with schemas
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest(serializers=OpenApiSerializer.class,defaultAccept="text/openapi")
-	public static class D {
-
-		@Response(schema=@Schema(collectionFormat="pipes"))
-		@RestMethod
-		public String[] d01() {
-			return new String[]{"foo","bar"};
-		}
-		@RestMethod
-		public D02 d02() {
-			return new D02();
-		}
-		@RestMethod
-		public String d03() throws D03 {
-			throw new D03();
-		}
-		@RestMethod
-		public void d04(@Response(schema=@Schema(collectionFormat="pipes")) Value<String[]> value) {
-			value.set(new String[]{"foo","bar"});
-		}
-		@Response(schema=@Schema(type="string",format="byte"))
-		@RestMethod
-		public byte[] d05() {
-			return "foo".getBytes();
-		}
-		@RestMethod
-		public D06 d06() {
-			return new D06();
-		}
-		@RestMethod
-		public String d07() throws D07 {
-			throw new D07();
-		}
-		@RestMethod
-		public void d08(@Response(schema=@Schema(type="string",format="byte")) Value<byte[]> value) {
-			value.set("foo".getBytes());
-		}
-	}
-
-	@Response(schema=@Schema(type="array",collectionFormat="pipes"))
-	public static class D02 {
-		public String[] toStringArray() {
-			return new String[]{"foo","bar"};
-		}
-	}
-
-	@Response(schema=@Schema(type="array",collectionFormat="pipes"))
-	public static class D03 extends Exception {
-		public String[] toStringArray() {
-			return new String[]{"foo","bar"};
-		}
-	}
-
-	@Response(schema=@Schema(format="byte"))
-	public static class D06 {
-		public byte[] toByteArray() {
-			return "foo".getBytes();
-		}
-	}
-
-	@Response(schema=@Schema(format="byte"))
-	public static class D07 extends Exception {
-		public byte[] toByteArray() {
-			return "foo".getBytes();
-		}
-	}
-
-	static MockRestClient d = MockRestClient.buildLax(D.class);
-
-	@Test
-	public void d01_useOnMethod() throws Exception {
-		d.get("/d01")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo|bar");
-	}
-	@Test
-	public void d02_useOnClass() throws Exception {
-		d.get("/d02")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo|bar");
-	}
-	@Test
-	public void d03_useOnThrown() throws Exception {
-		d.get("/d03")
-			.run()
-			.assertCode().is(500)
-			.assertBody().is("foo|bar");
-	}
-	@Test
-	public void d04_useOnParameter() throws Exception {
-		d.get("/d04")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo|bar");
-	}
-	@Test
-	public void d05_useOnMethodBytes() throws Exception {
-		d.get("/d05")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("Zm9v");
-	}
-	@Test
-	public void d06_useOnClassBytes() throws Exception {
-		d.get("/d06")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("Zm9v");
-	}
-	@Test
-	public void d07_useOnThrownBytes() throws Exception {
-		d.get("/d07")
-			.run()
-			.assertCode().is(500)
-			.assertBody().is("Zm9v");
-	}
-	@Test
-	public void d08_useOnParameterBytes() throws Exception {
-		d.get("/d08")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("Zm9v");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class E {
-		@RestMethod
-		public void e01(@Response Value<E01> body) {
-			body.set(new E01());
-		}
-		@RestMethod
-		public void e02(Value<E02> body) {
-			body.set(new E02());
-		}
-		@RestMethod
-		@Response
-		public E01 e03() {
-			return new E01();
-		}
-		@RestMethod
-		public E02 e04() {
-			return new E02();
-		}
-	}
-
-	public static class E01 {
-		@Override
-		public String toString() {return "foo";}
-	}
-
-	@Response
-	public static class E02 {
-		@Override
-		public String toString() {return "foo";}
-	}
-
-	static MockRestClient e = MockRestClient.build(E.class);
-
-	@Test
-	public void e01_basic_onParameter() throws Exception {
-		e.get("/e01")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo");
-	}
-	@Test
-	public void e02_basic_onType() throws Exception {
-		e.get("/e02")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo");
-	}
-	@Test
-	public void e03_basic_onMethod() throws Exception {
-		e.get("/e03")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo");
-	}
-	@Test
-	public void e04_basic_onReturnedType() throws Exception {
-		e.get("/e04")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic swagger
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest(serializers=OpenApiSerializer.class,defaultAccept="text/openapi")
-	public static class F {
-		@RestMethod
-		public void f01(@Response(schema=@Schema(description="f01", collectionFormat="pipes")) Value<List<Integer>> body) {
-			body.set(AList.of(1,2));
-		}
-		@RestMethod
-		public void f02(Value<F01> body) {
-			body.set(new F01());
-		}
-		@RestMethod
-		@Response(schema=@Schema(description="f03", collectionFormat="pipes"))
-		public List<Integer> f03() {
-			return AList.of(1,2);
-		}
-		@RestMethod
-		public F01 f04() {
-			return new F01();
-		}
-	}
-
-	@Response(schema=@Schema(description="f01", collectionFormat="pipes"))
-	public static class F01 extends ArrayList<Integer> {
-		public F01() {
-			add(1);
-			add(2);
-		}
-	}
-
-	static MockRestClient f = MockRestClient.build(F.class);
-	static Swagger sf = getSwagger(F.class);
-
-	@Test
-	public void f01a_basic_onParameter() throws Exception {
-		f.get("/f01")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("1|2");
-	}
-	@Test
-	public void f01b_basic_onParameter_swagger() throws Exception {
-		ResponseInfo ri = sf.getResponseInfo("/f01", "get", 200);
-		assertObject(ri).json().is("{description:'OK',schema:{description:'f01',collectionFormat:'pipes'}}");
-	}
-	@Test
-	public void f02a_basic_onType() throws Exception {
-		f.get("/f02")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("1|2");
-	}
-	@Test
-	public void f02b_basic_onParameter_swagger() throws Exception {
-		ResponseInfo ri = sf.getResponseInfo("/f02", "get", 200);
-		assertObject(ri).json().is("{description:'OK',schema:{description:'f01',collectionFormat:'pipes'}}");
-	}
-	@Test
-	public void f03a_basic_onMethod() throws Exception {
-		f.get("/f03")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("1|2");
-	}
-	@Test
-	public void f03b_basic_onParameter_swagger() throws Exception {
-		ResponseInfo ri = sf.getResponseInfo("/f03", "get", 200);
-		assertObject(ri).json().is("{description:'OK',schema:{description:'f03',collectionFormat:'pipes'}}");
-	}
-	@Test
-	public void f04a_basic_onReturnedType() throws Exception {
-		f.get("/f04")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("1|2");
-	}
-	@Test
-	public void f04b_basic_onParameter_swagger() throws Exception {
-		ResponseInfo ri = sf.getResponseInfo("/f04", "get", 200);
-		assertObject(ri).json().is("{description:'OK',schema:{description:'f01',collectionFormat:'pipes'}}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Test JSON Accept
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest(serializers=SimpleJsonSerializer.class)
-	public static class G {
-		@RestMethod
-		public void g01(@Response Value<List<Integer>> body) {
-			body.set(AList.of(1,2));
-		}
-		@RestMethod
-		public void g02(Value<G01> body) {
-			body.set(new G01());
-		}
-		@RestMethod
-		@Response
-		public List<Integer> g03() {
-			return AList.of(1,2);
-		}
-		@RestMethod
-		public G01 g04() {
-			return new G01();
-		}
-	}
-
-	@Response
-	public static class G01 extends ArrayList<Integer> {
-		public G01() {
-			add(1);
-			add(2);
-		}
-	}
-
-	static MockRestClient g = MockRestClient.build(G.class);
-	static Swagger sg = getSwagger(G.class);
-
-	@Test
-	public void g01a_basic_onParameter() throws Exception {
-		g.get("/g01").json()
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[1,2]");
-	}
-	@Test
-	public void g01b_basic_onParameter_swagger() throws Exception {
-		ResponseInfo ri = sg.getResponseInfo("/g01", "get", 200);
-		assertObject(ri).json().is("{description:'OK',schema:{type:'array',items:{type:'integer',format:'int32'}}}");
-	}
-	@Test
-	public void g02a_basic_onType() throws Exception {
-		g.get("/g02").json()
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[1,2]");
-	}
-	@Test
-	public void g02b_basic_onParameter_swagger() throws Exception {
-		ResponseInfo ri = sg.getResponseInfo("/g02", "get", 200);
-		assertObject(ri).json().is("{description:'OK',schema:{type:'array',items:{type:'integer',format:'int32'}}}");
-	}
-	@Test
-	public void g03a_basic_onMethod() throws Exception {
-		g.get("/g03").json()
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[1,2]");
-	}
-	@Test
-	public void g03b_basic_onParameter_swagger() throws Exception {
-		ResponseInfo ri = sg.getResponseInfo("/g03", "get", 200);
-		assertObject(ri).json().is("{description:'OK',schema:{type:'array',items:{type:'integer',format:'int32'}}}");
-	}
-	@Test
-	public void g04a_basic_onReturnedType() throws Exception {
-		g.get("/g04").json()
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("[1,2]");
-	}
-	@Test
-	public void g04b_basic_onParameter_swagger() throws Exception {
-		ResponseInfo ri = sg.getResponseInfo("/g04", "get", 200);
-		assertObject(ri).json().is("{description:'OK',schema:{type:'array',items:{type:'integer',format:'int32'}}}");
-	}
-
-	//=================================================================================================================
-	// PartSerializers
-	//=================================================================================================================
-
-
-	//=================================================================================================================
-	// @Response on RestMethod
-	//=================================================================================================================
-
-	@Rest(serializers=SimpleJsonSerializer.class, parsers=JsonParser.class)
-	public static class J {
-
-		@RestMethod(name="POST")
-		public String j01(@Body String body) {
-			return body;
-		}
-	}
-	static MockRestClient j = MockRestClient.build(J.class);
-
-	@Test
-	public void j01a_basic() throws Exception {
-		j.post("/j01", "foo").accept("text/plain")
-			.run()
-			.assertCode().is(200)
-			.assertBody().is("foo")
-			.assertStringHeader("Content-Type").is("text/plain");
-	}
-
-
-	//=================================================================================================================
-	// @Response on POJO
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SA {
-
-		@Response(
-			description={"a","b"},
-			schema=@Schema(type="string"),
-			headers=@ResponseHeader(name="foo",type="string"),
-			example="'a'",
-			examples=" {foo:'a'} "
-		)
-		public static class SA01 {
-			public SA01(String x){}
-		}
-		@RestMethod
-		public void sa01a(Value<SA01> r) {}
-		@RestMethod
-		public SA01 sa01b() {return null;}
-
-		@Response(
-			api={
-				"description:'a\nb',",
-				"schema:{type:'string'},",
-				"headers:{foo:{type:'string'}},",
-				"example:'a',",
-				"examples:{foo:'a'}"
-			}
-		)
-		public static class SA02 {
-			public SA02(String x){}
-		}
-		@RestMethod
-		public void sa02a(Value<SA02> r) {}
-		@RestMethod
-		public SA02 sa02b() {return null;}
-
-		@Response(
-			api={
-				"description:'b',",
-				"schema:{type:'number'},",
-				"headers:{bar:{type:'number'}},",
-				"example:'b',",
-				"examples:{bar:'b'}"
-			},
-			description={"a","b"},
-			schema=@Schema(type="string"),
-			headers=@ResponseHeader(name="foo",type="string"),
-			example="'a'",
-			examples=" {foo:'a'} "
-		)
-		public static class SA03 {
-			public SA03(String x){}
-		}
-		@RestMethod
-		public void sa03a(Value<SA03> r) {}
-		@RestMethod
-		public SA03 sa03b() {return null;}
-
-		@Response(code=100)
-		public static class SA04 {}
-		@RestMethod
-		public void sa04a(Value<SA04> r) {}
-		@RestMethod
-		public SA04 sa04b() {return null;}
-
-		@Response(100)
-		public static class SA05 {}
-		@RestMethod
-		public void sa05a(Value<SA05> r) {}
-		@RestMethod
-		public SA05 sa05b() {return null;}
-
-		@Response(headers=@ResponseHeader(name="foo",api=" type:'b' "))
-		public static class SA06 {}
-		@RestMethod
-		public void sa06a(Value<SA06> r) {}
-		@RestMethod
-		public SA06 sa06b() {return null;}
-	}
-
-	static Swagger sa = getSwagger(SA.class);
-
-	@Test
-	public void sa01a_Response_onPojo_basic() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa01a","get",200);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
-		assertEquals("'a'", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void sa01b_Response_onPojo_basic() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa01b","get",200);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
-		assertEquals("'a'", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void sa02a_Response_onPojo_api() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa02a","get",200);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
-		assertEquals("a", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void sa02b_Response_onPojo_api() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa02b","get",200);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
-		assertEquals("a", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void sa03a_Response_onPojo_mixed() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa03a","get",200);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertObject(x.getHeaders()).json().is("{bar:{type:'number'},foo:{type:'string'}}");
-		assertEquals("'a'", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void sa03b_Response_onPojo_mixed() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa03b","get",200);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertObject(x.getHeaders()).json().is("{bar:{type:'number'},foo:{type:'string'}}");
-		assertEquals("'a'", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void sa04a_Response_onPojo_code() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa04a","get",100);
-		assertEquals("Continue", x.getDescription());
-	}
-	@Test
-	public void sa04b_Response_onPojo_code() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa04b","get",100);
-		assertEquals("Continue", x.getDescription());
-	}
-	@Test
-	public void sa05a_Response_onPojo_value() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa05a","get",100);
-		assertEquals("Continue", x.getDescription());
-	}
-	@Test
-	public void sa05b_Response_onPojo_value() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa05b","get",100);
-		assertEquals("Continue", x.getDescription());
-	}
-	@Test
-	public void sa06a_Response_onPojo_headers() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa06a","get",200);
-		assertObject(x.getHeaders()).json().is("{foo:{type:'b'}}");
-	}
-	@Test
-	public void sa06b_Response_onPojo_headers() throws Exception {
-		ResponseInfo x = sa.getResponseInfo("/sa06b","get",200);
-		assertObject(x.getHeaders()).json().is("{foo:{type:'b'}}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SB {
-
-		@Response(schema=@Schema(" type:'number' "))
-		public static class SB01 {}
-		@RestMethod
-		public void sb01a(Value<SB01> r) {}
-		@RestMethod
-		public SB01 sb01b() {return null;}
-
-		@Response
-		public static class SB02 {
-			public String f1;
-		}
-		@RestMethod
-		public void sb02a(Value<SB02> b) {}
-		@RestMethod
-		public SB02 sb02b() {return null;}
-
-		@Response
-		public static class SB03 extends LinkedList<String> {
-			private static final long serialVersionUID = 1L;
-		}
-		@RestMethod
-		public void sb03a(Value<SB03> b) {}
-		@RestMethod
-		public SB03 sb03b() {return null;}
-
-		@Response
-		public static class SB04 {}
-		@RestMethod
-		public void sb04a(Value<SB04> b) {}
-		@RestMethod
-		public SB04 sb04b() {return null;}
-	}
-
-	static Swagger sb = getSwagger(SB.class);
-
-	@Test
-	public void sb01a_Response_onPojo_schemaValue() throws Exception {
-		ResponseInfo x = sb.getResponseInfo("/sb01a","get",200);
-		assertObject(x.getSchema()).json().is("{type:'number'}");
-	}
-	@Test
-	public void sb01b_Response_onPojo_schemaValue() throws Exception {
-		ResponseInfo x = sb.getResponseInfo("/sb01b","get",200);
-		assertObject(x.getSchema()).json().is("{type:'number'}");
-	}
-	@Test
-	public void sb02a_Response_onPojo_autoDetectBean() throws Exception {
-		ResponseInfo x = sb.getResponseInfo("/sb02a","get",200);
-		assertObject(x.getSchema()).json().is("{type:'object',properties:{f1:{type:'string'}}}");
-	}
-	@Test
-	public void sb02b_Response_onPojo_autoDetectBean() throws Exception {
-		ResponseInfo x = sb.getResponseInfo("/sb02b","get",200);
-		assertObject(x.getSchema()).json().is("{type:'object',properties:{f1:{type:'string'}}}");
-	}
-	@Test
-	public void sb03a_Response_onPojo_autoDetectList() throws Exception {
-		ResponseInfo x = sb.getResponseInfo("/sb03a","get",200);
-		assertObject(x.getSchema()).json().is("{type:'array',items:{type:'string'}}");
-	}
-	@Test
-	public void sb03b_Response_onPojo_autoDetectList() throws Exception {
-		ResponseInfo x = sb.getResponseInfo("/sb03b","get",200);
-		assertObject(x.getSchema()).json().is("{type:'array',items:{type:'string'}}");
-	}
-	@Test
-	public void sb04a_Response_onPojo_autoDetectStringObject() throws Exception {
-		ResponseInfo x = sb.getResponseInfo("/sb04a","get",200);
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-	}
-	@Test
-	public void sb04b_Response_onPojo_autoDetectStringObject() throws Exception {
-		ResponseInfo x = sb.getResponseInfo("/sb04b","get",200);
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class SC {
-
-		@Response(example="{f1:'a'}")
-		public static class SC01 {
-			public String f1;
-		}
-		@RestMethod
-		public void sc01a(Value<SC01> r) {}
-		@RestMethod
-		public SC01 sc01b() {return null;}
-
-		@Response(examples={" foo:'b' "})
-		public static class SC02 {
-			public SC02(String x){}
-		}
-		@RestMethod
-		public void sc02a(Value<SC02> r) {}
-		@RestMethod
-		public SC02 sc02b() {return null;}
-	}
-
-	static Swagger sc = getSwagger(SC.class);
-
-	@Test
-	public void sc01a_Response_onPojo_example() throws Exception {
-		ResponseInfo x = sc.getResponseInfo("/sc01a","get",200);
-		assertEquals("{f1:'a'}", x.getExample());
-	}
-	@Test
-	public void sc01b_Response_onPojo_example() throws Exception {
-		ResponseInfo x = sc.getResponseInfo("/sc01b","get",200);
-		assertEquals("{f1:'a'}", x.getExample());
-	}
-	@Test
-	public void sc02a_Response_onPojo_examples() throws Exception {
-		ResponseInfo x = sc.getResponseInfo("/sc02a","get",200);
-		assertObject(x.getExamples()).json().is("{foo:'b'}");
-	}
-	@Test
-	public void sc02b_Response_onPojo_examples() throws Exception {
-		ResponseInfo x = sc.getResponseInfo("/sc02b","get",200);
-		assertObject(x.getExamples()).json().is("{foo:'b'}");
-	}
-
-	//=================================================================================================================
-	// @Response on throwable
-	//=================================================================================================================
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Basic tests
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class UA {
-
-		@Response(
-			description= {"a","b"},
-			schema=@Schema(type="string"),
-			headers=@ResponseHeader(name="foo",type="string"),
-			example=" 'a' ",
-			examples=" {foo:'a'} "
-		)
-		public static class UA01 extends Throwable {}
-		@RestMethod
-		public void ua01() throws UA01 {}
-
-		@Response(
-			api={
-				"description:'a\nb',",
-				"schema:{type:'string'},",
-				"headers:{foo:{type:'string'}},",
-				"example:'a',",
-				"examples:{foo:'a'}"
-			}
-		)
-		public static class UA02 extends Throwable {}
-		@RestMethod
-		public void ua02() throws UA02 {}
-
-		@Response(
-			api={
-				"description:'b',",
-				"schema:{type:'number'},",
-				"headers:{bar:{type:'number'}},",
-				"example:'b',",
-				"examples:{bar:'b'}"
-			},
-			description= {"a","b"},
-			schema=@Schema(type="string"),
-			headers=@ResponseHeader(name="foo",type="string"),
-			example=" 'a' ",
-			examples=" {foo:'a'} "
-		)
-		public static class UA03 extends Throwable {}
-		@RestMethod
-		public void ua03() throws UA03 {}
-
-		@Response(code=100)
-		public static class UA04 extends Throwable {}
-		@RestMethod
-		public void ua04() throws UA04 {}
-
-		@Response(code=100)
-		public static class UA05 extends Throwable {}
-		@RestMethod
-		public void ua05() throws UA05 {}
-
-		@Response(headers=@ResponseHeader(name="foo", api=" {type:'number'} "))
-		public static class UA06 extends Throwable {}
-		@RestMethod
-		public void ua06() throws UA06 {}
-	}
-
-	static Swagger ua = getSwagger(UA.class);
-
-	@Test
-	public void ua01_Response_onThrowable_basic() throws Exception {
-		ResponseInfo x = ua.getResponseInfo("/ua01","get",500);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
-		assertEquals("'a'", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void ua02_Response_onThrowable_api() throws Exception {
-		ResponseInfo x = ua.getResponseInfo("/ua02","get",500);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertObject(x.getHeaders()).json().is("{foo:{type:'string'}}");
-		assertObject(x.getExample()).json().is("'a'");
-		assertObject(x.getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void ua03_Response_onThrowable_mixed() throws Exception {
-		ResponseInfo x = ua.getResponseInfo("/ua03","get",500);
-		assertEquals("a\nb", x.getDescription());
-		assertObject(x.getSchema()).json().is("{type:'string'}");
-		assertObject(x.getHeaders()).json().is("{bar:{type:'number'},foo:{type:'string'}}");
-		assertEquals("'a'", x.getExample());
-		assertObject(x.getExamples()).json().is("{foo:'a'}");
-	}
-	@Test
-	public void ua04_Response_onThrowable_code() throws Exception {
-		ResponseInfo x = ua.getResponseInfo("/ua04","get",100);
-		assertEquals("Continue", x.getDescription());
-	}
-	@Test
-	public void ua05_Response_onThrowable_value() throws Exception {
-		ResponseInfo x = ua.getResponseInfo("/ua05","get",100);
-		assertEquals("Continue", x.getDescription());
-	}
-	@Test
-	public void ua06_Response_onThrowable_headers1() throws Exception {
-		ResponseInfo x = ua.getResponseInfo("/ua06","get",500);
-		assertObject(x.getHeaders()).json().is("{foo:{type:'number'}}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Schema
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class UB {
-
-		@Response(schema=@Schema(" type:'number' "))
-		public static class UB01 extends Throwable {}
-		@RestMethod
-		public void ub01() throws UB01 {}
-	}
-
-	static Swagger ub = getSwagger(UB.class);
-
-	@Test
-	public void ub01_Response_onThrowable_schemaValue() throws Exception {
-		ResponseInfo x = ub.getResponseInfo("/ub01","get",500);
-		assertObject(x.getSchema()).json().is("{type:'number'}");
-	}
-
-	//-----------------------------------------------------------------------------------------------------------------
-	// Examples
-	//-----------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class UC {
-
-		@Response(example={" {f1:'b'} "})
-		public static class UC01 extends Throwable {}
-		@RestMethod
-		public void uc01() throws UC01 {}
-
-		@Response(examples={" foo:'b' "})
-		public static class UC02 extends Throwable {}
-		@RestMethod
-		public void uc02() throws UC02 {}
-	}
-
-	static Swagger uc = getSwagger(UC.class);
-
-	@Test
-	public void uc01_Response_onThrowable_example() throws Exception {
-		ResponseInfo x = uc.getResponseInfo("/uc01","get",500);
-		assertEquals("{f1:'b'}", x.getExample());
-	}
-	@Test
-	public void uc02_Response_onThrowable_examples() throws Exception {
-		ResponseInfo x = uc.getResponseInfo("/uc02","get",500);
-		assertObject(x.getExamples()).json().is("{foo:'b'}");
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestMethodInheritTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestMethodInheritTest.java
deleted file mode 100644
index d98486d..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestMethodInheritTest.java
+++ /dev/null
@@ -1,322 +0,0 @@
-// ***************************************************************************************************************************

-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

-// * with the License.  You may obtain a copy of the License at                                                              *

-// *                                                                                                                         *

-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

-// *                                                                                                                         *

-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

-// * specific language governing permissions and limitations under the License.                                              *

-// ***************************************************************************************************************************

-package org.apache.juneau.rest.annotation2;

-

-import static org.junit.runners.MethodSorters.*;

-

-import java.io.IOException;

-import java.util.*;

-

-import org.apache.juneau.*;

-import org.apache.juneau.annotation.*;

-import org.apache.juneau.collections.*;

-import org.apache.juneau.encoders.*;

-import org.apache.juneau.http.annotation.HasQuery;

-import org.apache.juneau.json.*;

-import org.apache.juneau.parser.*;

-import org.apache.juneau.rest.*;

-import org.apache.juneau.rest.annotation.*;

-import org.apache.juneau.rest.mock2.*;

-import org.apache.juneau.serializer.*;

-import org.apache.juneau.transform.*;

-import org.junit.*;

-

-@FixMethodOrder(NAME_ASCENDING)

-public class RestMethodInheritTest {

-

-	//=================================================================================================================

-	// Setup classes

-	//=================================================================================================================

-

-	public static class DummyParser extends ReaderParser {

-		public DummyParser(String...consumes) {

-			super(PropertyStore.DEFAULT, consumes);

-		}

-		@Override /* Parser */

-		public ReaderParserSession createSession(ParserSessionArgs args) {

-			return new ReaderParserSession(args) {

-				@Override /* ParserSession */

-				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

-					return null;

-				}

-			};

-		}

-	}

-

-	public static class DummySerializer extends WriterSerializer {

-		public DummySerializer(String produces) {

-			super(PropertyStore.DEFAULT, produces, null);

-		}

-		@Override /* Serializer */

-		public WriterSerializerSession createSession(SerializerSessionArgs args) {

-			return new WriterSerializerSession(args) {

-				@Override /* SerializerSession */

-				protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException {

-					out.getWriter().write(o.toString());

-				}

-			};

-		}

-	}

-

-	public static class P1 extends DummyParser{ public P1(PropertyStore ps) {super("text/p1");} }

-	public static class P2 extends DummyParser{ public P2(PropertyStore ps) {super("text/p2");} }

-	public static class P3 extends DummyParser{ public P3(PropertyStore ps) {super("text/p3");} }

-	public static class P4 extends DummyParser{ public P4(PropertyStore ps) {super("text/p4");} }

-	public static class P5 extends DummyParser{ public P5(PropertyStore ps) {super("text/p5");} }

-

-	public static class S1 extends DummySerializer{ public S1(PropertyStore ps) {super("text/s1");} }

-	public static class S2 extends DummySerializer{ public S2(PropertyStore ps) {super("text/s2");} }

-	public static class S3 extends DummySerializer{ public S3(PropertyStore ps) {super("text/s3");} }

-	public static class S4 extends DummySerializer{ public S4(PropertyStore ps) {super("text/s4");} }

-	public static class S5 extends DummySerializer{ public S5(PropertyStore ps) {super("text/s5");} }

-

-	public static class E1 extends IdentityEncoder {

-		@Override public String[] getCodings() {

-			return new String[]{"e1"};

-		}

-	}

-	public static class E2 extends IdentityEncoder {

-		@Override public String[] getCodings() {

-			return new String[]{"e2"};

-		}

-	}

-	public static class E3 extends IdentityEncoder {

-		@Override public String[] getCodings() {

-			return new String[]{"e3"};

-		}

-	}

-	public static class E4 extends IdentityEncoder {

-		@Override public String[] getCodings() {

-			return new String[]{"e4"};

-		}

-	}

-

-	public static class Foo1 {@Override public String toString(){return "Foo1";}}

-	public static class Foo2 {@Override public String toString(){return "Foo2";}}

-	public static class Foo3 {@Override public String toString(){return "Foo3";}}

-

-	public static class F1Swap extends StringSwap<Foo1> {

-		@Override /* PojoSwap */

-		public String swap(BeanSession session, Foo1 o) throws SerializeException {

-			return "F1";

-		}

-	}

-	public static class F2Swap extends StringSwap<Foo2> {

-		@Override /* PojoSwap */

-		public String swap(BeanSession session, Foo2 o) throws SerializeException {

-			return "F2";

-		}

-	}

-	public static class F3Swap extends StringSwap<Foo3> {

-		@Override /* PojoSwap */

-		public String swap(BeanSession session, Foo3 o) throws SerializeException {

-			return "F3";

-		}

-	}

-

-	//=================================================================================================================

-	// Test serializer inheritance.

-	//=================================================================================================================

-

-	@Rest(serializers={S1.class,S2.class})

-	public static class A {}

-

-	@Rest(serializers={S3.class,S4.class,Inherit.class})

-	public static class A01 extends A {}

-

-	@Rest

-	public static class A02 extends A01 {

-		@RestMethod(path="/default")

-		public OList a01(RestResponse res) {

-			// Should show ['text/s3','text/s4','text/s1','text/s2']

-			return OList.ofAll(res.getSupportedMediaTypes());

-		}

-		@RestMethod(path="/onMethod", serializers=S5.class)

-		public OList a02(RestResponse res) {

-			// Should show ['text/s5']

-			return OList.ofAll(res.getSupportedMediaTypes());

-		}

-		@RestMethod(path="/onMethodInherit", serializers={S5.class,Inherit.class})

-		public OList a03(RestResponse res) {

-			// Should show ['text/s5','text/s3','text/s4','text/s1','text/s2']

-			return OList.ofAll(res.getSupportedMediaTypes());

-		}

-	}

-	static MockRestClient a = MockRestClient.build(A02.class);

-

-	@Test

-	public void a01_serializers_default() throws Exception {

-		a.get("/default").run().assertBody().is("['text/s3','text/s4','text/s1','text/s2']");

-	}

-	@Test

-	public void a02_serializers_onMethod() throws Exception {

-		a.get("/onMethod").run().assertBody().is("['text/s5']");

-	}

-	@Test

-	public void a03_serializers_onMethodInherit() throws Exception {

-		a.get("/onMethodInherit").run().assertBody().is("['text/s5','text/s3','text/s4','text/s1','text/s2']");

-	}

-

-	//=================================================================================================================

-	// Test parser inheritance.

-	//=================================================================================================================

-

-	@Rest(parsers={P1.class,P2.class})

-	public static class B {}

-

-	@Rest(parsers={P3.class,P4.class,Inherit.class})

-	public static class B01 extends B {}

-

-	@Rest

-	public static class B02 extends B01 {

-		@RestMethod(path="/default")

-		public OList b01(RestRequest req) {

-			// Should show ['text/p3','text/p4','text/p1','text/p2']

-			return OList.ofAll(req.getConsumes());

-		}

-		@RestMethod(path="/onMethod", parsers=P5.class)

-		public OList b02(RestRequest req) {

-			// Should show ['text/p5']

-			return OList.ofAll(req.getConsumes());

-		}

-		@RestMethod(path="/onMethodInherit", parsers={P5.class,Inherit.class})

-		public OList bo3(RestRequest req) {

-			// Should show ['text/p5','text/p3','text/p4','text/p1','text/p2']

-			return OList.ofAll(req.getConsumes());

-		}

-	}

-	static MockRestClient b = MockRestClient.build(B02.class);

-

-	@Test

-	public void b01_parsers_default() throws Exception {

-		b.get("/default").run().assertBody().is("['text/p3','text/p4','text/p1','text/p2']");

-	}

-	@Test

-	public void b02_parsers_onMethod() throws Exception {

-		b.get("/onMethod").run().assertBody().is("['text/p5']");

-	}

-	@Test

-	public void b03_parsers_onMethodInherit() throws Exception {

-		b.get("/onMethodInherit").run().assertBody().is("['text/p5','text/p3','text/p4','text/p1','text/p2']");

-	}

-

-	//=================================================================================================================

-	// Test filter inheritance.

-	//=================================================================================================================

-

-	@Rest

-	@BeanConfig(pojoSwaps={F1Swap.class})

-	public static class D {}

-

-	@Rest

-	@BeanConfig(pojoSwaps={F2Swap.class})

-	public static class D01 extends D {}

-

-	@Rest(serializers=SimpleJsonSerializer.class)

-	public static class D02 extends D01 {

-		@RestMethod

-		public Object[] d01() {

-			// Should show ['F1','F2','Foo3']

-			return new Object[]{new Foo1(), new Foo2(), new Foo3()};

-		}

-		@RestMethod(pojoSwaps={F3Swap.class,Inherit.class})

-		public Object[] d02() {

-			// Should show ['F1','F2','F3']

-			return new Object[]{new Foo1(), new Foo2(), new Foo3()};

-		}

-		@RestMethod(serializers=SimpleJsonSerializer.class, pojoSwaps=F3Swap.class)

-		public Object[] d03() {

-			// Should show ['Foo1','Foo2','F3']"

-			// Overriding serializer does not have parent filters applied.

-			return new Object[]{new Foo1(), new Foo2(), new Foo3()};

-		}

-		@RestMethod(serializers=SimpleJsonSerializer.class, pojoSwaps={F3Swap.class,Inherit.class})

-		public Object[] d04() {

-			// Should show ['F1','F2','F3']

-			return new Object[]{new Foo1(), new Foo2(), new Foo3()};

-		}

-	}

-	static MockRestClient d = MockRestClient.build(D02.class);

-

-	@Test

-	public void d01_transforms_default() throws Exception {

-		d.get("/d01").json().run().assertBody().is("['F1','F2','Foo3']");

-	}

-	@Test

-	public void d02_transforms_inheritTransforms() throws Exception {

-		d.get("/d02").json().run().assertBody().is("['F1','F2','F3']");

-	}

-	@Test

-	public void d03_transforms_overrideSerializer() throws Exception {

-		d.get("/d03").json().run().assertBody().is("['Foo1','Foo2','F3']");

-	}

-	@Test

-	public void d04_transforms_overrideSerializerInheritTransforms() throws Exception {

-		d.get("/d04").json().run().assertBody().is("['F1','F2','F3']");

-	}

-

-	//=================================================================================================================

-	// Test properties inheritance.

-	//=================================================================================================================

-

-	@Rest(reqAttrs={"p1:v1","p2:v2"})

-	public static class E {}

-

-	@Rest(reqAttrs={"p2:v2a","p3:v3","p4:v4"})

-	public static class E01 extends E {}

-

-	@Rest

-	public static class E02 extends E01 {

-		@RestMethod

-		public OMap e01(RequestAttributes attrs) {

-			// Should show {p1:'v1',p2:'v2a',p3:'v3',p4:'v4'}

-			return transform(attrs);

-		}

-		@RestMethod(reqAttrs={"p4:v4a","p5:v5"})

-		public OMap e02(RequestAttributes attrs, @HasQuery("override") boolean override) {

-			// Should show {p1:'v1',p2:'v2a',p3:'v3',p4:'v4a',p5:'v5'} when override is false.

-			// Should show {p1:'x',p2:'x',p3:'x',p4:'x',p5:'x'} when override is true.

-			if (override) {

-				attrs.put("p1", "x");

-				attrs.put("p2", "x");

-				attrs.put("p3", "x");

-				attrs.put("p4", "x");

-				attrs.put("p5", "x");

-			}

-			return transform(attrs);

-		}

-

-		private OMap transform(RequestAttributes attrs) {

-			OMap m = new OMap();

-			for (Map.Entry<String,Object> e : attrs.entrySet()) {

-				if (e.getKey().startsWith("p"))

-					m.put(e.getKey(), e.getValue());

-			}

-			return m;

-		}

-	}

-	static MockRestClient e = MockRestClient.build(E02.class);

-

-	@Test

-	public void e01_properties_default() throws Exception {

-		e.get("/e01").run().assertBody().is("{p1:'v1',p2:'v2a',p3:'v3',p4:'v4'}");

-	}

-	@Test

-	public void e02a_properties_override_false() throws Exception {

-		e.get("/e02").run().assertBody().is("{p1:'v1',p2:'v2a',p3:'v3',p4:'v4a',p5:'v5'}");

-	}

-	@Test

-	public void e02b_properties_override_true() throws Exception {

-		e.get("/e02?override").run().assertBody().is("{p1:'x',p2:'x',p3:'x',p4:'x',p5:'x'}");

-	}

-}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestResourceParsersTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestResourceParsersTest.java
deleted file mode 100644
index a471b99..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/annotation2/RestResourceParsersTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-// ***************************************************************************************************************************

-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

-// * with the License.  You may obtain a copy of the License at                                                              *

-// *                                                                                                                         *

-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

-// *                                                                                                                         *

-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

-// * specific language governing permissions and limitations under the License.                                              *

-// ***************************************************************************************************************************

-package org.apache.juneau.rest.annotation2;

-

-import static org.apache.juneau.http.HttpMethod.*;

-import static org.apache.juneau.internal.IOUtils.*;

-import static org.junit.runners.MethodSorters.*;

-

-import java.io.IOException;

-

-import org.apache.juneau.*;

-import org.apache.juneau.http.annotation.Body;

-import org.apache.juneau.parser.*;

-import org.apache.juneau.rest.*;

-import org.apache.juneau.rest.annotation.*;

-import org.apache.juneau.rest.mock2.*;

-import org.junit.*;

-

-@FixMethodOrder(NAME_ASCENDING)

-public class RestResourceParsersTest {

-

-	//=================================================================================================================

-	// Setup

-	//=================================================================================================================

-

-	public static class PA extends ReaderParser {

-		public PA(PropertyStore ps) {

-			super(ps, "text/a");

-		}

-		@Override /* Parser */

-		public ReaderParserSession createSession(ParserSessionArgs args) {

-			return new ReaderParserSession(args) {

-				@Override /* ParserSession */

-				@SuppressWarnings("unchecked")

-				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

-					return (T)("text/a - " + read(pipe.getReader()).trim());

-				}

-			};

-		}

-	}

-

-	public static class PB extends ReaderParser {

-		public PB(PropertyStore ps) {

-			super(ps, "text/b");

-		}

-		@Override /* Parser */

-		public ReaderParserSession createSession(ParserSessionArgs args) {

-			return new ReaderParserSession(args) {

-				@Override /* ParserSession */

-				@SuppressWarnings("unchecked")

-				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

-					return (T)("text/b - " + read(pipe.getReader()).trim());

-				}

-			};

-		}

-	}

-

-	public static class PC extends ReaderParser {

-		public PC(PropertyStore ps) {

-			super(ps, "text/c");

-		}

-		@Override /* Parser */

-		public ReaderParserSession createSession(ParserSessionArgs args) {

-			return new ReaderParserSession(args) {

-				@Override /* ParserSession */

-				@SuppressWarnings("unchecked")

-				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

-					return (T)("text/c - " + read(pipe.getReader()).trim());

-				}

-			};

-		}

-	}

-

-	public static class PD extends ReaderParser {

-		public PD(PropertyStore ps) {

-			super(ps, "text/d");

-		}

-		@Override /* Parser */

-		public ReaderParserSession createSession(ParserSessionArgs args) {

-			return new ReaderParserSession(args) {

-				@Override /* ParserSession */

-				@SuppressWarnings("unchecked")

-				protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {

-					return (T)("text/d - " + read(pipe.getReader()).trim());

-				}

-			};

-		}

-	}

-

-	//=================================================================================================================

-	// Basic tests

-	//=================================================================================================================

-

-	@Rest(parsers=PA.class)

-	public static class A {

-		@RestMethod(name=PUT, path="/parserOnClass")

-		public String a01(@Body String in) {

-			return in;

-		}

-		@RestMethod(name=PUT, path="/parserOnMethod", parsers=PB.class)

-		public String a02(@Body String in) {

-			return in;

-		}

-		@RestMethod(name=PUT, path="/parserOverriddenOnMethod", parsers={Inherit.class, PB.class,PC.class})

-		public String a03(@Body String in) {

-			return in;

-		}

-		@RestMethod(name=PUT, path="/parserWithDifferentMediaTypes", parsers={Inherit.class, PD.class})

-		public String a04(@Body String in) {

-			return in;

-		}

-		@RestMethod(name=PUT, path="/validErrorResponse")

-		public String a05(@Body String in) {

-			return in;

-		}

-	}

-	static MockRestClient a = MockRestClient.buildLax(A.class);

-

-	@Test

-	public void a01_parserOnClass() throws Exception {

-		a.put("/parserOnClass", "test1")

-			.contentType("text/a")

-			.run()

-			.assertBody().is("text/a - test1");

-		a.put("/parserOnClass?noTrace=true", "test1")

-			.contentType("text/b")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Content-Type': 'text/b'",

-				"Supported media-types: ['text/a"

-			);

-	}

-	@Test

-	public void a02_parserOnMethod() throws Exception {

-		a.put("/parserOnMethod", "test2")

-			.contentType("text/b")

-			.run()

-			.assertBody().is("text/b - test2");

-		a.put("/parserOnMethod?noTrace=true", "test2")

-			.contentType("text/a")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Content-Type': 'text/a'",

-				"Supported media-types: ['text/b']"

-			);

-	}

-	@Test

-	public void a03_parserOverriddenOnMethod() throws Exception {

-		a.put("/parserOverriddenOnMethod", "test3")

-			.contentType("text/a")

-			.run()

-			.assertBody().is("text/a - test3");

-		a.put("/parserOverriddenOnMethod", "test3")

-			.contentType("text/b")

-			.run()

-			.assertBody().is("text/b - test3");

-	}

-	@Test

-	public void a04_parserWithDifferentMediaTypes() throws Exception {

-		a.put("/parserWithDifferentMediaTypes", "test4")

-			.contentType("text/a")

-			.run()

-			.assertBody().is("text/a - test4");

-		a.put("/parserWithDifferentMediaTypes", "test4")

-			.contentType("text/d")

-			.run()

-			.assertBody().is("text/d - test4");

-	}

-	@Test

-	public void a05_validErrorResponse() throws Exception {

-		a.put("/validErrorResponse?noTrace=true", "test1")

-			.contentType("text/bad")

-			.run()

-			.assertCode().is(415)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Content-Type': 'text/bad'",

-				"Supported media-types: ['text/a"

-			);

-	}

-}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/guard/RoleMatcherTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/guards/RoleMatcher_Test.java
similarity index 99%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/guard/RoleMatcherTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/guards/RoleMatcher_Test.java
index 59a2b36..7533d62 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/guard/RoleMatcherTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/guards/RoleMatcher_Test.java
@@ -10,7 +10,7 @@
 // * "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.rest.guard;
+package org.apache.juneau.rest.guards;
 
 import static org.junit.Assert.*;
 import static org.junit.runners.MethodSorters.*;
@@ -20,11 +20,10 @@
 
 import org.apache.juneau.collections.*;
 import org.apache.juneau.internal.*;
-import org.apache.juneau.rest.guards.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RoleMatcherTest {
+public class RoleMatcher_Test {
 
 	private void shouldMatch(RoleMatcher m, String...input) {
 		for (String i : input)
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/AcceptCharsetTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/AcceptCharsetTest.java
deleted file mode 100644
index 5966da8..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/AcceptCharsetTest.java
+++ /dev/null
@@ -1,118 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.headers;
-
-import static org.apache.juneau.http.HttpMethod.*;
-import static org.junit.runners.MethodSorters.*;
-
-import java.io.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.http.annotation.Body;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.plaintext.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.apache.juneau.serializer.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class AcceptCharsetTest {
-
-	//=================================================================================================================
-	// Test that Q-values are being resolved correctly.
-	//=================================================================================================================
-
-	@Rest(defaultCharset="utf-8",serializers=PlainTextSerializer.class)
-	public static class A {
-		@RestMethod
-		public String qValues() {
-			return "foo";
-		}
-	}
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01_qValues() throws Exception {
-		a.get("/qValues").accept("text/plain").acceptCharset("utf-8").run().assertCharset().is("utf-8");
-		a.get("/qValues").accept("text/plain").acceptCharset("iso-8859-1").run().assertCharset().is("iso-8859-1");
-		a.get("/qValues").accept("text/plain").acceptCharset("bad,utf-8").run().assertCharset().is("utf-8");
-		a.get("/qValues").accept("text/plain").acceptCharset("utf-8,bad").run().assertCharset().is("utf-8");
-		a.get("/qValues").accept("text/plain").acceptCharset("bad;q=0.9,utf-8;q=0.1").run().assertCharset().is("utf-8");
-		a.get("/qValues").accept("text/plain").acceptCharset("bad;q=0.1,utf-8;q=0.9").run().assertCharset().is("utf-8");
-		a.get("/qValues").accept("text/plain").acceptCharset("utf-8;q=0.9,iso-8859-1;q=0.1").run().assertCharset().is("utf-8");
-		a.get("/qValues").accept("text/plain").acceptCharset("utf-8;q=0.1,iso-8859-1;q=0.9").run().assertCharset().is("iso-8859-1");
-		a.get("/qValues").accept("text/plain").acceptCharset("*").run().assertCharset().is("utf-8");
-		a.get("/qValues").accept("text/plain").acceptCharset("bad,iso-8859-1;q=0.5,*;q=0.1").run().assertCharset().is("iso-8859-1");
-		a.get("/qValues").accept("text/plain").acceptCharset("bad,iso-8859-1;q=0.1,*;q=0.5").run().assertCharset().is("utf-8");
-	}
-
-	//=================================================================================================================
-	// Validate various Accept-Charset variations.
-	//=================================================================================================================
-
-	@Rest(defaultCharset="utf-8")
-	public static class B {
-
-		@RestMethod(name=PUT, parsers=TestParser.class, serializers=TestSerializer.class)
-		public String charsetOnResponse(@Body String in) {
-			return in;
-		}
-
-		public static class TestParser extends InputStreamParser {
-			public TestParser(PropertyStore ps) {
-				super(ps, "text/plain");
-			}
-			@Override /* Parser */
-			public InputStreamParserSession createSession(final ParserSessionArgs args) {
-				return new InputStreamParserSession(args) {
-					@Override /* ParserSession */
-					@SuppressWarnings("unchecked")
-					protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws IOException, ParseException, ExecutableException {
-						return (T)args.getProperty(ReaderParser.RPARSER_streamCharset).toString();
-					}
-				};
-			}
-		}
-
-		public static class TestSerializer extends OutputStreamSerializer {
-			public TestSerializer(PropertyStore ps) {
-				super(ps, "text/plain", null);
-			}
-			@Override /* Serializer */
-			public OutputStreamSerializerSession createSession(SerializerSessionArgs args) {
-				return new OutputStreamSerializerSession(args) {
-					@Override /* SerializerSession */
-					protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException {
-						try (Writer w = new OutputStreamWriter(out.getOutputStream())) {
-							Object sc = args.getProperty(WriterSerializer.WSERIALIZER_streamCharset);
-							w.append(o.toString()).append('/').append(sc == null ? null : sc.toString());
-						}
-					}
-				};
-			}
-		}
-	}
-	static MockRestClient b = MockRestClient.buildLax(B.class);
-
-	@Test
-	public void b01_testCharsetOnResponse() throws Exception {
-		b.put("/charsetOnResponse", null).plainText().run().assertBody().is("UTF-8/UTF-8");
-		b.put("/charsetOnResponse", null).plainText().acceptCharset("Shift_JIS").run().assertBody().is("UTF-8/Shift_JIS");
-		b.put("/charsetOnResponse?noTrace=true", null).plainText().acceptCharset("BAD").run().assertCode().is(406).assertBody().contains("No supported charsets in header 'Accept-Charset': 'BAD'");
-		b.put("/charsetOnResponse", null).plainText().acceptCharset("UTF-8").run().assertBody().is("UTF-8/UTF-8");
-		b.put("/charsetOnResponse", null).plainText().acceptCharset("bad,iso-8859-1").run().assertBody().is("UTF-8/ISO-8859-1");
-		b.put("/charsetOnResponse", null).plainText().acceptCharset("bad;q=0.9,iso-8859-1;q=0.1").run().assertBody().is("UTF-8/ISO-8859-1");
-		b.put("/charsetOnResponse", null).plainText().acceptCharset("bad;q=0.1,iso-8859-1;q=0.9").run().assertBody().is("UTF-8/ISO-8859-1");
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/AcceptTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/AcceptTest.java
deleted file mode 100644
index f32dd99..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/AcceptTest.java
+++ /dev/null
@@ -1,281 +0,0 @@
-// ***************************************************************************************************************************

-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

-// * with the License.  You may obtain a copy of the License at                                                              *

-// *                                                                                                                         *

-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

-// *                                                                                                                         *

-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

-// * specific language governing permissions and limitations under the License.                                              *

-// ***************************************************************************************************************************

-package org.apache.juneau.rest.headers;

-

-import static org.apache.juneau.http.HttpMethod.*;

-import static org.junit.runners.MethodSorters.*;

-

-import java.io.IOException;

-

-import org.apache.juneau.*;

-import org.apache.juneau.http.annotation.Body;

-import org.apache.juneau.rest.*;

-import org.apache.juneau.rest.annotation.*;

-import org.apache.juneau.rest.mock2.*;

-import org.apache.juneau.serializer.*;

-import org.junit.*;

-

-@FixMethodOrder(NAME_ASCENDING)

-public class AcceptTest {

-

-	//=================================================================================================================

-	// Setup classes

-	//=================================================================================================================

-

-	public static class DummySerializer extends WriterSerializer {

-		String name;

-		DummySerializer(PropertyStore ps, String name, String produces) {

-			super(ps, produces, null);

-			this.name = name;

-		}

-		@Override /* Serializer */

-		public WriterSerializerSession createSession(SerializerSessionArgs args) {

-			return new WriterSerializerSession(args) {

-				@Override /* SerializerSession */

-				protected void doSerialize(SerializerPipe out, Object o) throws IOException, SerializeException {

-					out.getWriter().write(name);

-				}

-			};

-		}

-	}

-

-	public static class S1 extends DummySerializer { public S1(PropertyStore ps) {super(ps, "s1", "text/s1");}}

-	public static class S2 extends DummySerializer { public S2(PropertyStore ps) {super(ps, "s2", "text/s2");}}

-	public static class S3 extends DummySerializer { public S3(PropertyStore ps) {super(ps, "s3", "text/s3");}}

-

-	//=================================================================================================================

-	// Test that default Accept headers on servlet annotation are picked up.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Accept : text/s2 "},

-		serializers={S1.class,S2.class}

-	)

-	public static class A {

-		@RestMethod

-		public String putA01(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient a = MockRestClient.buildLax(A.class);

-

-	@Test

-	public void a01_defaultHeadersOnServletAnnotation_valid() throws Exception {

-		a.put("/a01", null)

-			.run()

-			.assertBody().is("s2");

-		a.put("/a01", null)

-			.accept("text/s1")

-			.run()

-			.assertBody().is("s1");

-		a.put("/a01", null)

-			.accept("text/s2")

-			.run()

-			.assertBody().is("s2");

-	}

-

-	@Test

-	public void a02_defaultHeadersOnServletAnnotation_invalid() throws Exception {

-		a.put("/a01?noTrace=true", null)

-			.accept("text/s3")

-			.run()

-			.assertCode().is(406)

-			.assertBody().contains("Unsupported media-type in request header 'Accept': 'text/s3'");

-	}

-

-	//=================================================================================================================

-	// Test that default Accept headers on servlet annotation are picked up

-	// when @RestMethod.parsers/serializers annotations are used.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Accept : text/s2 "},

-		serializers={S1.class,S2.class}

-	)

-	public static class B {

-		@RestMethod(name=PUT, serializers=S3.class)

-		public String b(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient b = MockRestClient.buildLax(B.class);

-

-	@Test

-	public void b01_restMethodWithParsersSerializers_valid() throws Exception {

-		b.put("/b", null).accept("text/s3").run().assertBody().is("s3");

-	}

-

-	@Test

-	public void b02_restMethodWithParsersSerializers_invalid() throws Exception {

-		b.put("/b?noTrace=true", null)

-			.accept("text/s4")

-			.run()

-			.assertCode().is(406)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Accept': 'text/s4'",

-				"Supported media-types: ['text/s3']"

-			);

-	}

-

-	//=================================================================================================================

-	// Test that default Accept headers on servlet annotation are picked up

-	// when @RestMethod.addParsers/addSerializers annotations are used.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Accept : text/s2 "},

-		serializers={S1.class,S2.class}

-	)

-	public static class C {

-		@RestMethod(name=PUT, serializers={S3.class,Inherit.class})

-		public String c(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient c = MockRestClient.buildLax(C.class);

-

-	@Test

-	public void c01_restMethodAddParsersSerializersInherit() throws Exception {

-		c.put("/c", null)

-			.run()

-			.assertBody().is("s2");

-		c.put("/c", null)

-			.accept("text/s1")

-			.run()

-			.assertBody().is("s1");

-		c.put("/c", null)

-			.accept("text/s2")

-			.run()

-			.assertBody().is("s2");

-		c.put("/c", null)

-			.accept("text/s3")

-			.run()

-			.assertBody().is("s3");

-	}

-

-	@Test

-	public void c02_restMethodAddParsersSerializersInherit_invalid() throws Exception {

-		c.put("/c?noTrace=true", null)

-			.accept("text/s4")

-			.run()

-			.assertCode().is(406)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Accept': 'text/s4'",

-				"Supported media-types: ['text/s3','text/s1','text/s2']"

-			);

-	}

-

-	//=================================================================================================================

-	// Various Accept incantations.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Accept : text/s2 "},

-		serializers={S1.class,S2.class}

-	)

-	public static class D {

-		@RestMethod(name=PUT)

-		public String d(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient d = MockRestClient.buildLax(D.class);

-

-	@Test

-	public void d01_accept_valid() throws Exception {

-		// "*/*" should match the first serializer, not the default serializer.

-		d.put("/d", null).accept("*/*").run().assertBody().is("s1");

-		// "text/*" should match the first serializer, not the default serializer.

-		d.put("/d", null).accept("text/*").run().assertBody().is("s1");

-		d.put("/d", null).accept("bad/*,text/*").run().assertBody().is("s1");

-		d.put("/d", null).accept("text/*,bad/*").run().assertBody().is("s1");

-		d.put("/d", null).accept("text/s1;q=0.5,text/s2").run().assertBody().is("s2");

-		d.put("/d", null).accept("text/s1,text/s2;q=0.5").run().assertBody().is("s1");

-	}

-	@Test

-	public void d02_accept_invalid() throws Exception {

-		d.put("/d?noTrace=true", null)

-			.accept("bad/*")

-			.run()

-			.assertCode().is(406)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Accept': 'bad/*'",

-				"Supported media-types: ['text/s1','text/s2']"

-			);

-	}

-

-	//=================================================================================================================

-	// Test that default Accept headers on method annotation are picked up

-	// when @RestMethod.parsers/serializers annotations are used.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Accept : text/s2 "},

-		serializers={S1.class,S2.class}

-	)

-	public static class E {

-		@RestMethod(name=PUT, reqHeaders={"Accept: text/s3"}, serializers=S3.class)

-		public String d(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient e = MockRestClient.buildLax(E.class);

-

-	@Test

-	public void e01_restMethodParserSerializerAnnotations_valid() throws Exception {

-		e.put("/d", null).run().assertBody().is("s3");

-		e.put("/d", null).accept("text/s3").run().assertBody().is("s3");

-	}

-	@Test

-	public void e02_restMethodParserSerializerAnnotations_invalid() throws Exception {

-		e.put("/d?noTrace=true", null)

-			.accept("text/s1")

-			.run()

-			.assertCode().is(406)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Accept': 'text/s1'",

-				"Supported media-types: ['text/s3']"

-			);

-		e.put("/d?noTrace=true", null).accept("text/s2").run()

-			.assertCode().is(406)

-			.assertBody().contains(

-				"Unsupported media-type in request header 'Accept': 'text/s2'",

-				"Supported media-types: ['text/s3']"

-			);

-	}

-

-	//=================================================================================================================

-	// Test that default Accept headers on method annotation are picked up

-	// 	when @RestMethod.addParsers/addSerializers annotations are used.

-	//=================================================================================================================

-

-	@Rest(

-		reqHeaders={" Accept : text/s2 ",},

-		serializers={S1.class,S2.class}

-	)

-	public static class F {

-		@RestMethod(name=PUT, reqHeaders={"Accept: text/s3"}, serializers={Inherit.class, S3.class})

-		public String f(@Body String in) {

-			return in;

-		}

-	}

-	private static MockRestClient f = MockRestClient.build(F.class);

-

-	@Test

-	public void f01_restMethodAddParsersSerializersAnnotations_valid() throws Exception {

-		f.put("/f", null).run().assertBody().is("s3");

-		f.put("/f", null).accept("text/s1").run().assertBody().is("s1");

-		f.put("/f", null).accept("text/s2").run().assertBody().is("s2");

-		f.put("/f", null).accept("text/s3").run().assertBody().is("s3");

-	}

-}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/HeadersTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/HeadersTest.java
deleted file mode 100644
index ead49cd..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/HeadersTest.java
+++ /dev/null
@@ -1,792 +0,0 @@
-// ***************************************************************************************************************************

-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *

-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *

-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *

-// * with the License.  You may obtain a copy of the License at                                                              *

-// *                                                                                                                         *

-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *

-// *                                                                                                                         *

-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *

-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *

-// * specific language governing permissions and limitations under the License.                                              *

-// ***************************************************************************************************************************

-package org.apache.juneau.rest.headers;

-

-import static org.apache.juneau.assertions.Assertions.*;

-import static org.apache.juneau.rest.testutils.TestUtils.*;

-import static org.junit.runners.MethodSorters.*;

-

-import org.apache.juneau.*;

-import org.apache.juneau.collections.*;

-import org.apache.juneau.dto.swagger.*;

-import org.apache.juneau.encoders.*;

-import org.apache.juneau.http.annotation.Header;

-import org.apache.juneau.http.header.*;

-import org.apache.juneau.plaintext.*;

-import org.apache.juneau.rest.*;

-import org.apache.juneau.rest.annotation.*;

-import org.apache.juneau.rest.mock2.*;

-import org.junit.*;

-

-@FixMethodOrder(NAME_ASCENDING)

-public class HeadersTest {

-

-	//====================================================================================================

-	// HTTP 1.1 headers

-	//====================================================================================================

-

-	@Rest(

-		serializers=AnythingSerializer.class,

-		parsers=AnythingParser.class,

-		encoders=AnythingEncoder.class,

-		allowedHeaderParams="*"

-	)

-	public static class A {

-

-		@RestMethod

-		public String accept(Accept accept) {

-			return accept.getValue();

-		}

-		@RestMethod

-		public String acceptCharset(AcceptCharset acceptCharset) {

-			return acceptCharset.getValue();

-		}

-		@RestMethod

-		public String acceptEncoding(AcceptEncoding acceptEncoding) {

-			return acceptEncoding.getValue();

-		}

-		@RestMethod

-		public String acceptLanguage(AcceptLanguage acceptLanguage) {

-			return acceptLanguage.getValue();

-		}

-		@RestMethod

-		public String authorization(Authorization authorization) {

-			return authorization.getValue();

-		}

-		@RestMethod

-		public String cacheControl(CacheControl cacheControl) {

-			return cacheControl.getValue();

-		}

-		@RestMethod

-		public String connection(Connection connection) {

-			return connection.getValue();

-		}

-		@RestMethod

-		public String contentLength(ContentLength contentLength) {

-			return contentLength.getValue();

-		}

-		@RestMethod

-		public String contentType(ContentType contentType) {

-			return contentType.getValue();

-		}

-		@RestMethod

-		public String date(org.apache.juneau.http.header.Date date) {

-			return date.getValue();

-		}

-		@RestMethod

-		public String expect(Expect expect) {

-			return expect.getValue();

-		}

-		@RestMethod

-		public String from(From from) {

-			return from.getValue();

-		}

-		@RestMethod

-		public String host(Host host) {

-			return host.getValue();

-		}

-		@RestMethod

-		public String ifMatch(IfMatch ifMatch) {

-			return ifMatch.getValue();

-		}

-		@RestMethod

-		public String ifModifiedSince(IfModifiedSince ifModifiedSince) {

-			return ifModifiedSince.getValue();

-		}

-		@RestMethod

-		public String ifNoneMatch(IfNoneMatch ifNoneMatch) {

-			return ifNoneMatch.getValue();

-		}

-		@RestMethod

-		public String ifRange(IfRange ifRange) {

-			return ifRange.getValue();

-		}

-		@RestMethod

-		public String ifUnmodifiedSince(IfUnmodifiedSince ifUnmodifiedSince) {

-			return ifUnmodifiedSince.getValue();

-		}

-		@RestMethod

-		public String maxForwards(MaxForwards maxForwards) {

-			return maxForwards.getValue();

-		}

-		@RestMethod

-		public String pragma(Pragma pragma) {

-			return pragma.getValue();

-		}

-		@RestMethod

-		public String proxyAuthorization(ProxyAuthorization proxyAuthorization) {

-			return proxyAuthorization.getValue();

-		}

-		@RestMethod

-		public String range(Range range) {

-			return range.getValue();

-		}

-		@RestMethod

-		public String referer(Referer referer) {

-			return referer.getValue();

-		}

-		@RestMethod

-		public String te(TE te) {

-			return te.getValue();

-		}

-		@RestMethod

-		public String upgrade(Upgrade upgrade) {

-			return upgrade.getValue();

-		}

-		@RestMethod

-		public String userAgent(UserAgent userAgent) {

-			return userAgent.getValue();

-		}

-		@RestMethod

-		public String warning(Warning warning) {

-			return warning.getValue();

-		}

-	}

-	private static MockRestClient a = MockRestClient.build(A.class);

-

-	public static class AnythingSerializer extends PlainTextSerializer {

-		public AnythingSerializer(PropertyStore ps) {

-			super(ps, "text/plain", "*/*");

-		}

-	}

-

-	public static class AnythingParser extends PlainTextParser {

-		public AnythingParser(PropertyStore ps) {

-			super(ps, "*/*");

-		}

-	}

-

-	public static class AnythingEncoder extends IdentityEncoder {

-		@Override /* ConfigEncoder */

-		public String[] getCodings() {

-			return new String[]{"*"};

-		}

-	}

-

-	@Test

-	public void a01a_accept() throws Exception {

-		a.get("/accept").accept("text/foo").run().assertBody().is("text/foo");

-		a.get("/accept").accept("text/foo+bar").run().assertBody().is("text/foo+bar");

-		a.get("/accept").accept("text/*").run().assertBody().is("text/*");

-		a.get("/accept").accept("*/foo").run().assertBody().is("*/foo");

-	}

-	@Test

-	public void a01b_accept_qValues() throws Exception {

-		a.get("/accept").accept("text/foo;q=1.0").run().assertBody().is("text/foo");

-		a.get("/accept").accept("text/foo;q=0.9").run().assertBody().is("text/foo;q=0.9");

-		a.get("/accept").accept("text/foo;x=X;q=0.9;y=Y").run().assertBody().is("text/foo;x=X;q=0.9;y=Y");

-	}

-	@Test

-	public void a01b_accept_query() throws Exception {

-		a.get("/accept?Accept=text/foo").run().assertBody().is("text/foo");

-	}

-	@Test

-	public void a02a_acceptCharset() throws Exception {

-		a.get("/acceptCharset").acceptCharset("UTF-8").run().assertBody().is("UTF-8");

-	}

-	@Test

-	public void a02b_acceptCharset_query() throws Exception {

-		a.get("/acceptCharset?Accept-Charset=UTF-8").run().assertBody().is("UTF-8");

-	}

-	@Test

-	public void a03a_acceptEncoding() throws Exception {

-		a.get("/acceptEncoding").acceptEncoding("foo").run().assertBody().is("foo");

-		a.get("/acceptEncoding").acceptEncoding("*").run().assertBody().is("*");

-	}

-	@Test

-	public void a03b_acceptEncoding_query() throws Exception {

-		a.get("/acceptEncoding?Accept-Encoding=*").run().assertBody().is("*");

-	}

-	@Test

-	public void a04a_acceptLanguage() throws Exception {

-		a.get("/acceptLanguage").acceptLanguage("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a04b_acceptLanguage_query() throws Exception {

-		a.get("/acceptLanguage?Accept-Language=foo").acceptLanguage("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a05a_authorization() throws Exception {

-		a.get("/authorization").authorization("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a05b_authorization_query() throws Exception {

-		a.get("/authorization?Authorization=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a06a_cacheControl() throws Exception {

-		a.get("/cacheControl").cacheControl("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a06b_cacheControl_query() throws Exception {

-		a.get("/cacheControl?Cache-Control=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a07a_connection() throws Exception {

-		a.get("/connection").connection("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a07b_connection_query() throws Exception {

-		a.get("/connection?Connection=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a08a_contentLength() throws Exception {

-		a.get("/contentLength").contentLength(0).run().assertBody().is("0");

-	}

-	@Test

-	public void a08b_contentLength_query() throws Exception {

-		a.get("/contentLength?Content-Length=0").run().assertBody().is("0");

-	}

-	@Test

-	public void a09a_contentType() throws Exception {

-		a.get("/contentType").contentType("text/foo").run().assertBody().is("text/foo");

-	}

-	@Test

-	public void a09b_contentType_query() throws Exception {

-		a.get("/contentType?Content-Type=text/foo").run().assertBody().is("text/foo");

-	}

-	@Test

-	public void a10a_date() throws Exception {

-		a.get("/date").date("Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");

-	}

-	@Test

-	public void a10b_date_query() throws Exception {

-		a.get("/date?Date=Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");

-	}

-	@Test

-	public void a11a_expect() throws Exception {

-		a.get("/expect").expect("100-continue").run().assertBody().is("100-continue");

-	}

-	@Test

-	public void a11b_expect_query() throws Exception {

-		a.get("/expect?Expect=100-continue").run().assertBody().is("100-continue");

-	}

-	@Test

-	public void a12a_from() throws Exception {

-		a.get("/from").from("foo").run().assertBody().is("foo");

-	}

-	public void a12b_from_query() throws Exception {

-		a.get("/from?From=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a13a_host() throws Exception {

-		a.get("/host").host("localhost").run().assertBody().is("localhost");

-	}

-	@Test

-	public void a13b_host_query() throws Exception {

-		a.get("/host?Host=localhost").run().assertBody().is("localhost");

-	}

-	@Test

-	public void a14a_ifMatch() throws Exception {

-		a.get("/ifMatch").ifMatch("\"foo\"").run().assertBody().is("\"foo\"");

-		a.get("/ifMatch").ifMatch("W/\"foo\"").run().assertBody().is("W/\"foo\"");

-		a.get("/ifMatch").ifMatch("W/\"foo\",\"bar\"").run().assertBody().is("W/\"foo\",\"bar\"");

-	}

-	@Test

-	public void a14b_ifMatch_query() throws Exception {

-		a.get("/ifMatch?If-Match=\"foo\"").run().assertBody().is("\"foo\"");

-	}

-	@Test

-	public void a15a_ifModifiedSince() throws Exception {

-		a.get("/ifModifiedSince").ifModifiedSince("Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");

-	}

-	@Test

-	public void a15b_ifModifiedSince_query() throws Exception {

-		a.get("/ifModifiedSince?If-Modified-Since=Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");

-	}

-	@Test

-	public void a16a_ifNoneMatch() throws Exception {

-		a.get("/ifNoneMatch").ifNoneMatch("\"foo\"").run().assertBody().is("\"foo\"");

-		a.get("/ifNoneMatch").ifNoneMatch("W/\"foo\"").run().assertBody().is("W/\"foo\"");

-		a.get("/ifNoneMatch").ifNoneMatch("W/\"foo\",\"bar\"").run().assertBody().is("W/\"foo\",\"bar\"");

-	}

-	@Test

-	public void a16b_ifNoneMatch_query() throws Exception {

-		a.get("/ifNoneMatch?If-None-Match=\"foo\"").run().assertBody().is("\"foo\"");

-	}

-	@Test

-	public void a17a_ifRange() throws Exception {

-		a.get("/ifRange").ifRange("\"foo\"").run().assertBody().is("\"foo\"");

-	}

-	@Test

-	public void a17b_ifRange_query() throws Exception {

-		a.get("/ifRange?If-Range=\"foo\"").run().assertBody().is("\"foo\"");

-	}

-	@Test

-	public void a18a_ifUnmodifiedSince() throws Exception {

-		a.get("/ifUnmodifiedSince").ifUnmodifiedSince("Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");

-	}

-	@Test

-	public void a18b_ifUnmodifiedSince_query() throws Exception {

-		a.get("/ifUnmodifiedSince?If-Unmodified-Since=Wed, 21 Oct 2015 07:28:00 GMT").run().assertBody().is("Wed, 21 Oct 2015 07:28:00 GMT");

-	}

-	@Test

-	public void a19a_maxForwards() throws Exception {

-		a.get("/maxForwards").maxForwards(123).run().assertBody().is("123");

-	}

-	@Test

-	public void a19b_maxForwards_query() throws Exception {

-		a.get("/maxForwards?Max-Forwards=123").run().assertBody().is("123");

-	}

-	@Test

-	public void a20a_pragma() throws Exception {

-		a.get("/pragma").pragma("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a20b_pragma_query() throws Exception {

-		a.get("/pragma?Pragma=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a21a_proxyAuthorization() throws Exception {

-		a.get("/proxyAuthorization").proxyAuthorization("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a21b_proxyAuthorization_query() throws Exception {

-		a.get("/proxyAuthorization?Proxy-Authorization=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a22a_range() throws Exception {

-		a.get("/range").range("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a22b_range_query() throws Exception {

-		a.get("/range?Range=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a23a_referer() throws Exception {

-		a.get("/referer").referer("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a23b_referer_query() throws Exception {

-		a.get("/referer?Referer=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a24a_te() throws Exception {

-		a.get("/te").te("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a24b_te_query() throws Exception {

-		a.get("/te?TE=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a25a_upgrade() throws Exception {

-		a.get("/upgrade").upgrade("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a25b_upgrade_query() throws Exception {

-		a.get("/upgrade?Upgrade=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a26a_userAgent() throws Exception {

-		a.get("/userAgent").userAgent("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a26b_userAgent_query() throws Exception {

-		a.get("/userAgent?User-Agent=foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a27a_warning() throws Exception {

-		a.get("/warning").warning("foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void a27b_warning_query() throws Exception {

-		a.get("/warning?Warning=foo").run().assertBody().is("foo");

-	}

-

-	//====================================================================================================

-	// Custom header.

-	//====================================================================================================

-

-	@Rest(

-		paramResolvers=CustomHeaderParam.class,

-		allowedHeaderParams="Custom"

-	)

-	public static class B {

-		@RestMethod

-		public String customHeader(CustomHeader customHeader) {

-			return customHeader.toString();

-		}

-	}

-	static MockRestClient b = MockRestClient.build(B.class);

-

-	public static class CustomHeaderParam extends RestMethodParam {

-		public CustomHeaderParam() {

-			super(RestParamType.HEADER, "Custom", CustomHeader.class);

-		}

-		@Override

-		public Object resolve(RestRequest req, RestResponse res) throws Exception {

-			return new CustomHeader(req.getHeader("Custom"));

-		}

-	}

-

-	public static class CustomHeader {

-		public String value;

-		public CustomHeader(String value) {

-			this.value = value;

-		}

-		@Override

-		public String toString() {

-			return value;

-		}

-	}

-

-	@Test

-	public void b01a_customHeader() throws Exception {

-		b.get("/customHeader").header("Custom", "foo").run().assertBody().is("foo");

-	}

-	@Test

-	public void b01b_customHeader_query() throws Exception {

-		b.get("/customHeader?Custom=foo").run().assertBody().is("foo");

-	}

-

-	//====================================================================================================

-	// Default values - Default request headers

-	//====================================================================================================

-

-	@Rest

-	public static class C {

-		@RestMethod(reqHeaders={"H1:1","H2=2"," H3 : 3 "})

-		public OMap c(RequestHeaders headers) {

-			return OMap.of()

-				.a("h1", headers.getString("H1"))

-				.a("h2", headers.getString("H2"))

-				.a("h3", headers.getString("H3"));

-		}

-	}

-	static MockRestClient c = MockRestClient.build(C.class);

-

-	@Test

-	public void c01_reqHeaders_default() throws Exception {

-		c.get("/c").run().assertBody().is("{h1:'1',h2:'2',h3:'3'}");

-	}

-	@Test

-	public void c02_reqHeaders_override() throws Exception {

-		c.get("/c").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-	@Test

-	public void c03_reqHeaders_override_caseInsensitive() throws Exception {

-		c.get("/c").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-

-	//====================================================================================================

-	// Default values - Default request headers, case-insensitive matching

-	//====================================================================================================

-

-	@Rest

-	public static class D {

-		@RestMethod(reqHeaders={"H1:1","H2=2"," H3 : 3 "})

-		public OMap d(RequestHeaders headers) {

-			return OMap.of()

-				.a("h1", headers.getString("h1"))

-				.a("h2", headers.getString("h2"))

-				.a("h3", headers.getString("h3"));

-		}

-	}

-	static MockRestClient d = MockRestClient.build(D.class);

-

-	@Test

-	public void d01_reqHeadersCaseInsensitive_default() throws Exception {

-		d.get("/d").run().assertBody().is("{h1:'1',h2:'2',h3:'3'}");

-	}

-	@Test

-	public void d02_reqHeadersCaseInsensitive_override() throws Exception {

-		d.get("/d").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-	@Test

-	public void d03_reqHeadersCaseInsensitive_override_caseInsensitive() throws Exception {

-		d.get("/d").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-

-	//====================================================================================================

-	// Default values - Annotated headers.

-	//====================================================================================================

-

-	@Rest

-	public static class E {

-		@RestMethod

-		public OMap e(@Header(name="H1") String h1, @Header("H2") String h2, @Header("H3") String h3) {

-			return OMap.of()

-				.a("h1", h1)

-				.a("h2", h2)

-				.a("h3", h3);

-		}

-	}

-	static MockRestClient e = MockRestClient.build(E.class);

-

-	@Test

-	public void e01_annotatedHeaders_default() throws Exception {

-		e.get("/e").run().assertBody().is("{h1:null,h2:null,h3:null}");

-	}

-	@Test

-	public void e02_annotatedHeaders_override() throws Exception {

-		e.get("/e").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-	@Test

-	public void e03_annotatedHeaders_override_caseInsensitive() throws Exception {

-		e.get("/e").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-

-	//====================================================================================================

-	// Default values - Annotated headers, case-insensitive matching.

-	//====================================================================================================

-

-	@Rest

-	public static class F {

-		@RestMethod

-		public OMap f(@Header("h1") String h1, @Header("h2") String h2, @Header("h3") String h3) {

-			return OMap.of()

-				.a("h1", h1)

-				.a("h2", h2)

-				.a("h3", h3);

-		}

-	}

-	static MockRestClient f = MockRestClient.build(F.class);

-

-	@Test

-	public void f01_annotatedHeadersCaseInsensitive_default() throws Exception {

-		f.get("/f").run().assertBody().is("{h1:null,h2:null,h3:null}");

-	}

-	@Test

-	public void f02_annotatedHeadersCaseInsensitive_override() throws Exception {

-		f.get("/f").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-	@Test

-	public void f03_annotatedHeadersCaseInsensitive_override_caseInsensitive() throws Exception {

-		f.get("/f").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-

-	//====================================================================================================

-	// Default values - Annotated headers with default values.

-	//====================================================================================================

-

-	@Rest

-	public static class G {

-		@RestMethod

-		public OMap g(@Header(name="h1",_default="1") String h1, @Header(name="h2",_default="2") String h2, @Header(name="h3",_default="3") String h3) {

-			return OMap.of()

-				.a("h1", h1)

-				.a("h2", h2)

-				.a("h3", h3);

-		}

-	}

-	static MockRestClient g = MockRestClient.build(G.class);

-

-	@Test

-	public void g01_annotatedHeadersDefault_default() throws Exception {

-		g.get("/g").run().assertBody().is("{h1:'1',h2:'2',h3:'3'}");

-	}

-	@Test

-	public void g02_annotatedHeadersDefault_override() throws Exception {

-		g.get("/g").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-	@Test

-	public void g03_annotatedHeadersDefault_override_caseInsensitive() throws Exception {

-		g.get("/g").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-

-	@Rest

-	public static class GB {

-		@RestMethod

-		public OMap g(@Header(value="h1",_default="1") String h1, @Header(value="h2",_default="2") String h2, @Header(value="h3",_default="3") String h3) {

-			return OMap.of()

-				.a("h1", h1)

-				.a("h2", h2)

-				.a("h3", h3);

-		}

-	}

-	static MockRestClient gb = MockRestClient.build(GB.class);

-

-	@Test

-	public void gb01_annotatedHeadersDefault_default() throws Exception {

-		gb.get("/g").run().assertBody().is("{h1:'1',h2:'2',h3:'3'}");

-	}

-	@Test

-	public void gb02_annotatedHeadersDefault_override() throws Exception {

-		gb.get("/g").header("H1",4).header("H2",5).header("H3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-	@Test

-	public void gb03_annotatedHeadersDefault_override_caseInsensitive() throws Exception {

-		gb.get("/g").header("h1",4).header("h2",5).header("h3",6).run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-

-	//====================================================================================================

-	// Default values - Annotated headers with default values and default request headers.

-	//====================================================================================================

-

-	@Rest

-	public static class H {

-		@RestMethod(reqHeaders={"H1:1","H2=2"," H3 : 3 "})

-		public OMap h(@Header(value="h1",_default="4") String h1, @Header(value="h2",_default="5") String h2, @Header(value="h3",_default="6") String h3) {

-			return OMap.of()

-				.a("h1", h1)

-				.a("h2", h2)

-				.a("h3", h3);

-		}

-	}

-	static MockRestClient h = MockRestClient.build(H.class);

-

-	@Test

-	public void h01_annotatedAndDefaultHeaders_default() throws Exception {

-		h.get("/h").run().assertBody().is("{h1:'4',h2:'5',h3:'6'}");

-	}

-	@Test

-	public void h02_annotatedAndDefaultHeaders_override() throws Exception {

-		h.get("/h").header("H1",7).header("H2",8).header("H3",9).run().assertBody().is("{h1:'7',h2:'8',h3:'9'}");

-	}

-	@Test

-	public void h03_annotatedAndDefaultHeaders_override_caseInsensitive() throws Exception {

-		h.get("/h").header("h1",7).header("h2",8).header("h3",9).run().assertBody().is("{h1:'7',h2:'8',h3:'9'}");

-	}

-

-	//====================================================================================================

-	// Swagger on default headers.

-	//====================================================================================================

-

-	Swagger sa = getSwagger(A.class);

-

-	@Test

-	public void sa01_accept() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/accept","get","header","Accept");

-		assertObject(pi).json().is("{'in':'header',name:'Accept',type:'string'}");

-	}

-	@Test

-	public void sa02_acceptCharset() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/acceptCharset","get","header","Accept-Charset");

-		assertObject(pi).json().is("{'in':'header',name:'Accept-Charset',type:'string'}");

-	}

-	@Test

-	public void sa03_acceptEncoding() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/acceptEncoding","get","header","Accept-Encoding");

-		assertObject(pi).json().is("{'in':'header',name:'Accept-Encoding',type:'string'}");

-	}

-	@Test

-	public void sa04_acceptLanguage() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/acceptLanguage","get","header","Accept-Language");

-		assertObject(pi).json().is("{'in':'header',name:'Accept-Language',type:'string'}");

-	}

-	@Test

-	public void sa05_authorization() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/authorization","get","header","Authorization");

-		assertObject(pi).json().is("{'in':'header',name:'Authorization',type:'string'}");

-	}

-	@Test

-	public void sa06_cacheControl() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/cacheControl","get","header","Cache-Control");

-		assertObject(pi).json().is("{'in':'header',name:'Cache-Control',type:'string'}");

-	}

-	@Test

-	public void sa07_connection() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/connection","get","header","Connection");

-		assertObject(pi).json().is("{'in':'header',name:'Connection',type:'string'}");

-	}

-	@Test

-	public void sa08_contentLength() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/contentLength","get","header","Content-Length");

-		assertObject(pi).json().is("{'in':'header',name:'Content-Length',type:'integer',format:'int64'}");

-	}

-	@Test

-	public void sa09_contentType() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/contentType","get","header","Content-Type");

-		assertObject(pi).json().is("{'in':'header',name:'Content-Type',type:'string'}");

-	}

-	@Test

-	public void sa10_date() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/date","get","header","Date");

-		assertObject(pi).json().is("{'in':'header',name:'Date',type:'string'}");

-	}

-	@Test

-	public void sa11_expect() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/expect","get","header","Expect");

-		assertObject(pi).json().is("{'in':'header',name:'Expect',type:'string'}");

-	}

-	@Test

-	public void sa12_() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/from","get","header","From");

-		assertObject(pi).json().is("{'in':'header',name:'From',type:'string'}");

-	}

-	@Test

-	public void sa13_host() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/host","get","header","Host");

-		assertObject(pi).json().is("{'in':'header',name:'Host',type:'string'}");

-	}

-	@Test

-	public void sa14_ifMatch() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/ifMatch","get","header","If-Match");

-		assertObject(pi).json().is("{'in':'header',name:'If-Match',type:'string'}");

-	}

-	@Test

-	public void sa15_ifModifiedSince() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/ifModifiedSince","get","header","If-Modified-Since");

-		assertObject(pi).json().is("{'in':'header',name:'If-Modified-Since',type:'string'}");

-	}

-	@Test

-	public void sa16_ifNoneMatch() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/ifNoneMatch","get","header","If-None-Match");

-		assertObject(pi).json().is("{'in':'header',name:'If-None-Match',type:'string'}");

-	}

-	@Test

-	public void sa17_ifRange() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/ifRange","get","header","If-Range");

-		assertObject(pi).json().is("{'in':'header',name:'If-Range',type:'string'}");

-	}

-	@Test

-	public void sa18_ifUnmodifiedSince() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/ifUnmodifiedSince","get","header","If-Unmodified-Since");

-		assertObject(pi).json().is("{'in':'header',name:'If-Unmodified-Since',type:'string'}");

-	}

-	@Test

-	public void sa19_maxForwards() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/maxForwards","get","header","Max-Forwards");

-		assertObject(pi).json().is("{'in':'header',name:'Max-Forwards',type:'integer',format:'int32'}");

-	}

-	@Test

-	public void sa20_pragma() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/pragma","get","header","Pragma");

-		assertObject(pi).json().is("{'in':'header',name:'Pragma',type:'string'}");

-	}

-	@Test

-	public void sa21_proxyAuthorization() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/proxyAuthorization","get","header","Proxy-Authorization");

-		assertObject(pi).json().is("{'in':'header',name:'Proxy-Authorization',type:'string'}");

-	}

-	@Test

-	public void sa22_range() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/range","get","header","Range");

-		assertObject(pi).json().is("{'in':'header',name:'Range',type:'string'}");

-	}

-	@Test

-	public void sa23_referer() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/referer","get","header","Referer");

-		assertObject(pi).json().is("{'in':'header',name:'Referer',type:'string'}");

-	}

-	@Test

-	public void sa24_te() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/te","get","header","TE");

-		assertObject(pi).json().is("{'in':'header',name:'TE',type:'string'}");

-	}

-	@Test

-	public void sa25_upgrade() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/upgrade","get","header","Upgrade");

-		assertObject(pi).json().is("{'in':'header',name:'Upgrade',type:'string'}");

-	}

-	@Test

-	public void sa26_userAgent() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/userAgent","get","header","User-Agent");

-		assertObject(pi).json().is("{'in':'header',name:'User-Agent',type:'string'}");

-	}

-	@Test

-	public void sa27_warning() throws Exception {

-		ParameterInfo pi = sa.getParameterInfo("/warning","get","header","Warning");

-		assertObject(pi).json().is("{'in':'header',name:'Warning',type:'string'}");

-	}

-}

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/BasicHttpResourceTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/BasicHttpResourceTest.java
deleted file mode 100644
index eed5d18..0000000
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/BasicHttpResourceTest.java
+++ /dev/null
@@ -1,117 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.helper;
-
-import static org.junit.runners.MethodSorters.*;
-
-import java.io.*;
-
-import org.apache.juneau.http.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.mock2.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class BasicHttpResourceTest {
-
-	@Rest
-	public static class A {
-
-		@RestMethod
-		public BasicHttpResource a01() throws Exception {
-			return BasicHttpResource.of("foo");
-		}
-
-		@RestMethod
-		public BasicHttpResource a02() throws Exception {
-			return BasicHttpResource.of(null).header("Foo", "Bar");
-		}
-
-		@RestMethod
-		public BasicHttpResource a03() throws Exception {
-			return BasicHttpResource.of(null).contentType("application/json");
-		}
-
-		@RestMethod
-		public BasicHttpResource a04(RestRequest req) throws Exception {
-			return BasicHttpResource.of(()->req.getVarResolverSession().resolve("$RQ{foo}"));
-		}
-
-		@RestMethod
-		public BasicHttpResource a05() throws Exception {
-			return BasicHttpResource.of(new ByteArrayInputStream("foo".getBytes()));
-		}
-
-		@RestMethod
-		public BasicHttpResource a06() throws Exception {
-			return BasicHttpResource.of(new StringReader("foo"));
-		}
-
-		@RestMethod
-		public BasicHttpResource a07() throws Exception {
-			return BasicHttpResource.of(new StringBuilder("foo"));
-		}
-	}
-
-	static MockRestClient a = MockRestClient.build(A.class);
-
-	@Test
-	public void a01_basic() throws Exception {
-		a.get("/a01")
-			.run()
-			.assertBody().is("foo");
-	}
-
-	@Test
-	public void a02_headers() throws Exception {
-		a.get("/a02")
-			.run()
-			.assertStringHeader("Foo").is("Bar");
-	}
-
-	@Test
-	public void a03_contentType() throws Exception {
-		a.get("/a03")
-			.run()
-			.assertStringHeader("Content-Type").is("application/json");
-	}
-
-	@Test
-	public void a04_withVars() throws Exception {
-		a.get("/a04?foo=bar")
-			.run()
-			.assertBody().is("bar");
-	}
-
-	@Test
-	public void a05_inputStream() throws Exception {
-		a.get("/a05")
-			.run()
-			.assertBody().is("foo");
-	}
-
-	@Test
-	public void a06_reader() throws Exception {
-		a.get("/a06")
-			.run()
-			.assertBody().is("foo");
-	}
-
-	@Test
-	public void a07_charSequence() throws Exception {
-		a.get("/a07")
-			.run()
-			.assertBody().is("foo");
-	}
-}
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/HyperlinkTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/Hyperlink_Test.java
similarity index 83%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/HyperlinkTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/Hyperlink_Test.java
index af2f152..b1c80ea 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/HyperlinkTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/Hyperlink_Test.java
@@ -18,53 +18,42 @@
 
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client2.*;
 import org.apache.juneau.rest.mock2.*;
 import org.junit.*;
 
+@SuppressWarnings("serial")
 @FixMethodOrder(NAME_ASCENDING)
-public class HyperlinkTest {
+public class Hyperlink_Test {
 
 	@Rest
 	public static class A extends BasicRestServlet {
-		private static final long serialVersionUID = 1L;
-
 		@RestMethod
-		public Hyperlink a01() {
+		public Hyperlink a() {
 			return new Hyperlink("foo", "bar");
 		}
-
 		@RestMethod
-		public Hyperlink[] a02() {
-			return new Hyperlink[]{a01(),a01()};
+		public Hyperlink[] b() {
+			return new Hyperlink[]{a(),a()};
 		}
-
 		@RestMethod
-		public Collection<Hyperlink> a03() {
-			return Arrays.asList(a02());
+		public Collection<Hyperlink> c() {
+			return Arrays.asList(b());
 		}
 	}
 
-	static MockRestClient a = MockRestClient.build(A.class);
-
 	@Test
 	public void a01_basic() throws Exception {
-		a.get("/a01")
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/a")
 			.accept("text/html+stripped")
 			.run()
 			.assertBody().is("<a href=\"/foo\">bar</a>");
-	}
-
-	@Test
-	public void a02_array() throws Exception {
-		a.get("/a02")
+		a.get("/b")
 			.accept("text/html+stripped")
 			.run()
 			.assertBody().is("<ul><li><a href=\"/foo\">bar</a></li><li><a href=\"/foo\">bar</a></li></ul>");
-	}
-
-	@Test
-	public void a03_collection() throws Exception {
-		a.get("/a03")
+		a.get("/c")
 			.accept("text/html+stripped")
 			.run()
 			.assertBody().is("<ul><li><a href=\"/foo\">bar</a></li><li><a href=\"/foo\">bar</a></li></ul>");
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ResourceDescriptionTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/ResourceDescription_Test.java
similarity index 93%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ResourceDescriptionTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/ResourceDescription_Test.java
index c229aeb..07d27ee 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/headers/ResourceDescriptionTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/helper/ResourceDescription_Test.java
@@ -10,17 +10,16 @@
 // * "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.rest.headers;
+package org.apache.juneau.rest.helper;
 
 import static org.junit.Assert.*;
 import static org.junit.runners.MethodSorters.*;
 
 import org.apache.juneau.marshall.*;
-import org.apache.juneau.rest.helper.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class ResourceDescriptionTest {
+public class ResourceDescription_Test {
 
 	@Test
 	public void a01_basic() throws Exception {
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/mock2/MockServletRequestTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/mock2/MockServletRequest_Test.java
similarity index 98%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/mock2/MockServletRequestTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/mock2/MockServletRequest_Test.java
index f8b8248..cc457dc 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/mock2/MockServletRequestTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/mock2/MockServletRequest_Test.java
@@ -19,7 +19,7 @@
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class MockServletRequestTest {
+public class MockServletRequest_Test {
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// URIs
diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/RestUtilsTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/RestUtils_Test.java
similarity index 75%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/RestUtilsTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/RestUtils_Test.java
index 2deb0cb..500ba31 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/RestUtilsTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/RestUtils_Test.java
@@ -24,24 +24,24 @@
 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class RestUtilsTest {

+public class RestUtils_Test {

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// decode(String)

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Test

-	public void testDecode() throws Exception {

+	public void a01_testDecode() throws Exception {

 		assertNull(urlDecode(null));

 		assertEquals("foo/bar baz  bing", urlDecode("foo%2Fbar+baz++bing"));

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// encode(String)

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Test

-	public void testEncode() throws Exception {

+	public void b01_testEncode() throws Exception {

 		assertNull(urlEncode(null));

 		assertEquals("foo%2Fbar+baz++bing", urlEncode("foo/bar baz  bing"));

 		assertEquals("foobar", urlEncode("foobar"));

@@ -49,12 +49,12 @@
 		assertEquals("%2F", urlEncode("/"));

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// trimPathInfo(String,String)

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Test

-	public void testGetServletURI() throws Exception {

+	public void c01_testGetServletURI() throws Exception {

 		String e, sp, cp;

 

 		e = "http://hostname";

@@ -138,12 +138,12 @@
 		}

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// trimSlashes(String)

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Test

-	public void testTrimSlashes() throws Exception {

+	public void d01_testTrimSlashes() throws Exception {

 		assertNull(trimSlashes(null));

 		assertEquals("", trimSlashes(""));

 		assertEquals("", trimSlashes("/"));

@@ -154,12 +154,12 @@
 		assertEquals("foo/bar", trimSlashes("//foo/bar//"));

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// trimTrailingSlashes(String)

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Test

-	public void testTrimTrailingSlashes() throws Exception {

+	public void e01_testTrimTrailingSlashes() throws Exception {

 		assertNull(trimTrailingSlashes((String)null));

 		assertEquals("", trimTrailingSlashes(""));

 		assertEquals("", trimTrailingSlashes("/"));

@@ -170,12 +170,12 @@
 		assertEquals("//foo/bar", trimTrailingSlashes("//foo/bar//"));

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// trimTrailingSlashes(StringBuffer)

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Test

-	public void testTrimTrailingSlashes2() throws Exception {

+	public void f01_testTrimTrailingSlashes2() throws Exception {

 		assertNull(trimTrailingSlashes((StringBuffer)null));

 		assertEquals("", trimTrailingSlashes(new StringBuffer("")).toString());

 		assertEquals("", trimTrailingSlashes(new StringBuffer("/")).toString());

@@ -186,12 +186,12 @@
 		assertEquals("//foo/bar", trimTrailingSlashes(new StringBuffer("//foo/bar//")).toString());

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Test URL-encoded strings parsed into plain-text values using UrlEncodingParser.parseIntoSimpleMap().

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Test

-	public void testParseIntoSimpleMap() throws Exception {

+	public void g01_testParseIntoSimpleMap() throws Exception {

 		Map<String,String[]> m;

 

 		String s = "?f1=,()=&f2a=$b(true)&f2b=true&f3a=$n(123)&f3b=123&f4=$s(foo)";

@@ -217,12 +217,12 @@
 		assertNull(m.get("f3"));

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Test parsing URL-encoded strings with multiple values.

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Test

-	public void testParseIntoSimpleMapMultiValues() throws Exception {

+	public void h01_testParseIntoSimpleMapMultiValues() throws Exception {

 		Map<String,String[]> m;

 

 		String s = "?f1&f1&f2&f2=abc&f2=def&f2";

@@ -231,7 +231,7 @@
 	}

 

 	@Test

-	public void testEmptyString() throws Exception {

+	public void h02_testEmptyString() throws Exception {

 		UrlEncodingParser p = UrlEncodingParser.DEFAULT;

 

 		String s = "";

@@ -243,12 +243,12 @@
 		public String f1 = "f1";

 	}

 

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 	// Other tests

-	//=================================================================================================================

+	//------------------------------------------------------------------------------------------------------------------

 

 	@Test

-	public void testTrimContextPath() {

+	public void i01_testTrimContextPath() {

 		assertEquals("/bar", trimContextPath("/foo", "/bar"));

 		assertEquals("/", trimContextPath("/foo", "/"));

 		assertEquals("", trimContextPath("/foo", ""));

@@ -262,7 +262,7 @@
 	}

 

 	@Test

-	public void testIsValidContextPath() {

+	public void i02_testIsValidContextPath() {

 		assertTrue(isValidContextPath(""));

 		assertTrue(isValidContextPath("/foo"));

 		assertFalse(isValidContextPath("/"));

@@ -272,7 +272,7 @@
 	}

 

 	@Test

-	public void testIsValidServletPath() {

+	public void i03_testIsValidServletPath() {

 		assertTrue(isValidServletPath(""));

 		assertTrue(isValidServletPath("/foo"));

 		assertFalse(isValidServletPath("/"));

@@ -282,7 +282,7 @@
 	}

 

 	@Test

-	public void testIsValidPathInfo() {

+	public void i04_testIsValidPathInfo() {

 		assertFalse(isValidPathInfo(""));

 		assertTrue(isValidPathInfo("/foo"));

 		assertTrue(isValidPathInfo("/"));

@@ -290,5 +290,4 @@
 		assertTrue(isValidPathInfo(null));

 		assertFalse(isValidPathInfo("foo"));

 	}

-

 }

diff --git a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/UrlPathPatternTest.java b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/UrlPathPattern_Test.java
similarity index 99%
rename from juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/UrlPathPatternTest.java
rename to juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/UrlPathPattern_Test.java
index ed1bb9c..83ce099 100644
--- a/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/UrlPathPatternTest.java
+++ b/juneau-rest/juneau-rest-server-utest/src/test/java/org/apache/juneau/rest/util/UrlPathPattern_Test.java
@@ -22,7 +22,7 @@
 import org.junit.*;

 

 @FixMethodOrder(NAME_ASCENDING)

-public class UrlPathPatternTest {

+public class UrlPathPattern_Test {

 

 	private void shouldMatch(UrlPathPattern p, String path, String expected) {

 		assertObject(p.match(path)).json().is(expected);