diff --git a/pom.xml b/pom.xml
index 77ffea8..4861015 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
21
3.2.0
- 4.0.6
+ 4.0.7
3.5.3
@@ -28,10 +28,11 @@
false
3.3.1
3.7.1
- 7.0.7
+ 7.0.8
3.19.0
- 11.0.22
+ 11.0.24
5.14.1
+ 1.42.0
3.0.57
@@ -61,6 +62,7 @@
2.26.0
32.0.1-android
1.81.0
+ 3.1.4
@@ -143,6 +145,19 @@
${grpc-context.version}
compile
+
+ tools.jackson.core
+ jackson-core
+ ${jackson-core.version}
+ compile
+
+
+
+ io.opentelemetry.semconv
+ opentelemetry-semconv
+ ${opentelemetry-semconv.version}
+
+
@@ -187,6 +202,10 @@
org.apache.commons
commons-lang3
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
@@ -220,23 +239,63 @@
org.apache.commons
commons-lang3
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
uk.gov.companieshouse
api-helper-java
${api-helper-java-library.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
com.github.docker-java
docker-java-api
${docker-java-api.version}
compile
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
org.apache.commons
commons-lang3
${commons-lang3.version}
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
+
+
+ tools.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+
+
diff --git a/src/main/java/uk/gov/companieshouse/api/converter/ReadConverter.java b/src/main/java/uk/gov/companieshouse/api/converter/ReadConverter.java
index 2f3c8ba..db30df7 100644
--- a/src/main/java/uk/gov/companieshouse/api/converter/ReadConverter.java
+++ b/src/main/java/uk/gov/companieshouse/api/converter/ReadConverter.java
@@ -4,10 +4,8 @@
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import tools.jackson.databind.ObjectMapper;
-import uk.gov.companieshouse.api.exception.InternalServiceException;
@ReadingConverter
public class ReadConverter implements Converter {
@@ -22,10 +20,6 @@ public ReadConverter(ObjectMapper objectMapper, Class objectClass) {
@Override
public T convert(Document source) {
- try {
- return this.objectMapper.readValue(source.toJson(), objectClass);
- } catch (JsonProcessingException e) {
- throw new InternalServiceException("failed to read and convert Document to JSON", e);
- }
+ return this.objectMapper.readValue(source.toJson(), objectClass);
}
}
diff --git a/src/main/java/uk/gov/companieshouse/api/converter/WriteConverter.java b/src/main/java/uk/gov/companieshouse/api/converter/WriteConverter.java
index d3278bc..1de2719 100644
--- a/src/main/java/uk/gov/companieshouse/api/converter/WriteConverter.java
+++ b/src/main/java/uk/gov/companieshouse/api/converter/WriteConverter.java
@@ -1,7 +1,6 @@
package uk.gov.companieshouse.api.converter;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import tools.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.WritingConverter;
@@ -21,10 +20,6 @@ public WriteConverter(ObjectMapper objectMapper) {
*/
@Override
public BasicDBObject convert(S source) {
- try {
- return BasicDBObject.parse(objectMapper.writeValueAsString(source));
- } catch (JsonProcessingException e) {
- throw new IllegalArgumentException(e);
- }
+ return BasicDBObject.parse(objectMapper.writeValueAsString(source));
}
}
diff --git a/src/main/java/uk/gov/companieshouse/api/filinghistory/utils/TransactionKindResult.java b/src/main/java/uk/gov/companieshouse/api/filinghistory/utils/TransactionKindResult.java
index 1fe863b..d7fe43a 100644
--- a/src/main/java/uk/gov/companieshouse/api/filinghistory/utils/TransactionKindResult.java
+++ b/src/main/java/uk/gov/companieshouse/api/filinghistory/utils/TransactionKindResult.java
@@ -30,10 +30,9 @@ public void setKind(TransactionKind kind) {
@Override
public boolean equals(Object obj) {
- if (!(obj instanceof TransactionKindResult)) {
+ if (!(obj instanceof TransactionKindResult cmp)) {
return false;
}
- TransactionKindResult cmp = (TransactionKindResult) obj;
final boolean sameKind = (this.kind == null && cmp.kind == null) ||
(this.kind != null && this.kind.equals(cmp.kind));
diff --git a/src/main/java/uk/gov/companieshouse/api/serialization/LocalDateDeserializer.java b/src/main/java/uk/gov/companieshouse/api/serialization/LocalDateDeserializer.java
index 634afc5..382573f 100644
--- a/src/main/java/uk/gov/companieshouse/api/serialization/LocalDateDeserializer.java
+++ b/src/main/java/uk/gov/companieshouse/api/serialization/LocalDateDeserializer.java
@@ -1,34 +1,49 @@
package uk.gov.companieshouse.api.serialization;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.JsonNode;
+import tools.jackson.core.JsonParser;
+import tools.jackson.databind.DeserializationContext;
+import tools.jackson.databind.ValueDeserializer;
+import tools.jackson.databind.JsonNode;
import java.time.ZoneOffset;
import uk.gov.companieshouse.api.exception.BadRequestException;
-
import java.time.Instant;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
-public class LocalDateDeserializer extends JsonDeserializer {
+public class LocalDateDeserializer extends ValueDeserializer {
@Override
- public LocalDate deserialize(JsonParser jsonParser, DeserializationContext
- deserializationContext) {
+ public LocalDate deserialize(JsonParser jsonParser,
+ DeserializationContext deserializationContext) {
+ DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
+ JsonNode dateNode;
try {
- DateTimeFormatter dateTimeFormatter = DateTimeFormatter
- .ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
- JsonNode jsonNode = jsonParser.readValueAsTree();
- JsonNode dateNode = jsonNode.get("$date");
+ dateNode = ((JsonNode) jsonParser.readValueAsTree()).get("$date");
+ } catch (Exception e) {
+ throw new BadRequestException("Deserialization failed.", e);
+ }
- return dateNode.textValue() != null ?
- LocalDate.parse(dateNode.textValue(), dateTimeFormatter) :
- Instant.ofEpochMilli(dateNode.get("$numberLong").asLong())
- .atZone(ZoneOffset.UTC).toLocalDate();
+ if (dateNode == null || dateNode.isNull()) {
+ throw new BadRequestException("$date field is missing or null");
+ }
- } catch (Exception exception) {
- throw new BadRequestException("Deserialization failed.", exception);
+ if (dateNode.isString()) {
+ try {
+ return LocalDate.parse(dateNode.stringValue(), fmt);
+ } catch (Exception e) {
+ throw new BadRequestException("Deserialization failed.", e);
+ }
}
- }
-}
+ if (dateNode.isObject() && dateNode.has("$numberLong")) {
+ try {
+ return Instant.ofEpochMilli(Long.parseLong(dateNode.get("$numberLong").stringValue()))
+ .atZone(ZoneOffset.UTC)
+ .toLocalDate();
+ } catch (Exception e) {
+ throw new BadRequestException("Deserialization failed.", e);
+ }
+ }
+
+ throw new BadRequestException("Unrecognized $date format");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/uk/gov/companieshouse/api/serialization/LocalDateSerializer.java b/src/main/java/uk/gov/companieshouse/api/serialization/LocalDateSerializer.java
index bbdbfb9..8f51fbd 100644
--- a/src/main/java/uk/gov/companieshouse/api/serialization/LocalDateSerializer.java
+++ b/src/main/java/uk/gov/companieshouse/api/serialization/LocalDateSerializer.java
@@ -1,24 +1,21 @@
package uk.gov.companieshouse.api.serialization;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
+import tools.jackson.databind.ValueSerializer;
+import tools.jackson.databind.SerializationContext;
+import tools.jackson.core.JsonGenerator;
-import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
-public class LocalDateSerializer extends JsonSerializer {
-
+public class LocalDateSerializer extends ValueSerializer {
@Override
- public void serialize(LocalDate localDate, JsonGenerator jsonGenerator,
- SerializerProvider serializerProvider) throws IOException {
- if (localDate == null) {
- jsonGenerator.writeNull();
+ public void serialize(LocalDate value, JsonGenerator gen, SerializationContext ctxt) {
+ if (value == null) {
+ gen.writeNull();
} else {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
- String format = localDate.atStartOfDay().format(dtf);
- jsonGenerator.writeRawValue("ISODate(\"" + format + "\")");
+ String format = value.atStartOfDay().format(dtf);
+ gen.writeRawValue("ISODate(\"" + format + "\")");
}
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/uk/gov/companieshouse/api/converter/ReadConverterTest.java b/src/test/java/uk/gov/companieshouse/api/converter/ReadConverterTest.java
index 5d25427..769ef28 100644
--- a/src/test/java/uk/gov/companieshouse/api/converter/ReadConverterTest.java
+++ b/src/test/java/uk/gov/companieshouse/api/converter/ReadConverterTest.java
@@ -1,14 +1,13 @@
package uk.gov.companieshouse.api.converter;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import tools.jackson.core.JacksonException;
import org.bson.Document;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import uk.gov.companieshouse.api.exception.InternalServiceException;
+import tools.jackson.databind.ObjectMapper;
import uk.gov.companieshouse.api.psc.Statement;
import uk.gov.companieshouse.api.utils.TestHelper;
@@ -35,19 +34,19 @@ void correctlyConvertsDocumentToStatementObject(){
}
@Test
- void testConvertThrowsInternalServiceExceptionOnJsonError() throws Exception {
+ void testConvertThrowsInternalServiceExceptionOnJsonError() {
// GIVEN
ObjectMapper objectMapper = mock(ObjectMapper.class);
Document source = new Document();
when(objectMapper.readValue(anyString(), ArgumentMatchers.>any()))
- .thenThrow(new JsonProcessingException("Error") {});
+ .thenThrow(new JacksonException("Error") {});
// WHEN
ReadConverter converter = new ReadConverter<>(objectMapper, Statement.class);
// THEN
- Exception ex = Assertions.assertThrows(InternalServiceException.class, () -> converter.convert(source));
- Assertions.assertEquals("failed to read and convert Document to JSON", ex.getMessage());
+ Exception ex = Assertions.assertThrows(JacksonException.class, () -> converter.convert(source));
+ Assertions.assertEquals("Error", ex.getMessage());
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/uk/gov/companieshouse/api/converter/WriteConverterTest.java b/src/test/java/uk/gov/companieshouse/api/converter/WriteConverterTest.java
index 74635ed..d4c8128 100644
--- a/src/test/java/uk/gov/companieshouse/api/converter/WriteConverterTest.java
+++ b/src/test/java/uk/gov/companieshouse/api/converter/WriteConverterTest.java
@@ -6,7 +6,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import tools.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import uk.gov.companieshouse.api.psc.Statement;
diff --git a/src/test/java/uk/gov/companieshouse/api/filinghistory/utils/TransactionKindResultTest.java b/src/test/java/uk/gov/companieshouse/api/filinghistory/utils/TransactionKindResultTest.java
new file mode 100644
index 0000000..e60afbd
--- /dev/null
+++ b/src/test/java/uk/gov/companieshouse/api/filinghistory/utils/TransactionKindResultTest.java
@@ -0,0 +1,92 @@
+package uk.gov.companieshouse.api.filinghistory.utils;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+class TransactionKindResultTest {
+
+ @Test
+ void constructorShouldSetFields() {
+ TransactionKind kind = TransactionKind.TOP_LEVEL;
+
+ TransactionKindResult result = new TransactionKindResult("encoded-id", kind);
+
+ assertEquals("encoded-id", result.getEncodedId());
+ assertEquals(kind, result.getKind());
+ }
+
+ @Test
+ void settersShouldUpdateFields() {
+ TransactionKindResult result = new TransactionKindResult(null, null);
+
+ result.setEncodedId("new-id");
+ result.setKind(TransactionKind.TOP_LEVEL);
+
+ assertEquals("new-id", result.getEncodedId());
+ assertEquals(TransactionKind.TOP_LEVEL, result.getKind());
+ }
+
+ @Test
+ void equalsShouldReturnTrueForSameValues() {
+ TransactionKindResult first = new TransactionKindResult("id1", TransactionKind.TOP_LEVEL);
+
+ TransactionKindResult second = new TransactionKindResult("id1", TransactionKind.TOP_LEVEL);
+
+ assertEquals(first, second);
+ assertEquals(first.hashCode(), second.hashCode());
+ }
+
+ @Test
+ void equalsShouldReturnFalseForDifferentEncodedId() {
+ TransactionKindResult first = new TransactionKindResult("id1", TransactionKind.TOP_LEVEL);
+
+ TransactionKindResult second = new TransactionKindResult("id2", TransactionKind.TOP_LEVEL);
+
+ assertNotEquals(first, second);
+ assertNotEquals(first.hashCode(), second.hashCode());
+ }
+
+ @Test
+ void equalsShouldReturnFalseForDifferentKind() {
+ TransactionKindResult first = new TransactionKindResult("id1", TransactionKind.TOP_LEVEL);
+
+ TransactionKindResult second = new TransactionKindResult("id1", TransactionKind.ASSOCIATED_FILING);
+
+ assertNotEquals(first, second);
+ assertNotEquals(first.hashCode(), second.hashCode());
+ }
+
+ @Test
+ void equalsShouldReturnFalseForDifferentObjectType() {
+ TransactionKindResult result = new TransactionKindResult("id1", TransactionKind.ANNOTATION);
+
+ assertNotEquals("not-a-TransactionKindResult", result);
+ }
+
+ @Test
+ void equalsShouldHandleNullFields() {
+ TransactionKindResult first = new TransactionKindResult(null, null);
+
+ TransactionKindResult second = new TransactionKindResult(null, null);
+
+ assertEquals(first, second);
+ }
+
+ @Test
+ void hashCodeShouldHandleNullValues() {
+ TransactionKindResult result = new TransactionKindResult(null, null);
+
+ int hashcode = result.hashCode();
+ assertNotEquals(0, hashcode);
+ }
+
+ @Test
+ void hashCodeShouldHandleNonNullValues() {
+ TransactionKindResult result = new TransactionKindResult("id1", TransactionKind.RESOLUTION);
+
+ int hashcode = result.hashCode();
+ assertNotEquals(0, hashcode);
+ }
+}
diff --git a/src/test/java/uk/gov/companieshouse/api/serialization/LocalDateDeserializerTest.java b/src/test/java/uk/gov/companieshouse/api/serialization/LocalDateDeserializerTest.java
index e2fde41..56fab8b 100644
--- a/src/test/java/uk/gov/companieshouse/api/serialization/LocalDateDeserializerTest.java
+++ b/src/test/java/uk/gov/companieshouse/api/serialization/LocalDateDeserializerTest.java
@@ -1,22 +1,24 @@
package uk.gov.companieshouse.api.serialization;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
-import java.io.IOException;
import java.time.LocalDate;
-import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import tools.jackson.core.JsonParser;
+import tools.jackson.databind.ObjectMapper;
import uk.gov.companieshouse.api.exception.BadRequestException;
class LocalDateDeserializerTest {
+ private static final String DESERIALISATION_FALIED_EXCEPTION_MESSAGE = "Deserialization failed.";
+ private static final String DATE_FIELD_MISSING_OR_NULL = "$date field is missing or null";
private LocalDateDeserializer deserializer;
private ObjectMapper mapper;
@@ -29,54 +31,83 @@ void setUp() {
}
@Test
- void dateShouldDeserialize() throws IOException {
-
+ void dateShouldDeserialize() {
String jsonTestString = "{\"date\":{\"$date\": \"2023-01-09T00:00:00Z\"}}";
LocalDate returnedDate = deserialize(jsonTestString);
- Assertions.assertEquals(LocalDate.of(2023, 1, 9), returnedDate);
-
+ assertEquals(LocalDate.of(2023, 1, 9), returnedDate);
}
@Test
- void longStringReturnsLong() throws IOException {
-
+ void longStringReturnsLong() {
String jsonTestString = "{\"date\":{\"$date\": {\"$numberLong\":\"-1431388800000\"}}}";
LocalDate returnedDate = deserialize(jsonTestString);
- Assertions.assertEquals(LocalDate.of(1924, 8, 23), returnedDate);
-
+ assertEquals(LocalDate.of(1924, 8, 23), returnedDate);
}
@Test
void nullStringReturnsError() {
-
String jsonTestString = null;
-
- assertThrows(NullPointerException.class, ()->{
- deserialize(jsonTestString);
- });
+ assertThrows(IllegalArgumentException.class, () -> deserialize(jsonTestString));
}
@Test
void invalidStringReturnsError() {
-
String jsonTestString = "{\"date\":{\"$date\": \"NotADate\"}}}";
- assertThrows(BadRequestException.class, ()->{
- deserialize(jsonTestString);
- });
+ assertException(DESERIALISATION_FALIED_EXCEPTION_MESSAGE, jsonTestString);
+ }
+
+ @Test
+ void missingDateFieldReturnsError() {
+ String jsonTestString = "{\"date\":{}}";
+
+ assertException(DATE_FIELD_MISSING_OR_NULL, jsonTestString);
+ }
+
+ @Test
+ void nullDateFieldReturnsError() {
+ String jsonTestString = "{\"date\":{\"$date\":null}}";
+
+ assertException(DATE_FIELD_MISSING_OR_NULL, jsonTestString);
}
- private LocalDate deserialize(String jsonString) throws IOException {
- JsonParser parser = mapper.getFactory().createParser(jsonString);
- DeserializationContext deserializationContext = mapper.getDeserializationContext();
+ @Test
+ void invalidDateShouldReturnError() {
+
+ JsonParser parser = mock(JsonParser.class);
+ when(parser.readValueAsTree())
+ .thenThrow(new RuntimeException("Invalid JSON"));
+ BadRequestException exception = assertThrows(BadRequestException.class, () -> deserializer.deserialize(parser, null));
- parser.nextToken();
- parser.nextToken();
- parser.nextToken();
+ assertEquals(DESERIALISATION_FALIED_EXCEPTION_MESSAGE, exception.getMessage());
+ }
+
+ @Test
+ void invalidNumberLongReturnError() {
+ String jsonTestString = "{\"date\":{\"$date\": {\"$numberLong\":\"not-a-number\"}}}";
- return deserializer.deserialize(parser, deserializationContext);
+ assertException(DESERIALISATION_FALIED_EXCEPTION_MESSAGE, jsonTestString);
}
-
-}
+
+ private LocalDate deserialize(String jsonString) {
+ try {
+ JsonParser parser = mapper.createParser(jsonString);
+ parser.nextToken();
+ parser.nextToken();
+ parser.nextToken();
+ // Pass null for DeserializationContext as it's not used in the deserializer
+ return deserializer.deserialize(parser, null);
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+
+ private void assertException(String expectedMessage, String jsonTestString) {
+ BadRequestException exception = assertThrows(BadRequestException.class, () -> deserialize(jsonTestString));
+
+ assertEquals(expectedMessage, exception.getMessage());
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/uk/gov/companieshouse/api/serialization/LocalDateSerializerTest.java b/src/test/java/uk/gov/companieshouse/api/serialization/LocalDateSerializerTest.java
index 5c31e4d..2f66245 100644
--- a/src/test/java/uk/gov/companieshouse/api/serialization/LocalDateSerializerTest.java
+++ b/src/test/java/uk/gov/companieshouse/api/serialization/LocalDateSerializerTest.java
@@ -1,6 +1,5 @@
package uk.gov.companieshouse.api.serialization;
-import com.fasterxml.jackson.core.JsonGenerator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -9,6 +8,7 @@
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import tools.jackson.core.JsonGenerator;
import java.time.LocalDate;
@@ -31,7 +31,7 @@ void setUp() {
}
@Test
- void dateShouldSerialize() throws Exception {
+ void dateShouldSerialize() {
LocalDate date = LocalDate.of(2020, 1, 1);
serializer.serialize(date, generator, null);
@@ -41,10 +41,8 @@ void dateShouldSerialize() throws Exception {
}
@Test
- void assertNullDateReturnsNull() throws Exception {
-
+ void assertNullDateReturnsNull() {
serializer.serialize(null, generator, null);
-
verify(generator).writeNull();
}
-}
+}
\ No newline at end of file