diff --git a/.github/workflows/test-and-deploy.yml b/.github/workflows/test-and-deploy.yml
index cb88c7881f..58c20112a4 100644
--- a/.github/workflows/test-and-deploy.yml
+++ b/.github/workflows/test-and-deploy.yml
@@ -42,15 +42,15 @@ jobs:
- name: Run Unit Tests
run: mvn test -B
- - name: Run Cluster Test
- if: (!github.event.pull_request.head.repo.fork)
- env:
- TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
- TWILIO_API_KEY: ${{ secrets.TWILIO_CLUSTER_TEST_API_KEY}}
- TWILIO_API_SECRET: ${{ secrets.TWILIO_CLUSTER_TEST_API_KEY_SECRET }}
- TWILIO_FROM_NUMBER: ${{ secrets.TWILIO_FROM_NUMBER }}
- TWILIO_TO_NUMBER: ${{ secrets.TWILIO_TO_NUMBER }}
- run: mvn test -DTest="ClusterTest" -B
+# - name: Run Cluster Test
+# if: (!github.event.pull_request.head.repo.fork)
+# env:
+# TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
+# TWILIO_API_KEY: ${{ secrets.TWILIO_CLUSTER_TEST_API_KEY}}
+# TWILIO_API_SECRET: ${{ secrets.TWILIO_CLUSTER_TEST_API_KEY_SECRET }}
+# TWILIO_FROM_NUMBER: ${{ secrets.TWILIO_FROM_NUMBER }}
+# TWILIO_TO_NUMBER: ${{ secrets.TWILIO_TO_NUMBER }}
+# run: mvn test -DTest="ClusterTest" -B
- name: SonarCloud Scan
if: ${{ (github.event_name == 'pull_request' || github.ref_type == 'branch') && matrix.java == 11 && !github.event.pull_request.head.repo.fork }}
diff --git a/README.md b/README.md
index e06383635d..a239798cb0 100644
--- a/README.md
+++ b/README.md
@@ -41,7 +41,7 @@ Use the following dependency in your project to grab via Maven:
com.twilio.sdk
twilio
- 9.X.X
+ 10.X.X
compile
```
@@ -49,7 +49,7 @@ Use the following dependency in your project to grab via Maven:
or Gradle:
```groovy
-implementation "com.twilio.sdk:twilio:9.X.X"
+implementation "com.twilio.sdk:twilio:10.X.X"
```
If you want to compile it yourself, here's how:
diff --git a/UPGRADE.md b/UPGRADE.md
index a0f93b2554..8e7fe12cfb 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -2,6 +2,14 @@
_`MAJOR` version bumps will have upgrade notes posted here._
+[2024-02-08] 9.x.x to 10.x.x
+### Overview
+
+##### Twilio Java Helper Library’s major version 10.0.0 is now available. We ensured that you can upgrade to Java helper Library 10.0.0 version without any breaking changes of existing apis
+
+Behind the scenes Java Helper is now auto-generated via OpenAPI with this release. This enables us to rapidly add new features and enhance consistency across versions and languages.
+We're pleased to inform you that version 10.0.0 adds support for the application/json content type in the request body.
+
[2022-09-21] 8.x.x to 9.x.x
-----------------------------
### Overview
diff --git a/src/main/java/com/twilio/Domains.java b/src/main/java/com/twilio/Domains.java
index 035f623ce3..32da7bc0aa 100644
--- a/src/main/java/com/twilio/Domains.java
+++ b/src/main/java/com/twilio/Domains.java
@@ -26,6 +26,7 @@ public enum Domains {
IPMESSAGING("ip-messaging"),
LOOKUPS("lookups"),
MEDIA("media"),
+ PREVIEWMESSAGING("preview.messaging"),
MESSAGING("messaging"),
MICROVISOR("microvisor"),
MONITOR("monitor"),
diff --git a/src/main/java/com/twilio/Twilio.java b/src/main/java/com/twilio/Twilio.java
index 9eacb39dfd..724b73ce8a 100644
--- a/src/main/java/com/twilio/Twilio.java
+++ b/src/main/java/com/twilio/Twilio.java
@@ -241,7 +241,7 @@ public static void setExecutorService(final ExecutorService executorService) {
}
/**
- * Validate that we can connect to the new SSL certificate posted on api.twilio.com.
+ * Validate that we can connect to the new SSL certificate posted on tls-test.twilio.com
*
* @throws CertificateValidationException if the connection fails
*/
diff --git a/src/main/java/com/twilio/converter/Converter.java b/src/main/java/com/twilio/converter/Converter.java
index 1cb6e8bfc8..9ee29e0e3d 100644
--- a/src/main/java/com/twilio/converter/Converter.java
+++ b/src/main/java/com/twilio/converter/Converter.java
@@ -18,7 +18,7 @@ public class Converter {
* @param map map to convert
* @return converted JSON string
*/
- public static String mapToJson(final Map map) {
+ public static String mapToJson(final Map map) {
try {
return MAPPER.writeValueAsString(map);
} catch (JsonProcessingException e) {
diff --git a/src/main/java/com/twilio/http/NetworkHttpClient.java b/src/main/java/com/twilio/http/NetworkHttpClient.java
index 0088365ad9..efa058cb4c 100644
--- a/src/main/java/com/twilio/http/NetworkHttpClient.java
+++ b/src/main/java/com/twilio/http/NetworkHttpClient.java
@@ -1,6 +1,7 @@
package com.twilio.http;
import com.twilio.Twilio;
+import com.twilio.constant.EnumConstants;
import com.twilio.exception.ApiException;
import java.io.IOException;
@@ -19,6 +20,8 @@
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.BufferedHttpEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
@@ -129,13 +132,23 @@ public Response makeRequest(final Request request) {
}
if (method == HttpMethod.POST) {
- builder.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
-
- for (Map.Entry> entry : request.getPostParams().entrySet()) {
- for (String value : entry.getValue()) {
- builder.addParameter(entry.getKey(), value);
+ // TODO: It will be removed after one RC Release.
+ if (request.getContentType() == null) request.setContentType(EnumConstants.ContentType.FORM_URLENCODED);
+ if (EnumConstants.ContentType.JSON.getValue().equals(request.getContentType().getValue())) {
+ HttpEntity entity = new StringEntity(request.getBody(), ContentType.APPLICATION_JSON);
+ builder.setEntity(entity);
+ builder.addHeader(
+ HttpHeaders.CONTENT_TYPE, EnumConstants.ContentType.JSON.getValue());
+ } else {
+ builder.addHeader(
+ HttpHeaders.CONTENT_TYPE, EnumConstants.ContentType.FORM_URLENCODED.getValue());
+ for (Map.Entry> entry : request.getPostParams().entrySet()) {
+ for (String value : entry.getValue()) {
+ builder.addParameter(entry.getKey(), value);
+ }
}
}
+
}
builder.addHeader(HttpHeaders.USER_AGENT, HttpUtility.getUserAgentString(request.getUserAgentExtensions(), isCustomClient));
diff --git a/src/main/java/com/twilio/http/Request.java b/src/main/java/com/twilio/http/Request.java
index f72dd0bc1e..36aa7a5e03 100644
--- a/src/main/java/com/twilio/http/Request.java
+++ b/src/main/java/com/twilio/http/Request.java
@@ -1,15 +1,10 @@
package com.twilio.http;
+import com.twilio.constant.EnumConstants;
-import com.twilio.constant.EnumConstants.ContentType;
import com.twilio.exception.ApiException;
import com.twilio.exception.InvalidRequestException;
-import java.time.ZonedDateTime;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
-import java.time.LocalDate;
-
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
@@ -17,6 +12,10 @@
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.*;
public class Request {
@@ -39,7 +38,9 @@ public class Request {
private List userAgentExtensions;
- private ContentType contentType;
+ private EnumConstants.ContentType contentType;
+
+ private String body;
/**
* Create a new API request.
@@ -117,14 +118,22 @@ public List getUserAgentExtensions() {
return this.userAgentExtensions;
}
- public ContentType getContentType() {
+ public EnumConstants.ContentType getContentType() {
return contentType;
}
- public void setContentType(ContentType contentType) {
+ public void setContentType(EnumConstants.ContentType contentType) {
this.contentType = contentType;
}
+ public String getBody() {
+ return body;
+ }
+
+ public void setBody(String body) {
+ this.body = body;
+ }
+
/**
* Create auth string from username and password.
*
diff --git a/src/main/java/com/twilio/http/ValidationClient.java b/src/main/java/com/twilio/http/ValidationClient.java
index 4dd8841609..32dd43ab6a 100644
--- a/src/main/java/com/twilio/http/ValidationClient.java
+++ b/src/main/java/com/twilio/http/ValidationClient.java
@@ -1,13 +1,17 @@
package com.twilio.http;
import com.twilio.Twilio;
+import com.twilio.constant.EnumConstants;
import com.twilio.exception.ApiException;
+import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.config.SocketConfig;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
@@ -175,11 +179,20 @@ public Response makeRequest(Request request) {
HttpMethod method = request.getMethod();
if (method == HttpMethod.POST) {
- builder.addHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
-
- for (Map.Entry> entry : request.getPostParams().entrySet()) {
- for (String value : entry.getValue()) {
- builder.addParameter(entry.getKey(), value);
+ // TODO: It will be removed after one RC Release.
+ if (request.getContentType() == null) request.setContentType(EnumConstants.ContentType.FORM_URLENCODED);
+ if (EnumConstants.ContentType.JSON.getValue().equals(request.getContentType().getValue())) {
+ HttpEntity entity = new StringEntity(request.getBody(), ContentType.APPLICATION_JSON);
+ builder.setEntity(entity);
+ builder.addHeader(
+ HttpHeaders.CONTENT_TYPE, EnumConstants.ContentType.JSON.getValue());
+ } else {
+ builder.addHeader(
+ HttpHeaders.CONTENT_TYPE, EnumConstants.ContentType.FORM_URLENCODED.getValue());
+ for (Map.Entry> entry : request.getPostParams().entrySet()) {
+ for (String value : entry.getValue()) {
+ builder.addParameter(entry.getKey(), value);
+ }
}
}
}
diff --git a/src/test/java/com/twilio/http/NetworkHttpClientTest.java b/src/test/java/com/twilio/http/NetworkHttpClientTest.java
index d49a826482..ee5c9050f4 100644
--- a/src/test/java/com/twilio/http/NetworkHttpClientTest.java
+++ b/src/test/java/com/twilio/http/NetworkHttpClientTest.java
@@ -1,5 +1,6 @@
package com.twilio.http;
+import com.twilio.constant.EnumConstants;
import com.twilio.exception.ApiConnectionException;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
@@ -66,6 +67,7 @@ private void setup(
when(mockRequest.constructURL()).thenReturn(new URL("http://foo.com/hello"));
when(mockRequest.requiresAuthentication()).thenReturn(requiresAuthentication);
when(mockRequest.getAuthString()).thenReturn("foo:bar");
+ when(mockRequest.getContentType()).thenReturn(EnumConstants.ContentType.FORM_URLENCODED);
when(mockClient.execute(any())).thenReturn(mockResponse);
when(mockEntity.isRepeatable()).thenReturn(true);
when(mockEntity.getContentLength()).thenReturn(1L);
@@ -110,6 +112,18 @@ public void testPost() throws IOException {
assertEquals(resp.getContent(), "frobozz");
}
+ @Test
+ public void testJsonPost() throws IOException {
+ setup(201, "frobozz", HttpMethod.POST, false);
+ when(mockRequest.getContentType()).thenReturn(EnumConstants.ContentType.JSON);
+ String body = "{\"from\":\"+12345\",\"body\":\"message body\",\"messages\":[{\"to\":\"+12345\"}]}";
+ when(mockRequest.getBody()).thenReturn(body);
+ Response resp = client.makeRequest(mockRequest);
+
+ assertEquals(resp.getStatusCode(), 201);
+ assertEquals(resp.getContent(), "frobozz");
+ }
+
@Test
public void testReliableRequest() {
Request request = new Request(HttpMethod.GET, "http://foo.com/hello");
diff --git a/src/test/java/com/twilio/http/RequestTest.java b/src/test/java/com/twilio/http/RequestTest.java
index 29c597e0b3..cb9aa8b9c8 100644
--- a/src/test/java/com/twilio/http/RequestTest.java
+++ b/src/test/java/com/twilio/http/RequestTest.java
@@ -1,5 +1,6 @@
package com.twilio.http;
+import com.twilio.constant.EnumConstants;
import com.twilio.exception.ApiException;
import com.twilio.rest.Domains;
import java.time.ZonedDateTime;
@@ -317,4 +318,10 @@ public void testEquals() {
assertNotEquals(request, new Object());
assertNotEquals(null, request);
}
+ @Test
+ public void testContentType() {
+ Request r = new Request(HttpMethod.POST, "http://example.com/foobar");
+ r.setContentType(EnumConstants.ContentType.JSON);
+ assertEquals(EnumConstants.ContentType.JSON, r.getContentType());
+ }
}
diff --git a/src/test/java/com/twilio/http/ValidationClientTest.java b/src/test/java/com/twilio/http/ValidationClientTest.java
index 1df4497b26..3d5659de95 100644
--- a/src/test/java/com/twilio/http/ValidationClientTest.java
+++ b/src/test/java/com/twilio/http/ValidationClientTest.java
@@ -1,5 +1,6 @@
package com.twilio.http;
+import com.twilio.constant.EnumConstants;
import org.junit.Test;
import java.security.KeyPair;
@@ -23,6 +24,7 @@ public void testHttpGet() throws Exception {
@Test
public void testHttpPost() throws Exception {
exerciseHttpMethod(HttpMethod.POST);
+ testContentType(HttpMethod.POST);
}
@Test
@@ -46,6 +48,29 @@ private void exerciseHttpMethod(final HttpMethod httpMethod) throws Exception {
assertNotNull(validationHeaderValue);
assertTrue(validationHeaderValue.length() > 0);
}
+ private void testContentType(final HttpMethod httpMethod) throws Exception {
+ final KeyPair keyPair = generateKeyPair();
+ final MockWebServer server = new MockWebServer();
+ server.enqueue(new MockResponse().setBody("{\n" +
+ " \"key1\": \"value1\",\n" +
+ " \"key2\": \"value2\"\n" +
+ "}"));
+ final String path = "/example123";
+ final HttpUrl url = server.url(path);
+ final ValidationClient client = new ValidationClient("dummy-sid1", "dummy-sid2", "dummy-signing-key", keyPair.getPrivate());
+ final Request request = new Request(httpMethod, url.url().toString());
+ request.setContentType(EnumConstants.ContentType.JSON);
+ String body = "{\"from\":\"+12345\",\"body\":\"message body\",\"messages\":[{\"to\":\"+12345\"}]}";
+ request.setBody(body);
+ final Response response = client.makeRequest(request);
+ assertEquals(200, response.getStatusCode());
+ final RecordedRequest recordedRequest = server.takeRequest();
+ assertEquals(httpMethod.name(), recordedRequest.getMethod());
+ assertEquals(EnumConstants.ContentType.JSON.getValue(), recordedRequest.getHeader("Content-Type"));
+ final String validationHeaderValue = recordedRequest.getHeader("Twilio-Client-Validation");
+ assertNotNull(validationHeaderValue);
+ assertTrue(validationHeaderValue.length() > 0);
+ }
private static KeyPair generateKeyPair() throws Exception {
final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");