Skip to content

Commit dce6d18

Browse files
authored
Merge pull request #329 from recurly/remove-dependencies
chore: Remove external dependencies and upgrade to Java standard library APIs
2 parents b0eadea + 9df7e5b commit dce6d18

12 files changed

Lines changed: 113 additions & 89 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
name: Java ${{ matrix.java }} tests
1010
strategy:
1111
matrix:
12-
java: [8, 11, 16, 17]
12+
java: [8, 11, 16, 17, 18, 19, 20, 21]
1313
steps:
1414
- uses: actions/checkout@v6.0.3
1515
- name: Setup java

pom.xml

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@
6262
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
6363
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
6464
<okhttp3.version>4.12.0</okhttp3.version>
65-
<surefire.version>3.0.0-M4</surefire.version>
66-
<jacoco.version>0.8.12</jacoco.version>
65+
<surefire.version>3.5.5</surefire.version>
66+
<jacoco.version>0.8.13</jacoco.version>
6767
</properties>
6868

6969
<build>
@@ -84,7 +84,7 @@
8484
<plugin>
8585
<groupId>org.apache.maven.plugins</groupId>
8686
<artifactId>maven-compiler-plugin</artifactId>
87-
<version>3.8.1</version>
87+
<version>3.15.0</version>
8888
<configuration>
8989
<source>${java.version}</source>
9090
<target>${java.version}</target>
@@ -155,7 +155,7 @@
155155
<plugin>
156156
<groupId>org.apache.maven.plugins</groupId>
157157
<artifactId>maven-source-plugin</artifactId>
158-
<version>2.2.1</version>
158+
<version>3.4.0</version>
159159
<executions>
160160
<execution>
161161
<id>attach-sources</id>
@@ -168,7 +168,7 @@
168168
<plugin>
169169
<groupId>org.apache.maven.plugins</groupId>
170170
<artifactId>maven-javadoc-plugin</artifactId>
171-
<version>3.1.1</version>
171+
<version>3.12.0</version>
172172
<configuration>
173173
<source>${java.version}</source>
174174
<javadocExecutable>${java.home}/bin/javadoc</javadocExecutable>
@@ -186,7 +186,7 @@
186186
<plugin>
187187
<groupId>org.apache.maven.plugins</groupId>
188188
<artifactId>maven-gpg-plugin</artifactId>
189-
<version>1.5</version>
189+
<version>3.2.8</version>
190190
<executions>
191191
<execution>
192192
<id>sign-artifacts</id>
@@ -206,7 +206,7 @@
206206
<plugin>
207207
<groupId>org.sonatype.central</groupId>
208208
<artifactId>central-publishing-maven-plugin</artifactId>
209-
<version>0.8.0</version>
209+
<version>0.10.0</version>
210210
<extensions>true</extensions>
211211
<configuration>
212212
<publishingServerId>central</publishingServerId>
@@ -216,7 +216,7 @@
216216
<plugin>
217217
<groupId>org.owasp</groupId>
218218
<artifactId>dependency-check-maven</artifactId>
219-
<version>9.1.0</version>
219+
<version>12.1.3</version>
220220
</plugin>
221221
</plugins>
222222
</build>
@@ -225,7 +225,7 @@
225225
<dependency>
226226
<groupId>com.google.code.gson</groupId>
227227
<artifactId>gson</artifactId>
228-
<version>2.8.9</version>
228+
<version>2.13.1</version>
229229
</dependency>
230230
<dependency>
231231
<groupId>com.squareup.okhttp3</groupId>
@@ -243,16 +243,7 @@
243243
<version>${okhttp3.version}</version>
244244
<scope>test</scope>
245245
</dependency>
246-
<dependency>
247-
<groupId>joda-time</groupId>
248-
<artifactId>joda-time</artifactId>
249-
<version>2.10.6</version>
250-
</dependency>
251-
<dependency>
252-
<groupId>com.fatboyindustrial.gson-jodatime-serialisers</groupId>
253-
<artifactId>gson-jodatime-serialisers</artifactId>
254-
<version>1.8.0</version>
255-
</dependency>
246+
256247
<dependency>
257248
<groupId>org.apache.maven.surefire</groupId>
258249
<artifactId>surefire</artifactId>
@@ -263,7 +254,7 @@
263254
<dependency>
264255
<groupId>org.junit.jupiter</groupId>
265256
<artifactId>junit-jupiter-engine</artifactId>
266-
<version>5.6.2</version>
257+
<version>5.12.2</version>
267258
<scope>test</scope>
268259
</dependency>
269260
<dependency>
@@ -276,30 +267,40 @@
276267
<dependency>
277268
<groupId>org.mockito</groupId>
278269
<artifactId>mockito-core</artifactId>
279-
<version>4.4.0</version>
270+
<version>4.11.0</version>
280271
<scope>test</scope>
281272
</dependency>
282273
<dependency>
283274
<groupId>org.mockito</groupId>
284275
<artifactId>mockito-inline</artifactId>
285-
<version>4.4.0</version>
276+
<version>4.11.0</version>
277+
<scope>test</scope>
278+
</dependency>
279+
<!-- Override Byte Buddy to a version that supports Java 21 (65) and above.
280+
Mockito 4.11.0 bundles Byte Buddy 1.12.19 which only supports up to Java 20 (64).
281+
Byte Buddy 1.14.9+ supports Java 21 while remaining compatible with Java 8. -->
282+
<dependency>
283+
<groupId>net.bytebuddy</groupId>
284+
<artifactId>byte-buddy</artifactId>
285+
<version>1.18.8</version>
286286
<scope>test</scope>
287287
</dependency>
288288
<dependency>
289-
<groupId>org.hamcrest</groupId>
290-
<artifactId>hamcrest-library</artifactId>
291-
<version>2.2</version>
289+
<groupId>net.bytebuddy</groupId>
290+
<artifactId>byte-buddy-agent</artifactId>
291+
<version>1.18.8</version>
292292
<scope>test</scope>
293293
</dependency>
294294

