Skip to content

Commit c83394f

Browse files
authored
[BAEL-7021] Add Sample Code (#18699)
* [BAEL-7021] Add Sample Code * [BAEL-7021] Rename Test * [BAEL-7021] Update tests * [BAEL-7021] Fixes concurrency * [BAEL-7021] Fixes concurrency
1 parent 8b9d90e commit c83394f

File tree

4 files changed

+171
-0
lines changed

4 files changed

+171
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.baeldung.jackson.staticobjectmapper;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
5+
public class JsonUtils {
6+
public static final ObjectMapper MAPPER = new ObjectMapper();
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.baeldung.jackson.staticobjectmapper;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
5+
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
6+
import org.junit.jupiter.api.Test;
7+
8+
import java.text.SimpleDateFormat;
9+
import java.time.LocalDate;
10+
import java.time.ZoneId;
11+
import java.time.ZoneOffset;
12+
import java.util.Collections;
13+
import java.util.Date;
14+
import java.util.Map;
15+
16+
import static org.junit.jupiter.api.Assertions.assertEquals;
17+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
18+
19+
class ConflictingRequirementsUnitTest {
20+
21+
private static final ObjectMapper GLOBAL_MAPPER = new ObjectMapper();
22+
23+
@Test
24+
void whenSwitchingDateFormatGlobally_thenEndpointsCollide() throws Exception {
25+
SimpleDateFormat iso = new SimpleDateFormat("yyyy-MM-dd");
26+
GLOBAL_MAPPER.setDateFormat(iso);
27+
28+
Map<String, Date> payload = Collections.singletonMap(
29+
"dob",
30+
Date.from(LocalDate.of(1990, 10, 5)
31+
.atTime(12, 0)
32+
.toInstant(ZoneOffset.UTC)));
33+
34+
String forA = GLOBAL_MAPPER.writeValueAsString(payload);
35+
assertEquals("{\"dob\":\"1990-10-05\"}", forA);
36+
37+
SimpleDateFormat european = new SimpleDateFormat("dd/MM/yyyy");
38+
GLOBAL_MAPPER.setDateFormat(european);
39+
40+
String forB = GLOBAL_MAPPER.writeValueAsString(payload);
41+
assertEquals("{\"dob\":\"05/10/1990\"}", forB);
42+
43+
String nowBrokenForA = GLOBAL_MAPPER.writeValueAsString(payload);
44+
assertNotEquals(forA, nowBrokenForA);
45+
}
46+
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.baeldung.jackson.staticobjectmapper;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
5+
import org.junit.jupiter.api.Order;
6+
import org.junit.jupiter.api.Test;
7+
8+
import java.text.SimpleDateFormat;
9+
import java.time.LocalDate;
10+
import java.time.ZoneOffset;
11+
import java.util.Collections;
12+
import java.util.Date;
13+
import java.util.Map;
14+
15+
import static org.junit.jupiter.api.Assertions.assertEquals;
16+
import static org.junit.jupiter.api.Assertions.assertNotEquals;
17+
18+
class HiddenCouplingUnitTest {
19+
20+
private static final ObjectMapper GLOBAL_MAPPER = new ObjectMapper();
21+
22+
@Test
23+
@Order(1)
24+
void givenCustomDateFormat_whenConfiguredFirst_thenPasses() throws Exception {
25+
GLOBAL_MAPPER.setDateFormat(new SimpleDateFormat("dd-MM-yyyy"));
26+
Map<String, Date> payload = Collections.singletonMap("date", Date.from(LocalDate.of(1998, 2, 9).atTime(12, 0).toInstant(ZoneOffset.UTC)));
27+
String json = GLOBAL_MAPPER.writeValueAsString(payload);
28+
assertEquals("{\"date\":\"09-02-1998\"}", json);
29+
}
30+
31+
@Test
32+
@Order(2)
33+
void givenDefaultDateFormat_whenRunAfterMutation_thenFails() throws Exception {
34+
Map<String, Date> payload = Collections.singletonMap("date", Date.from(LocalDate.of(1998, 2, 9).atTime(12, 0).toInstant(ZoneOffset.UTC)));
35+
String json = GLOBAL_MAPPER.writeValueAsString(payload);
36+
assertNotEquals("{\"date\":887025600000}", json);
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.baeldung.jackson.staticobjectmapper;
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.fasterxml.jackson.databind.SerializationFeature;
5+
import org.junit.jupiter.api.AfterAll;
6+
import org.junit.jupiter.api.BeforeEach;
7+
import org.junit.jupiter.api.Test;
8+
9+
import java.text.SimpleDateFormat;
10+
import java.time.LocalDate;
11+
import java.time.ZoneOffset;
12+
import java.util.Date;
13+
import java.util.Map;
14+
import java.util.concurrent.Callable;
15+
import java.util.concurrent.ExecutorService;
16+
import java.util.concurrent.Executors;
17+
import java.util.concurrent.Future;
18+
19+
import static java.util.Collections.singletonMap;
20+
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
22+
23+
class ObjectMapperThreadSafetyUnitTest {
24+
25+
private ObjectMapper GLOBAL_MAPPER = new ObjectMapper();
26+
27+
/**
28+
* two real threads, created once and reused for every repetition
29+
*/
30+
private static final ExecutorService POOL = Executors.newFixedThreadPool(2);
31+
32+
@Test
33+
void whenRegisteringDateFormatGlobally_thenAffectsAllConsumers() throws Exception {
34+
Map<String, Date> payload = singletonMap("today", Date.from(LocalDate.of(1998, 2, 9).atTime(12, 0).toInstant(ZoneOffset.UTC)));
35+
36+
String before = GLOBAL_MAPPER.writeValueAsString(payload);
37+
assertEquals("{\"today\":887025600000}", before);
38+
39+
GLOBAL_MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
40+
41+
String after = GLOBAL_MAPPER.writeValueAsString(payload);
42+
assertEquals("{\"today\":\"1998-02-09\"}", after);
43+
}
44+
45+
@Test
46+
void whenSimpleDateFormatChanges_thenConflictHappens() throws Exception {
47+
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
48+
GLOBAL_MAPPER.setDateFormat(format);
49+
50+
Callable<String> task = () -> GLOBAL_MAPPER.writeValueAsString(singletonMap("key", Date.from(LocalDate.of(1998, 2, 9).atTime(12, 0).toInstant(ZoneOffset.UTC))));
51+
Callable<Void> mutator = () -> {
52+
format.applyPattern("dd-MM-yyyy");
53+
return null;
54+
};
55+
56+
Future<String> taskResult1 = POOL.submit(task);
57+
assertEquals("{\"key\":\"1998-02-09\"}", taskResult1.get());
58+
POOL.submit(mutator).get();
59+
Future<String> taskResult2 = POOL.submit(task);
60+
assertEquals("{\"key\":\"09-02-1998\"}", taskResult2.get());
61+
}
62+
63+
@Test
64+
void whenUsingCopyScopedMapper_thenNoInterference() throws Exception {
65+
ObjectMapper localCopy = GLOBAL_MAPPER.copy().enable(SerializationFeature.INDENT_OUTPUT);
66+
assertEquals("{\n \"key\" : \"value\"\n}", localCopy.writeValueAsString(singletonMap("key", "value")));
67+
assertEquals("{\"key\":\"value\"}", GLOBAL_MAPPER.writeValueAsString(singletonMap("key", "value")));
68+
}
69+
70+
@BeforeEach
71+
void setup() {
72+
GLOBAL_MAPPER = new ObjectMapper();
73+
}
74+
75+
@AfterAll
76+
static void shutdownPool() {
77+
POOL.shutdownNow();
78+
}
79+
}

0 commit comments

Comments
 (0)