diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 00ecbb54..14bd7863 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -7,11 +7,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v6
- name: Set up Maven Central Repository
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v5
with:
- java-version: 20
+ java-version: 21
+ distribution: temurin
server-id: ossrh
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index bd876e2f..1f0883ed 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -6,13 +6,14 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v6
with:
fetch-depth: 0
- - name: Set up JDK 20
- uses: actions/setup-java@v1
+ - name: Set up JDK 21
+ uses: actions/setup-java@v5
with:
- java-version: 20
+ java-version: 21
+ distribution: temurin
- name: Build and analyze
run: mvn -B verify -DskipTests=true -Dgpg.skip -Dmaven.javadoc.skip=true org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Pcoverage
env:
diff --git a/.github/workflows/publish_on_release.yml b/.github/workflows/publish_on_release.yml
index 01e13410..aa165f4b 100644
--- a/.github/workflows/publish_on_release.yml
+++ b/.github/workflows/publish_on_release.yml
@@ -8,11 +8,12 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v6
- name: Set up Maven Central Repository
- uses: actions/setup-java@v1
+ uses: actions/setup-java@v5
with:
- java-version: 20
+ java-version: 21
+ distribution: temurin
server-id: ossrh
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
diff --git a/pom.xml b/pom.xml
index 45c40d16..c6fac3bf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,9 +74,9 @@
1.15
1.7.35
4.5.13
- 2.13.3
+ 3.0.3
1.79
- 1.18.22
+ 1.18.42
3.2.3-RELEASE
@@ -161,18 +161,8 @@
provided
- com.fasterxml.jackson.datatype
- jackson-datatype-jdk8
- ${jackson.version}
-
-
- com.fasterxml.jackson.core
- jackson-annotations
- ${jackson.version}
-
-
- com.fasterxml.jackson.datatype
- jackson-datatype-jsr310
+ tools.jackson.core
+ jackson-databind
${jackson.version}
diff --git a/src/main/java/com/ibanity/apis/client/http/impl/IbanityHttpClientImpl.java b/src/main/java/com/ibanity/apis/client/http/impl/IbanityHttpClientImpl.java
index c1d5184c..60808a3e 100644
--- a/src/main/java/com/ibanity/apis/client/http/impl/IbanityHttpClientImpl.java
+++ b/src/main/java/com/ibanity/apis/client/http/impl/IbanityHttpClientImpl.java
@@ -1,6 +1,5 @@
package com.ibanity.apis.client.http.impl;
-import com.fasterxml.jackson.core.JsonProcessingException;
import com.ibanity.apis.client.http.IbanityHttpClient;
import com.ibanity.apis.client.http.handler.IbanityResponseHandler;
import lombok.NonNull;
@@ -11,6 +10,7 @@
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
+import tools.jackson.core.JacksonException;
import javax.net.ssl.SSLContext;
import java.io.IOException;
@@ -72,7 +72,7 @@ public HttpResponse post(@NonNull URI path, @NonNull Object requestApiModel, @No
HttpPost httpPost = new HttpPost(path);
httpPost.setEntity(createEntityRequest(objectMapper().writeValueAsString(requestApiModel)));
return execute(additionalHeaders, customerAccessToken, httpPost);
- } catch (JsonProcessingException exception) {
+ } catch (JacksonException exception) {
throw new RuntimeException("An error occurred while converting object to json", exception);
}
}
@@ -109,7 +109,7 @@ public HttpResponse patch(@NonNull URI path, @NonNull Object requestApiModel, @N
HttpPatch httpPatch = new HttpPatch(path);
httpPatch.setEntity(createEntityRequest(objectMapper().writeValueAsString(requestApiModel)));
return execute(additionalHeaders, customerAccessToken, httpPatch);
- } catch (JsonProcessingException exception) {
+ } catch (JacksonException exception) {
throw new RuntimeException("An error occurred while converting object to json", exception);
}
}
diff --git a/src/main/java/com/ibanity/apis/client/mappers/IbanityErrorMapper.java b/src/main/java/com/ibanity/apis/client/mappers/IbanityErrorMapper.java
index 6adcd6dc..5fb60401 100644
--- a/src/main/java/com/ibanity/apis/client/mappers/IbanityErrorMapper.java
+++ b/src/main/java/com/ibanity/apis/client/mappers/IbanityErrorMapper.java
@@ -1,12 +1,12 @@
package com.ibanity.apis.client.mappers;
-import com.fasterxml.jackson.core.JsonProcessingException;
import com.ibanity.apis.client.jsonapi.FinancialInstitutionResponseApiModel;
import com.ibanity.apis.client.jsonapi.IbanityErrorApiModel;
import com.ibanity.apis.client.jsonapi.OAuth2ErrorResourceApiModel;
import com.ibanity.apis.client.models.ErrorMeta;
import com.ibanity.apis.client.models.FinancialInstitutionResponse;
import com.ibanity.apis.client.models.IbanityError;
+import tools.jackson.core.JacksonException;
import static com.ibanity.apis.client.utils.IbanityUtils.objectMapper;
@@ -47,7 +47,7 @@ private static String parseBody(FinancialInstitutionResponseApiModel financialIn
} else {
try {
return objectMapper().writeValueAsString(body);
- } catch (JsonProcessingException e) {
+ } catch (JacksonException e) {
throw new RuntimeException("Invalid payload", e);
}
}
diff --git a/src/main/java/com/ibanity/apis/client/mappers/IbanityWebhookEventMapper.java b/src/main/java/com/ibanity/apis/client/mappers/IbanityWebhookEventMapper.java
index 465cdb56..1b450152 100644
--- a/src/main/java/com/ibanity/apis/client/mappers/IbanityWebhookEventMapper.java
+++ b/src/main/java/com/ibanity/apis/client/mappers/IbanityWebhookEventMapper.java
@@ -4,8 +4,8 @@
import com.ibanity.apis.client.jsonapi.ResourceApiModel;
import com.ibanity.apis.client.models.IbanityWebhookEvent;
import com.ibanity.apis.client.utils.IbanityUtils;
+import tools.jackson.core.JacksonException;
-import java.io.IOException;
import java.util.function.Function;
import static java.lang.String.format;
@@ -17,7 +17,7 @@ public static T mapWebhookResource(String payloa
try {
DataApiModel dataApiModel = IbanityUtils.objectMapper().readValue(payload, ResourceApiModel.class).getData();
return customMapping.apply(dataApiModel);
- } catch (IOException exception) {
+ } catch (JacksonException exception) {
throw new IllegalArgumentException("Response cannot be parsed", exception);
}
}
diff --git a/src/main/java/com/ibanity/apis/client/products/ponto_connect/services/impl/UsageServiceImpl.java b/src/main/java/com/ibanity/apis/client/products/ponto_connect/services/impl/UsageServiceImpl.java
index 823280dd..2bc3b752 100644
--- a/src/main/java/com/ibanity/apis/client/products/ponto_connect/services/impl/UsageServiceImpl.java
+++ b/src/main/java/com/ibanity/apis/client/products/ponto_connect/services/impl/UsageServiceImpl.java
@@ -1,6 +1,6 @@
package com.ibanity.apis.client.products.ponto_connect.services.impl;
-import com.fasterxml.jackson.databind.JsonNode;
+import tools.jackson.databind.JsonNode;
import com.ibanity.apis.client.http.IbanityHttpClient;
import com.ibanity.apis.client.models.IbanityProduct;
import com.ibanity.apis.client.products.ponto_connect.models.OrganizationUsage;
@@ -44,7 +44,7 @@ public OrganizationUsage getOrganizationUsage(OrganizationUsageReadQuery readQue
private OrganizationUsage map(JsonNode dataApiModel) {
return OrganizationUsage.builder()
- .id(dataApiModel.get("data").get("id").textValue())
+ .id(dataApiModel.get("data").get("id").asString())
.paymentCount(new BigDecimal(dataApiModel.get("data").get("attributes").get("paymentCount").toString()))
.accountCount(new BigDecimal(dataApiModel.get("data").get("attributes").get("accountCount").toString()))
.paymentAccountCount(new BigDecimal(dataApiModel.get("data").get("attributes").get("paymentAccountCount").toString()))
diff --git a/src/main/java/com/ibanity/apis/client/services/impl/ApiUrlProviderImpl.java b/src/main/java/com/ibanity/apis/client/services/impl/ApiUrlProviderImpl.java
index 7e493f69..cf37360d 100644
--- a/src/main/java/com/ibanity/apis/client/services/impl/ApiUrlProviderImpl.java
+++ b/src/main/java/com/ibanity/apis/client/services/impl/ApiUrlProviderImpl.java
@@ -1,6 +1,6 @@
package com.ibanity.apis.client.services.impl;
-import com.fasterxml.jackson.databind.JsonNode;
+import tools.jackson.databind.JsonNode;
import com.ibanity.apis.client.http.IbanityHttpClient;
import com.ibanity.apis.client.models.IbanityProduct;
import com.ibanity.apis.client.services.ApiUrlProvider;
@@ -59,7 +59,7 @@ public String find(String rootPath, String[] subPaths) {
return Stream.of(subPaths)
.reduce(apiUrls, JsonNode::get, (jsonNode1, jsonNode2) -> jsonNode2)
- .textValue();
+ .asString();
} catch (Exception exception) {
throw new IllegalArgumentException("Url cannot be found", exception);
}
diff --git a/src/main/java/com/ibanity/apis/client/utils/IbanityUtils.java b/src/main/java/com/ibanity/apis/client/utils/IbanityUtils.java
index 908e3376..2c45084c 100644
--- a/src/main/java/com/ibanity/apis/client/utils/IbanityUtils.java
+++ b/src/main/java/com/ibanity/apis/client/utils/IbanityUtils.java
@@ -1,11 +1,6 @@
package com.ibanity.apis.client.utils;
import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
-import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.ibanity.apis.client.builders.IbanityConfiguration;
import com.ibanity.apis.client.http.interceptor.IbanitySignatureInterceptor;
import com.ibanity.apis.client.http.interceptor.IdempotencyInterceptor;
@@ -17,6 +12,9 @@
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.DefaultClientConnectionReuseStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
+import tools.jackson.databind.DeserializationFeature;
+import tools.jackson.databind.ObjectMapper;
+import tools.jackson.databind.json.JsonMapper;
import javax.net.ssl.*;
import java.io.IOException;
@@ -35,6 +33,12 @@ public final class IbanityUtils {
private static final String CA_TRUST_STORE_KEY = "ibanity-ca";
private static final String TLS_PROTOCOL = "TLS";
+ public static final ObjectMapper OBJECT_MAPPER = JsonMapper.builder()
+ .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ .changeDefaultPropertyInclusion(incl -> incl.withValueInclusion(JsonInclude.Include.NON_NULL))
+ .changeDefaultPropertyInclusion(incl -> incl.withContentInclusion(JsonInclude.Include.NON_NULL))
+ .build();
+
private IbanityUtils() {
}
@@ -75,12 +79,7 @@ public static HttpClient httpClient(IbanityConfiguration configuration) {
}
public static ObjectMapper objectMapper() {
- return new ObjectMapper()
- .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
- .registerModule(new Jdk8Module())
- .registerModule(new JavaTimeModule())
- .setSerializationInclusion(JsonInclude.Include.NON_NULL)
- .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ return OBJECT_MAPPER;
}
private static void configureHttpClient(SSLContext sslContext,
diff --git a/src/main/java/com/ibanity/apis/client/webhooks/services/impl/WebhooksServiceImpl.java b/src/main/java/com/ibanity/apis/client/webhooks/services/impl/WebhooksServiceImpl.java
index 5b56e42a..3618b2cf 100644
--- a/src/main/java/com/ibanity/apis/client/webhooks/services/impl/WebhooksServiceImpl.java
+++ b/src/main/java/com/ibanity/apis/client/webhooks/services/impl/WebhooksServiceImpl.java
@@ -1,7 +1,7 @@
package com.ibanity.apis.client.webhooks.services.impl;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
+import tools.jackson.core.JacksonException;
+import tools.jackson.databind.JsonNode;
import com.ibanity.apis.client.exceptions.IbanityRuntimeException;
import com.ibanity.apis.client.http.IbanityHttpClient;
import com.ibanity.apis.client.models.IbanityWebhookEvent;
@@ -32,9 +32,9 @@ public IbanityWebhookEvent verifyAndParseEvent(String payload, String jwt) {
verify(payload, jwt);
try {
JsonNode jsonNode = IbanityUtils.objectMapper().readTree(payload);
- String type = jsonNode.get("data").get("type").textValue();
+ String type = jsonNode.get("data").get("type").asString();
return WebhooksUtils.webhookEventParser(payload, type);
- } catch (JsonProcessingException exception) {
+ } catch (JacksonException exception) {
throw new IllegalArgumentException("Response cannot be parsed", exception);
}
}
diff --git a/src/test/java/com/ibanity/apis/client/utils/IbanityUtilsTest.java b/src/test/java/com/ibanity/apis/client/utils/IbanityUtilsTest.java
new file mode 100644
index 00000000..c0693e82
--- /dev/null
+++ b/src/test/java/com/ibanity/apis/client/utils/IbanityUtilsTest.java
@@ -0,0 +1,88 @@
+package com.ibanity.apis.client.utils;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.junit.jupiter.api.Test;
+import tools.jackson.databind.ObjectMapper;
+
+import java.time.Instant;
+import java.util.Date;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class IbanityUtilsTest {
+
+ @Test
+ void objectMapper_shouldDeserializeJsonWithUnknownProperties() {
+ ObjectMapper objectMapper = IbanityUtils.objectMapper();
+
+ String jsonWithUnknownProperty = "{\"name\":\"John\",\"unknownField\":\"value\",\"anotherUnknown\":123}";
+
+ TestPerson person = objectMapper.readValue(jsonWithUnknownProperty, TestPerson.class);
+
+ assertThat(person.getName()).isEqualTo("John");
+ }
+
+ @Test
+ void objectMapper_shouldExcludeNullPropertiesFromSerialization() {
+ ObjectMapper objectMapper = IbanityUtils.objectMapper();
+
+ TestPerson person = TestPerson.builder()
+ .name("John")
+ .email(null)
+ .build();
+
+ String json = objectMapper.writeValueAsString(person);
+
+ assertThat(json).isEqualTo("{\"name\":\"John\"}");
+ }
+
+ @Test
+ void objectMapper_shouldWriteDateAsTimestamp() {
+ ObjectMapper objectMapper = IbanityUtils.objectMapper();
+
+ Instant instant = Instant.parse("2023-01-15T10:30:00.000Z");
+ Date date = Date.from(instant);
+
+ TestWithDate testObject = TestWithDate.builder()
+ .id("123")
+ .createdAt(instant)
+ .updatedAt(date)
+ .build();
+
+ String json = objectMapper.writeValueAsString(testObject);
+ assertThat(json).isEqualTo("{\"createdAt\":\"2023-01-15T10:30:00Z\",\"id\":\"123\",\"updatedAt\":\"2023-01-15T10:30:00.000Z\"}");
+ }
+
+ @Test
+ void objectMapper_shouldHandleEmptyObjectSerialization() {
+ ObjectMapper objectMapper = IbanityUtils.objectMapper();
+
+ TestPerson person = TestPerson.builder().build();
+
+ String json = objectMapper.writeValueAsString(person);
+
+ assertThat(json).isEqualTo("{}");
+ }
+
+ @Data
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ static class TestPerson {
+ private String name;
+ private String email;
+ }
+
+ @Data
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ static class TestWithDate {
+ private String id;
+ private Instant createdAt;
+ private Date updatedAt;
+ }
+}