Skip to content

Commit cecb286

Browse files
authored
fix(GH-232): SimpleDateFormat is not threadsafe (#261)
* fix(GH-232): SimpleDateFormat is not threadsafe * fix: add dateCoercionThreadSafe unit test
1 parent 5da68e8 commit cecb286

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

graphql-jpa-query-schema/src/main/java/com/introproventures/graphql/jpa/query/schema/JavaScalars.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,14 +290,14 @@ public LocalTime parseLiteral(Object input) {
290290
}
291291

292292
public static class GraphQLDateCoercing implements Coercing<Object, Object> {
293-
final DateFormat df;
293+
final String dateFormatString;
294294

295295

296296
/**
297297
* Default to pattern 'yyyy-MM-dd'
298298
*/
299299
public GraphQLDateCoercing() {
300-
df = new SimpleDateFormat("yyyy-MM-dd");
300+
dateFormatString = "yyyy-MM-dd";
301301
}
302302

303303
/**
@@ -306,7 +306,7 @@ public GraphQLDateCoercing() {
306306
* @param dateFormatString e.g. "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" for "2001-07-04T12:08:56.235-07:00"
307307
*/
308308
public GraphQLDateCoercing(String dateFormatString) {
309-
df = new SimpleDateFormat(dateFormatString);
309+
this.dateFormatString = dateFormatString;
310310
}
311311

312312
@Override
@@ -340,6 +340,8 @@ public Object parseLiteral(Object input) {
340340
}
341341

342342
private Date parseStringToDate(String input) {
343+
DateFormat df = new SimpleDateFormat(dateFormatString);
344+
343345
try {
344346
return df.parse(input);
345347
} catch (ParseException e) {
@@ -662,7 +664,7 @@ public Object parseValue(Object input) {
662664

663665
@Override
664666
public Object parseLiteral(Object input) {
665-
return parseLiteral((Value<?>) input, Collections.emptyMap());
667+
return parseLiteral(input, Collections.emptyMap());
666668
}
667669

668670
//recursively parse the input into a Map

graphql-jpa-query-schema/src/test/java/com/introproventures/graphql/jpa/query/schema/JavaScalarsTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828
import java.time.ZoneId;
2929
import java.time.ZoneOffset;
3030
import java.time.ZonedDateTime;
31+
import java.util.ArrayList;
32+
import java.util.List;
3133
import java.util.Map;
34+
import java.util.concurrent.CompletableFuture;
35+
import java.util.concurrent.ExecutionException;
3236
import java.util.concurrent.TimeUnit;
3337

3438
import org.junit.Test;
@@ -289,4 +293,29 @@ public void string2Instant() {
289293
assert resultLDT.getMinute() == 15;
290294
assert resultLDT.getSecond() == 07;
291295
}
296+
297+
@Test
298+
public void dateCoercionThreadSafe() throws InterruptedException, ExecutionException {
299+
//given
300+
String dateLiteral = "2018-06-22T10:00:00";
301+
Coercing<?, ?> subject = new JavaScalars.GraphQLDateCoercing();
302+
303+
List<CompletableFuture<Object>> dates = new ArrayList<>();
304+
305+
//when
306+
for(int i = 0; i < 1000; i++) {
307+
CompletableFuture<Object> task = CompletableFuture.supplyAsync(() -> {
308+
return subject.serialize(dateLiteral);
309+
});
310+
dates.add(task);
311+
}
312+
313+
CompletableFuture<Void> result = CompletableFuture.allOf(dates.toArray(new CompletableFuture[] {}));
314+
315+
result.join();
316+
317+
//then
318+
assertThat(result.isCompletedExceptionally()).isFalse();
319+
}
320+
292321
}

0 commit comments

Comments
 (0)