Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file, which loose
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Security
- Upgrade jackson to version 2.15.0 to fix security vulnerabilities:
- **CVE-2022-42003** Detail: https://cwe.mitre.org/data/definitions/502.html
- **CVE-2025-52999** Detail: https://cwe.mitre.org/data/definitions/121.html
- **CVE-2022-42004** Detail: https://cwe.mitre.org/data/definitions/400.html
- **CCVE-2025-49128** Detail: https://cwe.mitre.org/data/definitions/209.html

# [17.103.0] - 2025-07-16
### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Feature {

private final String featureName;
private final boolean enabled;

public Feature(final String featureName, final boolean enabled) {
@JsonCreator
public Feature(@JsonProperty("feature_name") final String featureName, @JsonProperty("enabled") final boolean enabled) {
this.featureName = featureName;
this.enabled = enabled;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class FeatureControl {

private final List<Feature> features;

@JsonCreator
public FeatureControl(final List<Feature> features) {
public FeatureControl(@JsonProperty("feature") final List<Feature> features) {
this.features = features;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ public void shouldCreateStringToJsonObjectConverter() throws Exception {
private void checkSetUpCorrectly(final ObjectMapper objectMapper) {
final Set<String> registeredModuleTypes = getValueOfField(objectMapper, "_registeredModuleTypes", Set.class);

assertThat(registeredModuleTypes, hasItem("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule"));
assertThat(registeredModuleTypes, hasItem("jackson-datatype-jsr310"));
assertThat(registeredModuleTypes, hasItem("com.fasterxml.jackson.datatype.jdk8.Jdk8Module"));
assertThat(registeredModuleTypes, hasItem("com.fasterxml.jackson.module.paramnames.ParameterNamesModule"));
assertThat(registeredModuleTypes, hasItem("uk.gov.justice.services.common.converter.jackson.jsr353.InclusionAwareJSR353Module"));
assertThat(registeredModuleTypes, hasItem("jackson-module-parameter-names"));
assertThat(registeredModuleTypes, hasItem("jackson-datatype-jsr353"));
assertThat(registeredModuleTypes, hasItem("uk.gov.justice.services.common.converter.jackson.additionalproperties.AdditionalPropertiesModule"));
assertThat(registeredModuleTypes, hasItem("uk.gov.justice.services.common.converter.jackson.integerenum.IntegerEnumModule"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
import static com.fasterxml.jackson.databind.DeserializationFeature.READ_ENUMS_USING_TO_STRING;
import static com.fasterxml.jackson.databind.MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_WITH_ZONE_ID;
import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_ENUMS_USING_TO_STRING;
Expand All @@ -23,10 +24,11 @@
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer;
Expand All @@ -43,37 +45,51 @@ public ObjectMapper objectMapper() {
return configureObjectMapper(new ObjectMapper());
}

public ObjectMapper objectMapperWith(final JsonFactory jsonFactory) {
return configureObjectMapper(new ObjectMapper(jsonFactory));
}

public ObjectMapper yamlObjectMapper() {
return configureObjectMapper(new ObjectMapper(new YAMLFactory()))
.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}

private ObjectMapper configureObjectMapper(final ObjectMapper objectMapper) {
return objectMapper
return new ObjectMapper(new YAMLFactory())
.registerModule(javaTimeModuleWithFormattedDateTime())
.registerModule(new Jdk8Module())
.registerModule(new ParameterNamesModule(PROPERTIES))
.registerModule(new InclusionAwareJSR353Module())
.registerModule(new AdditionalPropertiesModule())
.registerModule(new IntegerEnumModule())
.configure(WRITE_DATES_AS_TIMESTAMPS, false)
.configure(WRITE_DATES_WITH_ZONE_ID, false)
.configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(WRITE_NULL_MAP_VALUES, false)
.setTimeZone(getTimeZone(UTC))
.setSerializationInclusion(NON_ABSENT)
.enable(WRITE_ENUMS_USING_TO_STRING)
.configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
.enable(READ_ENUMS_USING_TO_STRING)
.setConstructorDetector(USE_PROPERTIES_BASED);
.enable(ACCEPT_CASE_INSENSITIVE_ENUMS)
.setConstructorDetector(USE_PROPERTIES_BASED)
.setSerializationInclusion(NON_ABSENT)
;
}

private JavaTimeModule javaTimeModuleWithFormattedDateTime() {
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(ZonedDateTime.class, new ZonedDateTimeSerializer(ofPattern(ISO_8601)));
return javaTimeModule;
}

private ObjectMapper configureObjectMapper(final ObjectMapper objectMapper) {
return objectMapper
.registerModule(javaTimeModuleWithFormattedDateTime())
.registerModule(new Jdk8Module())
.registerModule(new ParameterNamesModule(PROPERTIES))
.registerModule(new InclusionAwareJSR353Module())
.registerModule(new AdditionalPropertiesModule())
.registerModule(new IntegerEnumModule())
.configure(WRITE_DATES_AS_TIMESTAMPS, false)
.configure(WRITE_DATES_WITH_ZONE_ID, false)
.configure(WRITE_NULL_MAP_VALUES, false)
.setTimeZone(getTimeZone(UTC))
.setSerializationInclusion(NON_ABSENT)
.enable(WRITE_ENUMS_USING_TO_STRING)
.configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
.enable(READ_ENUMS_USING_TO_STRING)
.setConstructorDetector(USE_PROPERTIES_BASED)
;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public JsonDeserializer<?> modifyEnumDeserializer(

final Class<Enum<?>> enumClass = (Class<Enum<?>>) type.getRawClass();

final EnumResolver enumResolver = constructFor(enumClass, nopInstance());
final EnumResolver enumResolver = constructFor(config, enumClass);

return new IntegerEnumDeserializer(
enumResolver,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class IntegerEnumDeserializer extends EnumDeserializer {

public IntegerEnumDeserializer(final EnumResolver enumResolver,
final EnumObjectUtil enumObjectUtil) {
super(enumResolver);
super(enumResolver, true);
this.enumerations = asList(enumResolver.getRawEnums());
this.enumObjectUtil = enumObjectUtil;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package uk.gov.justice.services.yaml;

import static com.fasterxml.jackson.databind.cfg.ConstructorDetector.USE_PROPERTIES_BASED;
import static java.lang.String.format;

import uk.gov.justice.services.common.converter.jackson.ObjectMapperProducer;
Expand All @@ -9,6 +10,7 @@

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;

public class YamlParser {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package uk.gov.justice.services.common.converter;

import static java.time.ZoneOffset.UTC;
import static java.time.format.DateTimeFormatter.ofPattern;
import static java.util.UUID.randomUUID;
import static javax.json.Json.createObjectBuilder;
import static org.hamcrest.CoreMatchers.equalTo;
Expand All @@ -9,12 +11,14 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsCollectionContaining.hasItems;
import static org.mockito.Mockito.doThrow;
import static uk.gov.justice.services.common.converter.ZonedDateTimes.ISO_8601;

import uk.gov.justice.services.common.converter.jackson.ObjectMapperProducer;

import java.io.IOException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;

Expand Down Expand Up @@ -64,31 +68,41 @@ public void shouldConvertPojoToJsonObject() throws Exception {
@Test
public void shouldConvertToPojoWithUTCDateTime() throws Exception {

assertThat(jsonObjectToObjectConverter
.convert(Json.createObjectBuilder().add("dateTime", "2016-07-25T13:09:01.0+00:00").build(),
PojoWithDateTime.class).getDateTime(),
equalTo(ZonedDateTime.of(2016, 7, 25, 13, 9, 1, 0, ZoneId.of("UTC"))));
assertThat(jsonObjectToObjectConverter
.convert(Json.createObjectBuilder().add("dateTime", "2016-07-25T13:09:01.0Z").build(),
PojoWithDateTime.class).getDateTime(),
equalTo(ZonedDateTime.of(2016, 7, 25, 13, 9, 1, 0, ZoneId.of("UTC"))));
assertThat(jsonObjectToObjectConverter
.convert(Json.createObjectBuilder().add("dateTime", "2016-07-25T13:09:01Z").build(),
PojoWithDateTime.class).getDateTime(),
equalTo(ZonedDateTime.of(2016, 7, 25, 13, 9, 1, 0, ZoneId.of("UTC"))));
assertThat(jsonObjectToObjectConverter
.convert(Json.createObjectBuilder().add("dateTime", "2016-07-25T16:09:01.0+03:00").build(),
PojoWithDateTime.class).getDateTime(),
equalTo(ZonedDateTime.of(2016, 7, 25, 13, 9, 1, 0, ZoneId.of("UTC"))));

final ZonedDateTime expectedDateTime = ZonedDateTime.of(2016, 7, 25, 13, 9, 1, 0, UTC);

final PojoWithDateTime pojoWithDateTime_1 = jsonObjectToObjectConverter.convert(
createObjectBuilder()
.add("dateTime", "2016-07-25T13:09:01.0+00:00")
.build(),
PojoWithDateTime.class);
final PojoWithDateTime pojoWithDateTime_2 = jsonObjectToObjectConverter
.convert(createObjectBuilder()
.add("dateTime", "2016-07-25T13:09:01.0Z")
.build(),
PojoWithDateTime.class);
final PojoWithDateTime pojoWithDateTime_3 = jsonObjectToObjectConverter
.convert(createObjectBuilder()
.add("dateTime", "2016-07-25T16:09:01.0+03:00")
.build(),
PojoWithDateTime.class);
final PojoWithDateTime pojoWithDateTime_4 = jsonObjectToObjectConverter
.convert(createObjectBuilder()
.add("dateTime", "2016-07-25T13:09:01.000Z")
.build(),
PojoWithDateTime.class);

assertThat(pojoWithDateTime_1.getDateTime(), equalTo(expectedDateTime));
assertThat(pojoWithDateTime_2.getDateTime(), equalTo(expectedDateTime));
assertThat(pojoWithDateTime_3.getDateTime(), equalTo(expectedDateTime));
assertThat(pojoWithDateTime_4.getDateTime(), equalTo(expectedDateTime));
}

@Test
public void shouldThrowExceptionOnConversionError() throws IOException {

final UUID uuid = randomUUID();

final JsonObject jsonObject = Json.createObjectBuilder().add("id", uuid.toString()).build();
final JsonObject jsonObject = createObjectBuilder().add("id", uuid.toString()).build();

doThrow(JsonProcessingException.class).when(objectMapper).writeValueAsString(jsonObject);

Expand Down Expand Up @@ -119,10 +133,10 @@ private JsonObject jsonObject() {
.add(ATTRIBUTE_1)
.add(ATTRIBUTE_2).build();

return Json.createObjectBuilder()
return createObjectBuilder()
.add("id", ID.toString())
.add("name", NAME)
.add("internalPojo", Json.createObjectBuilder()
.add("internalPojo", createObjectBuilder()
.add("internalId", INTERNAL_ID.toString())
.add("internalName", INTERNAL_NAME).build())
.add("attributes", array).build();
Expand All @@ -135,7 +149,7 @@ public static class Pojo {
private List<String> attributes;
private InternalPojo internalPojo;

public Pojo () {
public Pojo() {

}

Expand Down Expand Up @@ -203,7 +217,7 @@ public ZonedDateTime getDateTime() {
public static class SingleArgumentConstructorPojo {
private UUID id;

public SingleArgumentConstructorPojo (UUID id) {
public SingleArgumentConstructorPojo(UUID id) {
this.id = id;
}

Expand Down
Loading
Loading