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<String,Integer> m = <jk>new</jk> AMap<String,Integer>()
- * .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 {