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 755f99a  Tests.
755f99a is described below

commit 755f99a2fd933ed67426ec50adafafab51edd22f
Author: JamesBognar <[email protected]>
AuthorDate: Mon Aug 20 16:28:51 2018 -0400

    Tests.
---
 .../java/org/apache/juneau/BeanConfigTest.java     |   2 +-
 .../org/apache/juneau/httppart/HttpPartSchema.java |  15 +
 .../juneau/httppart/OpenApiPartParserSession.java  |  14 +-
 .../java/org/apache/juneau/marshall/Marshall.java  |  15 +-
 .../main/java/org/apache/juneau/utils/AMap.java    |  20 +
 .../utils/{AMap.java => StringInputStream.java}    |  28 +-
 juneau-doc/src/main/javadoc/overview.html          |  13 +-
 .../01.RestProxies/03.Body.html                    |  13 +-
 juneau-rest/juneau-rest-client/pom.xml             |   7 +
 .../org/apache/juneau/rest/client/RestCall.java    |  32 +-
 .../rest/client/remote/BodyAnnotationTest.java     | 463 +++++++++++++++++++++
 .../java/org/apache/juneau/rest/RequestBody.java   |  22 +-
 .../java/org/apache/juneau/rest/RestRequest.java   |   1 +
 .../juneau/rest/reshandlers/DefaultHandler.java    |   2 +-
 .../juneau/rest/annotation/BodyAnnotationTest.java |  14 +-
 15 files changed, 595 insertions(+), 66 deletions(-)

diff --git 
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/BeanConfigTest.java
 
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/BeanConfigTest.java
index d34ade3..f4ba0b4 100755
--- 
a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/BeanConfigTest.java
+++ 
b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/BeanConfigTest.java
@@ -370,7 +370,7 @@ public class BeanConfigTest {
                assertEquals(new Integer(1), session.convertToType(o, 
LinkedList.class).get(0));
 
                // HashMap to TreeMap
-               o = new AMap<Integer,String>().append(1, "foo");
+               o = AMap.create(1, "foo");
                assertEquals("foo", session.convertToType(o, 
TreeMap.class).firstEntry().getValue());
 
                // String to TreeMap
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
index d223d54..9e9c85d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
@@ -1340,4 +1340,19 @@ public class HttpPartSchema {
                        throw new RuntimeException(e);
                }
        }
+
+       @Override
+       public String toString() {
+               return toString(new StringBuilder()).toString();
+       }
+
+       private StringBuilder toString(StringBuilder sb) {
+               ObjectMap m = new ObjectMap();
+               m.appendSkipEmpty("name", name);
+               m.appendSkipEmpty("type", type);
+               m.appendSkipEmpty("format", format);
+               sb.append(m.toString());
+               return sb;
+       }
+
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/OpenApiPartParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/OpenApiPartParserSession.java
index 971e720..2f1b23c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/OpenApiPartParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/OpenApiPartParserSession.java
@@ -141,14 +141,12 @@ public class OpenApiPartParserSession extends 
UonPartParserSession {
                                        ss = split(in, ',');
                                }
 
-                               Object[] o = null;
-                               if (schema.getItems() != null) {
-                                       o = new Object[ss.length];
-                                       for (int i = 0; i < ss.length; i++)
-                                               o[i] = parse(partType, 
schema.getItems(), ss[i], eType);
-                               } else {
-                                       o = ss;
-                               }
+                               HttpPartSchema items = schema.getItems();
+                               if (items == null)
+                                       items = HttpPartSchema.DEFAULT;
+                               Object[] o = new Object[ss.length];
+                               for (int i = 0; i < ss.length; i++)
+                                       o[i] = parse(partType, items, ss[i], 
eType);
                                if 
(type.hasTransformFrom(schema.getParsedType()) || 
schema.getParsedType().hasTransformTo(type))
                                        return toType(toType(o, 
schema.getParsedType()), type);
                                return toType(o, type);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/Marshall.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/Marshall.java
