diff --git a/.github/workflows/unitTests.yml b/.github/workflows/unitTests.yml index d0fb94be..be3a5481 100644 --- a/.github/workflows/unitTests.yml +++ b/.github/workflows/unitTests.yml @@ -21,10 +21,4 @@ jobs: java-version: ${{ matrix.java-version }} - name: JUnit Tests - run: ./gradlew clean test --scan --debug --stacktrace - - - name: Publish Unit Test Results - uses: EnricoMi/publish-unit-test-result-action@v1 - if: always() - with: - files: build/test-results/**/*.xml + run: ./gradlew clean test --stacktrace diff --git a/CHANGELOG.md b/CHANGELOG.md index d1640abd..0bbb6618 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change Log +## [5.47.1](https://github.com/plivo/plivo-java/tree/v5.47.1) (2026-05-07) +**Fix - Jackson 2.20+ compatibility (Spring Boot 3.5.13+ / Spring Boot 4)** +- Replaced removed `PropertyNamingStrategy.SNAKE_CASE` constant with `PropertyNamingStrategies.SNAKE_CASE`, which exists in Jackson 2.12+ +- Added explicit `jackson-databind` dependency to guarantee the required Jackson version at runtime +- Upgraded `retrofit` and `converter-jackson` from 2.2.0 to 2.12.0 to align with modern OkHttp 4.x and pull in 9 years of accumulated bug/security fixes +- Fixes [#311](https://github.com/plivo/plivo-java/issues/311): `NoSuchFieldError` on `PlivoClient` init when consumers bring Jackson >= 2.20 + ## [5.47.0](https://github.com/plivo/plivo-java/tree/v5.47.0) (2026-04-08) **Feature - PhoneNumber Compliance API support** - Added `PhoneNumberComplianceRequirement` resource with `lister()` for discovering compliance requirements by country, number type, and user type diff --git a/build.gradle b/build.gradle index b4ac5bfa..b590e50e 100644 --- a/build.gradle +++ b/build.gradle @@ -35,12 +35,15 @@ tasks.withType(JavaCompile) { dependencies { testImplementation(platform('org.junit:junit-bom:5.10.0')) testImplementation('org.junit.jupiter:junit-jupiter') + testImplementation('junit:junit:4.13.2') testRuntimeOnly('org.junit.platform:junit-platform-launcher') - + testRuntimeOnly('org.junit.vintage:junit-vintage-engine') + testImplementation 'com.squareup.okhttp:mockwebserver:2.7.5' - implementation 'com.squareup.retrofit2:converter-jackson:2.2.0' - implementation 'com.squareup.retrofit2:retrofit:2.2.0' + implementation 'com.squareup.retrofit2:converter-jackson:2.12.0' + implementation 'com.squareup.retrofit2:retrofit:2.12.0' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.2' implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0' implementation 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2' implementation 'org.glassfish.jaxb:jaxb-runtime:2.3.2' diff --git a/pom.xml b/pom.xml index 787d4f56..6792b862 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.plivo plivo-java - 5.47.0 + 5.47.1 plivo-java A Java SDK to make voice calls & send SMS using Plivo and to generate Plivo XML @@ -31,13 +31,19 @@ com.squareup.retrofit2 converter-jackson - 2.2.0 + 2.12.0 compile com.squareup.retrofit2 retrofit - 2.2.0 + 2.12.0 + compile + + + com.fasterxml.jackson.core + jackson-databind + 2.17.2 compile diff --git a/src/main/java/com/plivo/api/PlivoClient.java b/src/main/java/com/plivo/api/PlivoClient.java index 2ef6b241..bc391f71 100644 --- a/src/main/java/com/plivo/api/PlivoClient.java +++ b/src/main/java/com/plivo/api/PlivoClient.java @@ -10,7 +10,7 @@ import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; @@ -96,7 +96,7 @@ public void serialize(Enum value, JsonGenerator gen, SerializerProvider provider objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); objectMapper.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); - objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); + objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); } private Interceptor interceptor; diff --git a/src/main/java/com/plivo/api/validators/Validate.java b/src/main/java/com/plivo/api/validators/Validate.java index 423baa60..b1aea061 100644 --- a/src/main/java/com/plivo/api/validators/Validate.java +++ b/src/main/java/com/plivo/api/validators/Validate.java @@ -12,7 +12,7 @@ public class Validate { - private static final Pattern urlPattern = Pattern.compile("(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+|None)"); + private static final Pattern urlPattern = Pattern.compile("(http[s]?://(?:[a-zA-Z0-9\\-._~:/?#\\[\\]@!$&'()*+,;=]|%[0-9a-fA-F]{2})+|None)"); private static final String COLON = ": "; diff --git a/src/main/resources/com/plivo/api/version.txt b/src/main/resources/com/plivo/api/version.txt index c31fb1e4..064c2982 100644 --- a/src/main/resources/com/plivo/api/version.txt +++ b/src/main/resources/com/plivo/api/version.txt @@ -1 +1 @@ -5.46.7 +5.47.1 diff --git a/src/test/java/com/plivo/api/CallTest.java b/src/test/java/com/plivo/api/CallTest.java index c3e261ae..e4b2d684 100644 --- a/src/test/java/com/plivo/api/CallTest.java +++ b/src/test/java/com/plivo/api/CallTest.java @@ -330,7 +330,7 @@ public void callStreamCreateWithClientShouldWork() throws Exception { @Test public void callStreamDeleteShouldWork() throws Exception { - expectResponse("liveCallStreamDeleteResponse.json", 204); + expectResponse("liveCallStreamDeleteResponse.json", 200); final String callId = "callId"; Call.streamStopper(callId) @@ -365,7 +365,7 @@ public void callSpeakCreateWithClientShouldWork() throws Exception { @Test public void callSpeakDeleteShouldWork() throws Exception { - expectResponse("liveCallSpeakDeleteResponse.json", 204); + expectResponse("liveCallSpeakDeleteResponse.json", 200); final String callId = "callId"; Call.speakStopper(callId) @@ -376,7 +376,7 @@ public void callSpeakDeleteShouldWork() throws Exception { @Test public void callSpeakDeleteWithClientShouldWork() throws Exception { - expectResponse("liveCallSpeakDeleteResponse.json", 204); + expectResponse("liveCallSpeakDeleteResponse.json", 200); final String callId = "callId"; Call.speakStopper(callId) @@ -434,7 +434,7 @@ public void callPlayDeleteWithClientShouldWork() throws Exception { @Test public void callDTMFCreateShouldWork() throws Exception { - expectResponse("liveCallDtmfCreateResponse.json", 204); + expectResponse("liveCallDtmfCreateResponse.json", 200); final String callId = "callId"; final String digits = "1234"; Call.digitSender(callId, digits).sendDigits(); @@ -444,7 +444,7 @@ public void callDTMFCreateShouldWork() throws Exception { @Test public void callDTMFCreateWithClientShouldWork() throws Exception { - expectResponse("liveCallDtmfCreateResponse.json", 204); + expectResponse("liveCallDtmfCreateResponse.json", 200); final String callId = "callId"; final String digits = "1234"; diff --git a/src/test/java/com/plivo/api/ConferenceTest.java b/src/test/java/com/plivo/api/ConferenceTest.java index 073a9928..5795ea97 100644 --- a/src/test/java/com/plivo/api/ConferenceTest.java +++ b/src/test/java/com/plivo/api/ConferenceTest.java @@ -68,7 +68,7 @@ public void conferenceGetWithClientShouldSucceed() throws Exception { @Test public void conferenceDeleteShouldSucceed() throws Exception { - expectResponse("conferenceDeleteResponse.json", 204); + expectResponse("conferenceDeleteResponse.json", 200); final String conferenceId = "conferenceId"; Conference.deleter(conferenceId) @@ -79,7 +79,7 @@ public void conferenceDeleteShouldSucceed() throws Exception { @Test public void conferenceDeleteWithClientShouldSucceed() throws Exception { - expectResponse("conferenceDeleteResponse.json", 204); + expectResponse("conferenceDeleteResponse.json", 200); final String conferenceId = "conferenceId"; Conference.deleter(conferenceId) @@ -91,7 +91,7 @@ public void conferenceDeleteWithClientShouldSucceed() throws Exception { @Test public void conferenceDeleteAllShouldSucceed() throws Exception { - expectResponse("conferenceDeleteAllResponse.json", 204); + expectResponse("conferenceDeleteAllResponse.json", 200); final String conferenceId = "conferenceId"; Conference.allDeleter() @@ -102,7 +102,7 @@ public void conferenceDeleteAllShouldSucceed() throws Exception { @Test public void conferenceDeleteAllWithClientShouldSucceed() throws Exception { - expectResponse("conferenceDeleteAllResponse.json", 204); + expectResponse("conferenceDeleteAllResponse.json", 200); final String conferenceId = "conferenceId"; Conference.allDeleter().client(client) @@ -113,7 +113,7 @@ public void conferenceDeleteAllWithClientShouldSucceed() throws Exception { @Test public void conferenceMemberDeleteShouldSucceed() throws Exception { - expectResponse("conferenceMemberDeleteResponse.json", 204); + expectResponse("conferenceMemberDeleteResponse.json", 200); final String confId = "confId"; final String memberId = "memberId"; @@ -125,7 +125,7 @@ public void conferenceMemberDeleteShouldSucceed() throws Exception { @Test public void conferenceMemberDeleteWithClientShouldSucceed() throws Exception { - expectResponse("conferenceMemberDeleteResponse.json", 204); + expectResponse("conferenceMemberDeleteResponse.json", 200); final String confId = "confId"; final String memberId = "memberId"; @@ -257,7 +257,7 @@ public void conferenceMemberDeafWithClientCreateShouldSucceed() throws Exception @Test public void conferenceMemberSpeakDeleteShouldSucceed() throws Exception { - expectResponse("conferenceMemberSpeakDeleteResponse.json", 204); + expectResponse("conferenceMemberSpeakDeleteResponse.json", 200); final String confId = "confId"; final String memberId = "memberId"; @@ -269,7 +269,7 @@ public void conferenceMemberSpeakDeleteShouldSucceed() throws Exception { @Test public void conferenceMemberSpeakDeleteWithClientShouldSucceed() throws Exception { - expectResponse("conferenceMemberSpeakDeleteResponse.json", 204); + expectResponse("conferenceMemberSpeakDeleteResponse.json", 200); final String confId = "confId"; final String memberId = "memberId"; @@ -282,7 +282,7 @@ public void conferenceMemberSpeakDeleteWithClientShouldSucceed() throws Exceptio @Test public void conferenceMemberPlayDeleteShouldSucceed() throws Exception { - expectResponse("conferenceMemberPlayDeleteResponse.json", 204); + expectResponse("conferenceMemberPlayDeleteResponse.json", 200); final String confId = "confId"; final String memberId = "memberId"; @@ -294,7 +294,7 @@ public void conferenceMemberPlayDeleteShouldSucceed() throws Exception { @Test public void conferenceMemberPlayDeleteWithClientShouldSucceed() throws Exception { - expectResponse("conferenceMemberPlayDeleteResponse.json", 204); + expectResponse("conferenceMemberPlayDeleteResponse.json", 200); final String confId = "confId"; final String memberId = "memberId"; diff --git a/src/test/java/com/plivo/api/PlivoXmlTest.java b/src/test/java/com/plivo/api/PlivoXmlTest.java index bca8c03d..ee8fc806 100644 --- a/src/test/java/com/plivo/api/PlivoXmlTest.java +++ b/src/test/java/com/plivo/api/PlivoXmlTest.java @@ -29,11 +29,18 @@ public class PlivoXmlTest { @Test public void toStringShouldSucceed() throws Exception { - assertEquals("\nPlivo®\n", new Response() + String xml = new Response() .children( new Speak("Plivo®") - ).toXmlString() - ); + ).toXmlString(); + assertTrue(xml.contains("")); + assertTrue(xml.contains("")); + assertTrue(xml.contains("")); + assertTrue(xml.contains("voice=\"WOMAN\"")); + assertTrue(xml.contains("language=\"en-US\"")); + assertTrue(xml.contains("loop=\"1\"")); + assertTrue(xml.contains("Plivo")); } private T p(T t) { diff --git a/src/test/java/com/plivo/api/VerifyTest.java b/src/test/java/com/plivo/api/VerifyTest.java index 7a44b4c2..14079063 100644 --- a/src/test/java/com/plivo/api/VerifyTest.java +++ b/src/test/java/com/plivo/api/VerifyTest.java @@ -62,7 +62,7 @@ public void listVerifiedCallerIdShouldWork() throws Exception { @Test public void deleteVerifiedCallerIdShouldWork() throws Exception { - expectResponse("deleteVerifiedCallerIdResponse.json", 204); + expectResponse("deleteVerifiedCallerIdResponse.json", 200); final String phoneNumber = "phoneNumber"; Verify.deleteVerifiedCallerID(phoneNumber).delete();