diff --git a/src/main/java/com/ibm/cloud/sdk/core/http/RequestBuilder.java b/src/main/java/com/ibm/cloud/sdk/core/http/RequestBuilder.java
index b97c6657b..2f126e4a8 100644
--- a/src/main/java/com/ibm/cloud/sdk/core/http/RequestBuilder.java
+++ b/src/main/java/com/ibm/cloud/sdk/core/http/RequestBuilder.java
@@ -1,5 +1,5 @@
/**
- * (C) Copyright IBM Corp. 2015, 2019.
+ * (C) Copyright IBM Corp. 2015, 2020.
*
* Licensed 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
@@ -13,22 +13,22 @@
package com.ibm.cloud.sdk.core.http;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
import com.google.gson.Gson;
import com.google.gson.JsonObject;
-import com.ibm.cloud.sdk.core.service.BaseService;
import com.ibm.cloud.sdk.core.util.GsonSingleton;
import com.ibm.cloud.sdk.core.util.StringHelper;
import com.ibm.cloud.sdk.core.util.Validator;
+
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Convenience class for constructing HTTP/HTTPS requests.
*/
@@ -325,26 +325,33 @@ public RequestBuilder bodyContent(InputStream stream, String contentType) {
return body(InputStreamRequestBody.create(MediaType.parse(contentType), stream));
}
+
/**
- * Sets the request body content from one of three different sources, based on the content type.
+ * Sets the request body content from one of three different sources.
+ * The three input sources are used in this precedence order:
+ *
+ * - If 'jsonContent' is not null, then use that.
+ * - If 'jsonPatchContent' is not null, then use that.
+ * - Else use 'nonJsonContent'.
+ *
*
* @param contentType
- * the value of the "Content-Type" header associated with the outgoing request
+ * the value of the "Content-Type" header associated with the request body
* @param jsonContent
- * the body content to be used if the content type indicates JSON
+ * a model instance to be serialized and used for the request body
* @param jsonPatchContent
- * the body content to be used if the content type indicates JsonPatch
+ * a collection of JsonPatchOperation instances to be serialized and used for the request body
* @param nonJsonContent
- * the body content to be used if the content type indicates non-JSON content
+ * an InputStream whose contents should be used directly as the request body
* @return this
*/
public RequestBuilder bodyContent(String contentType, Object jsonContent, Object jsonPatchContent,
InputStream nonJsonContent) {
if (contentType != null) {
Gson requestGson = GsonSingleton.getGsonWithoutPrettyPrinting().newBuilder().create();
- if (BaseService.isJsonMimeType(contentType)) {
+ if (jsonContent != null) {
this.bodyContent(requestGson.toJson(jsonContent), contentType);
- } else if (BaseService.isJsonPatchMimeType(contentType)) {
+ } else if (jsonPatchContent != null) {
this.bodyContent(requestGson.toJson(jsonPatchContent), contentType);
} else {
this.bodyContent(nonJsonContent, contentType);
@@ -354,16 +361,22 @@ public RequestBuilder bodyContent(String contentType, Object jsonContent, Object
}
/**
- * Sets the request body content from one of three different sources, based on the content type.
+ * Sets the request body content from one of three different sources.
+ * The three input sources are used in this precedence order:
+ *
+ * - If 'jsonContent' is not null, then use that.
+ * - If 'jsonPatchContent' is not null, then use that.
+ * - Else use 'nonJsonContent'.
+ *
*
* @param contentType
- * the value of the "Content-Type" header associated with the outgoing request
+ * the value of the "Content-Type" header associated with the request body
* @param jsonContent
- * the body content to be used if the content type indicates JSON
+ * a model instance to be serialized and used for the request body
* @param jsonPatchContent
- * the body content to be used if the content type indicates JsonPatch
+ * a collection of JsonPatchOperation instances to be serialized and used for the request body
* @param nonJsonContent
- * the body content to be used if the content type indicates non-JSON content
+ * a string to be used directly as the request body
* @return this
*/
public RequestBuilder bodyContent(String contentType, Object jsonContent, Object jsonPatchContent,
diff --git a/src/test/java/com/ibm/cloud/sdk/core/test/service/RequestBuilderTest.java b/src/test/java/com/ibm/cloud/sdk/core/test/service/RequestBuilderTest.java
index f6cc86c20..7be777c0a 100644
--- a/src/test/java/com/ibm/cloud/sdk/core/test/service/RequestBuilderTest.java
+++ b/src/test/java/com/ibm/cloud/sdk/core/test/service/RequestBuilderTest.java
@@ -293,7 +293,7 @@ public void testConstructHttpUrlEmptyPath1() {
assertNotNull(url);
assertEquals("https://myserver.com/testservice/api/discovery", url.toString());
}
-
+
@Test
public void testConstructHttpUrlEmptyPath2() {
String[] pathSegments = { "" };
@@ -333,13 +333,66 @@ public void testConstructHttpUrlEmptyPathAndParams() {
public void testConstructHttpUrlEmpty() {
String[] pathSegments = { "v1/seg1", "seg2", "seg3"};
String[] pathParameters = { "param1", "param2" };
- HttpUrl url = RequestBuilder.constructHttpUrl("", pathSegments, pathParameters);
+ RequestBuilder.constructHttpUrl("", pathSegments, pathParameters);
}
@Test(expected = IllegalArgumentException.class)
public void testConstructHttpUrlNull() {
String[] pathSegments = { "v1/seg1", "seg2", "seg3"};
String[] pathParameters = { "param1", "param2" };
- HttpUrl url = RequestBuilder.constructHttpUrl(null, pathSegments, pathParameters);
+ RequestBuilder.constructHttpUrl(null, pathSegments, pathParameters);
+ }
+
+ /**
+ * Test bodyContent() with a model instance.
+ * @throws IOException
+ */
+ @Test
+ public void testBodyContent1() throws IOException {
+ Truck truck = new Truck.Builder().vehicleType("Truck").make("Ford").engineType("raptor").build();
+ final Request request = RequestBuilder.post(HttpUrl.parse(urlWithQuery))
+ .bodyContent("application/json", truck, null, (InputStream) null).build();
+ final RequestBody requestedBody = request.body();
+ final Buffer buffer = new Buffer();
+ requestedBody.writeTo(buffer);
+
+ assertEquals(GsonSingleton.getGsonWithoutPrettyPrinting().toJson(truck), buffer.readUtf8());
+ assertEquals(HttpMediaType.JSON, requestedBody.contentType());
+ }
+
+ /**
+ * Test bodyContent() with an already serialized model instance (a String).
+ * @throws IOException
+ */
+ @Test
+ public void testBodyContent2() throws IOException {
+ Truck truck = new Truck.Builder().vehicleType("Truck").make("Ford").engineType("raptor").build();
+ String jsonString = GsonSingleton.getGsonWithoutPrettyPrinting().toJson(truck);
+ final Request request = RequestBuilder.post(HttpUrl.parse(urlWithQuery))
+ .bodyContent("application/json", null, null, jsonString).build();
+ final RequestBody requestedBody = request.body();
+ final Buffer buffer = new Buffer();
+ requestedBody.writeTo(buffer);
+
+ assertEquals(jsonString, buffer.readUtf8());
+ assertEquals(MediaType.parse("application/json"), requestedBody.contentType());
}
+
+ /**
+ * Test bodyContent() with a multiple inputs (JSON input should win).
+ * @throws IOException
+ */
+ @Test
+ public void testBodyContent3() throws IOException {
+ Truck truck = new Truck.Builder().vehicleType("Truck").make("Ford").engineType("raptor").build();
+ final Request request = RequestBuilder.post(HttpUrl.parse(urlWithQuery))
+ .bodyContent("application/json", truck, "BAD JSON PATCH BODY", "BAD INPUTSTREAM REQUEST BODY").build();
+ final RequestBody requestedBody = request.body();
+ final Buffer buffer = new Buffer();
+ requestedBody.writeTo(buffer);
+
+ assertEquals(GsonSingleton.getGsonWithoutPrettyPrinting().toJson(truck), buffer.readUtf8());
+ assertEquals(HttpMediaType.JSON, requestedBody.contentType());
+ }
+
}