You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/27 19:48:57 UTC

[09/14] incubator-juneau git commit: Clean up test and test resource class names.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/GzipTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/GzipTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/GzipTest.java
new file mode 100755
index 0000000..927363d
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/GzipTest.java
@@ -0,0 +1,344 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static javax.servlet.http.HttpServletResponse.*;
+import static org.apache.juneau.server.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.io.*;
+import java.util.zip.*;
+
+import org.apache.http.impl.client.*;
+import org.apache.juneau.client.*;
+import org.apache.juneau.internal.*;
+import org.junit.*;
+
+/**
+ * Test Accept-Encoding and Content-Encoding handling.
+ *
+ * Note:  WAS does automatic gzip decompression on http request messages, so we have to invent
+ * 	our own 'mycoding' compression.
+ */
+public class GzipTest {
+
+	private static boolean debug = false;
+
+	private static String testGzipOff = "/testGzipOff";
+	private static String testGzipOn = "/testGzipOn";
+
+	// Converts string into a GZipped input stream.
+	private static InputStream compress(String contents) throws Exception {
+		ByteArrayOutputStream baos = new ByteArrayOutputStream(contents.length()>>1);
+		GZIPOutputStream gos = new GZIPOutputStream(baos);
+		gos.write(contents.getBytes());
+		gos.finish();
+		gos.close();
+		return new ByteArrayInputStream(baos.toByteArray());
+	}
+
+	private static String decompress(InputStream is) throws Exception {
+		return IOUtils.read(new GZIPInputStream(is));
+	}
+
+	//====================================================================================================
+	// Test with no compression enabled.
+	//====================================================================================================
+	@Test
+	public void testGzipOff() throws Exception {
+		RestClient c = new TestRestClient().setAccept("text/plain").setContentType("text/plain");
+		RestCall r;
+		String url = testGzipOff;
+
+		// *** GET ***
+
+		r = c.doGet(url);
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doGet(url).setHeader("Accept-Encoding", "");
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doGet(url).setHeader("Accept-Encoding", "*");
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doGet(url).setHeader("Accept-Encoding", "identity");
+		assertEquals("foo", r.getResponseAsString());
+
+		// Should match identity.
+		r = c.doGet(url).setHeader("Accept-Encoding", "mycoding");
+		assertEquals("foo", r.getResponseAsString());
+
+		// Shouldn't match.
+		try {
+			r = c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "mycoding,identity;q=0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': 'mycoding,identity;q=0'",
+				"Supported codings: [identity]"
+			);
+		}
+
+		// Shouldn't match.
+		try {
+			c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "mycoding,*;q=0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': 'mycoding,*;q=0'",
+				"Supported codings: [identity]"
+			);
+		}
+
+		// Should match identity
+		r = c.doGet(url).setHeader("Accept-Encoding", "identity;q=0.8,mycoding;q=0.6");
+		assertEquals("foo", r.getResponseAsString());
+
+		// Should match identity
+		r = c.doGet(url).setHeader("Accept-Encoding", "mycoding;q=0.8,identity;q=0.6");
+		assertEquals("foo", r.getResponseAsString());
+
+		// Should match identity
+		r = c.doGet(url).setHeader("Accept-Encoding", "mycoding;q=0.8,*;q=0.6");
+		assertEquals("foo", r.getResponseAsString());
+
+		// Should match identity
+		r = c.doGet(url).setHeader("Accept-Encoding", "*;q=0.8,myencoding;q=0.6");
+		assertEquals("foo", r.getResponseAsString());
+
+		// Shouldn't match
+		try {
+			c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "identity;q=0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': 'identity;q=0'",
+				"Supported codings: [identity]"
+			);
+		}
+
+		// Shouldn't match
+		try {
+			c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "identity;q=0.0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': 'identity;q=0.0'",
+				"Supported codings: [identity]"
+			);
+		}
+
+		// Shouldn't match
+		try {
+			c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "*;q=0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': '*;q=0'",
+				"Supported codings: [identity]"
+			);
+		}
+
+		// Shouldn't match
+		try {
+			c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "*;q=0.0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': '*;q=0.0'",
+				"Supported codings: [identity]"
+			);
+		}
+
+
+		// *** PUT ***
+
+		r = c.doPut(url, new StringReader("foo"));
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doPut(url, new StringReader("foo")).setHeader("Content-Encoding", "");
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doPut(url, new StringReader("foo")).setHeader("Content-Encoding", "identity");
+		assertEquals("foo", r.getResponseAsString());
+
+		try {
+			c.doPut(url+"?noTrace=true", compress("foo")).setHeader("Content-Encoding", "mycoding").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
+				"Unsupported encoding in request header 'Content-Encoding': 'mycoding'",
+				"Supported codings: [identity]"
+			);
+		}
+
+		c.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Test with compression enabled.
+	//====================================================================================================
+	@Test
+	public void testGzipOn() throws Exception {
+
+		// Create a client that disables content compression support so that we can get the gzipped content directly.
+		CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(TestRestClient.getSSLSocketFactory()).disableContentCompression().build();
+
+		RestClient c = new TestRestClient(httpClient).setAccept("text/plain").setContentType("text/plain");
+		RestCall r;
+		String url = testGzipOn;
+
+		// *** GET ***
+
+		r = c.doGet(url);
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doGet(url).setHeader("Accept-Encoding", "");
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doGet(url).setHeader("Accept-Encoding", "*");
+		assertEquals("foo", decompress(r.getInputStream()));
+
+		r = c.doGet(url).setHeader("Accept-Encoding", "identity");
+		assertEquals("foo", r.getResponseAsString());
+
+		// Should match identity.
+		r = c.doGet(url).setHeader("Accept-Encoding", "mycoding");
+		assertEquals("foo", decompress(r.getInputStream()));
+
+		r = c.doGet(url).setHeader("Accept-Encoding", "mycoding,identity;q=0").connect();
+		assertEquals("foo", decompress(r.getInputStream()));
+
+		r = c.doGet(url).setHeader("Accept-Encoding", "mycoding,*;q=0").connect();
+		assertEquals("foo", decompress(r.getInputStream()));
+
+		// Should match identity
+		r = c.doGet(url).setHeader("Accept-Encoding", "identity;q=0.8,mycoding;q=0.6");
+		assertEquals("foo", r.getResponseAsString());
+
+		// Should match mycoding
+		r = c.doGet(url).setHeader("Accept-Encoding", "mycoding;q=0.8,identity;q=0.6");
+		assertEquals("foo", decompress(r.getInputStream()));
+
+		// Should match mycoding
+		r = c.doGet(url).setHeader("Accept-Encoding", "mycoding;q=0.8,*;q=0.6");
+		assertEquals("foo", decompress(r.getInputStream()));
+
+		// Should match identity
+		r = c.doGet(url).setHeader("Accept-Encoding", "*;q=0.8,myencoding;q=0.6");
+		assertEquals("foo", decompress(r.getInputStream()));
+
+		// Shouldn't match
+		try {
+			c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "identity;q=0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': 'identity;q=0'",
+				"Supported codings: [mycoding, identity]"
+			);
+		}
+
+		// Shouldn't match
+		try {
+			c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "identity;q=0.0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': 'identity;q=0.0'",
+				"Supported codings: [mycoding, identity]"
+			);
+		}
+
+		// Shouldn't match
+		try {
+			c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "*;q=0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': '*;q=0'",
+				"Supported codings: [mycoding, identity]"
+			);
+		}
+
+		// Shouldn't match
+		try {
+			c.doGet(url+"?noTrace=true").setHeader("Accept-Encoding", "*;q=0.0").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
+				"Unsupported encoding in request header 'Accept-Encoding': '*;q=0.0'",
+				"Supported codings: [mycoding, identity]"
+			);
+		}
+
+
+		// *** PUT ***
+
+		r = c.doPut(url, new StringReader("foo"));
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doPut(url, new StringReader("foo")).setHeader("Content-Encoding", "");
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doPut(url, new StringReader("foo")).setHeader("Content-Encoding", "identity");
+		assertEquals("foo", r.getResponseAsString());
+
+		r = c.doPut(url, compress("foo")).setHeader("Content-Encoding", "mycoding");
+		assertEquals("foo", r.getResponseAsString());
+
+		c.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Test with compression enabled but with servlet using output stream directly.
+	//====================================================================================================
+	@Test
+	public void testGzipOnDirect() throws Exception {
+		// Create a client that disables content compression support so that we can get the gzipped content directly.
+		CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLSocketFactory(TestRestClient.getSSLSocketFactory()).build();
+		RestClient c = new TestRestClient(httpClient).setAccept("text/plain").setContentType("text/plain");
+		RestCall r = null;
+		String s = null;
+
+		// res.getOutputStream() called....should bypass encoding.
+		r = c.doGet(testGzipOn + "/direct").setHeader("Accept-Encoding", "mycoding");
+		s = r.getResponseAsString();
+		assertEquals("test", s);
+		assertTrue(r.getResponse().getHeaders("Content-Type")[0].getValue().contains("text/direct")); // Should get header set manually.
+		assertEquals(0, r.getResponse().getHeaders("Content-Encoding").length);                // Should not be set.
+
+		// res.getWriter() called....should bypass encoding.
+		r = c.doGet(testGzipOn + "/direct2").setHeader("Accept-Encoding", "mycoding");
+		s = r.getResponseAsString();
+		assertEquals("test", s);
+		assertEquals(0, r.getResponse().getHeaders("Content-Encoding").length);                // Should not be set.
+
+		// res.getNegotiateWriter() called....should NOT bypass encoding.
+		r = c.doGet(testGzipOn + "/direct3").setHeader("Accept-Encoding", "mycoding");
+		try {
+			assertEquals("mycoding", r.getResponse().getHeaders("content-encoding")[0].getValue());
+		} catch (RestCallException e) {
+			// OK - HttpClient doesn't know what mycoding is.
+			// Newer versions of HttpClient ignore this condition.
+		}
+
+		// res.getNegotiateWriter() called but @RestMethod(encoders={})...should bypass encoding.
+		r = c.doGet(testGzipOn + "/direct4").setHeader("Accept-Encoding", "mycoding");
+		s = r.getResponseAsString();
+		assertEquals("test", s);
+		assertEquals(0, r.getResponse().getHeaders("Content-Encoding").length);                // Should not be set.
+
+		c.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/InheritanceTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/InheritanceTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/InheritanceTest.java
new file mode 100755
index 0000000..3594d11
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/InheritanceTest.java
@@ -0,0 +1,126 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.client.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+public class InheritanceTest {
+
+	private static RestClient client;
+
+	@BeforeClass
+	public static void beforeClass() {
+		client = new TestRestClient();
+	}
+
+	@AfterClass
+	public static void afterClass() {
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Test serializer inheritance.
+	//====================================================================================================
+	@Test
+	public void testSerializers() throws Exception {
+		String r;
+		String url = "/testInheritanceSerializers";
+		r = client.doGet(url + "/test1").getResponseAsString();
+		assertEquals("['text/s3','text/s4','text/s1','text/s2']", r);
+
+		r = client.doGet(url + "/test2").getResponseAsString();
+		assertEquals("['text/s5']", r);
+
+		r = client.doGet(url + "/test3").getResponseAsString();
+		assertEquals("['text/s5','text/s3','text/s4','text/s1','text/s2']", r);
+	}
+
+	//====================================================================================================
+	// Test parser inheritance.
+	//====================================================================================================
+	@Test
+	public void testParsers() throws Exception {
+		String r;
+		String url = "/testInheritanceParsers";
+		r = client.doGet(url + "/test1").getResponseAsString();
+		assertEquals("['text/p3','text/p4','text/p1','text/p2']", r);
+
+		r = client.doGet(url + "/test2").getResponseAsString();
+		assertEquals("['text/p5']", r);
+
+		r = client.doGet(url + "/test3").getResponseAsString();
+		assertEquals("['text/p5','text/p3','text/p4','text/p1','text/p2']", r);
+	}
+
+	//====================================================================================================
+	// Test encoder inheritance.
+	//====================================================================================================
+	@Test
+	public void testEncoders() throws Exception {
+		String url = "/testInheritanceEncoders";
+		String r = client.doGet(url + "/test").getResponseAsString();
+		assertEquals("['e3','e4','e1','e2','identity']", r);
+	}
+
+	//====================================================================================================
+	// Test filter inheritance.
+	//====================================================================================================
+	@Test
+	public void testTransforms() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.class, JsonParser.class).setAccept("text/json+simple");
+		String r;
+		String url = "/testInheritanceTransforms";
+
+		r = client.doGet(url + "/test1").getResponseAsString();
+		assertEquals("['F1','F2','Foo3']", r);
+
+		r = client.doGet(url + "/test2").getResponseAsString();
+		assertEquals("['F1','F2','F3']", r);
+
+		r = client.doGet(url + "/test3").getResponseAsString();
+		assertEquals("['F1','F2','F3']", r);
+
+		r = client.doGet(url + "/test4").getResponseAsString();
+		assertEquals("['Foo1','Foo2','F3']", r);
+
+		r = client.doGet(url + "/test5").getResponseAsString();
+		assertEquals("['F1','F2','F3']", r);
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Test properties inheritance.
+	//====================================================================================================
+	@Test
+	public void testProperties() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.class, JsonParser.class).setAccept("text/json+simple");
+		String r;
+		String url = "/testInheritanceProperties";
+
+		r = client.doGet(url + "/test1").getResponseAsString();
+		assertEquals("{p1:'v1',p2:'v2a',p3:'v3',p4:'v4'}", r);
+
+		r = client.doGet(url + "/test2?override").getResponseAsString();
+		assertEquals("{p1:'x',p2:'x',p3:'x',p4:'x',p5:'x'}", r);
+
+		r = client.doGet(url + "/test2").getResponseAsString();
+		assertEquals("{p1:'v1',p2:'v2a',p3:'v3',p4:'v4a',p5:'v5'}", r);
+
+		client.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/LargePojosTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/LargePojosTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/LargePojosTest.java
new file mode 100755
index 0000000..7c139d5
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/LargePojosTest.java
@@ -0,0 +1,83 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import org.apache.juneau.client.*;
+import org.apache.juneau.html.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.urlencoding.*;
+import org.apache.juneau.xml.*;
+import org.junit.*;
+
+@Ignore
+public class LargePojosTest {
+
+	private static String URL = "/testLargePojos";
+	boolean debug = false;
+
+	//====================================================================================================
+	// Test how long it takes to serialize/parse various content types.
+	//====================================================================================================
+	@Test
+	public void test() throws Exception {
+		LargePojo p;
+		long t;
+		RestClient c;
+
+		System.err.println("\n---Testing JSON---");
+		c = new TestRestClient(JsonSerializer.class, JsonParser.class);
+		for (int i = 1; i <= 3; i++) {
+			t = System.currentTimeMillis();
+			p = c.doGet(URL).getResponse(LargePojo.class);
+			System.err.println("Download: ["+(System.currentTimeMillis() - t)+"] ms");
+			t = System.currentTimeMillis();
+			c.doPut(URL, p).run();
+			System.err.println("Upload: ["+(System.currentTimeMillis() - t)+"] ms");
+		}
+
+		System.err.println("\n---Testing XML---");
+		c = new TestRestClient(XmlSerializer.class, XmlParser.class);
+		for (int i = 1; i <= 3; i++) {
+			t = System.currentTimeMillis();
+			p = c.doGet(URL).getResponse(LargePojo.class);
+			System.err.println("Download: ["+(System.currentTimeMillis() - t)+"] ms");
+			t = System.currentTimeMillis();
+			c.doPut(URL, p).run();
+			System.err.println("Upload: ["+(System.currentTimeMillis() - t)+"] ms");
+		}
+
+		System.err.println("\n---Testing HTML---");
+		c = new TestRestClient(HtmlSerializer.class, HtmlParser.class).setAccept("text/html+stripped");
+		for (int i = 1; i <= 3; i++) {
+			t = System.currentTimeMillis();
+			p = c.doGet(URL).getResponse(LargePojo.class);
+			System.err.println("Download: ["+(System.currentTimeMillis() - t)+"] ms");
+			t = System.currentTimeMillis();
+			c.doPut(URL, p).run();
+			System.err.println("Upload: ["+(System.currentTimeMillis() - t)+"] ms");
+		}
+
+		System.err.println("\n---Testing UrlEncoding---");
+		c = new TestRestClient(UonSerializer.class, UonParser.class);
+		for (int i = 1; i <= 3; i++) {
+			t = System.currentTimeMillis();
+			p = c.doGet(URL).getResponse(LargePojo.class);
+			System.err.println("Download: ["+(System.currentTimeMillis() - t)+"] ms");
+			t = System.currentTimeMillis();
+			c.doPut(URL, p).run();
+			System.err.println("Upload: ["+(System.currentTimeMillis() - t)+"] ms");
+		}
+
+		c.closeQuietly();
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/MessagesTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/MessagesTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/MessagesTest.java
new file mode 100755
index 0000000..d6eb29e
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/MessagesTest.java
@@ -0,0 +1,47 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static org.apache.juneau.server.TestUtils.*;
+
+import java.util.*;
+
+import org.apache.juneau.client.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+/**
+ * Validates that resource bundles can be defined on both parent and child classes.
+ */
+public class MessagesTest {
+
+	//====================================================================================================
+	// Return contents of resource bundle.
+	//====================================================================================================
+	@SuppressWarnings("rawtypes")
+	@Test
+	public void test() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.class,JsonParser.class);
+
+		// Parent resource should just pick up values from its bundle.
+		TreeMap r = client.doGet("/testMessages/test").getResponse(TreeMap.class);
+		assertObjectEquals("{key1:'value1a',key2:'value2a'}", r);
+
+		// Child resource should pick up values from both parent and child,
+		// ordered child before parent.
+		r = client.doGet("/testMessages2/test").getResponse(TreeMap.class);
+		assertObjectEquals("{key1:'value1a',key2:'value2b',key3:'value3b'}", r);
+
+		client.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/NlsPropertyTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/NlsPropertyTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/NlsPropertyTest.java
new file mode 100755
index 0000000..0157540
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/NlsPropertyTest.java
@@ -0,0 +1,48 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.client.*;
+import org.apache.juneau.plaintext.*;
+import org.junit.*;
+
+public class NlsPropertyTest {
+
+	private static String URL = "/testNlsProperty";
+
+	//====================================================================================================
+	// Test getting an NLS property defined on a class.
+	//====================================================================================================
+	@Test
+	public void testInheritedFromClass() throws Exception {
+		RestClient client = new TestRestClient(PlainTextSerializer.class, PlainTextParser.class);
+		String r = client.doGet(URL + "/testInheritedFromClass").getResponseAsString();
+		assertEquals("value1", r);
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Test getting an NLS property defined on a method.
+	//====================================================================================================
+	@Test
+	public void testInheritedFromMethod() throws Exception {
+		RestClient client = new TestRestClient(PlainTextSerializer.class, PlainTextParser.class);
+		String r = client.doGet(URL + "/testInheritedFromMethod").getResponseAsString();
+		assertEquals("value2", r);
+
+		client.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/NlsTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/NlsTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/NlsTest.java
new file mode 100755
index 0000000..09789b6
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/NlsTest.java
@@ -0,0 +1,170 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.client.*;
+import org.apache.juneau.json.*;
+import org.junit.*;
+
+public class NlsTest {
+
+	private static String URL = "/testNls";
+
+	// ====================================================================================================
+	// test1 - Pull labels from annotations only.
+	// ====================================================================================================
+	@Test
+	public void test1() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		ObjectMap r = null;
+		String expected = null;
+
+		// Labels all pulled from annotations.
+		r = client.doOptions(URL + "/test1").getResponse(ObjectMap.class);
+		assertEquals("Test1.a", r.getString("label"));
+		assertEquals("Test1.b", r.getString("description"));
+		r = r.getObjectList("methods").getObjectMap(0);
+		assertEquals("test1", r.getString("javaMethod"));
+		assertEquals("POST", r.getString("httpMethod"));
+		expected = "[{category:'attr',name:'a',description:'Test1.d'},{category:'attr',name:'a2',description:'Test1.h'},{category:'attr',name:'e'},{category:'content',name:'',description:'Test1.f'},{category:'foo',name:'bar',description:'Test1.k'},{category:'header',name:'D',description:'Test1.g'},{category:'header',name:'D2',description:'Test1.j'},{category:'header',name:'g'},{category:'param',name:'b',description:'Test1.e'},{category:'param',name:'b2',description:'Test1.i'},{category:'param',name:'f'}]";
+		assertEquals(expected, r.getObjectList("input").toString());
+		expected = "[{status:200,description:'OK',output:[]},{status:201,description:'Test1.l',output:[{category:'foo',name:'bar',description:'Test1.m'}]}]";
+		assertEquals(expected, r.getObjectList("responses").toString());
+
+		client.closeQuietly();
+	}
+
+	// ====================================================================================================
+	// test2 - Pull labels from resource bundles only - simple keys.
+	// ====================================================================================================
+	@Test
+	public void test2() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		ObjectMap r = null;
+		String expected = null;
+
+		// Labels all pulled from annotations.
+		r = client.doOptions(URL + "/test2").getResponse(ObjectMap.class);
+		assertEquals("Test2.a", r.getString("label"));
+		assertEquals("Test2.b", r.getString("description"));
+		r = r.getObjectList("methods").getObjectMap(0);
+		assertEquals("test2", r.getString("javaMethod"));
+		assertEquals("POST", r.getString("httpMethod"));
+		expected = "[{category:'attr',name:'a',description:'Test2.d'},{category:'attr',name:'a2',description:'Test2.h'},{category:'attr',name:'e'},{category:'content',name:'',description:'Test2.f'},{category:'foo',name:'bar',description:'Test2.k'},{category:'header',name:'D',description:'Test2.g'},{category:'header',name:'D2',description:'Test2.j'},{category:'header',name:'g'},{category:'param',name:'b',description:'Test2.e'},{category:'param',name:'b2',description:'Test2.i'},{category:'param',name:'f'}]";
+		assertEquals(expected, r.getObjectList("input").toString());
+		expected = "[{status:200,description:'OK2',output:[]},{status:201,description:'Test2.l',output:[{category:'foo',name:'bar',description:'Test2.m'}]}]";
+		assertEquals(expected, r.getObjectList("responses").toString());
+
+		client.closeQuietly();
+	}
+
+	// ====================================================================================================
+	// test3 - Pull labels from resource bundles only - keys with class names.
+	// ====================================================================================================
+	@Test
+	public void test3() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		ObjectMap r = null;
+		String expected = null;
+
+		// Labels all pulled from annotations.
+		r = client.doOptions(URL + "/test3").getResponse(ObjectMap.class);
+		assertEquals("Test3.a", r.getString("label"));
+		assertEquals("Test3.b", r.getString("description"));
+		r = r.getObjectList("methods").getObjectMap(1);
+		assertEquals("test3", r.getString("javaMethod"));
+		assertEquals("POST", r.getString("httpMethod"));
+		expected = "[{category:'attr',name:'a',description:'Test3.d'},{category:'attr',name:'a2',description:'Test3.h'},{category:'attr',name:'e'},{category:'content',name:'',description:'Test3.f'},{category:'foo',name:'bar',description:'Test3.k'},{category:'header',name:'D',description:'Test3.g'},{category:'header',name:'D2',description:'Test3.j'},{category:'header',name:'g'},{category:'param',name:'b',description:'Test3.e'},{category:'param',name:'b2',description:'Test3.i'},{category:'param',name:'f'}]";
+		assertEquals(expected, r.getObjectList("input").toString());
+		expected = "[{status:200,description:'OK3',output:[]},{status:201,description:'Test3.l',output:[{category:'foo',name:'bar',description:'Test3.m'}]}]";
+		assertEquals(expected, r.getObjectList("responses").toString());
+
+		client.closeQuietly();
+	}
+
+	// ====================================================================================================
+	// test4 - Pull labels from resource bundles only. Values have localized variables to resolve.
+	// ====================================================================================================
+	@Test
+	public void test4() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		ObjectMap r = null;
+		String expected = null;
+
+		// Labels all pulled from annotations.
+		r = client.doOptions(URL + "/test4").getResponse(ObjectMap.class);
+		assertEquals("baz", r.getString("label"));
+		assertEquals("baz", r.getString("description"));
+		r = r.getObjectList("methods").getObjectMap(0);
+		assertEquals("test4", r.getString("javaMethod"));
+		assertEquals("POST", r.getString("httpMethod"));
+		expected = "[{category:'attr',name:'a',description:'baz'},{category:'attr',name:'a2',description:'baz'},{category:'attr',name:'e'},{category:'content',name:'',description:'baz'},{category:'foo',name:'bar',description:'baz'},{category:'header',name:'D',description:'baz'},{category:'header',name:'D2',description:'baz'},{category:'header',name:'g'},{category:'param',name:'b',description:'baz'},{category:'param',name:'b2',description:'baz'},{category:'param',name:'f'}]";
+		assertEquals(expected, r.getObjectList("input").toString());
+		expected = "[{status:200,description:'foobazfoobazfoo',output:[]},{status:201,description:'baz',output:[{category:'foo',name:'bar',description:'baz'}]}]";
+		assertEquals(expected, r.getObjectList("responses").toString());
+
+		client.closeQuietly();
+	}
+
+	// ====================================================================================================
+	// test5 - Pull labels from resource bundles only. Values have request variables to resolve.
+	// ====================================================================================================
+	@Test
+	public void test5() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		ObjectMap r = null;
+		String expected = null;
+
+		// Labels all pulled from annotations.
+		r = client.doOptions(URL + "/test5").getResponse(ObjectMap.class);
+		assertEquals("baz2", r.getString("label"));
+		assertEquals("baz2", r.getString("description"));
+		r = r.getObjectList("methods").getObjectMap(0);
+		assertEquals("test5", r.getString("javaMethod"));
+		assertEquals("POST", r.getString("httpMethod"));
+		expected = "[{category:'attr',name:'a',description:'baz2'},{category:'attr',name:'a2',description:'baz2'},{category:'attr',name:'e'},{category:'content',name:'',description:'baz2'},{category:'foo',name:'bar',description:'baz2'},{category:'header',name:'D',description:'baz2'},{category:'header',name:'D2',description:'baz2'},{category:'header',name:'g'},{category:'param',name:'b',description:'baz2'},{category:'param',name:'b2',description:'baz2'},{category:'param',name:'f'}]";
+		assertEquals(expected, r.getObjectList("input").toString());
+		expected = "[{status:200,description:'foobaz2foobaz2foo',output:[]},{status:201,description:'baz2',output:[{category:'foo',name:'bar',description:'baz2'}]}]";
+		assertEquals(expected, r.getObjectList("responses").toString());
+
+		client.closeQuietly();
+	}
+
+	// ====================================================================================================
+	// test6 - Pull labels from annotations only, but annotations contain variables.
+	// ====================================================================================================
+	@Test
+	public void test6() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		ObjectMap r = null;
+		String expected = null;
+
+		// Labels all pulled from annotations.
+		r = client.doOptions(URL + "/test6").getResponse(ObjectMap.class);
+		assertEquals("baz", r.getString("label"));
+		assertEquals("baz", r.getString("description"));
+		r = r.getObjectList("methods").getObjectMap(0);
+		assertEquals("test6", r.getString("javaMethod"));
+		assertEquals("POST", r.getString("httpMethod"));
+		expected = "[{category:'attr',name:'a',description:'baz'},{category:'attr',name:'a2',description:'baz'},{category:'attr',name:'e'},{category:'content',name:'',description:'baz'},{category:'foo',name:'bar',description:'baz'},{category:'header',name:'D',description:'baz'},{category:'header',name:'D2',description:'baz'},{category:'header',name:'g'},{category:'param',name:'b',description:'baz'},{category:'param',name:'b2',description:'baz'},{category:'param',name:'f'}]";
+		assertEquals(expected, r.getObjectList("input").toString());
+		expected = "[{status:200,description:'OK',output:[]},{status:201,description:'baz',output:[{category:'foo',name:'bar',description:'baz'}]}]";
+		assertEquals(expected, r.getObjectList("responses").toString());
+
+		client.closeQuietly();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/NoParserInputTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/NoParserInputTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/NoParserInputTest.java
new file mode 100755
index 0000000..04704ef
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/NoParserInputTest.java
@@ -0,0 +1,70 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static javax.servlet.http.HttpServletResponse.*;
+import static org.apache.juneau.server.TestUtils.*;
+import static org.junit.Assert.*;
+
+import org.apache.juneau.client.*;
+import org.apache.juneau.plaintext.*;
+import org.junit.*;
+
+public class NoParserInputTest {
+
+	private static String URL = "/testNoParserInput";
+	private static boolean debug = false;
+
+	//====================================================================================================
+	// @Content annotated InputStream.
+	//====================================================================================================
+	@Test
+	public void testInputStream() throws Exception {
+		RestClient client = new TestRestClient(PlainTextSerializer.class, PlainTextParser.class);
+		String r = client.doPut(URL + "/testInputStream", "foo").getResponseAsString();
+		assertEquals("foo", r);
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// @Content annotated Reader.
+	//====================================================================================================
+	@Test
+	public void testReader() throws Exception {
+		RestClient client = new TestRestClient(PlainTextSerializer.class, PlainTextParser.class);
+		String r = client.doPut(URL + "/testReader", "foo").getResponseAsString();
+		assertEquals("foo", r);
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// @Content annotated PushbackReader.
+	// This should always fail since the servlet reader is not a pushback reader.
+	//====================================================================================================
+	@Test
+	public void testPushbackReader() throws Exception {
+		RestClient client = new TestRestClient(PlainTextSerializer.class, PlainTextParser.class);
+		try {
+			client.doPut(URL + "/testPushbackReader?noTrace=true", "foo").getResponseAsString();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_BAD_REQUEST,
+				"Invalid argument type passed to the following method:",
+				"'public java.lang.String org.apache.juneau.server.NoParserInputResource.testPushbackReader(java.io.PushbackReader) throws java.lang.Exception'");
+		}
+
+		client.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/OnPostCallTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/OnPostCallTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/OnPostCallTest.java
new file mode 100755
index 0000000..edcc1d8
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/OnPostCallTest.java
@@ -0,0 +1,121 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static org.junit.Assert.*;
+
+import java.io.*;
+
+import org.apache.juneau.client.*;
+import org.junit.*;
+
+public class OnPostCallTest {
+
+	private static String URL = "/testOnPostCall";
+
+	//====================================================================================================
+	// Properties overridden via properties annotation.
+	//====================================================================================================
+	@Test
+	public void testPropertiesOverridenByAnnotation() throws Exception {
+		RestClient client = new TestRestClient().setAccept("text/s1");
+		String url = URL + "/testPropertiesOverridenByAnnotation";
+		String r;
+		RestCall rc;
+
+		r = client.doPut(url, new StringReader("")).getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5,contentType=text/s1", r);
+
+		r = client.doPut(url, new StringReader("")).setHeader("Override-Accept", "text/s2").getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5,contentType=text/s2", r);
+
+		rc = client.doPut(url, new StringReader("")).setHeader("Override-Content-Type", "text/s3").connect();
+		r = rc.getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5,contentType=text/s1", r);
+		assertTrue(rc.getResponse().getFirstHeader("Content-Type").getValue().startsWith("text/s3"));
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Properties overridden via properties annotation.  Default Accept header.
+	//====================================================================================================
+	@Test
+	public void testPropertiesOverridenByAnnotationDefaultAccept() throws Exception {
+		RestClient client = new TestRestClient().setAccept("");
+		String url = URL + "/testPropertiesOverridenByAnnotation";
+		String r;
+		RestCall rc;
+
+		r = client.doPut(url, new StringReader("")).getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5,contentType=text/s2", r);
+
+		r = client.doPut(url, new StringReader("")).setHeader("Override-Accept", "text/s3").getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5,contentType=text/s3", r);
+
+		rc = client.doPut(url, new StringReader("")).setHeader("Override-Content-Type", "text/s3").connect();
+		r = rc.getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5,contentType=text/s2", r);
+		assertTrue(rc.getResponse().getFirstHeader("Content-Type").getValue().startsWith("text/s3"));
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Properties overridden programmatically.
+	//====================================================================================================
+	@Test
+	public void testPropertiesOverriddenProgramatically() throws Exception {
+		RestClient client = new TestRestClient().setAccept("text/s1");
+		String url = URL + "/testPropertiesOverriddenProgramatically";
+		String r;
+		RestCall rc;
+
+		r = client.doPut(url, new StringReader("")).getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5,contentType=text/s1", r);
+
+		r = client.doPut(url, new StringReader("")).setHeader("Override-Accept", "text/s2").getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5,contentType=text/s2", r);
+
+		rc = client.doPut(url, new StringReader("")).setHeader("Override-Content-Type", "text/s3").connect();
+		r = rc.getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5,contentType=text/s1", r);
+		assertTrue(rc.getResponse().getFirstHeader("Content-Type").getValue().startsWith("text/s3"));
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Properties overridden programmatically.  Default Accept header.
+	//====================================================================================================
+	@Test
+	public void testPropertiesOverriddenProgramaticallyDefaultAccept() throws Exception {
+		RestClient client = new TestRestClient().setAccept("");
+		String url = URL + "/testPropertiesOverriddenProgramatically";
+		String r;
+		RestCall rc;
+
+		r = client.doPut(url, new StringReader("")).getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5,contentType=text/s2", r);
+
+		r = client.doPut(url, new StringReader("")).setHeader("Override-Accept", "text/s3").getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5,contentType=text/s3", r);
+
+		rc = client.doPut(url, new StringReader("")).setHeader("Override-Content-Type", "text/s3").connect();
+		r = rc.getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5,contentType=text/s2", r);
+		assertTrue(rc.getResponse().getFirstHeader("Content-Type").getValue().startsWith("text/s3"));
+
+		client.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/OnPreCallTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/OnPreCallTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/OnPreCallTest.java
new file mode 100755
index 0000000..f11ef24
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/OnPreCallTest.java
@@ -0,0 +1,61 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static org.junit.Assert.*;
+
+import java.io.*;
+
+import org.apache.juneau.client.*;
+import org.junit.*;
+
+public class OnPreCallTest {
+
+	private static String URL = "/testOnPreCall";
+
+	//====================================================================================================
+	// Properties overridden via properties annotation.
+	//====================================================================================================
+	@Test
+	public void testPropertiesOverriddenByAnnotation() throws Exception {
+		RestClient client = new TestRestClient().setContentType("text/a1").setAccept("text/plain");
+		String url = URL + "/testPropertiesOverriddenByAnnotation";
+		String r;
+
+		r = client.doPut(url, new StringReader("")).getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5,contentType=text/a1", r);
+
+		r = client.doPut(url, new StringReader("")).setHeader("Override-Content-Type", "text/a2").getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5,contentType=text/a2", r);
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Properties overridden programmatically.
+	//====================================================================================================
+	@Test
+	public void testPropertiesOverriddenProgrammatically() throws Exception {
+		RestClient client = new TestRestClient().setContentType("text/a1").setAccept("text/plain");
+		String url = URL + "/testPropertiesOverriddenProgrammatically";
+		String r;
+
+		r = client.doPut(url, new StringReader("")).getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5,contentType=text/a1", r);
+
+		r = client.doPut(url, new StringReader("")).setHeader("Override-Content-Type", "text/a2").getResponseAsString();
+		assertEquals("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5,contentType=text/a2", r);
+
+		client.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/OptionsWithoutNlsTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/OptionsWithoutNlsTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/OptionsWithoutNlsTest.java
new file mode 100755
index 0000000..ccd242e
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/OptionsWithoutNlsTest.java
@@ -0,0 +1,51 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.client.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.server.labels.*;
+import org.junit.*;
+
+public class OptionsWithoutNlsTest {
+
+	private static String URL = "/testOptionsWithoutNls";
+
+	//====================================================================================================
+	// Should get to the options page without errors
+	//====================================================================================================
+	@Test
+	public void testOptions() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		RestCall r = client.doOptions(URL + "/testOptions");
+		ResourceOptions o = r.getResponse(ResourceOptions.class);
+		assertEquals("", o.getDescription());
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Missing resource bundle should cause {!!x} string.
+	//====================================================================================================
+	@Test
+	public void testMissingResourceBundle() throws Exception {
+		RestClient client = new TestRestClient(JsonSerializer.DEFAULT, JsonParser.DEFAULT);
+		RestCall r = client.doGet(URL + "/testMissingResourceBundle");
+		String o = r.getResponse(String.class);
+		assertEquals("{!!bad}", o);
+
+		client.closeQuietly();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/bea31abd/juneau-server-test/src/test/java/org/apache/juneau/server/OverlappingMethodsTest.java
----------------------------------------------------------------------
diff --git a/juneau-server-test/src/test/java/org/apache/juneau/server/OverlappingMethodsTest.java b/juneau-server-test/src/test/java/org/apache/juneau/server/OverlappingMethodsTest.java
new file mode 100755
index 0000000..caa79d7
--- /dev/null
+++ b/juneau-server-test/src/test/java/org/apache/juneau/server/OverlappingMethodsTest.java
@@ -0,0 +1,170 @@
+/***************************************************************************************************************************
+ * 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.server;
+
+import static javax.servlet.http.HttpServletResponse.*;
+import static org.apache.juneau.server.TestUtils.*;
+import static org.junit.Assert.*;
+
+import org.apache.juneau.client.*;
+import org.junit.*;
+
+public class OverlappingMethodsTest {
+
+	private static String URL = "/testOverlappingMethods";
+	private static boolean debug = false;
+
+	//====================================================================================================
+	// Overlapping guards
+	//====================================================================================================
+	@Test
+	public void testOverlappingGuards1() throws Exception {
+		RestClient client = new TestRestClient().setHeader("Accept", "text/plain");
+		String r;
+		String url = URL + "/testOverlappingGuards1";
+
+		r = client.doGet(url + "?t1=1").getResponseAsString();
+		assertEquals("test1_doGet", r);
+
+		try {
+			client.doGet(url + "?noTrace=true").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_FORBIDDEN, "Access denied by guard");
+		}
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Overlapping guards
+	//====================================================================================================
+	@Test
+	public void testOverlappingGuards2() throws Exception {
+		RestClient client = new TestRestClient().setHeader("Accept", "text/plain");
+		String r;
+		String url = URL + "/testOverlappingGuards2";
+		try {
+			client.doGet(url + "?noTrace=true").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_FORBIDDEN, "Access denied by guard");
+		}
+
+		try {
+			client.doGet(url + "?t1=1&noTrace=true").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_FORBIDDEN, "Access denied by guard");
+		}
+
+		try {
+			client.doGet(url + "?t2=2&noTrace=true").connect();
+			fail("Exception expected");
+		} catch (RestCallException e) {
+			checkErrorResponse(debug, e, SC_FORBIDDEN, "Access denied by guard");
+		}
+
+		r = client.doGet(url + "?t1=1&t2=2").getResponseAsString();
+		assertEquals("test2_doGet", r);
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Overlapping matchers
+	//====================================================================================================
+	@Test
+	public void testOverlappingMatchers1() throws Exception {
+		RestClient client = new TestRestClient().setHeader("Accept", "text/plain");
+		String r;
+		String url = URL + "/testOverlappingMatchers1";
+
+		r = client.doGet(url + "?t1=1").getResponseAsString();
+		assertEquals("test3a", r);
+
+		r = client.doGet(url + "?t2=2").getResponseAsString();
+		assertEquals("test3b", r);
+
+		r = client.doGet(url).getResponseAsString();
+		assertEquals("test3c", r);
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Overlapping matchers
+	//====================================================================================================
+	@Test
+	public void testOverlappingMatchers2() throws Exception {
+		RestClient client = new TestRestClient().setHeader("Accept", "text/plain");
+		String r;
+		String url = URL + "/testOverlappingMatchers2";
+
+		r = client.doGet(url + "?t1=1").getResponseAsString();
+		assertEquals("test4b", r);
+
+		r = client.doGet(url + "?t2=2").getResponseAsString();
+		assertEquals("test4b", r);
+
+		r = client.doGet(url + "?t1=1&t2=2").getResponseAsString();
+		assertEquals("test4b", r);
+
+		r = client.doGet(url + "?tx=x").getResponseAsString();
+		assertEquals("test4a", r);
+
+		client.closeQuietly();
+	}
+
+	//====================================================================================================
+	// Overlapping URL patterns
+	//====================================================================================================
+	@Test
+	public void testOverlappingUrlPatterns() throws Exception {
+		RestClient client = new TestRestClient().setHeader("Accept", "text/plain");
+		String r;
+		String url = URL + "/testOverlappingUrlPatterns";
+
+		// [/test5] = [test5a]
+		// [/test5/*] = [test5b]   -- Cannot get called.
+		// [/test5/foo] = [test5c]
+		// [/test5/foo/*] = [test5d]
+		// [/test5/{id}] = [test5e]
+		// [/test5/{id}/*] = [test5f]
+		// [/test5/{id}/foo] = [test5g]
+		// [/test5/{id}/foo/*] = [test5h]
+
+		r = client.doGet(url).getResponseAsString();
+		assertEquals("test5a", r);
+
+		r = client.doGet(url + "/foo").getResponseAsString();
+		assertEquals("test5c", r);
+
+		r = client.doGet(url + "/foo/x").getResponseAsString();
+		assertEquals("test5d", r);
+
+		r = client.doGet(url + "/x").getResponseAsString();
+		assertEquals("test5e", r);
+
+		r = client.doGet(url + "/x/x").getResponseAsString();
+		assertEquals("test5f", r);
+
+		r = client.doGet(url + "/x/foo").getResponseAsString();
+		assertEquals("test5g", r);
+
+		r = client.doGet(url + "/x/foo/x").getResponseAsString();
+		assertEquals("test5h", r);
+
+		client.closeQuietly();
+	}
+}