index b5c364b..bec1206 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/Marshall.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/Marshall.java
@@ -114,10 +114,13 @@ public abstract class Marshall {
         *
         * @param o The object to serialize.
         * @return The output serialized to a string.
-        * @throws SerializeException If a problem occurred trying to convert 
the output.
         */
-       public final String toString(Object o) throws SerializeException {
-               return s.createSession().serializeToString(o);
+       public final String toString(Object o) {
+               try {
+                       return s.serializeToString(o);
+               } catch (Exception e) {
+                       throw new RuntimeException(e);
+               }
        }
 
 
@@ -128,11 +131,7 @@ public abstract class Marshall {
         * @return This object (for method chaining).
         */
        public final Marshall println(Object o) {
-               try {
-                       System.out.println(toString(o));
-               } catch (SerializeException e) {
-                       e.printStackTrace();
-               }
+               System.out.println(toString(o));
                return this;
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AMap.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AMap.java
index 543f0df..db85ecd 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AMap.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AMap.java
@@ -32,6 +32,26 @@ import java.util.*;
 public final class AMap<K,V> extends LinkedHashMap<K,V> {
 
        /**
+        * Creates an empty map.
+        *
+        * @return A new empty map.
+        */
+       public static <K,V> AMap<K,V> create() {
+               return new AMap<>();
+       }
+
+       /**
+        * Creates a map with one entry.
+        *
+        * @param key Entry key.
+        * @param value Entry value.
+        * @return A new map with one entry.
+        */
+       public static <K,V> AMap<K,V> create(K key, V value) {
+               return new AMap<K,V>().append(key, value);
+       }
+
+       /**
         * Adds an entry to this map.
         *
         * @param k The key.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AMap.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringInputStream.java
similarity index 68%
copy from 
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AMap.java
copy to 
juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringInputStream.java
index 543f0df..8bfc528 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/AMap.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringInputStream.java
@@ -12,34 +12,22 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.utils;
 
-import java.util.*;
+import java.io.*;
 
 /**
- * An extension of {@link LinkedHashMap} with a convenience {@link 
#append(Object,Object)} method.
+ * Convenience class for creating an input stream from a simple string.
  *
  * <p>
- * Primarily used for testing purposes for quickly creating populated maps.
- * <p class='bcode w800'>
- *     <jc>// Example:</jc>
- *     Map&lt;String,Integer&gt; m = <jk>new</jk> AMap&lt;String,Integer&gt;()
- *             .append(<js>"foo"</js>,1).append(<js>"bar"</js>,2);
- * </p>
- *
- * @param <K> The key type.
- * @param <V> The value type.
+ * Used primarily for testing purposes.
  */
-@SuppressWarnings("serial")
-public final class AMap<K,V> extends LinkedHashMap<K,V> {
+public class StringInputStream extends ByteArrayInputStream {
 
        /**
-        * Adds an entry to this map.
+        * Constructor.
         *
-        * @param k The key.
-        * @param v The value.
-        * @return This object (for method chaining).
+        * @param in The string to create an input stream from.
         */
-       public AMap<K,V> append(K k, V v) {
-               put(k, v);
-               return this;
+       public StringInputStream(String in) {
+               super(in.getBytes());
        }
 }
diff --git a/juneau-doc/src/main/javadoc/overview.html 
b/juneau-doc/src/main/javadoc/overview.html
index 100de39..7f525f0 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -20378,16 +20378,23 @@ TODO(7.2.0)
 </p>
 <ul class='spaced-list'>
        <li>
-               Any serializable POJO - Converted to output using the {@link 
org.apache.juneau.serializer.Serializer} or {@link 
org.apache.juneau.httppart.HttpPartSerializer} registered with the
+               Any serializable POJO - Converted to output using the {@link 
org.apache.juneau.serializer.Serializer} registered with the 
<code>RestClient</code>.
+               <br><code>Content-Type</code> is set to that of the 
<code>Serializer</code>.
+       <li>
+               Any part serializable POJO - Converted to output using the 
{@link org.apache.juneau.httppart.HttpPartSerializer} registered with the
                <code>RestClient</code> ({@link 
org.apache.juneau.httppart.OpenApiPartSerializer} by default) or associated via 
the {@link org.apache.juneau.http.annotation.Body#partSerializer() 
@Body(partSerializer)} annotation.
+               <br><code>Content-Type</code> is set to <js>"text/plain"</js>.
        <li>
                {@link java.io.Reader} - Raw contents of {@code Reader} will be 
serialized to remote resource.
+               <br><code>Content-Type</code> is set to <js>"text/plain"</js>.
        <li>
                {@link java.io.InputStream} - Raw contents of {@code 
InputStream} will be serialized to remote resource.
-       <li>
-               <code>HttpEntity</code> - Bypass Juneau serialization and pass 
HttpEntity directly to HttpClient.
+               <br><code>Content-Type</code> is not set.
        <li>
                <code>NameValuePairs</code> - Converted to a URL-encoded FORM 
post.
+               <br><code>Content-Type</code> is set to 
<js>"aplication/x-www-form-urlencoded"</js>.
+       <li>
+               <code>HttpEntity</code> - Bypass Juneau serialization and pass 
HttpEntity directly to HttpClient.
 </ul>
  
 <p>
diff --git 
a/juneau-doc/src/main/resources/Topics/09.juneau-rest-client/01.RestProxies/03.Body.html
 
b/juneau-doc/src/main/resources/Topics/09.juneau-rest-client/01.RestProxies/03.Body.html
index 2dfd78d..bffe6c0 100644
--- 
a/juneau-doc/src/main/resources/Topics/09.juneau-rest-client/01.RestProxies/03.Body.html
+++ 
b/juneau-doc/src/main/resources/Topics/09.juneau-rest-client/01.RestProxies/03.Body.html
@@ -57,16 +57,23 @@
 </p>
 <ul class='spaced-list'>
        <li>
-               Any serializable POJO - Converted to output using the {@link 
oaj.serializer.Serializer} or {@link oaj.httppart.HttpPartSerializer} 
registered with the
+               Any serializable POJO - Converted to output using the {@link 
oaj.serializer.Serializer} registered with the <code>RestClient</code>.
+               <br><code>Content-Type</code> is set to that of the 
<code>Serializer</code>.
+       <li>
+               Any part serializable POJO - Converted to output using the 
{@link oaj.httppart.HttpPartSerializer} registered with the
                <code>RestClient</code> ({@link 
oaj.httppart.OpenApiPartSerializer} by default) or associated via the {@link 
oaj.http.annotation.Body#partSerializer() @Body(partSerializer)} annotation.
+               <br><code>Content-Type</code> is set to <js>"text/plain"</js>.
        <li>
                {@link java.io.Reader} - Raw contents of {@code Reader} will be 
serialized to remote resource.
+               <br><code>Content-Type</code> is set to <js>"text/plain"</js>.
        <li>
                {@link java.io.InputStream} - Raw contents of {@code 
InputStream} will be serialized to remote resource.
-       <li>
-               <code>HttpEntity</code> - Bypass Juneau serialization and pass 
HttpEntity directly to HttpClient.
+               <br><code>Content-Type</code> is set to 
<js>"application/octet-stream"</js>.
        <li>
                <code>NameValuePairs</code> - Converted to a URL-encoded FORM 
post.
+               <br><code>Content-Type</code> is set to 
<js>"aplication/x-www-form-urlencoded"</js>.
+       <li>
+               <code>HttpEntity</code> - Bypass Juneau serialization and pass 
HttpEntity directly to HttpClient.
 </ul>
  
 <p>
diff --git a/juneau-rest/juneau-rest-client/pom.xml 
b/juneau-rest/juneau-rest-client/pom.xml
index 553af51..13329d4 100644
--- a/juneau-rest/juneau-rest-client/pom.xml
+++ b/juneau-rest/juneau-rest-client/pom.xml
@@ -45,6 +45,13 @@
                </dependency>
                <dependency>
                        <groupId>org.apache.juneau</groupId>
+                       <artifactId>juneau-core-test</artifactId>
+                       <version>${project.version}</version>
+                       <type>test-jar</type>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.juneau</groupId>
                        <artifactId>juneau-rest-server</artifactId>
                        <version>${project.version}</version>
                        <scope>test</scope>
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
index 7ac9deb..37c1c0e 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestCall.java
@@ -33,6 +33,7 @@ import org.apache.http.client.entity.*;
 import org.apache.http.client.methods.*;
 import org.apache.http.client.utils.*;
 import org.apache.http.entity.*;
+import org.apache.http.entity.ContentType;
 import org.apache.http.impl.client.*;
 import org.apache.http.util.*;
 import org.apache.juneau.*;
@@ -73,6 +74,8 @@ import org.apache.juneau.utils.*;
 @SuppressWarnings({ "unchecked" })
 public final class RestCall extends BeanSession implements Closeable {
 
+       private static final ContentType TEXT_PLAIN = 
ContentType.create("text/plain");
+
        private final RestClient client;                       // The client 
that created this call.
        private final HttpRequestBase request;                 // The request.
        private HttpResponse response;                         // The response.
@@ -540,10 +543,7 @@ public final class RestCall extends BeanSession implements 
Closeable {
         * @throws RestCallException If a retry was attempted, but the entity 
was not repeatable.
         */
        public RestCall body(Object input) throws RestCallException {
-               this.input = input;
-               this.hasInput = true;
-               this.formData = null;
-               return this;
+               return body(input, null, null);
        }
 
        /**
@@ -564,9 +564,11 @@ public final class RestCall extends BeanSession implements 
Closeable {
                        if (schema != null && schema.isUsePartSerializer())
                                partSerializer = this.partSerializer;
                        if (partSerializer != null)
-                               body(new 
StringEntity(partSerializer.serialize(BODY, schema, input)));
+                               this.input = new 
StringEntity(partSerializer.serialize(BODY, schema, input), TEXT_PLAIN);
                        else
-                               body(input);
+                               this.input = input;
+                       this.hasInput = true;
+                       this.formData = null;
                } catch (SchemaValidationException e) {
                        throw new RestCallException(e, "Validation error on 
request body.");
                } catch (Exception e) {
@@ -1567,13 +1569,15 @@ public final class RestCall extends BeanSession 
implements Closeable {
                                else if (input instanceof HttpEntity)
                                        entity = (HttpEntity)input;
                                else if (input instanceof Reader)
-                                       entity = new 
StringEntity(IOUtils.read((Reader)input));
+                                       entity = new 
StringEntity(IOUtils.read((Reader)input), getRequestContentType(TEXT_PLAIN));
                                else if (input instanceof InputStream)
-                                       entity = new 
InputStreamEntity((InputStream)input);
+                                       entity = new 
InputStreamEntity((InputStream)input, 
getRequestContentType(ContentType.APPLICATION_OCTET_STREAM));
                                else if (serializer != null)
                                        entity = new RestRequestEntity(input, 
serializer);
+                               else if (partSerializer != null)
+                                       entity = new 
StringEntity(partSerializer.serialize(null, input), 
getRequestContentType(TEXT_PLAIN));
                                else
-                                       entity = new 
StringEntity(getBeanContext().getClassMetaForObject(input).toString(input));
+                                       entity = new 
StringEntity(getBeanContext().getClassMetaForObject(input).toString(input), 
getRequestContentType(TEXT_PLAIN));
 
                                if (retries > 1 && ! entity.isRepeatable())
                                        throw new RestCallException("Rest call 
set to retryable, but entity is not repeatable.");
@@ -1646,6 +1650,16 @@ public final class RestCall extends BeanSession 
implements Closeable {
                return this;
        }
 
+       private ContentType getRequestContentType(ContentType def) {
+               Header h = request.getFirstHeader("Content-Type");
+               if (h != null) {
+                       String s = h.getValue();
+                       if (! isEmpty(s))
+                               return ContentType.create(s);
+               }
+               return def;
+       }
+
        private void reset() {
                if (response != null)
                        EntityUtils.consumeQuietly(response.getEntity());
diff --git 
a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/BodyAnnotationTest.java
 
b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/BodyAnnotationTest.java
new file mode 100644
index 0000000..e659721
--- /dev/null
+++ 
b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/BodyAnnotationTest.java
@@ -0,0 +1,463 @@
+// 
***************************************************************************************************************************
+// * 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.client.remote;
+
+import static org.apache.juneau.testutils.TestUtils.*;
+import static org.junit.Assert.*;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.http.*;
+import org.apache.http.entity.*;
+import org.apache.juneau.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.http.annotation.Header;
+import org.apache.juneau.json.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.client.*;
+import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.utils.*;
+import org.junit.*;
+import org.junit.runners.*;
+
+/**
+ * Tests the @RemoteResource annotation.
+ */
+@SuppressWarnings({"javadoc"})
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class BodyAnnotationTest {
+
+       public static class Bean {
+               public int f;
+
+               public static Bean create() {
+                       Bean b = new Bean();
+                       b.f = 1;
+                       return b;
+               }
+       }
+
+       
//=================================================================================================================
+       // Basic tests - JSON
+       
//=================================================================================================================
+
+       @RestResource(serializers=SimpleJsonSerializer.class, 
parsers=JsonParser.class)
+       public static class A {
+               @RestMethod
+               public Object postA01(@Body int b, @Header("Content-Type") 
String ct) {
+                       assertEquals("application/json", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postA02(@Body float b, @Header("Content-Type") 
String ct) {
+                       assertEquals("application/json", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postA03(@Body Bean b, @Header("Content-Type") 
String ct) {
+                       assertEquals("application/json", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postA04(@Body Bean[] b, @Header("Content-Type") 
String ct) {
+                       assertEquals("application/json", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postA05(@Body List<Bean> b, 
@Header("Content-Type") String ct) {
+                       assertEquals("application/json", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postA06(@Body Map<String,Bean> b, 
@Header("Content-Type") String ct) {
+                       assertEquals("application/json", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postA07(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/plain", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postA08(@Body InputStream b, 
@Header("Content-Type") String ct) {
+                       assertEquals("application/octet-stream", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postA09(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertTrue(ct.startsWith("text/plain"));
+                       return b;
+               }
+
+               @RestMethod
+               public Object postA10(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("application/x-www-form-urlencoded", ct);
+                       return b;
+               }
+       }
+       private static MockRest a = MockRest.create(A.class);
+
+       @RemoteResource
+       public static interface A01 {
+               Object postA01(@Body int b);
+               Object postA02(@Body float b);
+               Object postA03(@Body Bean b);
+               Object postA04(@Body Bean[] b);
+               Object postA05(@Body List<Bean> b);
+               Object postA06(@Body Map<String,Bean> b);
+               Object postA07(@Body Reader b);
+               Object postA08(@Body InputStream b);
+               Object postA09(@Body HttpEntity b);
+               Object postA10(@Body NameValuePairs b);
+       }
+
+       private static A01 a01 = 
RestClient.create().mockHttpConnection(a).json().build().getRemoteResource(A01.class);
+
+       @Test
+       public void a01_int() throws Exception {
+               Object o = a01.postA01(1);
+               assertObjectEquals("1", o);
+               assertClass(Integer.class, o);
+       }
+       @Test
+       public void a02_float() throws Exception {
+               Object o = a01.postA02(1f);
+               assertObjectEquals("1.0", o);
+               assertClass(Float.class, o);
+       }
+       @Test
+       public void a03_Bean() throws Exception {
+               Object o = a01.postA03(Bean.create());
+               assertObjectEquals("{f:1}", o);
+               assertClass(ObjectMap.class, o);
+       }
+       @Test
+       public void a04_BeanArray() throws Exception {
+               Object o = a01.postA04(new Bean[]{Bean.create()});
+               assertObjectEquals("[{f:1}]", o);
+               assertClass(ObjectList.class, o);
+       }
+       @Test
+       public void a05_ListOfBeans() throws Exception {
+               Object o = a01.postA05(AList.create(Bean.create()));
+               assertObjectEquals("[{f:1}]", o);
+               assertClass(ObjectList.class, o);
+       }
+       @Test
+       public void a06_MapOfBeans() throws Exception {
+               Object o = a01.postA06(AMap.create("k1",Bean.create()));
+               assertObjectEquals("{k1:{f:1}}", o);
+               assertClass(ObjectMap.class, o);
+       }
+       @Test
+       public void a07_Reader() throws Exception {
+               Object o = a01.postA07(new StringReader("xxx"));
+               assertObjectEquals("'xxx'", o);
+               assertClass(String.class, o);
+       }
+       @Test
+       public void a08_InputStream() throws Exception {
+               @SuppressWarnings("resource")
+               Object o = a01.postA08(new StringInputStream("xxx"));
+               assertObjectEquals("'xxx'", o);
+               assertClass(String.class, o);
+       }
+       @Test
+       public void a09_HttpEntity() throws Exception {
+               Object o = a01.postA09(new StringEntity("xxx"));
+               assertObjectEquals("'xxx'", o);
+               assertClass(String.class, o);
+       }
+       @Test
+       public void a10_NameValuePairs() throws Exception {
+               Object o = a01.postA10(new NameValuePairs().append("foo", 
"bar"));
+               assertObjectEquals("'foo=bar'", o);
+               assertClass(String.class, o);
+       }
+
+       
//=================================================================================================================
+       // Basic tests - OpenAPI
+       
//=================================================================================================================
+
+       @RestResource(parsers=JsonParser.class)
+       public static class B {
+               @RestMethod
+               public Object postB01(@Body int b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/plain", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postB02(@Body float b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/plain", ct);
+                       return b;
+               }
+
+               @RestMethod
+               @Response(schema=@Schema(type="object"))
+               public Object postB03(@Body(schema=@Schema(type="object")) Bean 
b, @Header("Content-Type") String ct) {
+                       assertEquals("text/plain", ct);
+                       return b;
+               }
+
+               @RestMethod
+               
@Response(schema=@Schema(type="array",items=@Items(type="object")))
+               public Object 
postB04(@Body(schema=@Schema(type="array",items=@Items(type="object"))) Bean[] 
b, @Header("Content-Type") String ct) {
+                       assertEquals("text/plain", ct);
+                       return b;
+               }
+
+               @RestMethod
+               
@Response(schema=@Schema(type="array",items=@Items(type="object")))
+               public Object 
postB05(@Body(schema=@Schema(type="array",items=@Items(type="object"))) 
List<Bean> b, @Header("Content-Type") String ct) {
+                       assertEquals("text/plain", ct);
+                       return b;
+               }
+
+               @RestMethod
+               @Response(schema=@Schema(type="object",format="uon"))
+               public Object 
postB06(@Body(schema=@Schema(type="object",format="uon")) Map<String,Bean> b, 
@Header("Content-Type") String ct) {
+                       assertEquals("text/plain", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postB07(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/plain", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postB08(@Body InputStream b, 
@Header("Content-Type") String ct) {
+                       assertEquals("application/octet-stream", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postB09(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/plain", ct);
+                       return b;
+               }
+
+               @RestMethod
+               public Object postB10(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("application/x-www-form-urlencoded", ct);
+                       return b;
+               }
+       }
+       private static MockRest b = MockRest.create(B.class);
+
+       @RemoteResource
+       public static interface B01 {
+               String postB01(@Body int b);
+               String postB02(@Body float b);
+               String postB03(@Body(schema=@Schema(type="object")) Bean b);
+               String 
postB04(@Body(schema=@Schema(type="array",items=@Items(type="object"))) Bean[] 
b);
+               String 
postB05(@Body(schema=@Schema(type="array",items=@Items(type="object"))) 
List<Bean> b);
+               String 
postB06(@Body(schema=@Schema(type="object",format="uon")) Map<String,Bean> b);
+               String postB07(@Body Reader b);
+               String postB08(@Body InputStream b);
+               String postB09(@Body HttpEntity b);
+               String postB10(@Body NameValuePairs b);
+       }
+
+       private static B01 b01 = 
RestClient.create().mockHttpConnection(b).build().getRemoteResource(B01.class);
+
+       @Test
+       public void b01_int() throws Exception {
+               String o = b01.postB01(1);
+               assertEquals("1", o);
+       }
+       @Test
+       public void b02_float() throws Exception {
+               String o = b01.postB02(1f);
+               assertEquals("1.0", o);
+       }
+       @Test
+       public void b03_Bean() throws Exception {
+               String o = b01.postB03(Bean.create());
+               assertEquals("(f=1)", o);
+       }
+       @Test
+       public void b04_BeanArray() throws Exception {
+               String o = b01.postB04(new Bean[]{Bean.create()});
+               assertEquals("(f=1)", o);
+       }
+       @Test
+       public void b05_ListOfBeans() throws Exception {
+               String o = b01.postB05(AList.create(Bean.create()));
+               assertEquals("(f=1)", o);
+       }
+       @Test
+       public void b06_MapOfBeans() throws Exception {
+               String o = b01.postB06(AMap.create("k1",Bean.create()));
+               assertEquals("(k1=(f=1))", o);
+       }
+       @Test
+       public void b07_Reader() throws Exception {
+               String o = b01.postB07(new StringReader("xxx"));
+               assertEquals("xxx", o);
+       }
+       @Test
+       public void b08_InputStream() throws Exception {
+               @SuppressWarnings("resource")
+               String o = b01.postB08(new StringInputStream("xxx"));
+               assertEquals("xxx", o);
+       }
+       @Test
+       public void b09_HttpEntity() throws Exception {
+               String o = b01.postB09(new StringEntity("xxx", 
ContentType.create("text/plain")));
+               assertEquals("xxx", o);
+       }
+       @Test
+       public void b10_NameValuePairs() throws Exception {
+               String o = b01.postB10(new NameValuePairs().append("foo", 
"bar"));
+               assertEquals("foo=bar", o);
+       }
+
+       
//=================================================================================================================
+       // Basic tests - OpenAPI, overridden Content-Type
+       
//=================================================================================================================
+
+       @RestResource
+       public static class C {
+               @RestMethod
+               public Reader postC01(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+               @RestMethod
+               public Reader postC02(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+               @RestMethod
+               public Reader postC03(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+               @RestMethod
+               public Reader postC04(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+               @RestMethod
+               public Reader postC05(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+               @RestMethod
+               public Reader postC06(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+               @RestMethod
+               public Reader postC07(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+               @RestMethod
+               public Reader postC08(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+               @RestMethod
+               public Reader postC09(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+               @RestMethod
+               public Reader postC10(@Body Reader b, @Header("Content-Type") 
String ct) {
+                       assertEquals("text/foo", ct);
+                       return b;
+               }
+       }
+       private static MockRest c = MockRest.create(C.class);
+
+       @RemoteResource
+       public static interface C01 {
+               String postC01(@Body int b);
+               String postC02(@Body float b);
+               String postC03(@Body(schema=@Schema(type="object")) Bean b);
+               String 
postC04(@Body(schema=@Schema(type="array",items=@Items(type="object"))) Bean[] 
b);
+               String 
postC05(@Body(schema=@Schema(type="array",items=@Items(type="object"))) 
List<Bean> b);
+               String 
postC06(@Body(schema=@Schema(type="object",format="uon")) Map<String,Bean> b);
+               String postC07(@Body Reader b);
+               String postC08(@Body InputStream b);
+               String postC09(@Body HttpEntity b);
+               String postC10(@Body NameValuePairs b);
+       }
+
+       private static C01 c01 = 
RestClient.create().mockHttpConnection(c).contentType("text/foo").build().getRemoteResource(C01.class);
+
+       @Test
+       public void c01_int() throws Exception {
+               String o = c01.postC01(1);
+               assertEquals("1", o);
+       }
+       @Test
+       public void c02_float() throws Exception {
+               String o = c01.postC02(1f);
+               assertEquals("1.0", o);
+       }
+       @Test
+       public void c03_Bean() throws Exception {
+               String o = c01.postC03(Bean.create());
+               assertEquals("(f=1)", o);
+       }
+       @Test
+       public void c04_BeanArray() throws Exception {
+               String o = c01.postC04(new Bean[]{Bean.create()});
+               assertEquals("(f=1)", o);
+       }
+       @Test
+       public void c05_ListOfBeans() throws Exception {
+               String o = c01.postC05(AList.create(Bean.create()));
+               assertEquals("(f=1)", o);
+       }
+       @Test
+       public void c06_MapOfBeans() throws Exception {
+               String o = c01.postC06(AMap.create("k1",Bean.create()));
+               assertEquals("(k1=(f=1))", o);
+       }
+       @Test
+       public void c07_Reader() throws Exception {
+               String o = c01.postC07(new StringReader("xxx"));
+               assertEquals("xxx", o);
+       }
+       @Test
+       public void c08_InputStream() throws Exception {
+               @SuppressWarnings("resource")
+               String o = c01.postC08(new StringInputStream("xxx"));
+               assertEquals("xxx", o);
+       }
+       @Test
+       public void c09_HttpEntity() throws Exception {
+               String o = c01.postC09(new StringEntity("xxx", 
ContentType.create("text/plain")));
+               assertEquals("xxx", o);
+       }
+       @Test
+       public void c10_NameValuePairs() throws Exception {
+               String o = c01.postC10(new NameValuePairs().append("foo", 
"bar"));
+               assertEquals("foo=bar", o);
+       }
+}
\ No newline at end of file
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 69f694a..cfeecd4 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
@@ -52,6 +52,7 @@ public class RequestBody {
        private int contentLength = 0;
        private MediaType mediaType;
        private Parser parser;
+       private HttpPartParser partParser;
 
        RequestBody(RestRequest req) {
                this.req = req;
@@ -67,6 +68,11 @@ public class RequestBody {
                return this;
        }
 
+       RequestBody partParser(HttpPartParser partParser) {
+               this.partParser = partParser;
+               return this;
+       }
+
        RequestBody headers(RequestHeaders headers) {
                this.headers = headers;
                return this;
@@ -471,14 +477,18 @@ public class RequestBody {
                if (cm.hasInputStreamTransform())
                        return 
cm.getInputStreamTransform().transform(getInputStream());
 
-               if (partParser != null) {
-                       String in = asString();
-                       return 
partParser.createSession(req.getParserSessionArgs()).parse(BODY, schema, 
isEmpty(in) ? null : in, cm);
-               }
+               if (partParser == null)
+                       partParser = this.partParser;
 
                MediaType mt = getMediaType();
-               if ((isEmpty(mt) || mt.toString().startsWith("text/plain")) && 
cm.hasStringTransform())
-                       return cm.getStringTransform().transform(asString());
+               if (isEmpty(mt) || mt.toString().startsWith("text/plain")) {
+                       if (partParser != null) {
+                               String in = asString();
+                               return 
partParser.createSession(req.getParserSessionArgs()).parse(BODY, schema, 
isEmpty(in) ? null : in, cm);
+                       }
+                       if (cm.hasStringTransform())
+                               return 
cm.getStringTransform().transform(asString());
+               }
 
                throw new UnsupportedMediaType(
                        "Unsupported media-type in request header 
''Content-Type'': ''{0}''\n\tSupported media-types: {1}",
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index e4ca291..90ee60a 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -181,6 +181,7 @@ public final class RestRequest extends 
HttpServletRequestWrapper {
                this.body
                        .encoders(rjm.encoders)
                        .parsers(rjm.parsers)
+                       .partParser(rjm.partParser)
                        .headers(headers)
                        .maxInput(rjm.maxInput);
 
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
index ac57f0c..d5fb9c3 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/reshandlers/DefaultHandler.java
@@ -189,7 +189,7 @@ public class DefaultHandler implements ResponseHandler {
                }
 
                // Non-existent Accept or plain/text can just be serialized 
as-is.
-               if ("".equals(accept) || "plain/text".equals(accept)) {
+               if (isEmpty(accept) || accept.startsWith("text/plain")) {
                        FinishablePrintWriter w = res.getNegotiatedWriter();
                        ClassMeta<?> cm = 
req.getBeanSession().getClassMetaForObject(o);
                        if (cm != null)
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
index a25b3d3..dfc7dd7 100644
--- 
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
@@ -153,7 +153,7 @@ public class BodyAnnotationTest {
        }
        @Test
        public void a03b_onParameter_int_noContentType() throws Exception {
-               a.put("/int?noTrace=true", 
"123").execute().assertBodyContains("Unsupported Media Type");
+               a.put("/int", "123").execute().assertBody("123"); // Uses part 
parser.
        }
        @Test
        public void a04a_onParameter_Boolean() throws Exception {
@@ -170,7 +170,7 @@ public class BodyAnnotationTest {
        }
        @Test
        public void a05b_onParameter_boolean_noContentType() throws Exception {
-               a.put("/boolean?noTrace=true", 
"true").execute().assertBodyContains("Unsupported Media Type");
+               a.put("/boolean", "true").execute().assertBody("true"); // Uses 
part parser.
        }
        @Test
        public void a06a_onParameter_float() throws Exception {
@@ -178,7 +178,7 @@ public class BodyAnnotationTest {
        }
        @Test
        public void a06b_onParameter_float_noContentType() throws Exception {
-               a.put("/float?noTrace=true", 
"1.23").execute().assertBodyContains("Unsupported Media Type");
+               a.put("/float", "1.23").execute().assertBody("1.23");  // Uses 
part parser.
        }
        @Test
        public void a07a_onParameter_Float() throws Exception {
@@ -195,7 +195,7 @@ public class BodyAnnotationTest {
        }
        @Test
        public void a08b_onParameter_Map_noContentType() throws Exception {
-               a.put("/Map?noTrace=true", 
"{foo:123}").execute().assertBodyContains("Unsupported Media Type");
+               a.put("/Map", "(foo=123)").execute().assertBody("{foo:123}");  
// Uses part parser.
        }
        @Test
        public void a09a_onParameter_enum() throws Exception {
@@ -211,7 +211,7 @@ public class BodyAnnotationTest {
        }
        @Test
        public void a11b_onParameter_Bean_noContentType() throws Exception {
-               a.put("/Bean?noTrace=true", 
"{f1:'a'}").execute().assertBodyContains("Unsupported Media Type");
+               a.put("/Bean", "(f1=a)").execute().assertBody("{f1:'a'}");  // 
Uses part parser.
        }
        @Test
        public void a12a_onParameter_InputStream() throws Exception {
@@ -328,7 +328,7 @@ public class BodyAnnotationTest {
        }
        @Test
        public void b02b_onPojo_Bean_noContentType() throws Exception {
-               b.put("/Bean?noTrace=true", 
"{f1:'a'}").execute().assertBodyContains("Unsupported Media Type");
+               b.put("/Bean", "(f1=a)").execute().assertBody("{f1:'a'}");  // 
Uses part parser.
        }
        @Test
        public void b03a_onPojo_BeanList() throws Exception {
@@ -336,7 +336,7 @@ public class BodyAnnotationTest {
        }
        @Test
        public void b03b_onPojo_BeanList_noContentType() throws Exception {
-               b.put("/BeanList?noTrace=true", 
"[{f1:'a'}]").execute().assertBodyContains("Unsupported Media Type");
+               b.put("/BeanList", 
"(f1=a)").execute().assertBody("[{f1:'a'}]");  // Uses part parser.
        }
        @Test
        public void b04a_onPojo_InputStreamTransform() throws Exception {

Reply via email to