This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new a447cb4 Tests
a447cb4 is described below
commit a447cb4a8d62b8b7a23b19714887b2f4adc36e2d
Author: JamesBognar <[email protected]>
AuthorDate: Sat May 12 12:08:45 2018 -0400
Tests
---
.../org/apache/juneau/testutils/TestUtils.java | 6 +
.../src/main/java/org/apache/juneau/ClassMeta.java | 74 +++
juneau-doc/src/main/javadoc/overview.html | 176 +++++-
.../rest/test/DefaultContentTypesResource.java | 140 -----
.../apache/juneau/rest/test/ParamsResource.java | 2 +-
.../java/org/apache/juneau/rest/test/Root.java | 1 -
.../juneau/rest/test/DefaultContentTypesTest.java | 427 -------------
.../org/apache/juneau/rest/test/ParamsTest.java | 2 +-
.../org/apache/juneau/rest/test/_TestSuite.java | 1 -
.../apache/juneau/rest/BasicRestCallHandler.java | 3 +
.../java/org/apache/juneau/rest/RequestBody.java | 29 +-
.../java/org/apache/juneau/rest/RestContext.java | 12 +-
.../org/apache/juneau/rest/RestParamDefaults.java | 9 -
.../org/apache/juneau/rest/annotation/Body.java | 77 ++-
.../juneau/rest/mock/MockServletRequest.java | 78 ++-
.../juneau/rest/mock/MockServletResponse.java | 44 ++
.../juneau/rest/annotation/BodyAnnotationTest.java | 680 +++++++++++++++++++++
.../apache/juneau/rest/annotation/BodyTest.java | 533 ----------------
.../rest/annotation/DefaultContentTypesTest.java | 384 ++++++++++++
.../juneau/rest/annotation/StatusCodesTest.java | 48 ++
20 files changed, 1565 insertions(+), 1161 deletions(-)
diff --git
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/testutils/TestUtils.java
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/testutils/TestUtils.java
index cb662e7..abdfced 100644
---
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/testutils/TestUtils.java
+++
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/testutils/TestUtils.java
@@ -474,6 +474,12 @@ public class TestUtils {
if (! isEquals(expected, actual))
throw new ComparisonFailure(format(msg, args),
toString(expected), toString(actual));
}
+
+ public static final void assertContains(Object value,
String...substrings) {
+ for (String substring : substrings)
+ if (! contains(toString(value), substring))
+ throw new ComparisonFailure("Text did not
contain expected substring.", toString(substring), toString(value));
+ }
/**
* Creates a ClassMeta for the given types.
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index a3e6ddc..1913e26 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -119,6 +119,9 @@ public final class ClassMeta<T> implements Type {
private final BeanRegistry beanRegistry; // The bean
registry of this class meta (if it has one).
private final ClassMeta<?>[] args; // Arg types if
this is an array of args.
private final Object example; // Example
object.
+ private final Transform<Reader,T> readerTransform;
+ private final Transform<InputStream,T> inputStreamTransform;
+ private final Transform<String,T> stringTransform;
private ReadWriteLock lock = new ReentrantReadWriteLock(false);
private Lock rLock = lock.readLock(), wLock = lock.writeLock();
@@ -198,6 +201,9 @@ public final class ClassMeta<T> implements Type {
this.exampleField = builder.exampleField;
this.example = builder.example;
this.args = null;
+ this.readerTransform = builder.readerTransform;
+ this.inputStreamTransform =
builder.inputStreamTransform;
+ this.stringTransform = builder.stringTransform;
} finally {
wLock.unlock();
}
@@ -260,6 +266,9 @@ public final class ClassMeta<T> implements Type {
this.exampleField = mainType.exampleField;
this.example = mainType.example;
this.args = null;
+ this.readerTransform = mainType.readerTransform;
+ this.inputStreamTransform = mainType.inputStreamTransform;
+ this.stringTransform = mainType.stringTransform;
}
/**
@@ -309,6 +318,9 @@ public final class ClassMeta<T> implements Type {
this.exampleMethod = null;
this.exampleField = null;
this.example = null;
+ this.readerTransform = null;
+ this.inputStreamTransform = null;
+ this.stringTransform = null;
}
@SuppressWarnings({"unchecked","rawtypes","hiding"})
@@ -361,6 +373,9 @@ public final class ClassMeta<T> implements Type {
Method exampleMethod;
Field exampleField;
Object example;
+ Transform<Reader,T> readerTransform;
+ Transform<InputStream,T> inputStreamTransform;
+ Transform<String,T> stringTransform;
ClassMetaBuilder(Class<T> innerClass, BeanContext beanContext,
Class<? extends T> implClass, BeanFilter beanFilter, PojoSwap<T,?>[] pojoSwaps,
PojoSwap<?,?>[] childPojoSwaps, Object example) {
this.innerClass = innerClass;
@@ -451,6 +466,7 @@ public final class ClassMeta<T> implements Type {
}
}
}
+ // TODO - should use transforms for above code.
// Special cases
try {
@@ -748,6 +764,10 @@ public final class ClassMeta<T> implements Type {
}
this.example = example;
+
+ this.readerTransform = TransformCache.get(Reader.class,
c);
+ this.inputStreamTransform =
TransformCache.get(InputStream.class, c);
+ this.stringTransform = TransformCache.get(String.class,
c);
}
private BeanFilter findBeanFilter() {
@@ -2026,4 +2046,58 @@ public final class ClassMeta<T> implements Type {
public int hashCode() {
return super.hashCode();
}
+
+ /**
+ * Returns <jk>true</jk> if this class has a transform associated with
it that allows it to be created from a Reader.
+ *
+ * @return <jk>true</jk> if this class has a transform associated with
it that allows it to be created from a Reader.
+ */
+ public boolean hasReaderTransform() {
+ return readerTransform != null;
+ }
+
+ /**
+ * Returns the transform for this class for creating instances from a
Reader.
+ *
+ * @return The transform, or <jk>null</jk> if no such transform exists.
+ */
+ public Transform<Reader,T> getReaderTransform() {
+ return readerTransform;
+ }
+
+ /**
+ * Returns <jk>true</jk> if this class has a transform associated with
it that allows it to be created from an InputStream.
+ *
+ * @return <jk>true</jk> if this class has a transform associated with
it that allows it to be created from an InputStream.
+ */
+ public boolean hasInputStreamTransform() {
+ return inputStreamTransform != null;
+ }
+
+ /**
+ * Returns the transform for this class for creating instances from an
InputStream.
+ *
+ * @return The transform, or <jk>null</jk> if no such transform exists.
+ */
+ public Transform<InputStream,T> getInputStreamTransform() {
+ return inputStreamTransform;
+ }
+
+ /**
+ * Returns <jk>true</jk> if this class has a transform associated with
it that allows it to be created from a String.
+ *
+ * @return <jk>true</jk> if this class has a transform associated with
it that allows it to be created from a String.
+ */
+ public boolean hasStringTransform() {
+ return stringTransform != null;
+ }
+
+ /**
+ * Returns the transform for this class for creating instances from a
String.
+ *
+ * @return The transform, or <jk>null</jk> if no such transform exists.
+ */
+ public Transform<String,T> getStringTransform() {
+ return stringTransform;
+ }
}
diff --git a/juneau-doc/src/main/javadoc/overview.html
b/juneau-doc/src/main/javadoc/overview.html
index 4d88d55..29d01ca 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -12279,40 +12279,172 @@
<h3 class='topic' onclick='toggle(this)'>7.7 - @Body</h3>
<div class='topic'>
<p>
- The {@link org.apache.juneau.rest.annotation.Body
@Body} annotation provides easy access to the HTTP body content as any <a
class='doclink' href='#juneau-marshall.PojoCategories'>parsable</a> POJO type
- <br>In the example below, we're POSTing beans.
+ The {@link org.apache.juneau.rest.annotation.Body
@Body} annotation is used to identify POJOs to be used as the body of an HTTP
request.
</p>
+ <h5 class='figure'>Example:</h5>
<p class='bcode w800'>
- <jc>// Example POST of a bean</jc>
- <ja>@RestMethod</ja>(name=<jsf>POST</jsf>, path=<js>"/"</js>)
- <jk>public void</jk> doPost(<ja>@Body</ja> Person person)
<jk>throws</jk> Exception {
- <jc>// Do something with person.</jc>
+ <ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
+ <jk>public void</jk> addPerson(<ja>@Body</ja> Person person) {
+ ...
}
</p>
<p>
- The HTTP body of a request can be retrieved as a parsed
POJO using either the
- {@link org.apache.juneau.rest.RestRequest#getBody()}
method, or a parameter annotated with
- {@link org.apache.juneau.rest.annotation.Body @Body}.
+ This is functionally equivalent to the following code...
</p>
<p class='bcode w800'>
- <jc>// Equivalent method 1</jc>
- <ja>@RestMethod</ja>(name=<jsf>POST</jsf>, path=<js>"/example1"</js>)
- <jk>public void</jk> doPost1(<ja>@Body</ja> Person p) {
- <jc>// Do something with p.</jc>
+ <ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
+ <jk>public void</jk> addPerson(RestRequest req) {
+ Person person = req.getBody().asType(Person.<jk>class</jk>);
+ ...
}
-
- <jc>// Equivalent method 2</jc>
- <ja>@RestMethod</ja>(name=<jsf>POST</jsf>, path=<js>"/example2"</js>)
- <jk>public void</jk> doPost2(RestRequest req) {
- Person p = req.getBody).asType(Person.<jk>class</jk>);
- <jc>// Do something with p.</jc>
+ </p>
+ <p>
+ This annotation can be applied at the following
locations:
+ </p>
+ <ul class='spaced-list'>
+ <li>
+ Parameters on a {@link RestMethod @RestMethod}.
+ <li>
+ POJO classes.
+ </ul>
+
+ <p>
+ Any of the following types can be used for the
parameter or POJO class:
+ </p>
+ <ol class='spaced-list'>
+ <li>
+ {@link Reader}
+ <br><ja>@Body</ja> annotation is optional.
+ <br><code>Content-Type</code> is ignored.
+ <li>
+ {@link InputStream}
+ <br><ja>@Body</ja> annotation is optional.
+ <br><code>Content-Type</code> is ignored.
+ <li>
+ Any <a class='doclink'
href='../../../../../overview-summary.html#juneau-marshall.PojoCategories'>parsable</a>
POJO type.
+ <br><code>Content-Type</code> is required to
identify correct parser.
+ <li>
+ Objects convertible from {@link Reader} by
having one of the following non-deprecated methods:
+ <ul>
+ <li><code><jk>public</jk> T(Reader in)
{...}</code>
+ <li><code><jk>public static</jk> T
<jsm>create</jsm>(Reader in) {...}</code>
+ <li><code><jk>public static</jk> T
<jsm>fromReader</jsm>(Reader in) {...}</code>
+ </ul>
+ <br><code>Content-Type</code> must not be
present or match an existing parser so that it's not parsed as a POJO.
+ <li>
+ Objects convertible from {@link InputStream} by
having one of the following non-deprecated methods:
+ <ul>
+ <li><code><jk>public</jk> T(InputStream
in) {...}</code>
+ <li><code><jk>public static</jk> T
<jsm>create</jsm>(InputStream in) {...}</code>
+ <li><code><jk>public static</jk> T
<jsm>fromInputStream</jsm>(InputStream in) {...}</code>
+ </ul>
+ <br><code>Content-Type</code> must not be
present or match an existing parser so that it's not parsed as a POJO.
+ <li>
+ Objects convertible from {@link String}
(including <code>String</code> itself) by having one of the following
non-deprecated methods:
+ <ul>
+ <li><code><jk>public</jk> T(String in)
{...}</code> (e.g. {@link Integer}, {@link Boolean})
+ <li><code><jk>public static</jk> T
<jsm>create</jsm>(String in) {...}</code>
+ <li><code><jk>public static</jk> T
<jsm>fromString</jsm>(String in) {...}</code>
+ <li><code><jk>public static</jk> T
<jsm>fromValue</jsm>(String in) {...}</code>
+ <li><code><jk>public static</jk> T
<jsm>valueOf</jsm>(String in) {...}</code> (e.g. enums)
+ <li><code><jk>public static</jk> T
<jsm>parse</jsm>(String in) {...}</code> (e.g. {@link Level})
+ <li><code><jk>public static</jk> T
<jsm>parseString</jsm>(String in) {...}</code>
+ <li><code><jk>public static</jk> T
<jsm>forName</jsm>(String in) {...}</code> (e.g. {@link Class}, {@link Charset})
+ <li><code><jk>public static</jk> T
<jsm>forString</jsm>(String in) {...}</code>
+ </ul>
+ <br><code>Content-Type</code> must not be
present or match an existing parser so that it's not parsed as a POJO.
+ </ol>
+ <p>
+ Special note should be taken on using {@link String} as
the body object:
+ </p>
+ <p class='bcode w800'>
+ <ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
+ <jk>public void</jk> add(<ja>@Body</ja> String body) {
+ ...
}
</p>
<p>
- The Juneau framework will automatically determine the
appropriate <l>Parser</l> to use based on the
- <l>Content-Type</l> HTTP header.
- <br>So the body content could be JSON or XML or any
other supported parsing types.
+ In the case above, when the <code>Content-Type</code>
header is present and matches a parser, the body will be parsed into a
<code>String</code> using the matched parser
+ using rule #3 above.
+ <br>For example, passing in a body of <js>"'foo'"</js>
with the header <code>Content-Type: application/json</code> will result in the
body being populated with
+ <js>"foo"</js>.
+ </p>
+ <p>
+ When the <code>Content-Type</code> header is not
present or match a parser, the body is pass as-is using rule #6 above.
+ <br>For example, passing in a body of <js>"'foo'"</js>
with no <code>Content-Type</code> header will result in the body being
populated with
+ <js>"'foo'"</js>.
</p>
+ <p>
+ The <ja>@Body</ja> annotation can also be used on POJO
classes used as parameters on a REST method.
+ <br>This can be useful if you're reusing the same POJOs
often in your REST interface and don't want to redefine your Swagger on each
method.
+ </p>
+
+ <h5 class='figure'>Examples:</h5>
+ <p class='bcode w800'>
+ <ja>@Body</ja>(description=<js>"POJO convertible from String"</js>)</ja>
+ <jk>public static class</jk> A {
+ <jk>private</jk> String <jf>val</jf>;
+ <jk>public</jk> A(String val) {
+ <jk>this</jk>.<jf>val</jf> = val;
+ }
+ <jk>public</jk> String toString() {
+ <jk>return</jk> <jf>val</jf>;
+ }
+ }
+
+ <ja>@RestMethod</ja>(name=<jsf>PUT</jsf>,
path=<js>"/testPojoFromString"</js>)
+ <jk>public</jk> A testPojoFromString(A a) {
+ <jk>return</jk> a;
+ }
+ </p>
+ <p class='bcode w800'>
+ <ja>@Body</ja>(description=<js>"Bean POJO"</js>)</ja>
+ <jk>public static class</jk> B {
+ <jk>public</jk> String <jf>f1</jf>;
+ }
+
+ <ja>@RestMethod</ja>(name=<jsf>PUT</jsf>, path=<js>"/testBean"</js>)
+ <jk>public</jk> B testBean(B b) {
+ <jk>return</jk> b;
+ }
+ </p>
+ <p class='bcode w800'>
+ <ja>@Body</ja>(description=<js>"Bean list"</js>)</ja>
+ <jk>public static class</jk> C extends LinkedList<B> {}
+
+ <ja>@RestMethod</ja>(name=<jsf>PUT</jsf>, path=<js>"/testBeanList"</js>)
+ <jk>public</jk> C testString(C c) {
+ <jk>return</jk> c;
+ }
+ </p>
+ <p class='bcode w800'>
+ <ja>@Body</ja>(description=<js>"POJO convertible from input
stream"</js>)</ja>
+ <jk>public static class</jk> D {
+ <jk>private</jk> String <jf>val</jf>;
+ <jk>public</jk> D(InputStream is) {
+ <jk>this</jk>.<jf>val</jf> =
IOUtils.<jsm>read</jsm>(is);
+ }
+ <jk>public</jk> String toString() {
+ <jk>return</jk> <jf>val</jf>;
+ }
+ }
+
+ <ja>@RestMethod</ja>(name=<jsf>PUT</jsf>,
path=<js>"/testPojoFromInputStream"</js>)
+ <jk>public</jk> D testPojoFromInputStream(D d) {
+ <jk>return</jk> d;
+ }
+ </p>
+
+ <h5 class='section'>Notes:</h5>
+ <ul class='spaced-list'>
+ <li>
+ Annotation parameter values will be aggregated
when used on POJO parent and child classes.
+ <br>Values on child classes override values on
parent classes.
+ <li>
+ Annotation parameter values will be aggregated
when used on both POJOs and REST methods.
+ <br>Values on methods override values on POJO
classes.
+ </ul>
+
<h5 class='section'>See Also:</h5>
<ul>
<li class='ja'>{@link
org.apache.juneau.rest.annotation.Body}
diff --git
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/DefaultContentTypesResource.java
b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/DefaultContentTypesResource.java
deleted file mode 100644
index c15a0d7..0000000
---
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/DefaultContentTypesResource.java
+++ /dev/null
@@ -1,140 +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.test;
-
-import static org.apache.juneau.http.HttpMethodName.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.serializer.*;
-
-/**
- * JUnit automated testcase resource.
- */
-@RestResource(
- path="/testDefaultContentTypes",
- defaultRequestHeaders={" Accept : text/s2 "," Content-Type : text/p2 "},
-
parsers={DefaultContentTypesResource.P1.class,DefaultContentTypesResource.P2.class},
serializers={DefaultContentTypesResource.S1.class,DefaultContentTypesResource.S2.class}
-)
-public class DefaultContentTypesResource extends RestServlet {
- private static final long serialVersionUID = 1L;
-
- 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");}}
-
- 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 and Content-Type headers on servlet
annotation are picked up.
- */
- @RestMethod(name=PUT, path="/testDefaultHeadersOnServletAnnotation")
- public String testDefaultHeadersOnServletAnnotation(@Body String in) {
- return in;
- }
-
-
//====================================================================================================
- // Test that default Accept and Content-Type headers on servlet
annotation are picked up
- // when @RestMethod.parsers/serializers annotations are used.
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testRestMethodParsersSerializers",
parsers=P3.class, serializers=S3.class)
- public String testRestMethodParsersSerializers(@Body String in) {
- return in;
- }
-
-
//====================================================================================================
- // Test that default Accept and Content-Type headers on servlet
annotation are picked up
- // when @RestMethod.addParsers/addSerializers annotations are used.
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testRestMethodAddParsersSerializers",
parsers=P3.class, serializers=S3.class, inherit="SERIALIZERS,PARSERS")
- public String testRestMethodAddParsersSerializers(@Body String in) {
- return in;
- }
-
-
//====================================================================================================
- // Various Accept incantations.
-
//====================================================================================================
- @RestMethod(name=PUT, path="/testAccept")
- public String testAccept(@Body String in) {
- return in;
- }
-
-
//====================================================================================================
- // Test that default Accept and Content-Type headers on method
annotation are picked up
- // when @RestMethod.parsers/serializers annotations are used.
-
//====================================================================================================
- @RestMethod(name=PUT,
path="/testRestMethodParserSerializerAnnotations",
defaultRequestHeaders={"Accept: text/s3","Content-Type: text/p3"},
parsers=P3.class, serializers=S3.class)
- public String testRestMethodParserSerializerAnnotations(@Body String
in) {
- return in;
- }
-
-
//====================================================================================================
- // Test that default Accept and Content-Type headers on method
annotation are picked up
- // when @RestMethod.addParsers/addSerializers annotations are used.
-
//====================================================================================================
- @RestMethod(name=PUT,
path="/testRestMethodAddParsersSerializersAnnotations",
defaultRequestHeaders={"Accept: text/s3","Content-Type: text/p3"},
parsers=P3.class, serializers=S3.class, inherit="SERIALIZERS,PARSERS")
- public String testRestMethodAddParsersSerializersAnnotations(@Body
String in) {
- return in;
- }
-
- public static class DummyParser extends ReaderParser {
-
- private String name;
-
- private DummyParser(PropertyStore ps, String name,
String...consumes) {
- super(ps, consumes);
- this.name = name;
- }
-
- @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 Exception {
- return (T)name;
- }
- };
- }
- }
-
- public static class DummySerializer extends WriterSerializer {
-
- private String name;
-
- private 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 Exception {
- out.getWriter().write(name + "/" + o);
- }
- };
- }
- }
-}
diff --git
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
index 69fe0e0..e15ca28 100644
---
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
+++
b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/ParamsResource.java
@@ -401,7 +401,7 @@ public class ParamsResource extends BasicRestServlet {
return t != null;
}
- @RestMethod(name=GET, path="/otherObjects/Parser")
+ @RestMethod(name=GET,
path="/otherObjects/Parser",parsers={JsonParser.class})
public String testOtherParser(Parser t) {
return t.getClass().getName();
}
diff --git
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
index 3b4973e..119996e 100644
---
a/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
+++
b/juneau-microservice/juneau-microservice-test/src/main/java/org/apache/juneau/rest/test/Root.java
@@ -32,7 +32,6 @@ import org.apache.juneau.rest.helper.*;
ClientFuturesResource.class,
ClientVersionResource.class,
ConfigResource.class,
- DefaultContentTypesResource.class,
ErrorConditionsResource.class,
TransformsResource.class,
FormDataResource.class,
diff --git
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/DefaultContentTypesTest.java
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/DefaultContentTypesTest.java
deleted file mode 100644
index 9ce9e19..0000000
---
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/DefaultContentTypesTest.java
+++ /dev/null
@@ -1,427 +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.test;
-
-import static javax.servlet.http.HttpServletResponse.*;
-import static org.apache.juneau.microservice.testutils.TestUtils.*;
-import static org.junit.Assert.*;
-
-import org.apache.juneau.rest.client.*;
-import org.junit.*;
-
-
-public class DefaultContentTypesTest extends RestTestcase {
-
- private static String URL = "/testDefaultContentTypes";
- private static boolean debug = false;
-
-
//====================================================================================================
- // Test that default Accept and Content-Type headers on servlet
annotation are picked up.
-
//====================================================================================================
- @Test
- public void testDefaultHeadersOnServletAnnotation() throws Exception {
- RestClient client = TestMicroservice.DEFAULT_CLIENT;
- String r;
-
- String url = URL + "/testDefaultHeadersOnServletAnnotation";
-
- r = client.doPut(url,
"").accept("").contentType("").getResponseAsString();
- assertEquals("s2/p2", r);
-
- r = client.doPut(url,
"").accept("text/s1").contentType("").getResponseAsString();
- assertEquals("s1/p2", r);
-
- r = client.doPut(url,
"").accept("").contentType("text/p1").getResponseAsString();
- assertEquals("s2/p1", r);
-
- r = client.doPut(url,
"").accept("text/s1").contentType("text/p1").getResponseAsString();
- assertEquals("s1/p1", r);
-
- r = client.doPut(url,
"").accept("text/s2").contentType("").getResponseAsString();
- assertEquals("s2/p2", r);
-
- r = client.doPut(url,
"").accept("").contentType("text/p2").getResponseAsString();
- assertEquals("s2/p2", r);
-
- r = client.doPut(url,
"").accept("text/s2").contentType("text/p2").getResponseAsString();
- assertEquals("s2/p2", r);
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s3").contentType("").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
- "Unsupported media-type in request header
'Accept': 'text/s3'",
- "Supported media-types: ['text/s1','text/s2']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("").contentType("text/p3").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p3'",
- "Supported media-types: ['text/p1','text/p2']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s3").contentType("text/p3").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p3'",
- "Supported media-types: ['text/p1','text/p2']"
- );
- }
- }
-
-
//====================================================================================================
- // Test that default Accept and Content-Type headers on servlet
annotation are picked up
- // when @RestMethod.parsers/serializers annotations are used.
-
//====================================================================================================
- @Test
- public void testRestMethodParsersSerializers() throws Exception {
- RestClient client = TestMicroservice.DEFAULT_CLIENT;
- String r;
-
- String url = URL + "/testRestMethodParsersSerializers";
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("").contentType("").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p2'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s1").contentType("").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p2'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("").contentType("text/p1").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p1'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s1").contentType("text/p1").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p1'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s2").contentType("").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p2'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("").contentType("text/p2").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p2'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s2").contentType("text/p2").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p2'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s3").contentType("").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p2'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("").contentType("text/p3").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
- "Unsupported media-type in request header
'Accept': 'text/s2'",
- "Supported media-types: ['text/s3']"
- );
- }
-
- r = client.doPut(url,
"").accept("text/s3").contentType("text/p3").getResponseAsString();
- assertEquals("s3/p3", r);
- }
-
-
//====================================================================================================
- // Test that default Accept and Content-Type headers on servlet
annotation are picked up
- // when @RestMethod.addParsers/addSerializers annotations are used.
-
//====================================================================================================
- @Test
- public void testRestMethodAddParsersSerializers() throws Exception {
- RestClient client = TestMicroservice.DEFAULT_CLIENT;
- String r;
-
- String url = URL + "/testRestMethodAddParsersSerializers";
-
- r = client.doPut(url,
"").accept("").contentType("").getResponseAsString();
- assertEquals("s2/p2", r);
-
- r = client.doPut(url,
"").accept("text/s1").contentType("").getResponseAsString();
- assertEquals("s1/p2", r);
-
- r = client.doPut(url,
"").accept("").contentType("text/p1").getResponseAsString();
- assertEquals("s2/p1", r);
-
- r = client.doPut(url,
"").accept("text/s1").contentType("text/p1").getResponseAsString();
- assertEquals("s1/p1", r);
-
- r = client.doPut(url,
"").accept("text/s2").contentType("").getResponseAsString();
- assertEquals("s2/p2", r);
-
- r = client.doPut(url,
"").accept("").contentType("text/p2").getResponseAsString();
- assertEquals("s2/p2", r);
-
- r = client.doPut(url,
"").accept("text/s2").contentType("text/p2").getResponseAsString();
- assertEquals("s2/p2", r);
-
- r = client.doPut(url,
"").accept("text/s3").contentType("").getResponseAsString();
- assertEquals("s3/p2", r);
-
- r = client.doPut(url,
"").accept("").contentType("text/p3").getResponseAsString();
- assertEquals("s2/p3", r);
-
- r = client.doPut(url,
"").accept("text/s3").contentType("text/p3").getResponseAsString();
- assertEquals("s3/p3", r);
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("").contentType("text/p4").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- // Note that parsers defined on method are listed
before parsers defined on class.
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p4'",
- "Supported media-types:
['text/p3','text/p1','text/p2']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s4").contentType("").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- // Note that serializers defined on method are listed
before serializers defined on class.
- checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
- "Unsupported media-type in request header
'Accept': 'text/s4'",
- "Supported media-types:
['text/s3','text/s1','text/s2']"
- );
- }
- }
-
-
//====================================================================================================
- // Various Accept incantations.
-
//====================================================================================================
- @Test
- public void testAccept() throws Exception {
- RestClient client =
TestMicroservice.client().contentType("text/p1").build();
- String r;
-
- String url = URL + "/testAccept";
-
- // "*/*" should match the first serializer, not the default
serializer.
- r = client.doPut(url, "").accept("*/*").getResponseAsString();
- assertEquals("s1/p1", r);
-
- // "text/*" should match the first serializer, not the default
serializer.
- r = client.doPut(url,
"").accept("text/*").getResponseAsString();
- assertEquals("s1/p1", r);
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("bad/*").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
- "Unsupported media-type in request header
'Accept': 'bad/*'",
- "Supported media-types: ['text/s1','text/s2']"
- );
- }
-
- r = client.doPut(url,
"").accept("bad/*,text/*").getResponseAsString();
- assertEquals("s1/p1", r);
-
- r = client.doPut(url,
"").accept("text/*,bad/*").getResponseAsString();
- assertEquals("s1/p1", r);
-
- r = client.doPut(url,
"").accept("text/s1;q=0.5,text/s2").getResponseAsString();
- assertEquals("s2/p1", r);
-
- r = client.doPut(url,
"").accept("text/s1,text/s2;q=0.5").getResponseAsString();
- assertEquals("s1/p1", r);
-
- client.closeQuietly();
- }
-
-
//====================================================================================================
- // Test that default Accept and Content-Type headers on method
annotation are picked up
- // when @RestMethod.parsers/serializers annotations are used.
-
//====================================================================================================
- @Test
- public void testRestMethodParserSerializerAnnotations() throws
Exception {
- RestClient client = TestMicroservice.DEFAULT_CLIENT;
- String r;
-
- String url = URL + "/testRestMethodParserSerializerAnnotations";
-
- r = client.doPut(url,
"").accept("").contentType("").getResponseAsString();
- assertEquals("s3/p3", r);
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s1").contentType("").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
- "Unsupported media-type in request header
'Accept': 'text/s1'",
- "Supported media-types: ['text/s3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("").contentType("text/p1").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p1'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s1").contentType("text/p1").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p1'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s2").contentType("").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_NOT_ACCEPTABLE,
- "Unsupported media-type in request header
'Accept': 'text/s2'",
- "Supported media-types: ['text/s3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("").contentType("text/p2").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p2'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- try {
- r = client.doPut(url+"?noTrace=true",
"").accept("text/s2").contentType("text/p2").getResponseAsString();
- fail("Exception expected");
- } catch (RestCallException e) {
- checkErrorResponse(debug, e, SC_UNSUPPORTED_MEDIA_TYPE,
- "Unsupported media-type in request header
'Content-Type': 'text/p2'",
- "Supported media-types: ['text/p3']"
- );
- }
-
- r = client.doPut(url,
"").accept("text/s3").contentType("").getResponseAsString();
- assertEquals("s3/p3", r);
-
- r = client.doPut(url,
"").accept("").contentType("text/p3").getResponseAsString();
- assertEquals("s3/p3", r);
-
- r = client.doPut(url,
"").accept("text/s3").contentType("text/p3").getResponseAsString();
- assertEquals("s3/p3", r);
- }
-
-
//====================================================================================================
- // Test that default Accept and Content-Type headers on method
annotation are picked up
- // when @RestMethod.addParsers/addSerializers annotations are used.
-
//====================================================================================================
- @Test
- public void testRestMethodAddParsersSerializersAnnotations() throws
Exception {
- RestClient client = TestMicroservice.DEFAULT_CLIENT;
- String r;
-
- String url = URL +
"/testRestMethodAddParsersSerializersAnnotations";
-
- r = client.doPut(url,
"").accept("").contentType("").getResponseAsString();
- assertEquals("s3/p3", r);
-
- r = client.doPut(url,
"").accept("text/s1").contentType("").getResponseAsString();
- assertEquals("s1/p3", r);
-
- r = client.doPut(url,
"").accept("").contentType("text/p1").getResponseAsString();
- assertEquals("s3/p1", r);
-
- r = client.doPut(url,
"").accept("text/s1").contentType("text/p1").getResponseAsString();
- assertEquals("s1/p1", r);
-
- r = client.doPut(url,
"").accept("text/s2").contentType("").getResponseAsString();
- assertEquals("s2/p3", r);
-
- r = client.doPut(url,
"").accept("").contentType("text/p2").getResponseAsString();
- assertEquals("s3/p2", r);
-
- r = client.doPut(url,
"").accept("text/s2").contentType("text/p2").getResponseAsString();
- assertEquals("s2/p2", r);
-
- r = client.doPut(url,
"").accept("text/s3").contentType("").getResponseAsString();
- assertEquals("s3/p3", r);
-
- r = client.doPut(url,
"").accept("").contentType("text/p3").getResponseAsString();
- assertEquals("s3/p3", r);
-
- r = client.doPut(url,
"").accept("text/s3").contentType("text/p3").getResponseAsString();
- assertEquals("s3/p3", r);
- }
-}
diff --git
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ParamsTest.java
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ParamsTest.java
index bd7bf6f..72cd276 100644
---
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ParamsTest.java
+++
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/ParamsTest.java
@@ -811,7 +811,7 @@ public class ParamsTest extends RestTestcase {
@Test
public void testOtherParser() throws Exception {
- String r = CLIENT.doGet(URL +
"/otherObjects/Parser").getResponseAsString();
+ String r = CLIENT.doGet(URL +
"/otherObjects/Parser").contentType("application/json").getResponseAsString();
assertEquals("\"org.apache.juneau.json.JsonParser\"", r);
}
diff --git
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
index 6841615..724cf8d 100644
---
a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
+++
b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
@@ -31,7 +31,6 @@ import org.junit.runners.Suite.*;
ClientFuturesTest.class,
ClientVersionTest.class,
ConfigTest.class,
- DefaultContentTypesTest.class,
ErrorConditionsTest.class,
FormDataTest.class,
GroupsTest.class,
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestCallHandler.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestCallHandler.java
index b0d007b..6ff40d7 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestCallHandler.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestCallHandler.java
@@ -167,6 +167,9 @@ public class BasicRestCallHandler implements
RestCallHandler {
// If not invoked above, see if it's an OPTIONs
request
if (rc != SC_OK)
handleNotFound(rc, req, res);
+
+ if (res.getStatus() == 0)
+ res.setStatus(rc);
}
if (res.hasOutput()) {
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
index b5e7c4a..0df1e58 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
@@ -343,16 +343,19 @@ public class RequestBody {
public ParserMatch getParserMatch() {
if (mediaType != null && parser != null)
return new ParserMatch(mediaType, parser);
+ MediaType mt = getMediaType();
+ return mt == null ? null : parsers.getParserMatch(mt);
+ }
+
+ private MediaType getMediaType() {
+ if (mediaType != null)
+ return mediaType;
MediaType mediaType = headers.getContentType();
- if (isEmpty(mediaType)) {
- if (body != null)
- mediaType = MediaType.UON;
- else
- mediaType = MediaType.JSON;
- }
- return parsers.getParserMatch(mediaType);
+ if (mediaType == null && body != null)
+ return MediaType.UON;
+ return mediaType;
}
-
+
/**
* Returns the parser matching the request <code>Content-Type</code>
header.
*
@@ -423,7 +426,17 @@ public class RequestBody {
);
}
}
+
+ if (cm.hasReaderTransform())
+ return
cm.getReaderTransform().transform(getReader());
+ if (cm.hasInputStreamTransform())
+ return
cm.getInputStreamTransform().transform(getInputStream());
+
+ MediaType mt = getMediaType();
+ if ((isEmpty(mt) || mt.toString().equals("text/plain"))
&& cm.hasStringTransform())
+ return
cm.getStringTransform().transform(asString());
+
throw new UnsupportedMediaType(
"Unsupported media-type in request header
''Content-Type'': ''{0}''\n\tSupported media-types: {1}",
headers.getContentType(),
req.getParsers().getSupportedMediaTypes()
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 097138a..abc0529 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -3029,10 +3029,16 @@ public final class RestContext extends BeanContext {
try {
// Parse the args and invoke the method.
Parser p = req.getBody().getParser();
-
try (Closeable in = p.isReaderParser() ? req.getReader() :
req.getInputStream()) {
-
Object output = m.invoke(o, p.parseArgs(in,
m.getGenericParameterTypes()));
-
res.setOutput(output);
+
Object[] args = null;
+
if (m.getGenericParameterTypes().length == 0)
+
args = new Object[0];
+
else {
+
try (Closeable in = p.isReaderParser() ?
req.getReader() : req.getInputStream()) {
+
args = p.parseArgs(in,
m.getGenericParameterTypes());
+
}
}
+
Object output = m.invoke(o, args);
+
res.setOutput(output);
return SC_OK;
} catch (Exception e) {
throw new InternalServerError(e);
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
index a0a33c0..e55623a 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestParamDefaults.java
@@ -589,21 +589,12 @@ class RestParamDefaults {
static final class BodyObject extends RestMethodParam {
- private final Transform<Reader,?> readerTransform;
- private final Transform<InputStream,?> inputStreamTransform;
-
protected BodyObject(Method method, Body a, Type type,
RestMethodParam existing) {
super(BODY, method, null, type, getMetaData(a,
castOrNull(existing, BodyObject.class)));
- readerTransform = TransformCache.get(Reader.class,
getTypeClass());
- inputStreamTransform =
TransformCache.get(InputStream.class, getTypeClass());
}
@Override /* RestMethodParam */
public Object resolve(RestRequest req, RestResponse res) throws
Exception {
- if (readerTransform != null)
- return
readerTransform.transform(req.getReader()); // Also passes Reader through.
- if (inputStreamTransform != null)
- return
inputStreamTransform.transform(req.getInputStream()); // Also passes
InputStream through.
return req.getBody().asType(type);
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
index 085fe31..3d6beb3 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/Body.java
@@ -17,15 +17,19 @@ import static java.lang.annotation.RetentionPolicy.*;
import java.io.*;
import java.lang.annotation.*;
+import java.nio.charset.*;
+import java.util.logging.*;
import org.apache.juneau.rest.*;
/**
- * Annotation that can be applied to a parameter of a {@link RestMethod
@RestMethod} annotated method or POJO class to identify it as the HTTP
- * request body converted to a POJO.
+ * REST request body annotation.
+ *
+ * <p>
+ * Identifies a POJO to be used as the body of an HTTP request.
*
* <h5 class='section'>Example:</h5>
- * <p class='bcode'>
+ * <p class='bcode w800'>
* <ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
* <jk>public void</jk> addPerson(<ja>@Body</ja> Person person) {
* ...
@@ -34,36 +38,81 @@ import org.apache.juneau.rest.*;
*
* <p>
* This is functionally equivalent to the following code...
- * <p class='bcode'>
+ * <p class='bcode w800'>
* <ja>@RestMethod</ja>(name=<jsf>POST</jsf>)
- * <jk>public void</jk> addPerson(RestRequest req, RestResponse res) {
+ * <jk>public void</jk> addPerson(RestRequest req) {
* Person person = req.getBody().asType(Person.<jk>class</jk>);
* ...
* }
* </p>
*
+ * <p>
+ * This annotation can be applied to the following:
+ * <ul class='spaced-list'>
+ * <li>
+ * Parameters on a {@link RestMethod @RestMethod}.
+ * <li>
+ * POJO classes.
+ * </ul>
+ *
+ * <p>
* Any of the following types can be used for the parameter:
- * <ul>
- * <li>{@link Reader}
- * <li>{@link InputStream}
- * <li>Primitives (e.g. <code>String</code>, <jk>int</jk>,
<jk>boolean</jk>, etc...)
- * <li>Beans
- * <li>Maps, collections, or arrays of beans or primitives.
- * <li>Any object convertible from a {@link Reader} by having one of the
following methods:
+ * <ul class='spaced-list'>
+ * <li>
+ * {@link Reader}
+ * <br><ja>@Body</ja> annotation is optional.
+ * <br><code>Content-Type</code> is always ignored.
+ * <li>
+ * {@link InputStream}
+ * <br><ja>@Body</ja> annotation is optional.
+ * <br><code>Content-Type</code> is always ignored.
+ * <li>
+ * Any <a class='doclink'
href='../../../../../overview-summary.html#juneau-marshall.PojoCategories'>parsable</a>
POJO type.
+ * <br><code>Content-Type</code> is required to identify correct
parser.
+ * <li>
+ * Objects convertible from {@link Reader} by having one of the
following non-deprecated methods:
* <ul>
* <li><code><jk>public</jk> T(Reader in) {...}</code>
* <li><code><jk>public static</jk> T
<jsm>create</jsm>(Reader in) {...}</code>
* <li><code><jk>public static</jk> T
<jsm>fromReader</jsm>(Reader in) {...}</code>
* </ul>
- * </ul>
- * <li>Any object convertible from an {@link InputStream} by having one of
the following methods:
+ * <br><code>Content-Type</code> must not be present or match an
existing parser so that it's not parsed as a POJO.
+ * <li>
+ * Objects convertible from {@link InputStream} by having one of
the following non-deprecated methods:
* <ul>
* <li><code><jk>public</jk> T(InputStream in) {...}</code>
* <li><code><jk>public static</jk> T
<jsm>create</jsm>(InputStream in) {...}</code>
* <li><code><jk>public static</jk> T
<jsm>fromInputStream</jsm>(InputStream in) {...}</code>
* </ul>
+ * <br><code>Content-Type</code> must not be present or match an
existing parser so that it's not parsed as a POJO.
+ * <li>
+ * Objects convertible from {@link String} (including
<code>String</code> itself) by having one of the following non-deprecated
methods:
+ * <ul>
+ * <li><code><jk>public</jk> T(String in) {...}</code>
(e.g. {@link Integer}, {@link Boolean})
+ * <li><code><jk>public static</jk> T
<jsm>create</jsm>(String in) {...}</code>
+ * <li><code><jk>public static</jk> T
<jsm>fromString</jsm>(String in) {...}</code>
+ * <li><code><jk>public static</jk> T
<jsm>fromValue</jsm>(String in) {...}</code>
+ * <li><code><jk>public static</jk> T
<jsm>valueOf</jsm>(String in) {...}</code> (e.g. enums)
+ * <li><code><jk>public static</jk> T
<jsm>parse</jsm>(String in) {...}</code> (e.g. {@link Level})
+ * <li><code><jk>public static</jk> T
<jsm>parseString</jsm>(String in) {...}</code>
+ * <li><code><jk>public static</jk> T
<jsm>forName</jsm>(String in) {...}</code> (e.g. {@link Class}, {@link Charset})
+ * <li><code><jk>public static</jk> T
<jsm>forString</jsm>(String in) {...}</code>
+ * </ul>
+ * <br><code>Content-Type</code> must not be present or match an
existing parser so that it's not parsed as a POJO.
+ * </ul>
+ *
+ *
+ * <h5 class='section'>Notes:</h5>
+ * <ul class='spaced-list'>
+ * <li>
+ * Annotation parameter values will be aggregated when used on
POJO parent and child classes.
+ * <br>Values on child classes override values on parent classes.
+ * <li>
+ * Annotation parameter values will be aggregated when used on
both POJOs and REST methods.
+ * <br>Values on methods override values on POJO classes.
* </ul>
*
+ *
* <h5 class='section'>See Also:</h5>
* <ul>
* <li class='link'><a class="doclink"
href="../../../../../overview-summary.html#juneau-rest-server.Body">Overview
> juneau-rest-server > @Body</a>
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
index 142b3a2..5369758 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
@@ -84,7 +84,6 @@ public class MockServletRequest implements HttpServletRequest
{
*/
public static MockServletRequest create() {
MockServletRequest r = new MockServletRequest();
- r.header("Accept", "text/json+simple").header("Content-Type",
"text/json");
return r;
}
@@ -110,6 +109,78 @@ public class MockServletRequest implements
HttpServletRequest {
}
/**
+ * Convenience method for setting <code>Accept</code> and
<code>Content-Type</code> headers to <js>"application/json"</js>.
+ *
+ * @return This object (for method chaining).
+ */
+ public MockServletRequest json() {
+ return header("Accept",
"application/json").header("Content-Type", "application/json");
+ }
+
+ /**
+ * Convenience method for setting <code>Accept</code> and
<code>Content-Type</code> headers to <js>"text/xml"</js>.
+ *
+ * @return This object (for method chaining).
+ */
+ public MockServletRequest xml() {
+ return header("Accept", "text/xml").header("Content-Type",
"text/xml");
+ }
+
+ /**
+ * Convenience method for setting <code>Accept</code> and
<code>Content-Type</code> headers to <js>"text/html"</js>.
+ *
+ * @return This object (for method chaining).
+ */
+ public MockServletRequest html() {
+ return header("Accept", "text/html").header("Content-Type",
"text/html");
+ }
+
+ /**
+ * Convenience method for setting <code>Accept</code> and
<code>Content-Type</code> headers to <js>"text/plain"</js>.
+ *
+ * @return This object (for method chaining).
+ */
+ public MockServletRequest plainText() {
+ return header("Accept", "text/plain").header("Content-Type",
"text/plain");
+ }
+
+ /**
+ * Convenience method for setting <code>Accept</code> and
<code>Content-Type</code> headers to <js>"octal/msgpack"</js>.
+ *
+ * @return This object (for method chaining).
+ */
+ public MockServletRequest msgpack() {
+ return header("Accept", "octal/msgpack").header("Content-Type",
"octal/msgpack");
+ }
+
+ /**
+ * Convenience method for setting <code>Accept</code> and
<code>Content-Type</code> headers to <js>"text/uon"</js>.
+ *
+ * @return This object (for method chaining).
+ */
+ public MockServletRequest uon() {
+ return header("Accept", "text/uon").header("Content-Type",
"text/uon");
+ }
+
+ /**
+ * Convenience method for setting <code>Accept</code> and
<code>Content-Type</code> headers to
<js>"application/x-www-form-urlencoded"</js>.
+ *
+ * @return This object (for method chaining).
+ */
+ public MockServletRequest urlEnc() {
+ return header("Accept",
"application/x-www-form-urlencoded").header("Content-Type",
"application/x-www-form-urlencoded");
+ }
+
+ /**
+ * Convenience method for setting <code>Accept</code> and
<code>Content-Type</code> headers to <js>"text/yaml"</js>.
+ *
+ * @return This object (for method chaining).
+ */
+ public MockServletRequest yaml() {
+ return header("Accept", "text/yaml").header("Content-Type",
"text/yaml");
+ }
+
+ /**
* Fluent setter.
*
* @param uri The URI of the request.
@@ -140,6 +211,11 @@ public class MockServletRequest implements
HttpServletRequest {
public MockServletResponse execute() throws Exception {
MockServletResponse res = MockServletResponse.create();
restContext.getCallHandler().service(this, res);
+
+ // If the status isn't set, something's broken.
+ if (res.getStatus() == 0)
+ throw new RuntimeException("Response status was 0.");
+
return res;
}
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletResponse.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletResponse.java
index 0e5efb2..f9845c6 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletResponse.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletResponse.java
@@ -12,7 +12,10 @@
//
***************************************************************************************************************************
package org.apache.juneau.rest.mock;
+import static org.apache.juneau.internal.StringUtils.*;
+
import java.io.*;
+import java.text.*;
import java.util.*;
import javax.servlet.*;
@@ -266,4 +269,45 @@ public class MockServletResponse implements
HttpServletResponse {
throw new RuntimeException(e);
}
}
+
+ /**
+ * Throws an {@link AssertionError} if the response status does not
match the expected status.
+ *
+ * @param status The expected status.
+ * @return This object (for method chaining).
+ * @throws AssertionError Thrown if status does not match.
+ */
+ public MockServletResponse assertStatus(int status) throws
AssertionError {
+ if (getStatus() != status)
+ throw new AssertionError(MessageFormat.format("Response
did not have the expected status. expected=[{0}], actual=[{1}]", status,
getStatus()));
+ return this;
+ }
+
+ /**
+ * Throws an {@link AssertionError} if the response body does not
contain all of the expected substrings.
+ *
+ * @param substrings The expected substrings.
+ * @return This object (for method chaining).
+ * @throws AssertionError Thrown if the body does not contain one or
more of the expected substrings.
+ */
+ public MockServletResponse assertBodyContains(String...substrings)
throws AssertionError {
+ String text = getBodyAsString();
+ for (String substring : substrings)
+ if (! contains(text, substring))
+ throw new
AssertionError(MessageFormat.format("Response did not have the expected
substring. expected=[{0}], body=[{1}]", substring, text));
+ return this;
+ }
+
+ /**
+ * Throws an {@link AssertionError} if the response body does not
contain the expected text.
+ *
+ * @param text The expected text of the body.
+ * @return This object (for method chaining).
+ * @throws AssertionError Thrown if the body does not contain the
expected text.
+ */
+ public MockServletResponse assertBody(String text) throws
AssertionError {
+ if (! StringUtils.isEquals(text, getBodyAsString()))
+ throw new AssertionError(MessageFormat.format("Response
did not have the expected text. expected=[{0}], actual=[{1}]", text,
getBodyAsString()));
+ return this;
+ }
}
diff --git
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyAnnotationTest.java
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyAnnotationTest.java
new file mode 100644
index 0000000..8836379
--- /dev/null
+++
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyAnnotationTest.java
@@ -0,0 +1,680 @@
+//
***************************************************************************************************************************
+// * 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.HttpMethodName.*;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.juneau.internal.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.rest.testutils.*;
+import org.apache.juneau.uon.*;
+import org.junit.*;
+import org.junit.runners.*;
+
+/**
+ * Tests the {@link Body} annotation.
+ */
+@SuppressWarnings({"javadoc","serial"})
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class BodyAnnotationTest {
+
+
//=================================================================================================================
+ // @Body on parameter
+
//=================================================================================================================
+
+ @RestResource(serializers=JsonSerializer.Simple.class,
parsers=JsonParser.class)
+ 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 MockRest a = MockRest.create(A.class);
+
+ @Test
+ public void a01a_onParameter_String() throws Exception {
+ a.request("PUT",
"/String").body("'foo'").json().execute().assertBody("'foo'");
+ }
+ @Test
+ public void a01b_onParameter_String_noContentType() throws Exception {
+ // If no Content-Type specified, should be treated as
plain-text.
+ a.request("PUT",
"/String").body("'foo'").execute().assertBody("'\\'foo\\''");
+ }
+ @Test
+ public void a01c_onParameter_String_noContentType_other() throws
Exception {
+ // If Content-Type not matched, should be treated as plain-text.
+ a.request("PUT",
"/String").body("'foo'").contentType("").execute().assertBody("'\\'foo\\''");
+ a.request("PUT",
"/String").body("'foo'").contentType("text/plain").execute().assertBody("'\\'foo\\''");
+ }
+ @Test
+ public void a02a_onParameter_Integer() throws Exception {
+ a.request("PUT",
"/Integer").body("123").json().execute().assertBody("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.request("PUT",
"/Integer").body("123").execute().assertBody("123");
+ }
+ @Test
+ public void a03a_onParameter_int() throws Exception {
+ a.request("PUT",
"/int").body("123").json().execute().assertBody("123");
+ }
+ @Test
+ public void a03b_onParameter_int_noContentType() throws Exception {
+ a.request("PUT",
"/int?noTrace=true").body("123").execute().assertBodyContains("Unsupported
Media Type");
+ }
+ @Test
+ public void a04a_onParameter_Boolean() throws Exception {
+ a.request("PUT",
"/Boolean").body("true").json().execute().assertBody("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.request("PUT",
"/Boolean").body("true").execute().assertBody("true");
+ }
+ @Test
+ public void a05a_onParameter_boolean() throws Exception {
+ a.request("PUT",
"/boolean").body("true").json().execute().assertBody("true");
+ }
+ @Test
+ public void a05b_onParameter_boolean_noContentType() throws Exception {
+ a.request("PUT",
"/boolean?noTrace=true").body("true").execute().assertBodyContains("Unsupported
Media Type");
+ }
+ @Test
+ public void a06a_onParameter_float() throws Exception {
+ a.request("PUT",
"/float").body("1.23").json().execute().assertBody("1.23");
+ }
+ @Test
+ public void a06b_onParameter_float_noContentType() throws Exception {
+ a.request("PUT",
"/float?noTrace=true").body("1.23").execute().assertBodyContains("Unsupported
Media Type");
+ }
+ @Test
+ public void a07a_onParameter_Float() throws Exception {
+ a.request("PUT",
"/Float").body("1.23").json().execute().assertBody("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.request("PUT",
"/Float").body("1.23").execute().assertBody("1.23");
+ }
+ @Test
+ public void a08a_onParameter_Map() throws Exception {
+ a.request("PUT",
"/Map").body("{foo:123}").json().execute().assertBody("{foo:123}");
+ }
+ @Test
+ public void a08b_onParameter_Map_noContentType() throws Exception {
+ a.request("PUT",
"/Map?noTrace=true").body("{foo:123}").execute().assertBodyContains("Unsupported
Media Type");
+ }
+ @Test
+ public void a09a_onParameter_enum() throws Exception {
+ a.request("PUT",
"/enum").body("'ONE'").json().execute().assertBody("'ONE'");
+ }
+ @Test
+ public void a09b_onParameter_enum_noContentType() throws Exception {
+ a.request("PUT",
"/enum").body("ONE").execute().assertBody("'ONE'");
+ }
+ @Test
+ public void a11a_onParameter_Bean() throws Exception {
+ a.request("PUT",
"/Bean").body("{f1:'a'}").json().execute().assertBody("{f1:'a'}");
+ }
+ @Test
+ public void a11b_onParameter_Bean_noContentType() throws Exception {
+ a.request("PUT",
"/Bean?noTrace=true").body("{f1:'a'}").execute().assertBodyContains("Unsupported
Media Type");
+ }
+ @Test
+ public void a12a_onParameter_InputStream() throws Exception {
+ // Content-Type should always be ignored.
+ a.request("PUT",
"/InputStream").body("'a'").json().execute().assertBody("'\\'a\\''");
+ }
+ @Test
+ public void a12b_onParameter_InputStream_noContentType() throws
Exception {
+ a.request("PUT",
"/InputStream").body("'a'").execute().assertBody("'\\'a\\''");
+ }
+ @Test
+ public void a13a_onParameter_Reader() throws Exception {
+ // Content-Type should always be ignored.
+ a.request("PUT",
"/Reader").body("'a'").json().execute().assertBody("'\\'a\\''");
+ }
+ @Test
+ public void a13b_onParameter_Reader_noContentType() throws Exception {
+ a.request("PUT",
"/Reader").body("'a'").execute().assertBody("'\\'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.request("PUT",
"/InputStreamTransform?noTrace=true").body("'a'").json().execute().assertBodyContains("Bad
Request");
+ }
+ @Test
+ public void a14b_onParameter_InputStreamTransform_noContentType()
throws Exception {
+ a.request("PUT",
"/InputStreamTransform").body("'a'").execute().assertBody("'\\'a\\''");
+ }
+ @Test
+ public void a15a_onParameter_ReaderTransform() throws Exception {
+ // Reader transform requests must not specify Content-Type or
else gets resolved as POJO.
+ a.request("PUT",
"/ReaderTransform?noTrace=true").body("'a'").json().execute().assertBodyContains("Bad
Request");
+ }
+ @Test
+ public void a15b_onParameter_ReaderTransform_noContentType() throws
Exception {
+ a.request("PUT",
"/ReaderTransform").body("'a'").execute().assertBody("'\\'a\\''");
+ }
+ @Test
+ public void a16a_onParameter_StringTransform() throws Exception {
+ // When Content-Type specified and matched, treated as a parsed
POJO.
+ a.request("PUT",
"/StringTransform").body("'a'").json().execute().assertBody("'a'");
+ }
+ @Test
+ public void a16b_onParameter_StringTransform_noContentType() throws
Exception {
+ // When Content-Type not matched, treated as plain text.
+ a.request("PUT",
"/StringTransform").body("'a'").execute().assertBody("'\\'a\\''");
+ }
+
+
+
//=================================================================================================================
+ // @Body on POJO
+
//=================================================================================================================
+
+ @RestResource(serializers=JsonSerializer.Simple.class,
parsers=JsonParser.class)
+ 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;
+ }
+ @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 MockRest b = MockRest.create(B.class);
+
+ @Test
+ public void b01a_onPojo_StringTransform() throws Exception {
+ b.request("PUT",
"/StringTransform").body("'foo'").json().execute().assertBody("'foo'");
+ }
+ @Test
+ public void b01b_onPojo_StringTransform_noContentType() throws
Exception {
+ // When Content-Type not matched, treated as plain text.
+ b.request("PUT",
"/StringTransform").body("'foo'").execute().assertBody("'\\'foo\\''");
+ }
+ @Test
+ public void b02a_onPojo_Bean() throws Exception {
+ b.request("PUT",
"/Bean").body("{f1:'a'}").json().execute().assertBody("{f1:'a'}");
+ }
+ @Test
+ public void b02b_onPojo_Bean_noContentType() throws Exception {
+ b.request("PUT",
"/Bean?noTrace=true").body("{f1:'a'}").execute().assertBodyContains("Unsupported
Media Type");
+ }
+ @Test
+ public void b03a_onPojo_BeanList() throws Exception {
+ b.request("PUT",
"/BeanList").body("[{f1:'a'}]").json().execute().assertBody("[{f1:'a'}]");
+ }
+ @Test
+ public void b03b_onPojo_BeanList_noContentType() throws Exception {
+ b.request("PUT",
"/BeanList?noTrace=true").body("[{f1:'a'}]").execute().assertBodyContains("Unsupported
Media Type");
+ }
+ @Test
+ public void b04a_onPojo_InputStreamTransform() throws Exception {
+ b.request("PUT",
"/InputStreamTransform").body("a").execute().assertBody("'a'");
+ }
+ @Test
+ public void b04b_onPojo_InputStreamTransform_withContentType() throws
Exception {
+ // When Content-Type matched, treated as parsed POJO.
+ b.request("PUT",
"/InputStreamTransform?noTrace=true").body("a").json().execute().assertBodyContains("Bad
Request");
+ }
+ @Test
+ public void b05a_onPojo_ReaderTransform() throws Exception {
+ b.request("PUT",
"/ReaderTransform").body("a").execute().assertBody("'a'");
+ }
+ @Test
+ public void b05b_onPojo_ReaderTransform_withContentType() throws
Exception {
+ // When Content-Type matched, treated as parsed POJO.
+ b.request("PUT",
"/ReaderTransform?noTrace=true").body("a").json().execute().assertBodyContains("Bad
Request");
+ }
+
+
+
//=================================================================================================================
+ // Basic tests using @Body parameter
+
//=================================================================================================================
+
+ public void c01_bodyParam_String() throws Exception {
+ a.request("PUT",
"/String?body=foo").execute().assertBody("'foo'");
+ a.request("PUT",
"/String?body=null").execute().assertBody("null");
+ a.request("PUT", "/String?body=").execute().assertBody("''");
+ }
+ @Test
+ public void c02_bodyParam_Integer() throws Exception {
+ a.request("PUT",
"/Integer?body=123").execute().assertBody("123");
+ a.request("PUT",
"/Integer?body=-123").execute().assertBody("-123");
+ a.request("PUT",
"/Integer?body=null").execute().assertBody("null");
+ a.request("PUT", "/Integer?body=").execute().assertBody("null");
+ a.request("PUT",
"/Integer?body=bad&noTrace=true").execute().assertStatus(400);
+ }
+ @Test
+ public void c03_bodyParam_int() throws Exception {
+ a.request("PUT", "/int?body=123").execute().assertBody("123");
+ a.request("PUT", "/int?body=-123").execute().assertBody("-123");
+ a.request("PUT", "/int?body=null").execute().assertBody("0");
+ a.request("PUT", "/int?body=").execute().assertBody("0");
+ a.request("PUT",
"/int?body=bad&noTrace=true").execute().assertStatus(400);
+ }
+ @Test
+ public void c04_bodyParam_Boolean() throws Exception {
+ a.request("PUT",
"/Boolean?body=true").execute().assertBody("true");
+ a.request("PUT",
"/Boolean?body=false").execute().assertBody("false");
+ a.request("PUT",
"/Boolean?body=null").execute().assertBody("null");
+ a.request("PUT", "/Boolean?body=").execute().assertBody("null");
+ a.request("PUT",
"/Boolean?body=bad&noTrace=true").execute().assertStatus(400);
+ }
+ @Test
+ public void c05_bodyParam_boolean() throws Exception {
+ a.request("PUT",
"/boolean?body=true").execute().assertBody("true");
+ a.request("PUT",
"/boolean?body=false").execute().assertBody("false");
+ a.request("PUT",
"/boolean?body=null").execute().assertBody("false");
+ a.request("PUT",
"/boolean?body=").execute().assertBody("false");
+ a.request("PUT",
"/boolean?body=bad&noTrace=true").execute().assertStatus(400);
+ }
+ @Test
+ public void c06_bodyParam_Float() throws Exception {
+ a.request("PUT",
"/Float?body=1.23").execute().assertBody("1.23");
+ a.request("PUT",
"/Float?body=-1.23").execute().assertBody("-1.23");
+ a.request("PUT",
"/Float?body=null").execute().assertBody("null");
+ a.request("PUT", "/Float?body=").execute().assertBody("null");
+ a.request("PUT",
"/Float?body=bad&noTrace=true").execute().assertStatus(400);
+ }
+ @Test
+ public void c07_bodyParam_float() throws Exception {
+ a.request("PUT",
"/float?body=1.23").execute().assertBody("1.23");
+ a.request("PUT",
"/float?body=-1.23").execute().assertBody("-1.23");
+ a.request("PUT",
"/float?body=null").execute().assertBody("0.0");
+ a.request("PUT", "/float?body=").execute().assertBody("0.0");
+ a.request("PUT",
"/float?body=bad&noTrace=true").execute().assertStatus(400);
+ }
+ @Test
+ public void c08_bodyParam_Map() throws Exception {
+ a.request("PUT",
"/Map?body=(foo=123)").execute().assertBody("{foo:123}");
+ a.request("PUT", "/Map?body=()").execute().assertBody("{}");
+ a.request("PUT", "/Map?body=null").execute().assertBody("null");
+ a.request("PUT", "/Map?body=").execute().assertBody("null");
+ a.request("PUT",
"/Map?body=bad&noTrace=true").execute().assertStatus(400);
+ }
+ @Test
+ public void c09_bodyParam_enum() throws Exception {
+ a.request("PUT",
"/enum?body=ONE").execute().assertBody("'ONE'");
+ a.request("PUT",
"/enum?body=TWO").execute().assertBody("'TWO'");
+ a.request("PUT",
"/enum?body=null").execute().assertBody("null");
+ a.request("PUT", "/enum?body=").execute().assertBody("null");
+ a.request("PUT",
"/enum?body=bad&noTrace=true").execute().assertStatus(400);
+ }
+ @Test
+ public void c11_bodyParam_Bean() throws Exception {
+ a.request("PUT",
"/Bean?body=(f1=a)").execute().assertBody("{f1:'a'}");
+ a.request("PUT", "/Bean?body=()").execute().assertBody("{}");
+ a.request("PUT",
"/Bean?body=null").execute().assertBody("null");
+ a.request("PUT", "/Bean?body=").execute().assertBody("null");
+ a.request("PUT",
"/Bean?body=bad&noTrace=true").execute().assertStatus(400);
+ }
+ @Test
+ public void c12_bodyParam_InputStream() throws Exception {
+ a.request("PUT",
"/InputStream?body=a").execute().assertBody("'a'");
+ a.request("PUT",
"/InputStream?body=null").execute().assertBody("'null'");
+ a.request("PUT",
"/InputStream?body=").execute().assertBody("''");
+ }
+ @Test
+ public void c13_bodyParam_Reader() throws Exception {
+ a.request("PUT", "/Reader?body=a").execute().assertBody("'a'");
+ a.request("PUT",
"/Reader?body=null").execute().assertBody("'null'");
+ a.request("PUT", "/Reader?body=").execute().assertBody("''");
+ }
+
+ // 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.
+
//=================================================================================================================
+
+ @RestResource
+ 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 MockRest d = MockRest.create(D.class);
+
+ @Test
+ public void d01a_noMediaTypes_String() throws Exception {
+ d.request("PUT", "/String").body("a").execute().assertBody("a");
+ }
+ @Test
+ public void d01b_noMediaTypes_String_withContentType() throws Exception
{
+ d.request("PUT",
"/String").body("a").json().execute().assertBody("a");
+ }
+ @Test
+ public void d02a_noMediaTypes_InputStream() throws Exception {
+ d.request("PUT",
"/InputStream").body("a").execute().assertBody("a");
+ }
+ @Test
+ public void d02b_noMediaTypes_InputStream_withContentType() throws
Exception {
+ d.request("PUT",
"/InputStream").body("a").json().execute().assertBody("a");
+ }
+ @Test
+ public void d03a_noMediaTypes_Reader() throws Exception {
+ d.request("PUT", "/Reader").body("a").execute().assertBody("a");
+ }
+ @Test
+ public void d03b_noMediaTypes_Reader_withContentType() throws Exception
{
+ d.request("PUT",
"/Reader").body("a").json().execute().assertBody("a");
+ }
+ @Test
+ public void d04a_noMediaTypes_StringTransform() throws Exception {
+ d.request("PUT",
"/StringTransform").body("a").execute().assertBody("a");
+ }
+ @Test
+ public void d04b_noMediaTypes_StringTransform_withContentType() throws
Exception {
+ d.request("PUT",
"/StringTransform?noTrace=true").body("a").json().execute().assertStatus(415);
+ }
+ @Test
+ public void d05a_noMediaTypes_InputStreamTransform() throws Exception {
+ d.request("PUT",
"/InputStreamTransform").body("a").execute().assertBody("a");
+ }
+ @Test
+ public void d05b_noMediaTypes_InputStreamTransform_withContentType()
throws Exception {
+ d.request("PUT",
"/InputStreamTransform").body("a").json().execute().assertBody("a");
+ }
+ @Test
+ public void d06a_noMediaTypes_ReaderTransform() throws Exception {
+ d.request("PUT",
"/ReaderTransform").body("a").execute().assertBody("a");
+ }
+ @Test
+ public void d06b_noMediaTypes_ReaderTransform_withContentType() throws
Exception {
+ d.request("PUT",
"/ReaderTransform").body("a").json().execute().assertBody("a");
+ }
+ @Test
+ public void d07a_noMediaTypes_StringTransformBodyOnPojo() throws
Exception {
+ d.request("PUT",
"/StringTransformBodyOnPojo").body("a").execute().assertBody("a");
+ }
+ @Test
+ public void
d07b_noMediaTypes_StringTransformBodyOnPojo_withContentType() throws Exception {
+ d.request("PUT",
"/StringTransformBodyOnPojo?noTrace=true").body("a").json().execute().assertStatus(415);
+ }
+ @Test
+ public void d08a_noMediaTypes_InputStreamTransformBodyOnPojo() throws
Exception {
+ d.request("PUT",
"/InputStreamTransformBodyOnPojo").body("a").execute().assertBody("a");
+ }
+ @Test
+ public void
d08b_noMediaTypes_InputStreamTransformBodyOnPojo_withContentType() throws
Exception {
+ d.request("PUT",
"/InputStreamTransformBodyOnPojo").body("a").json().execute().assertBody("a");
+ }
+ @Test
+ public void d09a_noMediaTypes_ReaderTransformBodyOnPojo() throws
Exception {
+ d.request("PUT",
"/ReaderTransformBodyOnPojo").body("a").execute().assertBody("a");
+ }
+ @Test
+ public void
d09b_noMediaTypes_ReaderTransformBodyOnPojo_withContentType() throws Exception {
+ d.request("PUT",
"/ReaderTransformBodyOnPojo").body("a").json().execute().assertBody("a");
+ }
+
+
+
//=================================================================================================================
+ // Complex POJOs
+
//=================================================================================================================
+
+ @RestResource(serializers=JsonSerializer.Simple.class,
parsers=JsonParser.class)
+ public static class E {
+
+ @RestMethod(name=PUT, path="/B")
+ public DTOs.B testPojo1(@Body DTOs.B b) {
+ return b;
+ }
+
+ @RestMethod(name=PUT, path="/C")
+ public DTOs.C testPojo2(@Body DTOs.C c) {
+ return c;
+ }
+ }
+
+ private static MockRest e = MockRest.create(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}
[...]
+ e.request("PUT",
"/B").body(JsonSerializer.DEFAULT_LAX.toString(DTOs.B.INSTANCE)).json().execute().assertBody(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}
[...]
+ e.request("PUT", "/B?body=" +
UonSerializer.DEFAULT.serialize(DTOs.B.INSTANCE)).body("a").execute().assertBody(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}
[...]
+ e.request("PUT",
"/C").body(JsonSerializer.DEFAULT_LAX.toString(DTOs.B.INSTANCE)).json().execute().assertBody(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}
[...]
+ e.request("PUT", "/C?body=" +
UonSerializer.DEFAULT.serialize(DTOs.B.INSTANCE)).body("a").execute().assertBody(expected);
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyTest.java
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyTest.java
deleted file mode 100644
index 07707bb..0000000
---
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/BodyTest.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.apache.juneau.http.HttpMethodName.*;
-import static org.junit.Assert.*;
-
-import java.io.*;
-import java.util.*;
-
-
-import org.apache.juneau.internal.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.rest.mock.*;
-import org.apache.juneau.rest.testutils.*;
-import org.apache.juneau.uon.*;
-import org.junit.*;
-import org.junit.runners.*;
-
-/**
- * Tests the {@link Body} annotation.
- */
-@SuppressWarnings({"javadoc","serial"})
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class BodyTest {
-
-
//-----------------------------------------------------------------------------------------------------------------
- // @Body on parameter
-
//-----------------------------------------------------------------------------------------------------------------
-
- @RestResource(serializers=JsonSerializer.Simple.class,
parsers=JsonParser.class)
- 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);
- }
-
- public static class A14 {
- String s;
-
- public A14(InputStream in) throws Exception {
- this.s = IOUtils.read(in);
- }
-
- @Override /* Object */
- public String toString() {
- return s;
- }
- }
-
- @RestMethod(name=PUT, path="/inputStreamTransform")
- public A14 a14(@Body A14 b) throws Exception {
- return b;
- }
-
- public static class A15 {
- private String s;
-
- public A15(Reader in) throws Exception {
- this.s = IOUtils.read(in);
- }
-
- @Override /* Object */
- public String toString() {
- return s;
- }
- }
-
- @RestMethod(name=PUT, path="/readerTransform")
- public A15 a15(@Body A15 b) throws Exception {
- return b;
- }
- }
-
- private MockRest a = MockRest.create(A.class);
-
- @Test
- public void a01_onParameter_String() throws Exception {
- assertEquals("'foo'", a.request("PUT",
"/String").body("'foo'").execute().getBodyAsString());
- }
- @Test
- public void a02_onParameter_Integer() throws Exception {
- assertEquals("123", a.request("PUT",
"/Integer").body("123").execute().getBodyAsString());
- }
- @Test
- public void a03_onParameter_int() throws Exception {
- assertEquals("123", a.request("PUT",
"/int").body("123").execute().getBodyAsString());
- }
- @Test
- public void a04_onParameter_Boolean() throws Exception {
- assertEquals("true", a.request("PUT",
"/Boolean").body("true").execute().getBodyAsString());
- }
- @Test
- public void a05_onParameter_boolean() throws Exception {
- assertEquals("true", a.request("PUT",
"/boolean").body("true").execute().getBodyAsString());
- }
- @Test
- public void a06_onParameter_float() throws Exception {
- assertEquals("1.23", a.request("PUT",
"/float").body("1.23").execute().getBodyAsString());
- }
- @Test
- public void a07_onParameter_Float() throws Exception {
- assertEquals("1.23", a.request("PUT",
"/Float").body("1.23").execute().getBodyAsString());
- }
- @Test
- public void a08_onParameter_Map() throws Exception {
- assertEquals("{foo:123}", a.request("PUT",
"/Map").body("{foo:123}").execute().getBodyAsString());
- }
- @Test
- public void a09_onParameter_enum() throws Exception {
- assertEquals("'ONE'", a.request("PUT",
"/enum").body("'ONE'").execute().getBodyAsString());
- }
- @Test
- public void a11_onParameter_bean() throws Exception {
- assertEquals("{f1:'a'}", a.request("PUT",
"/bean").body("{f1:'a'}").execute().getBodyAsString());
- }
- @Test
- public void a12_onParameter_inputStream() throws Exception {
- assertEquals("'a'", a.request("PUT",
"/inputStream").body("a").execute().getBodyAsString());
- }
- @Test
- public void a13_onParameter_reader() throws Exception {
- assertEquals("'a'", a.request("PUT",
"/reader").body("a").execute().getBodyAsString());
- }
- @Test
- public void a14_onParameter_inputStreamTransform() throws Exception {
- assertEquals("'a'", a.request("PUT",
"/inputStreamTransform").body("a").execute().getBodyAsString());
- }
- @Test
- public void a15_onParameter_readerTransform() throws Exception {
- assertEquals("'a'", a.request("PUT",
"/readerTransform").body("a").execute().getBodyAsString());
- }
-
-
-
//-----------------------------------------------------------------------------------------------------------------
- // @Body on POJO
-
//-----------------------------------------------------------------------------------------------------------------
-
- @RestResource(serializers=JsonSerializer.Simple.class,
parsers=JsonParser.class)
- public static class 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="/string")
- public B01 simple(B01 b) {
- return b;
- }
-
- @Body
- public static class B02 {
- public String f1;
- }
-
- @RestMethod(name=PUT, path="/bean")
- public B02 b02(B02 b) {
- return b;
- }
-
- @Body
- public static class B03 extends LinkedList<B02> {}
-
- @RestMethod(name=PUT, path="/beanList")
- public B03 b03(B03 b) {
- return b;
- }
-
- @Body
- public static class B04 {
- String s;
-
- public B04(InputStream in) throws Exception {
- this.s = IOUtils.read(in);
- }
-
- @Override /* Object */
- public String toString() {
- return s;
- }
- }
-
- @RestMethod(name=PUT, path="/inputStreamTransform")
- public B04 b04(B04 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 /* Object */
- public String toString() {
- return s;
- }
- }
-
- @RestMethod(name=PUT, path="/readerTransform")
- public B05 b05(B05 b) throws Exception {
- return b;
- }
- }
-
- private MockRest b = MockRest.create(B.class);
-
- @Test
- public void b01_onPojo_string() throws Exception {
- assertEquals("'foo'", b.request("PUT",
"/string").body("'foo'").execute().getBodyAsString());
- }
- @Test
- public void b02_onPojo_bean() throws Exception {
- assertEquals("{f1:'a'}", b.request("PUT",
"/bean").body("{f1:'a'}").execute().getBodyAsString());
- }
- @Test
- public void b03_onPojo_beanList() throws Exception {
- assertEquals("[{f1:'a'}]", b.request("PUT",
"/beanList").body("[{f1:'a'}]").execute().getBodyAsString());
- }
- @Test
- public void b04_onPojo_inputStream() throws Exception {
- assertEquals("'a'", b.request("PUT",
"/inputStreamTransform").body("a").execute().getBodyAsString());
- }
- @Test
- public void b05_onPojo_reader() throws Exception {
- assertEquals("'a'", b.request("PUT",
"/readerTransform").body("a").execute().getBodyAsString());
- }
-
-
-
//-----------------------------------------------------------------------------------------------------------------
- // Basic tests using @Body parameter
-
//-----------------------------------------------------------------------------------------------------------------
-
- public void c01_bodyParam_String() throws Exception {
- assertEquals("'foo'", a.request("PUT",
"/String?body=foo").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/String?body=null").execute().getBodyAsString());
- assertEquals("''", a.request("PUT",
"/String?body=").execute().getBodyAsString());
- }
- @Test
- public void c02_bodyParam_Integer() throws Exception {
- assertEquals("123", a.request("PUT",
"/Integer?body=123").execute().getBodyAsString());
- assertEquals("-123", a.request("PUT",
"/Integer?body=-123").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/Integer?body=null").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/Integer?body=").execute().getBodyAsString());
- assertEquals(400, a.request("PUT",
"/Integer?body=bad&noTrace=true").execute().getStatus());
- }
- @Test
- public void c03_bodyParam_int() throws Exception {
- assertEquals("123", a.request("PUT",
"/int?body=123").execute().getBodyAsString());
- assertEquals("-123", a.request("PUT",
"/int?body=-123").execute().getBodyAsString());
- assertEquals("0", a.request("PUT",
"/int?body=null").execute().getBodyAsString());
- assertEquals("0", a.request("PUT",
"/int?body=").execute().getBodyAsString());
- assertEquals(400, a.request("PUT",
"/int?body=bad&noTrace=true").execute().getStatus());
- }
- @Test
- public void c04_bodyParam_Boolean() throws Exception {
- assertEquals("true", a.request("PUT",
"/Boolean?body=true").execute().getBodyAsString());
- assertEquals("false", a.request("PUT",
"/Boolean?body=false").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/Boolean?body=null").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/Boolean?body=").execute().getBodyAsString());
- assertEquals(400, a.request("PUT",
"/Boolean?body=bad&noTrace=true").execute().getStatus());
- }
- @Test
- public void c05_bodyParam_boolean() throws Exception {
- assertEquals("true", a.request("PUT",
"/boolean?body=true").execute().getBodyAsString());
- assertEquals("false", a.request("PUT",
"/boolean?body=false").execute().getBodyAsString());
- assertEquals("false", a.request("PUT",
"/boolean?body=null").execute().getBodyAsString());
- assertEquals("false", a.request("PUT",
"/boolean?body=").execute().getBodyAsString());
- assertEquals(400, a.request("PUT",
"/boolean?body=bad&noTrace=true").execute().getStatus());
- }
- @Test
- public void c06_bodyParam_Float() throws Exception {
- assertEquals("1.23", a.request("PUT",
"/Float?body=1.23").execute().getBodyAsString());
- assertEquals("-1.23", a.request("PUT",
"/Float?body=-1.23").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/Float?body=null").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/Float?body=").execute().getBodyAsString());
- assertEquals(400, a.request("PUT",
"/Float?body=bad&noTrace=true").execute().getStatus());
- }
- @Test
- public void c07_bodyParam_float() throws Exception {
- assertEquals("1.23", a.request("PUT",
"/float?body=1.23").execute().getBodyAsString());
- assertEquals("-1.23", a.request("PUT",
"/float?body=-1.23").execute().getBodyAsString());
- assertEquals("0.0", a.request("PUT",
"/float?body=null").execute().getBodyAsString());
- assertEquals("0.0", a.request("PUT",
"/float?body=").execute().getBodyAsString());
- assertEquals(400, a.request("PUT",
"/float?body=bad&noTrace=true").execute().getStatus());
- }
- @Test
- public void c08_bodyParam_Map() throws Exception {
- assertEquals("{foo:123}", a.request("PUT",
"/Map?body=(foo=123)").execute().getBodyAsString());
- assertEquals("{}", a.request("PUT",
"/Map?body=()").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/Map?body=null").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/Map?body=").execute().getBodyAsString());
- assertEquals(400, a.request("PUT",
"/Map?body=bad&noTrace=true").execute().getStatus());
- }
- @Test
- public void c09_bodyParam_enum() throws Exception {
- assertEquals("'ONE'", a.request("PUT",
"/enum?body=ONE").execute().getBodyAsString());
- assertEquals("'TWO'", a.request("PUT",
"/enum?body=TWO").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/enum?body=null").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/enum?body=").execute().getBodyAsString());
- assertEquals(400, a.request("PUT",
"/enum?body=bad&noTrace=true").execute().getStatus());
- }
- @Test
- public void c11_bodyParam_bean() throws Exception {
- assertEquals("{f1:'a'}", a.request("PUT",
"/bean?body=(f1=a)").execute().getBodyAsString());
- assertEquals("{}", a.request("PUT",
"/bean?body=()").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/bean?body=null").execute().getBodyAsString());
- assertEquals("null", a.request("PUT",
"/bean?body=").execute().getBodyAsString());
- assertEquals(400, a.request("PUT",
"/bean?body=bad&noTrace=true").execute().getStatus());
- }
- @Test
- public void c12_bodyParam_inputStream() throws Exception {
- assertEquals("'a'", a.request("PUT",
"/inputStream?body=a").execute().getBodyAsString());
- assertEquals("'null'", a.request("PUT",
"/inputStream?body=null").execute().getBodyAsString());
- assertEquals("''", a.request("PUT",
"/inputStream?body=").execute().getBodyAsString());
- }
- @Test
- public void c13_bodyParam_reader() throws Exception {
- assertEquals("'a'", a.request("PUT",
"/reader?body=a").execute().getBodyAsString());
- assertEquals("'null'", a.request("PUT",
"/reader?body=null").execute().getBodyAsString());
- assertEquals("''", a.request("PUT",
"/reader?body=").execute().getBodyAsString());
- }
- @Test
- public void c14_bodyParam_inputStreamTransform() throws Exception {
- assertEquals("'a'", a.request("PUT",
"/inputStreamTransform?body=a").execute().getBodyAsString());
- assertEquals("'null'", a.request("PUT",
"/inputStreamTransform?body=null").execute().getBodyAsString());
- assertEquals("''", a.request("PUT",
"/inputStreamTransform?body=").execute().getBodyAsString());
- }
- @Test
- public void c15_bodyParam_readerTransform() throws Exception {
- assertEquals("'a'", a.request("PUT",
"/readerTransform?body=a").execute().getBodyAsString());
- assertEquals("'null'", a.request("PUT",
"/readerTransform?body=null").execute().getBodyAsString());
- assertEquals("''", a.request("PUT",
"/readerTransform?body=").execute().getBodyAsString());
- }
-
-
-
//-----------------------------------------------------------------------------------------------------------------
- // No serializers or parsers needed when using only streams and readers.
-
//-----------------------------------------------------------------------------------------------------------------
-
- @RestResource
- public static class D {
-
- @RestMethod(name=PUT, path="/inputStream")
- public InputStream d01(@Body InputStream b) throws Exception {
- return b;
- }
-
- @RestMethod(name=PUT, path="/reader")
- public Reader d02(@Body Reader b) throws Exception {
- return b;
- }
-
- public static class D03 {
- String s;
-
- public D03(InputStream in) throws Exception {
- this.s = IOUtils.read(in);
- }
-
- @Override /* Object */
- public String toString() {
- return s;
- }
- }
-
- @RestMethod(name=PUT, path="/inputStreamTransform")
- public Reader d03(@Body D03 b) throws Exception {
- return new StringReader(b.toString());
- }
-
- public static class D04 {
- private String s;
-
- public D04(Reader in) throws Exception {
- this.s = IOUtils.read(in);
- }
-
- @Override /* Object */
- public String toString() {
- return s;
- }
- }
-
- @RestMethod(name=PUT, path="/readerTransform")
- public Reader d04(@Body D04 b) throws Exception {
- return new StringReader(b.toString());
- }
- }
-
- private MockRest d = MockRest.create(D.class);
-
- @Test
- public void d01_noMediaTypes_inputStream() throws Exception {
- assertEquals("a", d.request("PUT",
"/inputStream").body("a").execute().getBodyAsString());
- }
- @Test
- public void d02_noMediaTypes_reader() throws Exception {
- assertEquals("a", d.request("PUT",
"/reader").body("a").execute().getBodyAsString());
- }
- @Test
- public void d03_noMediaTypes_inputStreamTransform() throws Exception {
- assertEquals("a", d.request("PUT",
"/inputStreamTransform").body("a").execute().getBodyAsString());
- }
- @Test
- public void d04_noMediaTypes_readerTransform() throws Exception {
- assertEquals("a", d.request("PUT",
"/readerTransform").body("a").execute().getBodyAsString());
- }
-
-
-
//-----------------------------------------------------------------------------------------------------------------
- // Complex POJOs
-
//-----------------------------------------------------------------------------------------------------------------
-
- @RestResource(serializers=JsonSerializer.Simple.class,
parsers=JsonParser.class)
- public static class E {
-
- @RestMethod(name=PUT, path="/B")
- public DTOs.B testPojo1(@Body DTOs.B b) {
- return b;
- }
-
- @RestMethod(name=PUT, path="/C")
- public DTOs.C testPojo2(@Body DTOs.C c) {
- return c;
- }
- }
-
- private MockRest e = MockRest.create(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}
[...]
- assertEquals(expected, e.request("PUT",
"/B").body(JsonSerializer.DEFAULT_LAX.toString(DTOs.B.INSTANCE)).execute().getBodyAsString());
- }
- @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}
[...]
- assertEquals(expected, e.request("PUT", "/B?body=" +
UonSerializer.DEFAULT.serialize(DTOs.B.INSTANCE)).body("a").execute().getBodyAsString());
- }
- @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}
[...]
- assertEquals(expected, e.request("PUT",
"/C").body(JsonSerializer.DEFAULT_LAX.toString(DTOs.B.INSTANCE)).execute().getBodyAsString());
- }
- @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}
[...]
- assertEquals(expected, e.request("PUT", "/C?body=" +
UonSerializer.DEFAULT.serialize(DTOs.B.INSTANCE)).body("a").execute().getBodyAsString());
- }
-}
diff --git
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/DefaultContentTypesTest.java
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/DefaultContentTypesTest.java
new file mode 100644
index 0000000..3a9907b
--- /dev/null
+++
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/DefaultContentTypesTest.java
@@ -0,0 +1,384 @@
+//
***************************************************************************************************************************
+// * 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.HttpMethodName.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.serializer.*;
+import org.junit.*;
+import org.junit.runners.*;
+
+
+/**
+ * Tests related to @RestRequest(defaultRequestHeaders).
+ */
+@SuppressWarnings({"javadoc"})
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class DefaultContentTypesTest {
+
+
//=================================================================================================================
+ // Setup classes
+
//=================================================================================================================
+
+ public static class DummyParser extends ReaderParser {
+
+ String name;
+
+ DummyParser(PropertyStore ps, String name, String...consumes) {
+ super(ps, consumes);
+ this.name = name;
+ }
+
+ @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 Exception {
+ return (T)name;
+ }
+ };
+ }
+ }
+
+ 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 Exception {
+ out.getWriter().write(name + "/" + o);
+ }
+ };
+ }
+ }
+
+ 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");}}
+ 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 and Content-Type headers on servlet
annotation are picked up.
+
//====================================================================================================
+
+ @RestResource(
+ defaultRequestHeaders={" Accept : text/s2 "," Content-Type :
text/p2 "},
+ parsers={P1.class,P2.class}, serializers={S1.class,S2.class}
+ )
+ public static class A {
+ @RestMethod(name=PUT)
+ public String a01(@Body String in) {
+ return in;
+ }
+ }
+
+ private static MockRest a = MockRest.create(A.class);
+
+ @Test
+ public void a01_defaultHeadersOnServletAnnotation_valid() throws
Exception {
+ a.request("PUT", "/").execute().assertBody("s2/p2");
+ a.request("PUT",
"/").accept("text/s1").execute().assertBody("s1/p2");
+ a.request("PUT",
"/").contentType("text/p1").execute().assertBody("s2/p1");
+ a.request("PUT",
"/").accept("text/s1").contentType("text/p1").execute().assertBody("s1/p1");
+ a.request("PUT",
"/").accept("text/s2").execute().assertBody("s2/p2");
+ a.request("PUT",
"/").contentType("text/p2").execute().assertBody("s2/p2");
+ a.request("PUT",
"/").accept("text/s2").contentType("text/p2").execute().assertBody("s2/p2");
+ }
+
+ @Test
+ public void a02_defaultHeadersOnServletAnnotation_invalid() throws
Exception {
+ a.request("PUT",
"?noTrace=true").accept("text/s3").execute().assertStatus(406).assertBodyContains("Unsupported
media-type in request header 'Accept': 'text/s3'");
+ a.request("PUT",
"?noTrace=true").contentType("text/p3").execute().assertStatus(415).assertBodyContains("Unsupported
media-type in request header 'Content-Type': 'text/p3'");
+ a.request("PUT",
"?noTrace=true").accept("text/s3").contentType("text/p3").execute().assertStatus(415).assertBodyContains("Unsupported
media-type in request header 'Content-Type': 'text/p3'");
+ }
+
+
//====================================================================================================
+ // Test that default Accept and Content-Type headers on servlet
annotation are picked up
+ // when @RestMethod.parsers/serializers annotations are used.
+
//====================================================================================================
+
+ @RestResource(
+ defaultRequestHeaders={" Accept : text/s2 "," Content-Type :
text/p2 "},
+ parsers={P1.class,P2.class}, serializers={S1.class,S2.class}
+ )
+ public static class B {
+ @RestMethod(name=PUT, parsers=P3.class, serializers=S3.class)
+ public String b(@Body String in) {
+ return in;
+ }
+ }
+
+ private static MockRest b = MockRest.create(B.class);
+
+ @Test
+ public void b01_restMethodWithParsersSerializers_valid() throws
Exception {
+ b.request("PUT",
"/").accept("text/s3").contentType("text/p3").execute().assertBody("s3/p3");
+ }
+
+ @Test
+ public void b02_restMethodWithParsersSerializers_invalid() throws
Exception {
+ b.request("PUT", "?noTrace=true").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p2'",
+ "Supported media-types: ['text/p3']"
+ );
+ b.request("PUT", "?noTrace=true").accept("text/s1").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p2'",
+ "Supported media-types: ['text/p3']"
+ );
+ b.request("PUT",
"?noTrace=true").contentType("text/p1").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p1'",
+ "Supported media-types: ['text/p3']"
+ );
+ b.request("PUT",
"?noTrace=true").accept("text/s1").contentType("text/p1").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p1'",
+ "Supported media-types: ['text/p3']"
+ );
+ b.request("PUT",
"?noTrace=true").accept("text/s1").accept("text/s2").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p2'",
+ "Supported media-types: ['text/p3']"
+ );
+ b.request("PUT",
"?noTrace=true").accept("text/s1").contentType("text/p2").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p2'",
+ "Supported media-types: ['text/p3']"
+ );
+ b.request("PUT",
"?noTrace=true").accept("text/s2").contentType("text/p2").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p2'",
+ "Supported media-types: ['text/p3']"
+ );
+ b.request("PUT", "?noTrace=true").accept("text/s3").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p2'",
+ "Supported media-types: ['text/p3']"
+ );
+ b.request("PUT",
"?noTrace=true").contentType("text/p3").execute()
+ .assertStatus(406)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Accept': 'text/s2'",
+ "Supported media-types: ['text/s3']"
+ );
+ }
+
+
+
//====================================================================================================
+ // Test that default Accept and Content-Type headers on servlet
annotation are picked up
+ // when @RestMethod.addParsers/addSerializers annotations are used.
+
//====================================================================================================
+
+ @RestResource(
+ defaultRequestHeaders={" Accept : text/s2 "," Content-Type :
text/p2 "},
+ parsers={P1.class,P2.class}, serializers={S1.class,S2.class}
+ )
+ public static class C {
+ @RestMethod(name=PUT, parsers=P3.class, serializers=S3.class,
inherit="SERIALIZERS,PARSERS")
+ public String c(@Body String in) {
+ return in;
+ }
+ }
+
+ private static MockRest c = MockRest.create(C.class);
+
+ @Test
+ public void c01_restMethodAddParsersSerializersInherit() throws
Exception {
+ c.request("PUT", "/").execute().assertBody("s2/p2");
+ c.request("PUT",
"/").accept("text/s1").execute().assertBody("s1/p2");
+ c.request("PUT",
"/").contentType("text/p1").execute().assertBody("s2/p1");
+ c.request("PUT",
"/").accept("text/s1").contentType("text/p1").execute().assertBody("s1/p1");
+ c.request("PUT",
"/").accept("text/s2").execute().assertBody("s2/p2");
+ c.request("PUT",
"/").contentType("text/p2").execute().assertBody("s2/p2");
+ c.request("PUT",
"/").accept("text/s2").contentType("text/p2").execute().assertBody("s2/p2");
+ c.request("PUT",
"/").accept("text/s3").execute().assertBody("s3/p2");
+ c.request("PUT",
"/").contentType("text/p3").execute().assertBody("s2/p3");
+ c.request("PUT",
"/").accept("text/s3").contentType("text/p3").execute().assertBody("s3/p3");
+ }
+
+ @Test
+ public void c02_restMethodAddParsersSerializersInherit_invalid() throws
Exception {
+ c.request("PUT",
"?noTrace=true").contentType("text/p4").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p4'",
+ "Supported media-types:
['text/p3','text/p1','text/p2']"
+ );
+ c.request("PUT", "?noTrace=true").accept("text/s4").execute()
+ .assertStatus(406)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Accept': 'text/s4'",
+ "Supported media-types:
['text/s3','text/s1','text/s2']"
+ );
+ }
+
+
+
//====================================================================================================
+ // Various Accept incantations.
+
//====================================================================================================
+ @RestResource(
+ defaultRequestHeaders={" Accept : text/s2 "," Content-Type :
text/p2 "},
+ parsers={P1.class,P2.class}, serializers={S1.class,S2.class}
+ )
+ public static class D {
+ @RestMethod(name=PUT)
+ public String d(@Body String in) {
+ return in;
+ }
+ }
+
+ private static MockRest d = MockRest.create(D.class);
+
+ @Test
+ public void d01_accept_valid() throws Exception {
+ // "*/*" should match the first serializer, not the default
serializer.
+ d.request("PUT",
"/").contentType("text/p1").accept("*/*").execute().assertBody("s1/p1");
+ // "text/*" should match the first serializer, not the default
serializer.
+ d.request("PUT",
"/").contentType("text/p1").accept("text/*").execute().assertBody("s1/p1");
+ d.request("PUT",
"/").contentType("text/p1").accept("bad/*,text/*").execute().assertBody("s1/p1");
+ d.request("PUT",
"/").contentType("text/p1").accept("text/*,bad/*").execute().assertBody("s1/p1");
+ d.request("PUT",
"/").contentType("text/p1").accept("text/s1;q=0.5,text/s2").execute().assertBody("s2/p1");
+ d.request("PUT",
"/").contentType("text/p1").accept("text/s1,text/s2;q=0.5").execute().assertBody("s1/p1");
+ }
+ @Test
+ public void d02_accept_invalid() throws Exception {
+ d.request("PUT",
"?noTrace=true").contentType("text/p1").accept("bad/*").execute()
+ .assertStatus(406)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Accept': 'bad/*'",
+ "Supported media-types: ['text/s1','text/s2']"
+ );
+ }
+
+
+
//====================================================================================================
+ // Test that default Accept and Content-Type headers on method
annotation are picked up
+ // when @RestMethod.parsers/serializers annotations are used.
+
//====================================================================================================
+ @RestResource(
+ defaultRequestHeaders={" Accept : text/s2 "," Content-Type :
text/p2 "},
+ parsers={P1.class,P2.class}, serializers={S1.class,S2.class}
+ )
+ public static class E {
+ @RestMethod(name=PUT, defaultRequestHeaders={"Accept:
text/s3","Content-Type: text/p3"}, parsers=P3.class, serializers=S3.class)
+ public String e(@Body String in) {
+ return in;
+ }
+ }
+
+ private static MockRest e = MockRest.create(E.class);
+
+ @Test
+ public void e01_restMethodParserSerializerAnnotations_valid() throws
Exception {
+ e.request("PUT", "/").execute().assertBody("s3/p3");
+ e.request("PUT",
"/").accept("text/s3").execute().assertBody("s3/p3");
+ e.request("PUT",
"/").contentType("text/p3").execute().assertBody("s3/p3");
+ e.request("PUT",
"/").accept("text/s3").contentType("text/p3").execute().assertBody("s3/p3");
+ }
+ @Test
+ public void e02_restMethodParserSerializerAnnotations_invalid() throws
Exception {
+ e.request("PUT", "?noTrace=true").accept("text/s1").execute()
+ .assertStatus(406)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Accept': 'text/s1'",
+ "Supported media-types: ['text/s3']"
+ );
+ e.request("PUT",
"?noTrace=true").contentType("text/p1").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p1'",
+ "Supported media-types: ['text/p3']"
+ );
+ e.request("PUT",
"?noTrace=true").accept("text/s1").contentType("text/p1").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p1'",
+ "Supported media-types: ['text/p3']"
+ );
+ e.request("PUT", "?noTrace=true").accept("text/s2").execute()
+ .assertStatus(406)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Accept': 'text/s2'",
+ "Supported media-types: ['text/s3']"
+ );
+ e.request("PUT",
"?noTrace=true").contentType("text/p2").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p2'",
+ "Supported media-types: ['text/p3']"
+ );
+ e.request("PUT",
"?noTrace=true").accept("text/s2").contentType("text/p2").execute()
+ .assertStatus(415)
+ .assertBodyContains(
+ "Unsupported media-type in request header
'Content-Type': 'text/p2'",
+ "Supported media-types: ['text/p3']"
+ );
+ }
+
+
+
//====================================================================================================
+ // Test that default Accept and Content-Type headers on method
annotation are picked up
+ // when @RestMethod.addParsers/addSerializers annotations are used.
+
//====================================================================================================
+ @RestResource(
+ defaultRequestHeaders={" Accept : text/s2 "," Content-Type :
text/p2 "},
+ parsers={P1.class,P2.class}, serializers={S1.class,S2.class}
+ )
+ public static class F {
+ @RestMethod(name=PUT, defaultRequestHeaders={"Accept:
text/s3","Content-Type: text/p3"}, parsers=P3.class, serializers=S3.class,
inherit="SERIALIZERS,PARSERS")
+ public String f(@Body String in) {
+ return in;
+ }
+ }
+
+ private static MockRest f = MockRest.create(F.class);
+
+ @Test
+ public void f01_restMethodAddParsersSerializersAnnotations_valid()
throws Exception {
+ f.request("PUT", "/").execute().assertBody("s3/p3");
+ f.request("PUT",
"/").accept("text/s1").execute().assertBody("s1/p3");
+ f.request("PUT",
"/").contentType("text/p1").execute().assertBody("s3/p1");
+ f.request("PUT",
"/").accept("text/s1").contentType("text/p1").execute().assertBody("s1/p1");
+ f.request("PUT",
"/").accept("text/s2").execute().assertBody("s2/p3");
+ f.request("PUT",
"/").contentType("text/p2").execute().assertBody("s3/p2");
+ f.request("PUT",
"/").accept("text/s2").contentType("text/p2").execute().assertBody("s2/p2");
+ f.request("PUT",
"/").accept("text/s3").execute().assertBody("s3/p3");
+ f.request("PUT",
"/").contentType("text/p3").execute().assertBody("s3/p3");
+ f.request("PUT",
"/").accept("text/s3").contentType("text/p3").execute().assertBody("s3/p3");
+ }
+}
diff --git
a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/StatusCodesTest.java
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/StatusCodesTest.java
new file mode 100644
index 0000000..546844a
--- /dev/null
+++
b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/StatusCodesTest.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.rest.annotation;
+
+import static org.apache.juneau.http.HttpMethodName.*;
+
+import java.io.*;
+
+import org.apache.juneau.rest.mock.*;
+import org.junit.*;
+
+/**
+ * Validates that the correct status codes are returned on REST requests.
+ */
+@SuppressWarnings("javadoc")
+public class StatusCodesTest {
+
+
//=================================================================================================================
+ // OK
+
//=================================================================================================================
+
+ @RestResource
+ public static class A {
+ @RestMethod(name=PUT)
+ public Reader a01(@Body String b) {
+ return new StringReader(b);
+ }
+ }
+
+ private static MockRest a = MockRest.create(A.class);
+
+ @Test
+ public void a01a_OK() throws Exception {
+ a.request("PUT", "/").body("foo").execute().assertStatus(200);
+ }
+
+ // TODO - Test all the status codes
+}
--
To stop receiving notification emails like this one, please contact
[email protected].