295-
<!-- Specify versions of transitive dependencies
296-
plexus:plexus-utils introduced through jacoco-maven-plugin, maven-compiler-plugin, and others
297-
- can be removed when mvn dependency:list shows version 3.0.24 or higher and no snyk reported vulnerabilities
298-
-->
295+
<!-- Override transitive plexus-utils to ensure a CVE-free version.
296+
Pulled in via test-scoped jacoco-maven-plugin and surefire deps.
297+
Scoped to test so it does not appear in consumers' transitive deps.
298+
Can be removed once those deps pull in 4.0.3+ transitively. -->
299299
<dependency>
300300
<groupId>org.codehaus.plexus</groupId>
301301
<artifactId>plexus-utils</artifactId>
302-
<version>3.5.1</version>
302+
<version>4.0.3</version>
303+
<scope>test</scope>
303304
</dependency>
304305
</dependencies>
305306
</project>

scripts/clean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ rm -f src/main/java/com/recurly/v3/Constants.java
66
rm -f src/main/java/com/recurly/v3/requests/*
77
rm -f src/main/java/com/recurly/v3/resources/*
88
rm -f src/main/java/com/recurly/v3/exception/*
9+
rm -f src/main/java/com/recurly/v3/queryparams/*

src/main/java/com/recurly/v3/BaseClient.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
import okhttp3.*;
2323
import okhttp3.Request.Builder;
2424
import okhttp3.logging.HttpLoggingInterceptor;
25-
import org.joda.time.DateTime;
25+
import java.time.ZonedDateTime;
26+
import java.time.format.DateTimeFormatter;
2627

2728
public abstract class BaseClient {
2829
private static final List<String> BINARY_TYPES = Arrays.asList("application/pdf");
@@ -34,25 +35,28 @@ public abstract class BaseClient {
3435
private String apiUrl;
3536

3637
protected BaseClient(final String apiKey) {
37-
this(apiKey, newHttpClient(apiKey), new ClientOptions());
38+
this(apiKey, newHttpClient(validateApiKey(apiKey)), new ClientOptions());
3839
}
3940

4041
protected BaseClient(final String apiKey, final ClientOptions clientOptions) {
41-
this(apiKey, newHttpClient(apiKey), clientOptions);
42+
this(apiKey, newHttpClient(validateApiKey(apiKey)), clientOptions);
4243
}
4344

4445
protected BaseClient(final String apiKey, final OkHttpClient client) {
4546
this(apiKey, client, new ClientOptions());
4647
}
4748

4849
protected BaseClient(final String apiKey, final OkHttpClient client, final ClientOptions clientOptions) {
50+
this.apiKey = validateApiKey(apiKey);
51+
this.client = client;
52+
this.apiUrl = clientOptions.getBaseUrl();
53+
}
54+
55+
private static String validateApiKey(final String apiKey) {
4956
if (apiKey == null || apiKey.isEmpty()) {
5057
throw new IllegalArgumentException("apiKey cannot be null or empty");
5158
}
52-
53-
this.apiKey = apiKey;
54-
this.client = client;
55-
this.apiUrl = clientOptions.getBaseUrl();
59+
return apiKey;
5660
}
5761

5862
private static OkHttpClient newHttpClient(final String apiKey) {
@@ -207,8 +211,8 @@ private okhttp3.Request buildRequest(
207211
continue;
208212
} else if (value instanceof String) {
209213
stringValue = value.toString();
210-
} else if (value instanceof DateTime) {
211-
stringValue = value.toString();
214+
} else if (value instanceof ZonedDateTime) {
215+
stringValue = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format((ZonedDateTime) value);
212216
} else if (value instanceof Integer) {
213217
stringValue = Integer.toString((Integer) value);
214218
} else if (value instanceof Float) {

src/main/java/com/recurly/v3/JsonSerializer.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.recurly.v3;
22

3-
import com.fatboyindustrial.gsonjodatime.Converters;
3+
import java.time.LocalDateTime;
4+
import java.time.ZoneOffset;
5+
import java.time.format.DateTimeFormatter;
6+
import java.time.format.DateTimeParseException;
47
import com.google.gson.*;
58
import com.google.gson.annotations.SerializedName;
69
import com.google.gson.reflect.TypeToken;
@@ -14,22 +17,37 @@
1417
import java.util.HashMap;
1518
import java.util.Map;
1619

17-
import org.joda.time.DateTime;
20+
import java.time.ZonedDateTime;
1821

1922
public class JsonSerializer {
20-
private class DateDeserializer implements JsonDeserializer<DateTime> {
23+
private class DateDeserializer implements JsonDeserializer<ZonedDateTime> {
2124
@Override
22-
public DateTime deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2)
25+
public ZonedDateTime deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2)
2326
throws JsonParseException {
24-
return DateTime.parse(element.getAsString());
27+
String s = element.getAsString();
28+
try {
29+
return ZonedDateTime.parse(s);
30+
} catch (DateTimeParseException e) {
31+
return LocalDateTime.parse(s).atZone(ZoneOffset.UTC);
32+
}
33+
}
34+
}
35+
36+
private class DateSerializer implements com.google.gson.JsonSerializer<ZonedDateTime> {
37+
@Override
38+
public JsonElement serialize(ZonedDateTime src, Type typeOfSrc, JsonSerializationContext context) {
39+
return new JsonPrimitive(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(src));
2540
}
2641
}
2742

28-
private final Gson gsonSerializer = Converters.registerDateTime(new GsonBuilder()).create();
43+
private final Gson gsonSerializer =
44+
new GsonBuilder()
45+
.registerTypeAdapter(ZonedDateTime.class, new DateSerializer())
46+
.create();
2947
private final Gson gsonDeserializer =
3048
new GsonBuilder()
3149
.excludeFieldsWithoutExposeAnnotation()
32-
.registerTypeAdapter(DateTime.class, new DateDeserializer())
50+
.registerTypeAdapter(ZonedDateTime.class, new DateDeserializer())
3351
.registerTypeAdapterFactory(new RecurlyEnumTypeAdapterFactory())
3452
.create();
3553

src/test/java/com/recurly/v3/BaseClientTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
import okhttp3.Response;
2222

2323
import org.apache.commons.io.IOUtils;
24-
import org.joda.time.DateTime;
24+
import java.time.ZonedDateTime;
25+
import java.time.format.DateTimeFormatter;
2526
import org.junit.Assert;
2627
import org.junit.jupiter.api.Test;
2728
import org.mockito.stubbing.Answer;
@@ -132,14 +133,14 @@ public void testMakeRequestWithoutResource() throws IOException {
132133

133134
@Test
134135
public void testMakeRequestWithQueryParams() throws IOException {
135-
DateTime dateTime = new DateTime();
136+
ZonedDateTime dateTime = ZonedDateTime.now();
136137

137138
final Call mCall = mock(Call.class);
138139
Answer answer = (i) -> {
139140
Request request = i.getArgument(0);
140141
HttpUrl url = request.url();
141142
assertEquals("Aaron", url.queryParameter("my_string"));
142-
assertEquals(dateTime.toString(), url.queryParameter("my_date_time"));
143+
assertEquals(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(dateTime), url.queryParameter("my_date_time"));
143144
assertEquals("1", url.queryParameter("my_integer"));
144145
assertEquals("2.3", url.queryParameter("my_float"));
145146
assertEquals("4.5", url.queryParameter("my_double"));

src/test/java/com/recurly/v3/ClientTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package com.recurly.v3;
22

3-
import static org.hamcrest.MatcherAssert.assertThat;
4-
import static org.hamcrest.Matchers.matchesPattern;
53
import static org.junit.jupiter.api.Assertions.assertThrows;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
65

76
import org.junit.jupiter.api.Test;
87

@@ -25,6 +24,6 @@ public void testCantInitializeWithoutApiKey() {
2524

2625
@Test
2726
public void testRespondsWithValidApiVersion() {
28-
assertThat(Client.API_VERSION, matchesPattern("v\\d{4}-\\d{2}-\\d{2}"));
27+
assertTrue(Client.API_VERSION.matches("v\\d{4}-\\d{2}-\\d{2}"));
2928
}
3029
}

src/test/java/com/recurly/v3/JsonSerializerTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import com.recurly.v3.fixtures.MyRequest;
88
import com.recurly.v3.fixtures.MyResource;
99
import com.recurly.v3.Constants;
10-
import org.joda.time.DateTime;
10+
import java.time.ZonedDateTime;
1111
import org.junit.jupiter.api.Test;
1212

1313
public class JsonSerializerTest {
@@ -125,13 +125,13 @@ private static String getDateTimesJson() {
125125
+ "}";
126126
}
127127

128-
private static void checkDateTime(DateTime date) {
129-
assertEquals(DateTime.class, date.getClass());
128+
private static void checkDateTime(ZonedDateTime date) {
129+
assertEquals(ZonedDateTime.class, date.getClass());
130130
assertEquals(2019, date.getYear());
131-
assertEquals(5, date.getMonthOfYear());
131+
assertEquals(5, date.getMonthValue());
132132
assertEquals(31, date.getDayOfMonth());
133-
assertEquals(15, date.getHourOfDay());
134-
assertEquals(31, date.getMinuteOfHour());
135-
assertEquals(24, date.getSecondOfMinute());
133+
assertEquals(15, date.getHour());
134+
assertEquals(31, date.getMinute());
135+
assertEquals(24, date.getSecond());
136136
}
137137
}

0 commit comments

Comments
 (0)