diff --git a/pom.xml b/pom.xml index e0e5ab50c..34ea256be 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.7 + 4.0.2 @@ -37,26 +37,24 @@ - 10.0.0-SNAPSHOT - 5.1.0-SNAPSHOT - 3.4.0-SNAPSHOT - - + 10.0.0-RC1 + 6.0.0-SNAPSHOT + 4.0.0-SNAPSHOT + 5.11.0-SNAPSHOT + 3.0.0-SNAPSHOT 2.0.0-SNAPSHOT 2.0.0-SNAPSHOT 2.0.0-SNAPSHOT 1.0.0-SNAPSHOT + 3.15.2 2.21.0 4.5.0 1.14.1 1.6.3 1.18.42 0.2.0 - 3.15.2 - 5.10.15 - 2.0.3 13.2.0 2.10.0 @@ -146,12 +144,8 @@ spring-boot-starter-web - org.apache.logging.log4j - log4j-to-slf4j - - - ch.qos.logback - logback-classic + org.springframework.boot + spring-boot-starter-logging @@ -159,16 +153,34 @@ org.springframework.boot spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-logging + + org.springframework.boot spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-logging + + - org.springframework.kafka - spring-kafka + org.springframework.boot + spring-boot-starter-kafka + + + org.springframework.boot + spring-boot-starter-logging + + @@ -202,14 +214,9 @@ ${apache-commons-io.version} - - com.fasterxml.jackson.module - jackson-module-jaxb-annotations - - io.hypersistence - hypersistence-utils-hibernate-63 + hypersistence-utils-hibernate-73 ${hypersistence-utils-hibernate} @@ -227,20 +234,12 @@ org.springframework.boot - spring-boot-starter-test + spring-boot-starter-webmvc-test test - org.junit.vintage - junit-vintage-engine - - - org.apache.logging.log4j - log4j-to-slf4j - - - ch.qos.logback - logback-classic + org.springframework.boot + spring-boot-starter-logging diff --git a/src/main/java/org/folio/linked/data/LinkedDataApplication.java b/src/main/java/org/folio/linked/data/LinkedDataApplication.java index 584494a26..5779a5033 100644 --- a/src/main/java/org/folio/linked/data/LinkedDataApplication.java +++ b/src/main/java/org/folio/linked/data/LinkedDataApplication.java @@ -6,15 +6,15 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; -import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.ComponentScan; +import org.springframework.resilience.annotation.EnableResilientMethods; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; @EnableCaching @EnableAsync -@EnableFeignClients @EnableScheduling +@EnableResilientMethods @SpringBootApplication @ComponentScan(value = "org.folio", excludeFilters = @Filter(type = REGEX, pattern = {"org.folio.spring.tools.systemuser.*", "org.folio.spring.tools.batch.*"})) diff --git a/src/main/java/org/folio/linked/data/configuration/FeignRequestInterceptor.java b/src/main/java/org/folio/linked/data/configuration/FeignRequestInterceptor.java deleted file mode 100644 index 781b19f1f..000000000 --- a/src/main/java/org/folio/linked/data/configuration/FeignRequestInterceptor.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.folio.linked.data.configuration; - -import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; -import static org.folio.spring.integration.XOkapiHeaders.TENANT; -import static org.folio.spring.integration.XOkapiHeaders.TOKEN; - -import feign.RequestInterceptor; -import feign.RequestTemplate; -import java.util.Collections; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; -import org.folio.spring.FolioExecutionContext; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -@Profile("!" + STANDALONE_PROFILE) -public class FeignRequestInterceptor implements RequestInterceptor { - - private final FolioExecutionContext folioExecutionContext; - - @Override - @SneakyThrows - public void apply(RequestTemplate template) { - template.header(TOKEN, Collections.singletonList(folioExecutionContext.getToken())); - template.header(TENANT, Collections.singletonList(folioExecutionContext.getTenantId())); - } -} diff --git a/src/main/java/org/folio/linked/data/configuration/HttpClientConfiguration.java b/src/main/java/org/folio/linked/data/configuration/HttpClientConfiguration.java new file mode 100644 index 000000000..666a29294 --- /dev/null +++ b/src/main/java/org/folio/linked/data/configuration/HttpClientConfiguration.java @@ -0,0 +1,45 @@ +package org.folio.linked.data.configuration; + +import org.folio.linked.data.integration.rest.authoritysource.AuthoritySourceFilesClient; +import org.folio.linked.data.integration.rest.configuration.ConfigurationClient; +import org.folio.linked.data.integration.rest.search.SearchClient; +import org.folio.linked.data.integration.rest.settings.SettingsClient; +import org.folio.linked.data.integration.rest.specification.SpecClient; +import org.folio.linked.data.integration.rest.srs.SrsClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.service.invoker.HttpServiceProxyFactory; + +@Configuration +public class HttpClientConfiguration { + + @Bean + public AuthoritySourceFilesClient authoritySourceFilesClient(HttpServiceProxyFactory factory) { + return factory.createClient(AuthoritySourceFilesClient.class); + } + + @Bean + public ConfigurationClient configurationClient(HttpServiceProxyFactory factory) { + return factory.createClient(ConfigurationClient.class); + } + + @Bean + public SearchClient searchClient(HttpServiceProxyFactory factory) { + return factory.createClient(SearchClient.class); + } + + @Bean + public SettingsClient settingsClient(HttpServiceProxyFactory factory) { + return factory.createClient(SettingsClient.class); + } + + @Bean + public SpecClient specClient(HttpServiceProxyFactory factory) { + return factory.createClient(SpecClient.class); + } + + @Bean + public SrsClient srsClient(HttpServiceProxyFactory factory) { + return factory.createClient(SrsClient.class); + } +} diff --git a/src/main/java/org/folio/linked/data/configuration/json/JsonMapperConfig.java b/src/main/java/org/folio/linked/data/configuration/json/JsonMapperConfig.java new file mode 100644 index 000000000..ad938ac75 --- /dev/null +++ b/src/main/java/org/folio/linked/data/configuration/json/JsonMapperConfig.java @@ -0,0 +1,21 @@ +package org.folio.linked.data.configuration.json; + +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import tools.jackson.databind.json.JsonMapper; + +@Configuration +public class JsonMapperConfig { + + @Bean + @Primary + public JsonMapper jacksonJsonMapper() { + return JSON_MAPPER; + } +} + + + diff --git a/src/main/java/org/folio/linked/data/configuration/json/ObjectMapperConfig.java b/src/main/java/org/folio/linked/data/configuration/json/ObjectMapperConfig.java deleted file mode 100644 index 7449c9291..000000000 --- a/src/main/java/org/folio/linked/data/configuration/json/ObjectMapperConfig.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.folio.linked.data.configuration.json; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.Module; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import org.folio.linked.data.configuration.json.deserialization.ResourceRequestFieldDeserializer; -import org.folio.linked.data.configuration.json.deserialization.event.SourceRecordDomainEventDeserializer; -import org.folio.linked.data.configuration.json.deserialization.instance.IdentifierFieldDeserializer; -import org.folio.linked.data.configuration.json.deserialization.title.TitleFieldRequestDeserializer; -import org.folio.linked.data.configuration.json.serialization.MarcRecordSerializationConfig; -import org.folio.linked.data.domain.dto.IdentifierField; -import org.folio.linked.data.domain.dto.MarcRecord; -import org.folio.linked.data.domain.dto.ResourceRequestField; -import org.folio.linked.data.domain.dto.SourceRecordDomainEvent; -import org.folio.linked.data.domain.dto.TitleFieldRequestTitleInner; -import org.folio.linked.data.exception.RequestProcessingExceptionBuilder; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - -@Configuration -public class ObjectMapperConfig { - - @Bean - @Primary - public ObjectMapper objectMapper(RequestProcessingExceptionBuilder exceptionBuilder) { - var om = new ObjectMapper() - .setSerializationInclusion(JsonInclude.Include.NON_EMPTY) - .configure(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID, true) - .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true) - .addMixIn(MarcRecord.class, MarcRecordSerializationConfig.class); - om.registerModule(new JavaTimeModule()); - om.registerModule(monographModule(om, exceptionBuilder)); - return om; - } - - private Module monographModule(ObjectMapper objectMapper, RequestProcessingExceptionBuilder exceptionBuilder) { - return new SimpleModule() - .addDeserializer(ResourceRequestField.class, new ResourceRequestFieldDeserializer(exceptionBuilder)) - .addDeserializer(TitleFieldRequestTitleInner.class, new TitleFieldRequestDeserializer(exceptionBuilder)) - .addDeserializer(IdentifierField.class, new IdentifierFieldDeserializer(exceptionBuilder)) - .addDeserializer(SourceRecordDomainEvent.class, new SourceRecordDomainEventDeserializer(objectMapper)); - } - -} diff --git a/src/main/java/org/folio/linked/data/configuration/json/deserialization/ResourceRequestFieldDeserializer.java b/src/main/java/org/folio/linked/data/configuration/json/deserialization/ResourceRequestFieldDeserializer.java index 6743aacbe..c91038f54 100644 --- a/src/main/java/org/folio/linked/data/configuration/json/deserialization/ResourceRequestFieldDeserializer.java +++ b/src/main/java/org/folio/linked/data/configuration/json/deserialization/ResourceRequestFieldDeserializer.java @@ -1,19 +1,17 @@ package org.folio.linked.data.configuration.json.deserialization; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import java.io.IOException; import java.util.Map; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.linked.data.domain.dto.HubField; import org.folio.linked.data.domain.dto.InstanceField; import org.folio.linked.data.domain.dto.ResourceRequestField; import org.folio.linked.data.domain.dto.WorkField; -import org.folio.linked.data.exception.RequestProcessingExceptionBuilder; import org.folio.linked.data.util.DtoDeserializer; +import tools.jackson.core.JsonParser; +import tools.jackson.databind.DeserializationContext; +import tools.jackson.databind.ValueDeserializer; -public class ResourceRequestFieldDeserializer extends JsonDeserializer { +public class ResourceRequestFieldDeserializer extends ValueDeserializer { private static final Map> IDENDTITY_MAP = Map.of( ResourceTypeDictionary.INSTANCE.getUri(), InstanceField.class, @@ -22,12 +20,12 @@ public class ResourceRequestFieldDeserializer extends JsonDeserializer dtoDeserializer; - public ResourceRequestFieldDeserializer(RequestProcessingExceptionBuilder exceptionBuilder) { - dtoDeserializer = new DtoDeserializer<>(ResourceRequestField.class, IDENDTITY_MAP, exceptionBuilder); + public ResourceRequestFieldDeserializer() { + dtoDeserializer = new DtoDeserializer<>(ResourceRequestField.class, IDENDTITY_MAP); } @Override - public ResourceRequestField deserialize(JsonParser jp, DeserializationContext dc) throws IOException { - return dtoDeserializer.deserialize(jp); + public ResourceRequestField deserialize(JsonParser jp, DeserializationContext dc) { + return dtoDeserializer.deserialize(jp, dc); } } diff --git a/src/main/java/org/folio/linked/data/configuration/json/deserialization/event/SourceRecordDomainEventDeserializer.java b/src/main/java/org/folio/linked/data/configuration/json/deserialization/event/SourceRecordDomainEventDeserializer.java index a70787b0c..c78bc87f6 100644 --- a/src/main/java/org/folio/linked/data/configuration/json/deserialization/event/SourceRecordDomainEventDeserializer.java +++ b/src/main/java/org/folio/linked/data/configuration/json/deserialization/event/SourceRecordDomainEventDeserializer.java @@ -1,26 +1,22 @@ package org.folio.linked.data.configuration.json.deserialization.event; import static org.folio.linked.data.domain.dto.SourceRecordDomainEvent.EventTypeEnum; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.folio.linked.data.domain.dto.ParsedRecord; import org.folio.linked.data.domain.dto.SourceRecord; import org.folio.linked.data.domain.dto.SourceRecordDomainEvent; +import tools.jackson.core.JsonParser; +import tools.jackson.databind.DeserializationContext; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.ValueDeserializer; /** * Class responsible for deserializing the Kafka event from SRS module into {@link SourceRecordDomainEvent} object. */ @Log4j2 -@RequiredArgsConstructor -public class SourceRecordDomainEventDeserializer extends JsonDeserializer { +public class SourceRecordDomainEventDeserializer extends ValueDeserializer { private static final String ID = "id"; private static final String EVENT_TYPE = "eventType"; @@ -30,14 +26,12 @@ public class SourceRecordDomainEventDeserializer extends JsonDeserializer { +public class IdentifierFieldDeserializer extends ValueDeserializer { private static final Map> IDENTITY_MAP = Map.of( ID_LCCN.getUri(), LccnField.class, @@ -31,12 +29,12 @@ public class IdentifierFieldDeserializer extends JsonDeserializer dtoDeserializer; - public IdentifierFieldDeserializer(RequestProcessingExceptionBuilder exceptionBuilder) { - dtoDeserializer = new DtoDeserializer<>(IdentifierField.class, IDENTITY_MAP, exceptionBuilder); + public IdentifierFieldDeserializer() { + dtoDeserializer = new DtoDeserializer<>(IdentifierField.class, IDENTITY_MAP); } @Override - public IdentifierField deserialize(JsonParser jp, DeserializationContext dc) throws IOException { - return dtoDeserializer.deserialize(jp); + public IdentifierField deserialize(JsonParser jp, DeserializationContext dc) { + return dtoDeserializer.deserialize(jp, dc); } } diff --git a/src/main/java/org/folio/linked/data/configuration/json/deserialization/title/TitleFieldRequestDeserializer.java b/src/main/java/org/folio/linked/data/configuration/json/deserialization/title/TitleFieldRequestDeserializer.java index f6e94126f..e5db6599a 100644 --- a/src/main/java/org/folio/linked/data/configuration/json/deserialization/title/TitleFieldRequestDeserializer.java +++ b/src/main/java/org/folio/linked/data/configuration/json/deserialization/title/TitleFieldRequestDeserializer.java @@ -4,19 +4,17 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.TITLE; import static org.folio.ld.dictionary.ResourceTypeDictionary.VARIANT_TITLE; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import java.io.IOException; import java.util.Map; import org.folio.linked.data.domain.dto.ParallelTitleField; import org.folio.linked.data.domain.dto.PrimaryTitleField; import org.folio.linked.data.domain.dto.TitleFieldRequestTitleInner; import org.folio.linked.data.domain.dto.VariantTitleField; -import org.folio.linked.data.exception.RequestProcessingExceptionBuilder; import org.folio.linked.data.util.DtoDeserializer; +import tools.jackson.core.JsonParser; +import tools.jackson.databind.DeserializationContext; +import tools.jackson.databind.ValueDeserializer; -public class TitleFieldRequestDeserializer extends JsonDeserializer { +public class TitleFieldRequestDeserializer extends ValueDeserializer { private static final Map> IDENDTITY_MAP = Map.of( TITLE.getUri(), PrimaryTitleField.class, @@ -25,13 +23,13 @@ public class TitleFieldRequestDeserializer extends JsonDeserializer dtoDeserializer; - public TitleFieldRequestDeserializer(RequestProcessingExceptionBuilder exceptionBuilder) { - dtoDeserializer = new DtoDeserializer<>(TitleFieldRequestTitleInner.class, IDENDTITY_MAP, exceptionBuilder); + public TitleFieldRequestDeserializer() { + dtoDeserializer = new DtoDeserializer<>(TitleFieldRequestTitleInner.class, IDENDTITY_MAP); } @Override - public TitleFieldRequestTitleInner deserialize(JsonParser jp, DeserializationContext dc) throws IOException { - return dtoDeserializer.deserialize(jp); + public TitleFieldRequestTitleInner deserialize(JsonParser jp, DeserializationContext dc) { + return dtoDeserializer.deserialize(jp, dc); } } diff --git a/src/main/java/org/folio/linked/data/configuration/json/serialization/MarcRecordSerializationConfig.java b/src/main/java/org/folio/linked/data/configuration/json/serialization/MarcRecordSerializationConfig.java index 6c5e21f30..40f08c232 100644 --- a/src/main/java/org/folio/linked/data/configuration/json/serialization/MarcRecordSerializationConfig.java +++ b/src/main/java/org/folio/linked/data/configuration/json/serialization/MarcRecordSerializationConfig.java @@ -1,6 +1,6 @@ package org.folio.linked.data.configuration.json.serialization; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import tools.jackson.databind.annotation.JsonSerialize; public interface MarcRecordSerializationConfig { diff --git a/src/main/java/org/folio/linked/data/configuration/json/serialization/RawValueJsonSerializer.java b/src/main/java/org/folio/linked/data/configuration/json/serialization/RawValueJsonSerializer.java index f4aa50595..4eb40ba33 100644 --- a/src/main/java/org/folio/linked/data/configuration/json/serialization/RawValueJsonSerializer.java +++ b/src/main/java/org/folio/linked/data/configuration/json/serialization/RawValueJsonSerializer.java @@ -1,19 +1,22 @@ package org.folio.linked.data.configuration.json.serialization; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import java.io.IOException; import java.util.Objects; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.SerializationContext; +import tools.jackson.databind.ValueSerializer; -public class RawValueJsonSerializer extends JsonSerializer { +public class RawValueJsonSerializer extends ValueSerializer { @Override - public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - if (Objects.nonNull(value)) { - gen.writeRawValue(value); - } else { - gen.writeNull(); + public void serialize(String value, JsonGenerator gen, SerializationContext ctx) { + try { + if (Objects.nonNull(value)) { + gen.writeRawValue(value); + } else { + gen.writeNull(); + } + } catch (Exception e) { + throw new RuntimeException("Failed to serialize raw value", e); } } } diff --git a/src/main/java/org/folio/linked/data/configuration/kafka/KafkaListenerConfiguration.java b/src/main/java/org/folio/linked/data/configuration/kafka/KafkaListenerConfiguration.java index 48a4150ce..662ae765c 100644 --- a/src/main/java/org/folio/linked/data/configuration/kafka/KafkaListenerConfiguration.java +++ b/src/main/java/org/folio/linked/data/configuration/kafka/KafkaListenerConfiguration.java @@ -1,18 +1,19 @@ package org.folio.linked.data.configuration.kafka; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.function.Supplier; +import lombok.RequiredArgsConstructor; import org.apache.kafka.common.serialization.Deserializer; import org.apache.kafka.common.serialization.StringDeserializer; import org.folio.linked.data.domain.dto.ImportOutputEvent; import org.folio.linked.data.domain.dto.InventoryInstanceEvent; import org.folio.linked.data.domain.dto.SourceRecordDomainEvent; import org.folio.spring.tools.kafka.FolioKafkaProperties; -import org.springframework.boot.autoconfigure.kafka.KafkaProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.kafka.autoconfigure.KafkaProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; @@ -20,9 +21,10 @@ import org.springframework.kafka.core.ConsumerFactory; import org.springframework.kafka.core.DefaultKafkaConsumerFactory; import org.springframework.kafka.support.serializer.ErrorHandlingDeserializer; -import org.springframework.kafka.support.serializer.JsonDeserializer; +import org.springframework.kafka.support.serializer.JacksonJsonDeserializer; @Configuration +@RequiredArgsConstructor @Profile("!" + STANDALONE_PROFILE) public class KafkaListenerConfiguration { @@ -36,58 +38,54 @@ public FolioKafkaProperties folioKafkaProperties() { public ConcurrentKafkaListenerContainerFactory srsEventListenerContainerFactory( ConsumerFactory sourceRecordDomainEventConsumerFactory ) { - return concurrentKafkaBatchListenerContainerFactory(sourceRecordDomainEventConsumerFactory, true); + return concurrentKafkaBatchListenerContainerFactory(sourceRecordDomainEventConsumerFactory); } @Bean public ConcurrentKafkaListenerContainerFactory inventoryEventListenerContainerFactory( ConsumerFactory inventoryInstanceEventConsumerFactory ) { - return concurrentKafkaBatchListenerContainerFactory(inventoryInstanceEventConsumerFactory, true); + return concurrentKafkaBatchListenerContainerFactory(inventoryInstanceEventConsumerFactory); } @Bean public ConcurrentKafkaListenerContainerFactory importOutputEventListenerContainerFactory( ConsumerFactory ldImportOutputEventConsumerFactory ) { - return concurrentKafkaBatchListenerContainerFactory(ldImportOutputEventConsumerFactory, true); + return concurrentKafkaBatchListenerContainerFactory(ldImportOutputEventConsumerFactory); } @Bean - public ConsumerFactory srsDomainEventConsumerFactory(ObjectMapper mapper, - KafkaProperties properties) { - return errorHandlingConsumerFactory(SourceRecordDomainEvent.class, mapper, properties); + public ConsumerFactory srsDomainEventConsumerFactory(KafkaProperties properties) { + return errorHandlingConsumerFactory(SourceRecordDomainEvent.class, properties); } @Bean - public ConsumerFactory inventoryEventConsumerFactory(ObjectMapper mapper, - KafkaProperties properties) { - return errorHandlingConsumerFactory(InventoryInstanceEvent.class, mapper, properties); + public ConsumerFactory inventoryEventConsumerFactory(KafkaProperties properties) { + return errorHandlingConsumerFactory(InventoryInstanceEvent.class, properties); } @Bean - public ConsumerFactory ldImportOutputEventConsumerFactory(ObjectMapper mapper, - KafkaProperties properties) { - return errorHandlingConsumerFactory(ImportOutputEvent.class, mapper, properties); + public ConsumerFactory ldImportOutputEventConsumerFactory(KafkaProperties properties) { + return errorHandlingConsumerFactory(ImportOutputEvent.class, properties); } private ConcurrentKafkaListenerContainerFactory concurrentKafkaBatchListenerContainerFactory( - ConsumerFactory consumerFactory, boolean batch) { + ConsumerFactory consumerFactory) { var factory = new ConcurrentKafkaListenerContainerFactory(); - factory.setBatchListener(batch); + factory.setBatchListener(true); factory.setConsumerFactory(consumerFactory); return factory; } private ConsumerFactory errorHandlingConsumerFactory(Class clazz, - ObjectMapper mapper, KafkaProperties kafkaProperties) { - var properties = new HashMap<>(kafkaProperties.buildConsumerProperties(null)); + var properties = new HashMap<>(kafkaProperties.buildConsumerProperties()); Supplier> keyDeserializer = StringDeserializer::new; Supplier> valueDeserializer = () -> - new ErrorHandlingDeserializer<>(new JsonDeserializer<>(clazz, mapper)); + new ErrorHandlingDeserializer<>(new JacksonJsonDeserializer<>(clazz, JSON_MAPPER)); return new DefaultKafkaConsumerFactory<>(properties, keyDeserializer, valueDeserializer); } } diff --git a/src/main/java/org/folio/linked/data/configuration/kafka/KafkaProducerConfiguration.java b/src/main/java/org/folio/linked/data/configuration/kafka/KafkaProducerConfiguration.java index 15fec9f07..4413805d6 100644 --- a/src/main/java/org/folio/linked/data/configuration/kafka/KafkaProducerConfiguration.java +++ b/src/main/java/org/folio/linked/data/configuration/kafka/KafkaProducerConfiguration.java @@ -1,8 +1,8 @@ package org.folio.linked.data.configuration.kafka; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.function.Supplier; import lombok.RequiredArgsConstructor; @@ -15,14 +15,14 @@ import org.folio.linked.data.domain.dto.ResourceIndexEvent; import org.folio.spring.tools.kafka.FolioMessageProducer; import org.jetbrains.annotations.NotNull; -import org.springframework.boot.autoconfigure.kafka.KafkaProperties; +import org.springframework.boot.kafka.autoconfigure.KafkaProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.kafka.core.DefaultKafkaProducerFactory; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.kafka.core.ProducerFactory; -import org.springframework.kafka.support.serializer.JsonSerializer; +import org.springframework.kafka.support.serializer.JacksonJsonSerializer; @Configuration @RequiredArgsConstructor @@ -92,25 +92,24 @@ public KafkaTemplate importResultEventTemplate( } @Bean - public ProducerFactory resourceIndexEventProducerFactory(ObjectMapper objectMapper) { - return getKafkaProducerFactory(objectMapper); + public ProducerFactory resourceIndexEventProducerFactory() { + return getKafkaProducerFactory(); } @Bean - public ProducerFactory instanceIngressEventProducerFactory(ObjectMapper objectMapper) { - return getKafkaProducerFactory(objectMapper); + public ProducerFactory instanceIngressEventProducerFactory() { + return getKafkaProducerFactory(); } @Bean - public ProducerFactory importResultEventProducerFactory( - ObjectMapper objectMapper) { - return getKafkaProducerFactory(objectMapper); + public ProducerFactory importResultEventProducerFactory() { + return getKafkaProducerFactory(); } - private @NotNull DefaultKafkaProducerFactory getKafkaProducerFactory(ObjectMapper objectMapper) { - var properties = new HashMap<>(kafkaProperties.buildProducerProperties(null)); + private @NotNull DefaultKafkaProducerFactory getKafkaProducerFactory() { + var properties = new HashMap<>(kafkaProperties.buildProducerProperties()); Supplier> keySerializer = StringSerializer::new; - Supplier> valueSerializer = () -> new JsonSerializer<>(objectMapper); + Supplier> valueSerializer = () -> new JacksonJsonSerializer<>(JSON_MAPPER); return new DefaultKafkaProducerFactory<>(properties, keySerializer, valueSerializer); } } diff --git a/src/main/java/org/folio/linked/data/controller/advice/ApiExceptionHandler.java b/src/main/java/org/folio/linked/data/controller/advice/ApiExceptionHandler.java index 9e33ddab3..b3ea59dc2 100644 --- a/src/main/java/org/folio/linked/data/controller/advice/ApiExceptionHandler.java +++ b/src/main/java/org/folio/linked/data/controller/advice/ApiExceptionHandler.java @@ -7,7 +7,9 @@ import lombok.extern.log4j.Log4j2; import org.apache.logging.log4j.Level; import org.folio.linked.data.domain.dto.ErrorResponse; +import org.folio.linked.data.exception.JsonMappingException; import org.folio.linked.data.exception.RequestProcessingException; +import org.folio.linked.data.exception.RequestProcessingExceptionBuilder; import org.folio.linked.data.mapper.error.ConstraintViolationExceptionMapper; import org.folio.linked.data.mapper.error.EntityNotFoundExceptionMapper; import org.folio.linked.data.mapper.error.GenericBadRequestMapper; @@ -29,12 +31,19 @@ public class ApiExceptionHandler { private final GenericBadRequestMapper genericBadRequestMapper; + private final RequestProcessingExceptionBuilder exceptionBuilder; private final GenericServerExceptionMapper genericServerExceptionMapper; private final EntityNotFoundExceptionMapper entityNotFoundExceptionMapper; private final RequestProcessingExceptionMapper requestProcessingExceptionMapper; private final ConstraintViolationExceptionMapper constraintViolationExceptionMapper; private final MethodArgumentNotValidExceptionMapper methodArgumentNotValidExceptionMapper; + @ExceptionHandler(JsonMappingException.class) + public ResponseEntity handleRequestProcessingException(JsonMappingException exception) { + var rpe = exceptionBuilder.mappingException(exception.getDtoClass(), exception.getFieldName()); + return handleRequestProcessingException(rpe); + } + @ExceptionHandler(RequestProcessingException.class) public ResponseEntity handleRequestProcessingException(RequestProcessingException exception) { return requestProcessingExceptionMapper.errorResponseEntity(exception); @@ -107,7 +116,7 @@ public ResponseEntity handleAllOtherExceptions(Exception exceptio return genericServerExceptionMapper.errorResponseEntity(exception); } - private static void logException(Exception exception) { + private void logException(Exception exception) { log.log(Level.WARN, "Handling exception", exception); } } diff --git a/src/main/java/org/folio/linked/data/exception/JsonMappingException.java b/src/main/java/org/folio/linked/data/exception/JsonMappingException.java new file mode 100644 index 000000000..cb05c2e77 --- /dev/null +++ b/src/main/java/org/folio/linked/data/exception/JsonMappingException.java @@ -0,0 +1,12 @@ +package org.folio.linked.data.exception; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class JsonMappingException extends RuntimeException { + private final String dtoClass; + private final String fieldName; + +} diff --git a/src/main/java/org/folio/linked/data/integration/kafka/listener/InventoryInstanceEventListener.java b/src/main/java/org/folio/linked/data/integration/kafka/listener/InventoryInstanceEventListener.java index 2744f3085..ea29014a6 100644 --- a/src/main/java/org/folio/linked/data/integration/kafka/listener/InventoryInstanceEventListener.java +++ b/src/main/java/org/folio/linked/data/integration/kafka/listener/InventoryInstanceEventListener.java @@ -1,6 +1,5 @@ package org.folio.linked.data.integration.kafka.listener; -import static java.util.Optional.ofNullable; import static org.folio.linked.data.domain.dto.ResourceIndexEventType.UPDATE; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; import static org.folio.linked.data.util.KafkaUtils.handleForExistedTenant; @@ -9,14 +8,12 @@ import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.apache.logging.log4j.Level; import org.folio.linked.data.domain.dto.InventoryInstanceEvent; import org.folio.linked.data.integration.kafka.listener.handler.ExternalEventHandler; import org.folio.linked.data.service.tenant.LinkedDataTenantService; import org.folio.linked.data.service.tenant.TenantScopedExecutionService; import org.springframework.context.annotation.Profile; import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.retry.RetryContext; import org.springframework.stereotype.Component; @Log4j2 @@ -48,22 +45,13 @@ private void handleRecord(ConsumerRecord consume var event = consumerRecord.value(); if (event.getType() == UPDATE) { tenantScopedExecutionService.executeWithRetry( - consumerRecord.headers(), - retryContext -> runRetryableJob(event, retryContext), - ex -> logFailedEvent(event, ex, false) + consumerRecord.headers(), () -> { + inventoryInstanceEventHandler.handle(event, null); + return null; + }, + ex -> log.error("Failed to reindex inventory instance with id {}. Retrying: {}", event.getNew().getId(), ex) ); } } - private void runRetryableJob(InventoryInstanceEvent event, RetryContext retryContext) { - ofNullable(retryContext.getLastThrowable()) - .ifPresent(ex -> logFailedEvent(event, ex, true)); - inventoryInstanceEventHandler.handle(event, null); - } - - private void logFailedEvent(InventoryInstanceEvent event, Throwable ex, boolean isRetrying) { - var logLevel = isRetrying ? Level.INFO : Level.ERROR; - log.log(logLevel, "Failed to reindex inventory instance with id {}. Retrying: {}", - event.getNew().getId(), isRetrying, ex); - } } diff --git a/src/main/java/org/folio/linked/data/integration/kafka/listener/LdImportOutputEventListener.java b/src/main/java/org/folio/linked/data/integration/kafka/listener/LdImportOutputEventListener.java index ec2d5b9c6..dd68ff1c5 100644 --- a/src/main/java/org/folio/linked/data/integration/kafka/listener/LdImportOutputEventListener.java +++ b/src/main/java/org/folio/linked/data/integration/kafka/listener/LdImportOutputEventListener.java @@ -1,6 +1,5 @@ package org.folio.linked.data.integration.kafka.listener; -import static java.util.Optional.ofNullable; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; import static org.folio.linked.data.util.KafkaUtils.handleForExistedTenant; @@ -9,14 +8,12 @@ import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.apache.kafka.clients.consumer.ConsumerRecord; -import org.apache.logging.log4j.Level; import org.folio.linked.data.domain.dto.ImportOutputEvent; import org.folio.linked.data.integration.kafka.listener.handler.ExternalEventHandler; import org.folio.linked.data.service.tenant.LinkedDataTenantService; import org.folio.linked.data.service.tenant.TenantScopedExecutionService; import org.springframework.context.annotation.Profile; import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.retry.RetryContext; import org.springframework.stereotype.Component; @Log4j2 @@ -51,20 +48,12 @@ private void handleRecord(ConsumerRecord consumerReco var startTime = OffsetDateTime.now(); tenantScopedExecutionService.executeWithRetry( consumerRecord.headers(), - retryContext -> runRetryableJob(event, startTime, retryContext), - ex -> logFailedEvent(event, ex, false) + () -> { + ldImportOutputEventHandler.handle(event, startTime); + return null; + }, + ex -> log.error("Failed to handle LD-Import output event with id {}. Retrying: {}", event.getTs(), ex) ); } - private void runRetryableJob(ImportOutputEvent event, OffsetDateTime startTime, RetryContext retryContext) { - ofNullable(retryContext.getLastThrowable()) - .ifPresent(ex -> logFailedEvent(event, ex, true)); - ldImportOutputEventHandler.handle(event, startTime); - } - - private void logFailedEvent(ImportOutputEvent event, Throwable ex, boolean isRetrying) { - var logLevel = isRetrying ? Level.INFO : Level.ERROR; - log.log(logLevel, "Failed to handle LD-Import output event with id {}. Retrying: {}", - event.getTs(), isRetrying, ex); - } } diff --git a/src/main/java/org/folio/linked/data/integration/kafka/listener/SourceRecordDomainEventListener.java b/src/main/java/org/folio/linked/data/integration/kafka/listener/SourceRecordDomainEventListener.java index cfa63a7e6..6502b5f38 100644 --- a/src/main/java/org/folio/linked/data/integration/kafka/listener/SourceRecordDomainEventListener.java +++ b/src/main/java/org/folio/linked/data/integration/kafka/listener/SourceRecordDomainEventListener.java @@ -1,6 +1,5 @@ package org.folio.linked.data.integration.kafka.listener; -import static java.util.Optional.ofNullable; import static org.folio.linked.data.domain.dto.SourceRecordType.MARC_AUTHORITY; import static org.folio.linked.data.domain.dto.SourceRecordType.MARC_BIB; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; @@ -15,7 +14,6 @@ import lombok.extern.log4j.Log4j2; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.common.header.Headers; -import org.apache.logging.log4j.Level; import org.folio.linked.data.domain.dto.SourceRecordDomainEvent; import org.folio.linked.data.domain.dto.SourceRecordType; import org.folio.linked.data.integration.kafka.listener.handler.srs.SourceRecordDomainEventHandler; @@ -23,7 +21,6 @@ import org.folio.linked.data.service.tenant.TenantScopedExecutionService; import org.springframework.context.annotation.Profile; import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.retry.RetryContext; import org.springframework.stereotype.Component; @Log4j2 @@ -69,24 +66,15 @@ private void processRecord(ConsumerRecord consu if (sourceRecordType == MARC_AUTHORITY || sourceRecordType == MARC_BIB) { tenantScopedExecutionService.executeWithRetrySystemUser( tenantId, - retryContext -> runRetryableJob(event, sourceRecordType, retryContext), - ex -> logFailedEvent(event, sourceRecordType, ex, false) + () -> { + sourceRecordDomainEventHandler.handle(event, sourceRecordType); + return null; + }, + ex -> log.error("Failed to process MARC {} record {}.", sourceRecordType.name(), event.getEventPayload(), ex) ); } } - private void runRetryableJob(SourceRecordDomainEvent event, SourceRecordType type, RetryContext context) { - ofNullable(context.getLastThrowable()) - .ifPresent(ex -> logFailedEvent(event, type, ex, true)); - sourceRecordDomainEventHandler.handle(event, type); - } - - private void logFailedEvent(SourceRecordDomainEvent event, SourceRecordType type, Throwable ex, boolean isRetrying) { - var marcRecord = event.getEventPayload(); - var logLevel = isRetrying ? Level.INFO : Level.ERROR; - log.log(logLevel, "Failed to process MARC {} record {}. Retrying: {}", type.name(), marcRecord, isRetrying, ex); - } - private boolean notAllRequiredHeaders(Headers headers) { return !REQUIRED_HEADERS.stream() .map(required -> headers.headers(required).iterator()) diff --git a/src/main/java/org/folio/linked/data/integration/kafka/sender/inventory/InstanceCreateMessageSender.java b/src/main/java/org/folio/linked/data/integration/kafka/sender/inventory/InstanceCreateMessageSender.java index a1cb173ae..1eb9af3e0 100644 --- a/src/main/java/org/folio/linked/data/integration/kafka/sender/inventory/InstanceCreateMessageSender.java +++ b/src/main/java/org/folio/linked/data/integration/kafka/sender/inventory/InstanceCreateMessageSender.java @@ -12,7 +12,6 @@ import java.util.Collection; import java.util.List; import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; import org.folio.linked.data.domain.dto.InstanceIngressEvent; import org.folio.linked.data.integration.kafka.sender.CreateMessageSender; @@ -47,7 +46,6 @@ public Collection apply(Resource resource) { } @Override - @SneakyThrows public void accept(Resource resource) { log.debug("Publishing CREATE_INSTANCE message to inventory for instance with ID [{}]", resource.getId()); var message = instanceIngressMessageMapper.toInstanceIngressEvent(resource) diff --git a/src/main/java/org/folio/linked/data/integration/rest/authoritysource/AuthoritySourceFilesClient.java b/src/main/java/org/folio/linked/data/integration/rest/authoritysource/AuthoritySourceFilesClient.java index b2dd7d9fc..2c4fae5b7 100644 --- a/src/main/java/org/folio/linked/data/integration/rest/authoritysource/AuthoritySourceFilesClient.java +++ b/src/main/java/org/folio/linked/data/integration/rest/authoritysource/AuthoritySourceFilesClient.java @@ -5,17 +5,17 @@ import org.folio.linked.data.domain.dto.AuthoritySourceFiles; import org.springframework.cache.annotation.Cacheable; -import org.springframework.cloud.openfeign.FeignClient; import org.springframework.context.annotation.Profile; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; -@FeignClient(name = "authority-source-files") @Profile("!" + STANDALONE_PROFILE) +@HttpExchange("authority-source-files") public interface AuthoritySourceFilesClient { @SuppressWarnings("java:S7180") @Cacheable(cacheNames = AUTHORITY_SOURCE_FILES, key = "@folioExecutionContext.tenantId + '_' + #limit") - @GetMapping + @GetExchange AuthoritySourceFiles getAuthoritySourceFiles(@RequestParam("limit") int limit); } diff --git a/src/main/java/org/folio/linked/data/integration/rest/configuration/ConfigurationClient.java b/src/main/java/org/folio/linked/data/integration/rest/configuration/ConfigurationClient.java index 0c92216ba..6e3935856 100644 --- a/src/main/java/org/folio/linked/data/integration/rest/configuration/ConfigurationClient.java +++ b/src/main/java/org/folio/linked/data/integration/rest/configuration/ConfigurationClient.java @@ -5,18 +5,18 @@ import org.folio.linked.data.domain.dto.Configurations; import org.springframework.cache.annotation.Cacheable; -import org.springframework.cloud.openfeign.FeignClient; import org.springframework.context.annotation.Profile; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; -@FeignClient(name = "configurations") +@HttpExchange("configurations") @Profile("!" + STANDALONE_PROFILE) public interface ConfigurationClient { @SuppressWarnings("java:S7180") @Cacheable(cacheNames = SETTINGS_ENTRIES, key = "@folioExecutionContext.tenantId + '_' + #code") - @GetMapping("${config.client.path:/entries}?query=module=={moduleName} and code=={code}") + @GetExchange("/entries?query=module=={moduleName} and code=={code}") Configurations lookupConfig(@PathVariable("moduleName") String moduleName, @PathVariable("code") String code); diff --git a/src/main/java/org/folio/linked/data/integration/rest/search/SearchClient.java b/src/main/java/org/folio/linked/data/integration/rest/search/SearchClient.java index 5f5591ccc..655a6a57b 100644 --- a/src/main/java/org/folio/linked/data/integration/rest/search/SearchClient.java +++ b/src/main/java/org/folio/linked/data/integration/rest/search/SearchClient.java @@ -4,19 +4,19 @@ import org.folio.linked.data.domain.dto.AuthoritySearchResponse; import org.folio.linked.data.domain.dto.SearchResponseTotalOnly; -import org.springframework.cloud.openfeign.FeignClient; import org.springframework.context.annotation.Profile; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; -@FeignClient(name = "search") @Profile("!" + STANDALONE_PROFILE) +@HttpExchange("search") public interface SearchClient { - @GetMapping("/instances") + @GetExchange("/instances") ResponseEntity searchInstances(@RequestParam("query") String query); - @GetMapping("/authorities") + @GetExchange("/authorities") ResponseEntity searchAuthorities(@RequestParam("query") String query); } diff --git a/src/main/java/org/folio/linked/data/integration/rest/settings/SettingsClient.java b/src/main/java/org/folio/linked/data/integration/rest/settings/SettingsClient.java index 925543b02..0c3cfcc44 100644 --- a/src/main/java/org/folio/linked/data/integration/rest/settings/SettingsClient.java +++ b/src/main/java/org/folio/linked/data/integration/rest/settings/SettingsClient.java @@ -5,18 +5,18 @@ import org.folio.linked.data.domain.dto.SettingsSearchResponse; import org.springframework.cache.annotation.Cacheable; -import org.springframework.cloud.openfeign.FeignClient; import org.springframework.context.annotation.Profile; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; -@FeignClient("settings") +@HttpExchange("settings") @Profile("!" + STANDALONE_PROFILE) public interface SettingsClient { @SuppressWarnings("java:S7180") @Cacheable(cacheNames = SETTINGS_ENTRIES, key = "@folioExecutionContext.tenantId + '_' + #query") - @GetMapping("/entries") + @GetExchange("/entries") ResponseEntity getEntries(@RequestParam("query") String query); } diff --git a/src/main/java/org/folio/linked/data/integration/rest/specification/SpecClient.java b/src/main/java/org/folio/linked/data/integration/rest/specification/SpecClient.java index b572f09c4..0a9abfced 100644 --- a/src/main/java/org/folio/linked/data/integration/rest/specification/SpecClient.java +++ b/src/main/java/org/folio/linked/data/integration/rest/specification/SpecClient.java @@ -7,22 +7,22 @@ import org.folio.rspec.domain.dto.SpecificationDtoCollection; import org.folio.rspec.domain.dto.SpecificationRuleDtoCollection; import org.springframework.cache.annotation.Cacheable; -import org.springframework.cloud.openfeign.FeignClient; import org.springframework.context.annotation.Profile; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; @SuppressWarnings("java:S7180") @Profile("!" + STANDALONE_PROFILE) -@FeignClient(name = "specification-storage") +@HttpExchange("specification-storage") public interface SpecClient { @Cacheable(cacheNames = "bib-marc-specs", key = "@folioExecutionContext.tenantId") - @GetMapping(value = "/specifications?profile=bibliographic&family=MARC") + @GetExchange("/specifications?profile=bibliographic&family=MARC") ResponseEntity getBibMarcSpecs(); @Cacheable(cacheNames = SPEC_RULES, key = "@folioExecutionContext.tenantId + '_' + #specId") - @GetMapping(value = "/specifications/{specId}/rules") + @GetExchange("/specifications/{specId}/rules") ResponseEntity getSpecRules(@PathVariable("specId") UUID specId); } diff --git a/src/main/java/org/folio/linked/data/integration/rest/specification/SpecProviderFolio.java b/src/main/java/org/folio/linked/data/integration/rest/specification/SpecProviderFolio.java index f6042a25a..53d1fcef8 100644 --- a/src/main/java/org/folio/linked/data/integration/rest/specification/SpecProviderFolio.java +++ b/src/main/java/org/folio/linked/data/integration/rest/specification/SpecProviderFolio.java @@ -2,7 +2,6 @@ import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; -import feign.FeignException; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -16,6 +15,7 @@ import org.springframework.context.annotation.Profile; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpClientErrorException; @Log4j2 @Component @@ -41,7 +41,7 @@ public List getSpecRules() { .stream() .flatMap(Collection::stream) .toList(); - } catch (FeignException e) { + } catch (HttpClientErrorException e) { log.error("Unexpected exception during specification rules retrieval", e); return Collections.emptyList(); } diff --git a/src/main/java/org/folio/linked/data/integration/rest/srs/SrsClient.java b/src/main/java/org/folio/linked/data/integration/rest/srs/SrsClient.java index 8e6ce618d..9bb57a681 100644 --- a/src/main/java/org/folio/linked/data/integration/rest/srs/SrsClient.java +++ b/src/main/java/org/folio/linked/data/integration/rest/srs/SrsClient.java @@ -1,20 +1,24 @@ package org.folio.linked.data.integration.rest.srs; +import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; + import org.folio.rest.jaxrs.model.Record; -import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.context.annotation.Profile; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; -@FeignClient(name = "source-storage") +@Profile("!" + STANDALONE_PROFILE) +@HttpExchange("source-storage") public interface SrsClient { - @GetMapping(value = "/records/{inventoryId}/formatted?idType=INSTANCE") + @GetExchange("/records/{inventoryId}/formatted?idType=INSTANCE") ResponseEntity getSourceStorageInstanceRecordById(@PathVariable("inventoryId") String inventoryId); - @GetMapping(value = "/records/{srsId}/formatted?idType=SRS_RECORD") + @GetExchange("/records/{srsId}/formatted?idType=SRS_RECORD") ResponseEntity getAuthorityBySrsId(@PathVariable("srsId") String srsId); - @GetMapping(value = "/records/{inventoryId}/formatted?idType=AUTHORITY") + @GetExchange("/records/{inventoryId}/formatted?idType=AUTHORITY") ResponseEntity getAuthorityByInventoryId(@PathVariable("inventoryId") String inventoryId); } diff --git a/src/main/java/org/folio/linked/data/mapper/ResourceModelMapper.java b/src/main/java/org/folio/linked/data/mapper/ResourceModelMapper.java index c36acaf11..55bab2fb8 100644 --- a/src/main/java/org/folio/linked/data/mapper/ResourceModelMapper.java +++ b/src/main/java/org/folio/linked/data/mapper/ResourceModelMapper.java @@ -27,6 +27,7 @@ import org.mapstruct.MappingTarget; import org.mapstruct.Qualifier; import org.mapstruct.TargetType; +import tools.jackson.databind.JsonNode; @Mapper(componentModel = SPRING) public abstract class ResourceModelMapper { @@ -101,6 +102,11 @@ protected PredicateDictionary map(PredicateEntity predicateEntity) { return PredicateDictionary.fromUri(predicateEntity.getUri()).orElse(null); } + protected JsonNode map(JsonNode jsonNode) { + // JsonNode is immutable, so we can return the same instance + return jsonNode; + } + @Mapping(source = "resource", target = "resource") protected abstract FolioMetadata mapFolioMetadata(org.folio.ld.dictionary.model.FolioMetadata folioMetadata, Resource resource); diff --git a/src/main/java/org/folio/linked/data/mapper/dto/ResourceSubgraphViewMapper.java b/src/main/java/org/folio/linked/data/mapper/dto/ResourceSubgraphViewMapper.java index e9044918c..b2481bd27 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/ResourceSubgraphViewMapper.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/ResourceSubgraphViewMapper.java @@ -1,32 +1,30 @@ package org.folio.linked.data.mapper.dto; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; -import java.io.IOException; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; + import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.folio.ld.dictionary.model.Resource; import org.folio.ld.dictionary.util.ResourceViewDeserializer; import org.springframework.stereotype.Component; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.json.JsonMapper; +import tools.jackson.databind.module.SimpleModule; @Log4j2 @Component @RequiredArgsConstructor public class ResourceSubgraphViewMapper { - private final ObjectMapper objectMapper = new ObjectMapper() - .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true) - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .registerModule(new SimpleModule() - .addDeserializer(Resource.class, new ResourceViewDeserializer()) - ); + private final JsonMapper jsonMapper = JSON_MAPPER.rebuild() + .addModule(new SimpleModule().addDeserializer(Resource.class, new ResourceViewDeserializer())) + .build(); public Optional fromJson(String jsonGraph) { try { - return Optional.of(objectMapper.readValue(jsonGraph, Resource.class)); - } catch (IOException e) { + return Optional.of(jsonMapper.readValue(jsonGraph, Resource.class)); + } catch (JacksonException e) { log.error("Failed to convert resource graph JSON to DTO: {}", jsonGraph, e); return Optional.empty(); } diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapper.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapper.java index 0ff4ca04d..9ae49aad7 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapper.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapper.java @@ -1,11 +1,11 @@ package org.folio.linked.data.mapper.dto.resource.base; -import com.fasterxml.jackson.databind.JsonNode; import java.util.List; import java.util.Map; import lombok.NonNull; import org.folio.ld.dictionary.model.Predicate; import org.folio.linked.data.model.entity.Resource; +import tools.jackson.databind.JsonNode; public interface CoreMapper { diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapperImpl.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapperImpl.java index 05e10b591..14b76a055 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapperImpl.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapperImpl.java @@ -3,11 +3,8 @@ import static java.util.Objects.nonNull; import static java.util.Optional.ofNullable; import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.NullNode; import java.util.Collection; import java.util.List; import java.util.Map; @@ -19,19 +16,19 @@ import org.folio.linked.data.model.entity.ResourceEdge; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; +import tools.jackson.core.JacksonException; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.node.NullNode; @Log4j2 @Component public class CoreMapperImpl implements CoreMapper { - private final ObjectMapper jsonMapper; private final SingleResourceMapper singleResourceMapper; private final RequestProcessingExceptionBuilder exceptionBuilder; - public CoreMapperImpl(ObjectMapper objectMapper, - @Lazy SingleResourceMapper singleResourceMapper, + public CoreMapperImpl(@Lazy SingleResourceMapper singleResourceMapper, RequestProcessingExceptionBuilder exceptionBuilder) { - this.jsonMapper = objectMapper; this.singleResourceMapper = singleResourceMapper; this.exceptionBuilder = exceptionBuilder; } @@ -79,19 +76,19 @@ private T readResourceDoc(@NonNull Resource resource, @NonNull Class dtoC @Override public JsonNode toJson(Map> map) { - var node = jsonMapper.convertValue(map, JsonNode.class); - return !(node instanceof NullNode) ? node : jsonMapper.createObjectNode(); + var node = JSON_MAPPER.convertValue(map, JsonNode.class); + return !(node instanceof NullNode) ? node : JSON_MAPPER.createObjectNode(); } private T readDoc(JsonNode node, Class dtoClass) { try { if (nonNull(node)) { - return jsonMapper.treeToValue(node, dtoClass); + return JSON_MAPPER.treeToValue(node, dtoClass); } else { - return jsonMapper.treeToValue(jsonMapper.createObjectNode(), dtoClass); + return JSON_MAPPER.treeToValue(JSON_MAPPER.createObjectNode(), dtoClass); } - } catch (JsonProcessingException e) { - log.error("JsonProcessingException during doc mapping to [{}]", dtoClass); + } catch (JacksonException e) { + log.error("JacksonException during doc mapping to [{}]", dtoClass); throw exceptionBuilder.mappingException(dtoClass.getSimpleName(), String.valueOf(node)); } } diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/base/SingleResourceMapperImpl.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/base/SingleResourceMapperImpl.java index 95302feb3..09dcae8c2 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/base/SingleResourceMapperImpl.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/base/SingleResourceMapperImpl.java @@ -11,14 +11,13 @@ import static org.folio.linked.data.util.Constants.IS_NOT_SUPPORTED_FOR; import static org.folio.linked.data.util.Constants.PREDICATE; import static org.folio.linked.data.util.Constants.RIGHT_SQUARE_BRACKET; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; import static org.folio.linked.data.util.ResourceUtils.getTypeUris; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Optional; import lombok.NonNull; import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; import org.folio.ld.dictionary.model.Predicate; import org.folio.linked.data.exception.NotSupportedException; @@ -32,11 +31,9 @@ @RequiredArgsConstructor public class SingleResourceMapperImpl implements SingleResourceMapper { - private final ObjectMapper objectMapper; private final List mapperUnits; private final RequestProcessingExceptionBuilder exceptionBuilder; - @SneakyThrows @Override public

Resource toEntity(@NonNull Object dto, @NonNull Class

parentRequestDto, Predicate predicate, Resource parentEntity) { @@ -52,8 +49,8 @@ public

Resource toEntity(@NonNull Object dto, @NonNull Class

parentReques } catch (Exception e) { log.warn("Exception during toEntity mapping", e); throw exceptionBuilder.mappingException(dto.getClass().getSimpleName() - + ofNullable(predicate).map(p -> " under Predicate: " + p.getUri()).orElse(""), - objectMapper.writeValueAsString(dto)); + + ofNullable(predicate).map(p -> " under Predicate: " + p.getUri()).orElse(""), + JSON_MAPPER.writeValueAsString(dto)); } } @@ -79,7 +76,7 @@ public D toDto(@NonNull Resource source, @NonNull D parentDto, Resource pare } private Optional getMapperUnit(String typeUri, Predicate pred, Class parentResponseDto, - Class requestDto) { + Class requestDto) { return mapperUnits.stream() .filter(m -> isNull(parentResponseDto) || m.supportedParents().contains(parentResponseDto)) .filter(m -> { diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/NoteMapper.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/NoteMapper.java index 8cd8b2743..5e04a270a 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/NoteMapper.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/NoteMapper.java @@ -8,7 +8,6 @@ import static org.folio.ld.dictionary.PropertyDictionary.fromValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; import java.util.List; import java.util.Map; @@ -16,6 +15,7 @@ import org.folio.ld.dictionary.PropertyDictionary; import org.folio.linked.data.domain.dto.Note; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component public class NoteMapper { @@ -32,7 +32,7 @@ public List toNotes(JsonNode doc, Set noteProperties) .flatMap(entry -> stream(spliteratorUnknownSize(entry.getValue().iterator(), ORDERED), false) .map(value -> new Note() - .value(List.of(value.textValue())) + .value(List.of(value.stringValue())) .type(List.of(entry.getKey())) ) ) diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/StatusMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/StatusMapperUnit.java index 784af40d4..3b961fd7e 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/StatusMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/StatusMapperUnit.java @@ -9,7 +9,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import java.util.Set; @@ -28,6 +27,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/category/CategoryMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/category/CategoryMapperUnit.java index 8b9a564d4..700383b99 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/category/CategoryMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/category/CategoryMapperUnit.java @@ -11,7 +11,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import java.util.Set; @@ -27,6 +26,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.model.entity.ResourceEdge; import org.folio.linked.data.service.resource.hash.HashService; +import tools.jackson.databind.JsonNode; @RequiredArgsConstructor public abstract class CategoryMapperUnit implements SingleResourceMapperUnit, MarcCodeProvider { diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/InstanceMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/InstanceMapperUnit.java index 65cf6ab76..78e2a81d1 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/InstanceMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/InstanceMapperUnit.java @@ -48,7 +48,6 @@ import static org.folio.linked.data.util.ResourceUtils.putProperty; import static org.springframework.util.ObjectUtils.isEmpty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import java.util.Set; @@ -70,6 +69,7 @@ import org.folio.linked.data.service.profile.ResourceProfileLinkingService; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/AccessLocationMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/AccessLocationMapperUnit.java index 7e3d35a92..b7ceaa1ac 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/AccessLocationMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/AccessLocationMapperUnit.java @@ -7,7 +7,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -19,6 +18,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/AdminMetadataMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/AdminMetadataMapperUnit.java index 3a9ce4eba..cbf52603a 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/AdminMetadataMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/AdminMetadataMapperUnit.java @@ -11,7 +11,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -22,6 +21,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/CopyrightEventMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/CopyrightEventMapperUnit.java index 4d1f1a6a7..bbd745d3b 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/CopyrightEventMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/CopyrightEventMapperUnit.java @@ -6,7 +6,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -18,6 +17,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/ExtentMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/ExtentMapperUnit.java index 6f45aa448..a8ef82806 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/ExtentMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/ExtentMapperUnit.java @@ -4,7 +4,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -18,6 +17,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/InstanceSupplementaryContentMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/InstanceSupplementaryContentMapperUnit.java index c5807f736..4cf042613 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/InstanceSupplementaryContentMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/InstanceSupplementaryContentMapperUnit.java @@ -4,7 +4,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -18,6 +17,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/ProviderEventMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/ProviderEventMapperUnit.java index 4775b8a3c..d4927a27f 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/ProviderEventMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/ProviderEventMapperUnit.java @@ -15,7 +15,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -28,6 +27,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @RequiredArgsConstructor @MapperUnit( diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/identifier/AbstractIdentifierMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/identifier/AbstractIdentifierMapperUnit.java index f50388168..785f3b80c 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/identifier/AbstractIdentifierMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/instance/sub/identifier/AbstractIdentifierMapperUnit.java @@ -7,7 +7,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import org.folio.ld.dictionary.ResourceTypeDictionary; @@ -19,6 +18,7 @@ import org.folio.linked.data.mapper.dto.resource.common.instance.sub.InstanceSubResourceMapperUnit; import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; +import tools.jackson.databind.JsonNode; abstract class AbstractIdentifierMapperUnit implements InstanceSubResourceMapperUnit { private final CoreMapper coreMapper; diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/language/AbstractLanguageMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/language/AbstractLanguageMapperUnit.java index 9087581fe..eaa5c429d 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/language/AbstractLanguageMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/language/AbstractLanguageMapperUnit.java @@ -7,7 +7,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -17,6 +16,7 @@ import org.folio.linked.data.mapper.dto.resource.common.category.MarcCodeProvider; import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; +import tools.jackson.databind.JsonNode; @RequiredArgsConstructor public abstract class AbstractLanguageMapperUnit implements SingleResourceMapperUnit, MarcCodeProvider { diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/place/PlaceMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/place/PlaceMapperUnit.java index ba4c56247..d7ad4dcab 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/place/PlaceMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/place/PlaceMapperUnit.java @@ -7,7 +7,6 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.PLACE; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import java.util.Set; @@ -22,6 +21,7 @@ import org.folio.linked.data.mapper.dto.resource.common.category.MarcCodeProvider; import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; +import tools.jackson.databind.JsonNode; @RequiredArgsConstructor public abstract class PlaceMapperUnit implements SingleResourceMapperUnit, MarcCodeProvider { diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/ParallelTitleMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/ParallelTitleMapperUnit.java index 0d33fc9d0..e9b1fb8a0 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/ParallelTitleMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/ParallelTitleMapperUnit.java @@ -11,7 +11,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -25,6 +24,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/PrimaryTitleMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/PrimaryTitleMapperUnit.java index 34b6a8a77..c2ffa0c78 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/PrimaryTitleMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/PrimaryTitleMapperUnit.java @@ -9,7 +9,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -24,6 +23,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/VariantTitleMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/VariantTitleMapperUnit.java index 0e3f8c882..cb16d6a9d 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/VariantTitleMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/title/VariantTitleMapperUnit.java @@ -12,7 +12,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -26,6 +25,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/WorkMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/WorkMapperUnit.java index c03da6e17..a613ba046 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/WorkMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/WorkMapperUnit.java @@ -32,7 +32,6 @@ import static org.folio.linked.data.util.ResourceUtils.putProperty; import static org.springframework.util.CollectionUtils.isEmpty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; @@ -62,6 +61,7 @@ import org.folio.linked.data.service.profile.ResourceProfileLinkingService; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/ClassificationMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/ClassificationMapperUnit.java index c634139d8..0e26787c1 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/ClassificationMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/ClassificationMapperUnit.java @@ -12,7 +12,6 @@ import static org.folio.marc4ld.util.Constants.Classification.DDC; import static org.folio.marc4ld.util.Constants.Classification.LC; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -25,6 +24,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/DissertationMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/DissertationMapperUnit.java index 58e5cd2b9..24f98d0e2 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/DissertationMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/DissertationMapperUnit.java @@ -9,7 +9,6 @@ import static org.folio.ld.dictionary.PropertyDictionary.LABEL; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -22,6 +21,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/PartOfSeriesMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/PartOfSeriesMapperUnit.java index 6266232f5..0c45067c6 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/PartOfSeriesMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/PartOfSeriesMapperUnit.java @@ -19,7 +19,6 @@ import static org.folio.linked.data.util.ResourceUtils.getPropertyValues; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import java.util.Objects; @@ -35,6 +34,7 @@ import org.folio.linked.data.model.entity.ResourceEdge; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/reference/SubjectMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/reference/SubjectMapperUnit.java index 84c445f4b..6d60080a0 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/reference/SubjectMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/reference/SubjectMapperUnit.java @@ -8,7 +8,6 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.CONCEPT; import static org.folio.linked.data.util.ResourceUtils.copyWithoutPreferred; -import com.fasterxml.jackson.databind.JsonNode; import java.util.Optional; import java.util.Set; import org.folio.linked.data.domain.dto.Reference; @@ -21,6 +20,7 @@ import org.folio.linked.data.service.reference.ReferenceService; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @MapperUnit(type = CONCEPT, predicate = SUBJECT, requestDto = Reference.class) diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/hub/HubMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/hub/HubMapperUnit.java index 218bd0976..cff1e0aaf 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/hub/HubMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/hub/HubMapperUnit.java @@ -8,7 +8,6 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.HUB; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import lombok.RequiredArgsConstructor; @@ -28,6 +27,7 @@ import org.folio.linked.data.service.profile.ResourceProfileLinkingService; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/dto/resource/serial/PublicationFrequencyMapperUnit.java b/src/main/java/org/folio/linked/data/mapper/dto/resource/serial/PublicationFrequencyMapperUnit.java index 1abeab1c1..802ecad79 100644 --- a/src/main/java/org/folio/linked/data/mapper/dto/resource/serial/PublicationFrequencyMapperUnit.java +++ b/src/main/java/org/folio/linked/data/mapper/dto/resource/serial/PublicationFrequencyMapperUnit.java @@ -8,7 +8,6 @@ import static org.folio.linked.data.util.ResourceUtils.getFirstValue; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; import java.util.HashMap; import java.util.List; import java.util.Optional; @@ -23,6 +22,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.hash.HashService; import org.springframework.stereotype.Component; +import tools.jackson.databind.JsonNode; @Component @RequiredArgsConstructor diff --git a/src/main/java/org/folio/linked/data/mapper/kafka/search/WorkSearchMessageMapper.java b/src/main/java/org/folio/linked/data/mapper/kafka/search/WorkSearchMessageMapper.java index acbb91c5a..de92ef819 100644 --- a/src/main/java/org/folio/linked/data/mapper/kafka/search/WorkSearchMessageMapper.java +++ b/src/main/java/org/folio/linked/data/mapper/kafka/search/WorkSearchMessageMapper.java @@ -34,7 +34,6 @@ import static org.folio.linked.data.util.ResourceUtils.getTypeUris; import static org.mapstruct.MappingConstants.ComponentModel.SPRING; -import com.fasterxml.jackson.databind.JsonNode; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -67,6 +66,7 @@ import org.mapstruct.Mapping; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.lang.Nullable; +import tools.jackson.databind.JsonNode; @Log4j2 @Mapper(componentModel = SPRING, imports = {WorkMapperUnit.class, UUID.class}) @@ -180,7 +180,7 @@ protected Stream getPropertyValues(JsonNode doc, String... properties) { .stream() .flatMap(d -> Arrays.stream(properties) .filter(p -> d.has(p) && !d.get(p).isEmpty()) - .flatMap(p -> StreamSupport.stream(doc.get(p).spliterator(), true).map(JsonNode::asText))); + .flatMap(p -> StreamSupport.stream(doc.get(p).spliterator(), true).map(JsonNode::asString))); } protected List extractClassifications(Resource resource) { @@ -263,7 +263,7 @@ protected String getValue(JsonNode doc, String... values) { if (nonNull(doc)) { for (String value : values) { if (doc.has(value) && !doc.get(value).isEmpty()) { - return doc.get(value).get(0).asText(); + return doc.get(value).get(0).asString(); } } } diff --git a/src/main/java/org/folio/linked/data/mapper/kafka/search/identifier/IndexIdentifierMapperImpl.java b/src/main/java/org/folio/linked/data/mapper/kafka/search/identifier/IndexIdentifierMapperImpl.java index a768f40e7..3841672c4 100644 --- a/src/main/java/org/folio/linked/data/mapper/kafka/search/identifier/IndexIdentifierMapperImpl.java +++ b/src/main/java/org/folio/linked/data/mapper/kafka/search/identifier/IndexIdentifierMapperImpl.java @@ -6,7 +6,6 @@ import static org.folio.linked.data.domain.dto.LinkedDataIdentifier.TypeEnum; import static org.folio.linked.data.util.ResourceUtils.getTypeUris; -import com.fasterxml.jackson.databind.JsonNode; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -18,6 +17,7 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.model.entity.ResourceEdge; import org.springframework.stereotype.Service; +import tools.jackson.databind.JsonNode; @Log4j2 @Service @@ -57,7 +57,7 @@ private Optional getValue(JsonNode doc) { .map(doc::get) .filter(node -> !node.isEmpty()) .map(value -> value.get(0)) - .map(JsonNode::asText) + .map(JsonNode::asString) .findFirst(); } diff --git a/src/main/java/org/folio/linked/data/model/entity/Resource.java b/src/main/java/org/folio/linked/data/model/entity/Resource.java index 2ad7ab841..815090a29 100644 --- a/src/main/java/org/folio/linked/data/model/entity/Resource.java +++ b/src/main/java/org/folio/linked/data/model/entity/Resource.java @@ -9,7 +9,6 @@ import static java.util.Optional.ofNullable; import static org.folio.ld.dictionary.ResourceTypeDictionary.INSTANCE; -import com.fasterxml.jackson.databind.JsonNode; import io.hypersistence.utils.hibernate.type.json.JsonBinaryType; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -51,6 +50,7 @@ import org.springframework.data.annotation.CreatedBy; import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.domain.Persistable; +import tools.jackson.databind.JsonNode; @Entity @Data diff --git a/src/main/java/org/folio/linked/data/service/profile/ProfileServiceImpl.java b/src/main/java/org/folio/linked/data/service/profile/ProfileServiceImpl.java index bf8345b58..8c5a1f707 100644 --- a/src/main/java/org/folio/linked/data/service/profile/ProfileServiceImpl.java +++ b/src/main/java/org/folio/linked/data/service/profile/ProfileServiceImpl.java @@ -3,10 +3,8 @@ import static java.util.stream.Collectors.toSet; import static org.apache.commons.collections4.CollectionUtils.isEmpty; import static org.folio.linked.data.util.Constants.Cache.PROFILES; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; @@ -25,6 +23,7 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import tools.jackson.databind.JsonNode; @Service @RequiredArgsConstructor @@ -32,11 +31,9 @@ @Transactional(readOnly = true) public class ProfileServiceImpl implements ProfileService { private static final String PROFILE_DIRECTORY = "profiles"; - private final ProfileRepository profileRepository; private final ResourceTypeRepository typeRepository; private final RequestProcessingExceptionBuilder exceptionBuilder; - private final ObjectMapper objectMapper; @Override @Transactional @@ -69,7 +66,7 @@ public List getMetadataByResourceType(String resourceTypeUri) { private void saveProfile(Path file) { try (var inputStream = Files.newInputStream(file)) { - var profile = objectMapper.readValue(inputStream, ProfileDto.class); + var profile = JSON_MAPPER.readValue(inputStream, ProfileDto.class); var profileEntity = toProfileEntity(profile); profileRepository.save(profileEntity); } catch (IOException e) { @@ -77,9 +74,9 @@ private void saveProfile(Path file) { } } - private Profile toProfileEntity(ProfileDto profileDto) throws JsonProcessingException { + private Profile toProfileEntity(ProfileDto profileDto) { var resourceType = typeRepository.findByUri(profileDto.resourceType()); - var profileContent = objectMapper.writeValueAsString(profileDto.value()); + var profileContent = JSON_MAPPER.writeValueAsString(profileDto.value()); var additionalTypes = isEmpty(profileDto.additionalResourceTypes()) ? Set.of() : profileDto.additionalResourceTypes().stream().map(typeRepository::findByUri).collect(toSet()); diff --git a/src/main/java/org/folio/linked/data/service/profile/ProfileSettingsServiceImpl.java b/src/main/java/org/folio/linked/data/service/profile/ProfileSettingsServiceImpl.java index a8d6eabfa..d7747db89 100644 --- a/src/main/java/org/folio/linked/data/service/profile/ProfileSettingsServiceImpl.java +++ b/src/main/java/org/folio/linked/data/service/profile/ProfileSettingsServiceImpl.java @@ -1,7 +1,7 @@ package org.folio.linked.data.service.profile; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; + import java.util.UUID; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; @@ -16,6 +16,7 @@ import org.folio.linked.data.repo.ProfileSettingsRepository; import org.folio.spring.FolioExecutionContext; import org.springframework.stereotype.Service; +import tools.jackson.core.JacksonException; @Service @RequiredArgsConstructor @@ -25,7 +26,6 @@ public class ProfileSettingsServiceImpl implements ProfileSettingsService { private final ProfileRepository profileRepository; private final RequestProcessingExceptionBuilder exceptionBuilder; private final FolioExecutionContext executionContext; - private final ObjectMapper objectMapper; @Override public CustomProfileSettingsResponseDto getProfileSettings(Integer profileId) { @@ -33,10 +33,8 @@ public CustomProfileSettingsResponseDto getProfileSettings(Integer profileId) { profileRepository.findById(profileId) .orElseThrow(() -> exceptionBuilder.notFoundLdResourceByIdException("Profile", String.valueOf(profileId))); var settings = profileSettingsRepository.getByIdUserIdAndIdProfileId(userId, profileId); - if (settings.isPresent()) { - return toDto(profileId, userId, settings.get()); - } - return defaultToProfile(profileId); + return settings.map(profileSettings -> toDto(profileId, userId, profileSettings)) + .orElseGet(() -> defaultToProfile(profileId)); } @Override @@ -47,7 +45,7 @@ public void setProfileSettings(Integer profileId, CustomProfileSettingsRequestDt try { var settings = toEntity(profile, userId, profileSettingsRequest); profileSettingsRepository.save(settings); - } catch (JsonProcessingException e) { + } catch (JacksonException e) { throw exceptionBuilder.badRequestException("Could not process settings", String.valueOf(profileId)); } } @@ -64,23 +62,22 @@ private CustomProfileSettingsResponseDto defaultToProfile(Integer profileId) { private CustomProfileSettingsResponseDto toDto(Integer profileId, UUID userId, ProfileSettings settings) { try { - var customProfileSettings = objectMapper.readValue(settings.getSettings(), CustomProfileSettings.class); + var customProfileSettings = JSON_MAPPER.readValue(settings.getSettings(), CustomProfileSettings.class); return new CustomProfileSettingsResponseDto( profileId, customProfileSettings.getActive(), customProfileSettings.getChildren()); - } catch (JsonProcessingException e) { + } catch (JacksonException e) { log.error("Could not read stored profile settings (user: {}, profile: {}) - default to profile", userId, profileId); return defaultToProfile(profileId); } } - private ProfileSettings toEntity(Profile profile, UUID userId, CustomProfileSettingsRequestDto requestDto) - throws JsonProcessingException { + private ProfileSettings toEntity(Profile profile, UUID userId, CustomProfileSettingsRequestDto requestDto) { return new ProfileSettings() .setId(new ProfileSettingsPk(userId, profile.getId())) .setProfile(profile) - .setSettings(objectMapper.writeValueAsString(requestDto)); + .setSettings(JSON_MAPPER.writeValueAsString(requestDto)); } } diff --git a/src/main/java/org/folio/linked/data/service/resource/copy/ResourceCopyServiceImpl.java b/src/main/java/org/folio/linked/data/service/resource/copy/ResourceCopyServiceImpl.java index 0d339af78..788d01f25 100644 --- a/src/main/java/org/folio/linked/data/service/resource/copy/ResourceCopyServiceImpl.java +++ b/src/main/java/org/folio/linked/data/service/resource/copy/ResourceCopyServiceImpl.java @@ -13,20 +13,18 @@ import static org.folio.ld.dictionary.PropertyDictionary.REFERENCES; import static org.folio.ld.dictionary.ResourceTypeDictionary.INSTANCE; import static org.folio.ld.dictionary.ResourceTypeDictionary.WORK; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.service.resource.edge.ResourceEdgeService; import org.springframework.stereotype.Service; +import tools.jackson.core.type.TypeReference; +import tools.jackson.databind.JsonNode; @RequiredArgsConstructor @Service @@ -51,7 +49,6 @@ public class ResourceCopyServiceImpl implements ResourceCopyService { ); private final ResourceEdgeService resourceEdgeService; - private final ObjectMapper objectMapper; @Override public void copyEdgesAndProperties(Resource old, Resource updated) { @@ -60,7 +57,6 @@ public void copyEdgesAndProperties(Resource old, Resource updated) { copyProperties(old, updated); } - @SneakyThrows private void copyProperties(Resource from, Resource to) { if (from.getDoc() == null) { return; @@ -69,14 +65,14 @@ private void copyProperties(Resource from, Resource to) { if (!properties.isEmpty()) { var toDoc = to.getDoc() == null ? new HashMap>() - : objectMapper.treeToValue(to.getDoc(), new TypeReference>>() {}); + : JSON_MAPPER.treeToValue(to.getDoc(), new TypeReference>>() {}); properties.forEach(entry -> toDoc.put(entry.getKey(), entry.getValue())); - to.setDoc(objectMapper.convertValue(toDoc, JsonNode.class)); + to.setDoc(JSON_MAPPER.convertValue(toDoc, JsonNode.class)); } } - private List>> getProperties(Resource from) throws JsonProcessingException { - var fromDoc = objectMapper.treeToValue(from.getDoc(), new TypeReference>>() {}); + private List>> getProperties(Resource from) { + var fromDoc = JSON_MAPPER.treeToValue(from.getDoc(), new TypeReference>>() {}); var fromType = from.getTypes() .stream() .findFirst() diff --git a/src/main/java/org/folio/linked/data/service/resource/graph/ResourceGraphServiceImpl.java b/src/main/java/org/folio/linked/data/service/resource/graph/ResourceGraphServiceImpl.java index 58356c8f9..9c4e28409 100644 --- a/src/main/java/org/folio/linked/data/service/resource/graph/ResourceGraphServiceImpl.java +++ b/src/main/java/org/folio/linked/data/service/resource/graph/ResourceGraphServiceImpl.java @@ -9,7 +9,6 @@ import static org.folio.linked.data.util.ResourceUtils.isPreferred; import static org.springframework.transaction.annotation.Propagation.REQUIRES_NEW; -import com.fasterxml.jackson.databind.JsonNode; import java.util.LinkedHashSet; import java.util.Set; import java.util.function.Function; @@ -29,6 +28,7 @@ import org.folio.linked.data.util.JsonUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import tools.jackson.databind.JsonNode; @Log4j2 @Service diff --git a/src/main/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceImpl.java b/src/main/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceImpl.java index 2d60b1b9f..21c047585 100644 --- a/src/main/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceImpl.java +++ b/src/main/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceImpl.java @@ -5,11 +5,8 @@ import static org.folio.linked.data.domain.dto.AssignmentCheckResponseDto.InvalidAssignmentReasonEnum.NOT_VALID_FOR_TARGET; import static org.folio.linked.data.domain.dto.AssignmentCheckResponseDto.InvalidAssignmentReasonEnum.UNSUPPORTED_MARC; import static org.folio.linked.data.util.Constants.MSG_NOT_FOUND_IN; -import static org.folio.linked.data.util.JsonUtils.writeValueAsString; import static org.folio.linked.data.util.ResourceUtils.setPreferred; -import com.fasterxml.jackson.databind.ObjectMapper; -import feign.FeignException; import java.util.Objects; import java.util.Optional; import java.util.function.Function; @@ -31,6 +28,7 @@ import org.folio.linked.data.repo.ResourceRepository; import org.folio.linked.data.service.resource.graph.ResourceGraphService; import org.folio.linked.data.service.resource.graph.SaveGraphResult; +import org.folio.linked.data.util.JsonUtils; import org.folio.marc4ld.service.marc2ld.authority.MarcAuthority2ldMapper; import org.folio.rest.jaxrs.model.ParsedRecord; import org.folio.rest.jaxrs.model.Record; @@ -38,6 +36,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.HttpClientErrorException; @Log4j2 @Service @@ -46,7 +45,6 @@ public class ResourceMarcAuthorityServiceImpl implements ResourceMarcAuthorityService { private final SrsClient srsClient; - private final ObjectMapper objectMapper; private final ResourceRepository resourceRepo; private final ResourceModelMapper resourceModelMapper; private final ResourceGraphService resourceGraphService; @@ -93,7 +91,7 @@ public Resource importResourceFromSrs(String srsId) { .map(resourceGraphService::saveMergingGraph) .map(SaveGraphResult::rootResource) .orElseThrow(() -> notFoundException(srsId)); - } catch (FeignException.NotFound e) { + } catch (HttpClientErrorException e) { log.error("Failed to convert authority with srsId [{}] into graph resource", srsId, e); throw notFoundException(srsId); } @@ -105,7 +103,7 @@ public Optional fetchResourceFromSrsByIn return ofNullable(srsClient.getAuthorityByInventoryId(inventoryId)) .flatMap(this::contentAsJsonString) .flatMap(this::firstAuthorityToModel); - } catch (FeignException.NotFound e) { + } catch (HttpClientErrorException e) { log.error("Authority with inventoryId [{}] not found in SRS", inventoryId); return Optional.empty(); } @@ -115,7 +113,7 @@ private Optional contentAsJsonString(ResponseEntity response) { return ofNullable(response.getBody()) .map(Record::getParsedRecord) .map(ParsedRecord::getContent) - .map(c -> writeValueAsString(c, objectMapper)); + .map(JsonUtils::writeValueAsString); } private Optional firstAuthorityToModel(String marcJson) { diff --git a/src/main/java/org/folio/linked/data/service/resource/marc/ResourceMarcBibServiceImpl.java b/src/main/java/org/folio/linked/data/service/resource/marc/ResourceMarcBibServiceImpl.java index 44ea6bf7b..1c6785035 100644 --- a/src/main/java/org/folio/linked/data/service/resource/marc/ResourceMarcBibServiceImpl.java +++ b/src/main/java/org/folio/linked/data/service/resource/marc/ResourceMarcBibServiceImpl.java @@ -8,15 +8,13 @@ import static org.folio.linked.data.util.Constants.IS_NOT_FOUND; import static org.folio.linked.data.util.Constants.MSG_NOT_FOUND_IN; import static org.folio.linked.data.util.Constants.RESOURCE_WITH_GIVEN_ID; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; import static org.folio.linked.data.util.ResourceUtils.extractWorkFromInstance; import static org.folio.linked.data.util.ResourceUtils.getTypeUris; -import com.fasterxml.jackson.databind.ObjectMapper; -import feign.FeignException; import java.util.Map; import java.util.Optional; import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; import org.folio.linked.data.domain.dto.ResourceIdDto; import org.folio.linked.data.domain.dto.ResourceMarcViewDto; @@ -45,6 +43,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.HttpClientErrorException; @Log4j2 @Service @@ -53,7 +52,6 @@ public class ResourceMarcBibServiceImpl implements ResourceMarcBibService { private final SrsClient srsClient; - private final ObjectMapper objectMapper; private final Ld2MarcMapper ld2MarcMapper; private final ResourceRepository resourceRepo; private final ResourceEdgeRepository edgeRepo; @@ -176,7 +174,7 @@ private RequestProcessingException createSrNotFoundException(String inventoryId) private Optional> getRecord(String inventoryId) { try { return Optional.of(srsClient.getSourceStorageInstanceRecordById(inventoryId)); - } catch (FeignException.NotFound e) { + } catch (HttpClientErrorException e) { return Optional.empty(); } } @@ -190,9 +188,8 @@ private Optional getResource(String inve .flatMap(marcBib2ldMapper::fromMarcJson); } - @SneakyThrows private String toJsonString(Object content) { - return objectMapper.writeValueAsString(content); + return JSON_MAPPER.writeValueAsString(content); } private Resource saveAndPublishEvents(org.folio.ld.dictionary.model.Resource modelResource) { diff --git a/src/main/java/org/folio/linked/data/service/tenant/TenantScopedExecutionService.java b/src/main/java/org/folio/linked/data/service/tenant/TenantScopedExecutionService.java index 1baa9e36a..a922dc86f 100644 --- a/src/main/java/org/folio/linked/data/service/tenant/TenantScopedExecutionService.java +++ b/src/main/java/org/folio/linked/data/service/tenant/TenantScopedExecutionService.java @@ -6,6 +6,7 @@ import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.function.Consumer; @@ -15,14 +16,17 @@ import org.apache.kafka.common.header.Header; import org.apache.kafka.common.header.Headers; import org.folio.spring.FolioExecutionContext; +import org.folio.spring.integration.XOkapiHeaders; import org.folio.spring.scope.FolioExecutionContextSetter; import org.folio.spring.service.SystemUserScopedExecutionService; import org.folio.spring.tools.context.ExecutionContextBuilder; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Profile; +import org.springframework.core.retry.RetryException; +import org.springframework.core.retry.RetryTemplate; +import org.springframework.core.retry.Retryable; import org.springframework.messaging.MessageHeaders; -import org.springframework.retry.RetryContext; -import org.springframework.retry.support.RetryTemplate; import org.springframework.stereotype.Service; @Service @@ -32,60 +36,58 @@ public class TenantScopedExecutionService { @Qualifier(DEFAULT_KAFKA_RETRY_TEMPLATE_NAME) private final RetryTemplate retryTemplate; private final ExecutionContextBuilder contextBuilder; + @SuppressWarnings({"removal"}) private final SystemUserScopedExecutionService executionService; + @Value("${folio.okapi-url}") + private String okapiUrl; @SneakyThrows public T execute(String tenantId, Callable job) { - try (var fex = new FolioExecutionContextSetter(dbOnlyContext(tenantId))) { + try (var fex = new FolioExecutionContextSetter(tenantContext(tenantId))) { return job.call(); } } - public void execute(String tenantId, Runnable job) { - try (var fex = new FolioExecutionContextSetter(dbOnlyContext(tenantId))) { - job.run(); - } - } - - public void executeWithRetry(Headers headers, Consumer job, Consumer failureHandler) { + public void executeWithRetry(Headers headers, Retryable retryable, Consumer failureHandler) { try (var fex = new FolioExecutionContextSetter(kafkaFolioExecutionContext(headers))) { - retryTemplate.execute( - context -> runJob(job, context), - context -> handleError(failureHandler, context) - ); + retryTemplate.execute(retryable); + } catch (RetryException re) { + failureHandler.accept(re.getLastException()); } } - public void executeWithRetrySystemUser(String tenant, - Consumer job, - Consumer failureHandler) { + public void executeWithRetrySystemUser(String tenant, + Retryable retryable, + Consumer failureHandler) { + //noinspection removal executionService.executeSystemUserScoped(tenant, () -> { - retryTemplate.execute( - context -> runJob(job, context), - context -> handleError(failureHandler, context) - ); + try { + retryTemplate.execute( + () -> retryTemplate.execute(retryable) + ); + } catch (Throwable t) { + failureHandler.accept(t); + } return null; }); } - private boolean runJob(Consumer job, RetryContext context) { - job.accept(context); - return true; - } - - private boolean handleError(Consumer failureHandler, RetryContext context) { - failureHandler.accept(context.getLastThrowable()); - return false; - } - private FolioExecutionContext kafkaFolioExecutionContext(Headers headers) { var headersMap = Arrays.stream(headers.toArray()) .collect(toMap(Header::key, Header::value, (o, o2) -> o2, (Supplier>) HashMap::new)); return contextBuilder.forMessageHeaders(new MessageHeaders(headersMap)); } - public FolioExecutionContext dbOnlyContext(String tenantId) { - return contextBuilder.builder().withTenantId(tenantId).build(); + private FolioExecutionContext tenantContext(String tenantId) { + return contextBuilder.builder() + .withTenantId(tenantId) + .withOkapiUrl(okapiUrl) + .withOkapiHeaders(Map.of( + XOkapiHeaders.TENANT, List.of(tenantId), + XOkapiHeaders.URL, List.of(okapiUrl) + ) + ) + .build(); } } diff --git a/src/main/java/org/folio/linked/data/util/DtoDeserializer.java b/src/main/java/org/folio/linked/data/util/DtoDeserializer.java index 6134ab4d5..d6bb9709f 100644 --- a/src/main/java/org/folio/linked/data/util/DtoDeserializer.java +++ b/src/main/java/org/folio/linked/data/util/DtoDeserializer.java @@ -1,38 +1,30 @@ package org.folio.linked.data.util; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import java.io.IOException; import java.util.Map; import lombok.RequiredArgsConstructor; -import org.folio.linked.data.exception.RequestProcessingExceptionBuilder; +import org.folio.linked.data.exception.JsonMappingException; +import tools.jackson.core.JsonParser; +import tools.jackson.databind.DeserializationContext; +import tools.jackson.databind.JsonNode; @RequiredArgsConstructor public class DtoDeserializer { private final Class dtoClass; private final Map> identityMap; - private final RequestProcessingExceptionBuilder exceptionBuilder; - public D deserialize(JsonParser jp) - throws IOException { - JsonNode node = jp.getCodec().readTree(jp); - return identityMap.entrySet() - .stream() - .filter(entry -> node.has(entry.getKey())) - .map(Map.Entry::getValue) - .map(clazz -> deserialize(jp, node, clazz)) - .findFirst() - .orElseThrow(() -> exceptionBuilder.mappingException(dtoClass.getSimpleName(), String.valueOf(node))); - } - - - private T deserialize(JsonParser jp, JsonNode node, Class clazz) { + public D deserialize(JsonParser jp, DeserializationContext dc) { try { - return jp.getCodec().treeToValue(node, clazz); - } catch (JsonProcessingException e) { - throw exceptionBuilder.mappingException(clazz.getSimpleName(), String.valueOf(node)); + JsonNode node = jp.readValueAsTree(); + return identityMap.entrySet() + .stream() + .filter(entry -> node.has(entry.getKey())) + .map(Map.Entry::getValue) + .map(clazz -> dc.readTreeAsValue(node, clazz)) + .findFirst() + .orElseThrow(() -> new JsonMappingException(dtoClass.getSimpleName(), String.valueOf(node))); + } catch (Exception e) { + throw new JsonMappingException(dtoClass.getSimpleName(), "Failed to parse JSON: " + e.getMessage()); } } diff --git a/src/main/java/org/folio/linked/data/util/JsonUtils.java b/src/main/java/org/folio/linked/data/util/JsonUtils.java index 1565639e8..adc4d591e 100644 --- a/src/main/java/org/folio/linked/data/util/JsonUtils.java +++ b/src/main/java/org/folio/linked/data/util/JsonUtils.java @@ -1,11 +1,8 @@ package org.folio.linked.data.util; +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_EMPTY; import static org.apache.commons.lang3.StringUtils.isAnyBlank; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.Option; @@ -14,14 +11,43 @@ import java.util.Optional; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import lombok.SneakyThrows; import lombok.experimental.UtilityClass; import lombok.extern.log4j.Log4j2; +import org.folio.linked.data.configuration.json.deserialization.ResourceRequestFieldDeserializer; +import org.folio.linked.data.configuration.json.deserialization.event.SourceRecordDomainEventDeserializer; +import org.folio.linked.data.configuration.json.deserialization.instance.IdentifierFieldDeserializer; +import org.folio.linked.data.configuration.json.deserialization.title.TitleFieldRequestDeserializer; +import org.folio.linked.data.configuration.json.serialization.MarcRecordSerializationConfig; +import org.folio.linked.data.domain.dto.IdentifierField; +import org.folio.linked.data.domain.dto.MarcRecord; +import org.folio.linked.data.domain.dto.ResourceRequestField; +import org.folio.linked.data.domain.dto.SourceRecordDomainEvent; +import org.folio.linked.data.domain.dto.TitleFieldRequestTitleInner; +import tools.jackson.databind.DeserializationFeature; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.SerializationFeature; +import tools.jackson.databind.json.JsonMapper; +import tools.jackson.databind.module.SimpleModule; +import tools.jackson.databind.node.ArrayNode; +import tools.jackson.databind.node.ObjectNode; @Log4j2 @UtilityClass public class JsonUtils { + public static final JsonMapper JSON_MAPPER = JsonMapper.builder() + .changeDefaultPropertyInclusion(incl -> incl.withValueInclusion(NON_EMPTY)) + .configure(SerializationFeature.USE_EQUALITY_FOR_OBJECT_ID, true) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true) + .addMixIn(MarcRecord.class, MarcRecordSerializationConfig.class) + .addModule(new SimpleModule() + .addDeserializer(ResourceRequestField.class, new ResourceRequestFieldDeserializer()) + .addDeserializer(TitleFieldRequestTitleInner.class, new TitleFieldRequestDeserializer()) + .addDeserializer(IdentifierField.class, new IdentifierFieldDeserializer()) + .addDeserializer(SourceRecordDomainEvent.class, new SourceRecordDomainEventDeserializer())) + .build(); + private static final Configuration JSONPATH_CONFIG = Configuration.builder() .options(Option.SUPPRESS_EXCEPTIONS) .build(); @@ -40,9 +66,8 @@ public static Optional getElementByJsonPath(String json, String jsonPath, return Optional.ofNullable(JsonPath.using(JSONPATH_CONFIG).parse(json).read(jsonPath, type)); } - @SneakyThrows - public static String writeValueAsString(Object obj, ObjectMapper objectMapper) { - return obj instanceof String str ? str : objectMapper.writeValueAsString(obj); + public static String writeValueAsString(Object obj) { + return obj instanceof String str ? str : JSON_MAPPER.writeValueAsString(obj); } /** @@ -88,10 +113,12 @@ private static JsonNode mergeNodes(JsonNode existing, JsonNode incoming) { if (anyNonObject(existing, incoming)) { return existing; } - var copyOfExisting = existing.deepCopy(); - incoming.fieldNames().forEachRemaining(incomingFieldName -> { + var copyOfExisting = (ObjectNode) existing.deepCopy(); + + incoming.properties().forEach(entry -> { + var incomingFieldName = entry.getKey(); + var incomingField = entry.getValue(); var existingField = copyOfExisting.get(incomingFieldName); - var incomingField = incoming.get(incomingFieldName); if (isNull(existingField) && nonNull(incomingField)) { copyOfExisting.set(incomingFieldName, incomingField.deepCopy()); } else if (allArray(existingField, incomingField)) { @@ -108,16 +135,16 @@ private static ArrayNode mergeArrays(ArrayNode existingArray, ArrayNode incoming } private static void addIfNotExist(ArrayNode array, JsonNode node) { - if (node.isTextual() && arrayNotContainsElement(array, node)) { + if (node.stringValue() != null && arrayNotContainsElement(array, node)) { array.add(node); } } private static boolean arrayNotContainsElement(ArrayNode array, JsonNode value) { return StreamSupport.stream(array.spliterator(), false) - .filter(JsonNode::isTextual) - .map(JsonNode::asText) - .noneMatch(text -> text.equals(value.asText())); + .filter(node -> node.stringValue() != null) + .map(JsonNode::textValue) + .noneMatch(text -> text.equals(value.stringValue())); } private static boolean allArray(JsonNode... nodes) { diff --git a/src/main/java/org/folio/linked/data/util/ResourceUtils.java b/src/main/java/org/folio/linked/data/util/ResourceUtils.java index 256be1aa4..7378364f8 100644 --- a/src/main/java/org/folio/linked/data/util/ResourceUtils.java +++ b/src/main/java/org/folio/linked/data/util/ResourceUtils.java @@ -13,9 +13,6 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.INSTANCE; import static org.folio.ld.dictionary.ResourceTypeDictionary.WORK; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeParseException; @@ -35,6 +32,9 @@ import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.model.entity.ResourceEdge; import org.folio.linked.data.model.entity.ResourceTypeEntity; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.node.JsonNodeFactory; +import tools.jackson.databind.node.ObjectNode; @Log4j2 @UtilityClass @@ -183,7 +183,7 @@ public static JsonNode copyWithoutPreferred(Resource subject) { public static List getPropertyValues(Resource resource, PropertyDictionary property) { return ofNullable(resource.getDoc()) .map(doc -> doc.get(property.getValue())) - .map(node -> stream(node.spliterator(), false).map(JsonNode::asText).toList()) + .map(node -> stream(node.spliterator(), false).map(JsonNode::asString).toList()) .orElse(List.of()); } diff --git a/src/main/java/org/folio/linked/data/validation/entity/PrimaryTitleEntityValidator.java b/src/main/java/org/folio/linked/data/validation/entity/PrimaryTitleEntityValidator.java index b124d3443..eed02247e 100644 --- a/src/main/java/org/folio/linked/data/validation/entity/PrimaryTitleEntityValidator.java +++ b/src/main/java/org/folio/linked/data/validation/entity/PrimaryTitleEntityValidator.java @@ -8,13 +8,13 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.TITLE; import static org.folio.ld.dictionary.ResourceTypeDictionary.WORK; -import com.fasterxml.jackson.databind.JsonNode; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import org.folio.ld.dictionary.PredicateDictionary; import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.model.entity.ResourceEdge; import org.folio.linked.data.validation.PrimaryTitleConstraint; +import tools.jackson.databind.JsonNode; public class PrimaryTitleEntityValidator implements ConstraintValidator { diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 357dd4bd8..53995bb42 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -5,12 +5,6 @@ spring: password: folio_admin kafka: bootstrap-servers: localhost:29092 - cloud: - openfeign: - client: - config: - search: - url: http://localhost:9130/search management: endpoints: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f4ca6f453..d9b16723c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,10 +1,6 @@ spring: application: name: mod-linked-data - cloud: - openfeign: - okhttp: - enabled: true datasource: username: ${DB_USERNAME:postgres} password: ${DB_PASSWORD:postgres} @@ -46,6 +42,8 @@ spring: folio: environment: ${ENV:folio} + exchange: + enabled: true okapiUrl: ${okapi.url} tenant: validation: @@ -53,10 +51,9 @@ folio: logging: request: enabled: true - feign: + exchange: enabled: true - retry: - enabled: true + level: BASIC kafka: listener: source-record-domain-event: @@ -83,6 +80,8 @@ folio: system-user: username: mod-linked-data # This isn't actually used, but we get dependency injection errors from folio-spring-system-user if we don't have it password: dummy # This isn't actually used, but we get dependency injection errors from folio-spring-system-user if we don't have it + retry: + enabled: true mod-linked-data: authority-source-files: diff --git a/src/main/resources/swagger.api/schema/resource/request/TitleFieldRequest.json b/src/main/resources/swagger.api/schema/resource/request/TitleFieldRequest.json index e6deb092a..abbe0a3be 100644 --- a/src/main/resources/swagger.api/schema/resource/request/TitleFieldRequest.json +++ b/src/main/resources/swagger.api/schema/resource/request/TitleFieldRequest.json @@ -49,6 +49,5 @@ "x-json-property": "http://bibfra.me/vocab/library/title", "x-field-extra-annotation": "@org.folio.linked.data.validation.PrimaryTitleConstraint" } - }, - "required": ["title"] + } } diff --git a/src/test/java/org/folio/linked/data/configuration/FeignRequestInterceptorTest.java b/src/test/java/org/folio/linked/data/configuration/FeignRequestInterceptorTest.java deleted file mode 100644 index b5a651a44..000000000 --- a/src/test/java/org/folio/linked/data/configuration/FeignRequestInterceptorTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.folio.linked.data.configuration; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.entry; -import static org.folio.linked.data.test.TestUtil.randomString; -import static org.folio.spring.integration.XOkapiHeaders.TENANT; -import static org.folio.spring.integration.XOkapiHeaders.TOKEN; -import static org.mockito.Mockito.when; - -import feign.RequestTemplate; -import java.util.Collections; -import org.folio.spring.FolioExecutionContext; -import org.folio.spring.testing.type.UnitTest; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -@UnitTest -@ExtendWith(MockitoExtension.class) -class FeignRequestInterceptorTest { - - @InjectMocks - private FeignRequestInterceptor feignRequestInterceptor; - @Mock - private FolioExecutionContext folioExecutionContext; - - @Test - void apply_shouldSetTokenAndTenantHeaders() { - // given - var requestTemplate = new RequestTemplate(); - var tenantId = randomString(); - var token = randomString(); - when(folioExecutionContext.getTenantId()).thenReturn(tenantId); - when(folioExecutionContext.getToken()).thenReturn(token); - - // when - feignRequestInterceptor.apply(requestTemplate); - - // then - assertThat(requestTemplate.headers()).contains(entry(TENANT, Collections.singletonList(tenantId))); - assertThat(requestTemplate.headers()).contains(entry(TOKEN, Collections.singletonList(token))); - } -} diff --git a/src/test/java/org/folio/linked/data/configuration/json/ObjectMapperConfigTest.java b/src/test/java/org/folio/linked/data/configuration/json/JsonMapperConfigTest.java similarity index 73% rename from src/test/java/org/folio/linked/data/configuration/json/ObjectMapperConfigTest.java rename to src/test/java/org/folio/linked/data/configuration/json/JsonMapperConfigTest.java index 53df6d472..2f4cfa36d 100644 --- a/src/test/java/org/folio/linked/data/configuration/json/ObjectMapperConfigTest.java +++ b/src/test/java/org/folio/linked/data/configuration/json/JsonMapperConfigTest.java @@ -2,11 +2,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.ld.dictionary.ResourceTypeDictionary.INSTANCE; -import static org.folio.linked.data.test.TestUtil.EMPTY_EXCEPTION_BUILDER; import static org.folio.linked.data.test.TestUtil.loadResourceAsString; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import org.folio.linked.data.domain.dto.ImportOutputEvent; import org.folio.linked.data.domain.dto.MarcRecord; @@ -14,12 +12,10 @@ import org.junit.jupiter.api.Test; @UnitTest -class ObjectMapperConfigTest { - - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapperConfig().objectMapper(EMPTY_EXCEPTION_BUILDER); +class JsonMapperConfigTest { @Test - void serializationStringFieldMarkedAsRaw_shouldReturnOriginalString() throws JsonProcessingException { + void serializationStringFieldMarkedAsRaw_shouldReturnOriginalString() { // given var jsonField = """ {"raw": "some value"}"""; @@ -29,7 +25,7 @@ void serializationStringFieldMarkedAsRaw_shouldReturnOriginalString() throws Jso {"content":{"raw": "some value"}}"""; // when - var jsonString = OBJECT_MAPPER.writeValueAsString(markRecord); + var jsonString = JSON_MAPPER.writeValueAsString(markRecord); // then assertThat(jsonString) @@ -37,7 +33,7 @@ void serializationStringFieldMarkedAsRaw_shouldReturnOriginalString() throws Jso } @Test - void serializationStringFieldNotMarkedAsRaw_shouldReturnFormattedString() throws JsonProcessingException { + void serializationStringFieldNotMarkedAsRaw_shouldReturnFormattedString() { // given var jsonField = """ {"raw": "some value"}"""; @@ -47,7 +43,7 @@ void serializationStringFieldNotMarkedAsRaw_shouldReturnFormattedString() throws {"content":"{\\"raw\\": \\"some value\\"}"}"""; // when - var jsonString = OBJECT_MAPPER.writeValueAsString(notMarcRecord); + var jsonString = JSON_MAPPER.writeValueAsString(notMarcRecord); // then assertThat(jsonString) @@ -60,12 +56,12 @@ private static class TestClass { } @Test - void importOutputEventDeserialization() throws JsonProcessingException { + void importOutputEventDeserialization() { // given var value = loadResourceAsString("samples/importOutputEvent.json"); // when - var result = OBJECT_MAPPER.readValue(value, ImportOutputEvent.class); + var result = JSON_MAPPER.readValue(value, ImportOutputEvent.class); // then assertThat(result.getTs()).isEqualTo("1762182290977"); diff --git a/src/test/java/org/folio/linked/data/configuration/json/deserialization/event/SourceRecordDomainEventDeserializerTest.java b/src/test/java/org/folio/linked/data/configuration/json/deserialization/event/SourceRecordDomainEventDeserializerTest.java index e900825b8..6018e5e65 100644 --- a/src/test/java/org/folio/linked/data/configuration/json/deserialization/event/SourceRecordDomainEventDeserializerTest.java +++ b/src/test/java/org/folio/linked/data/configuration/json/deserialization/event/SourceRecordDomainEventDeserializerTest.java @@ -3,7 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.linked.data.domain.dto.SourceRecord.StateEnum.ACTUAL; import static org.folio.linked.data.domain.dto.SourceRecordDomainEvent.EventTypeEnum.SOURCE_RECORD_CREATED; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.loadResourceAsString; import org.folio.spring.testing.type.UnitTest; @@ -12,13 +12,12 @@ @UnitTest class SourceRecordDomainEventDeserializerTest { - private final SourceRecordDomainEventDeserializer deserializer = - new SourceRecordDomainEventDeserializer(OBJECT_MAPPER); + private final SourceRecordDomainEventDeserializer deserializer = new SourceRecordDomainEventDeserializer(); @Test - void deserialize_shouldReturnCorrectlyMappedEvent() throws Exception { + void deserialize_shouldReturnCorrectlyMappedEvent() { // given - var jsonParser = OBJECT_MAPPER.createParser(loadResourceAsString("samples/srsDomainEvent.json")); + var jsonParser = TEST_JSON_MAPPER.createParser(loadResourceAsString("samples/srsDomainEvent.json")); // when var deserializedEvent = deserializer.deserialize(jsonParser, null); diff --git a/src/test/java/org/folio/linked/data/configuration/json/serialization/RawValueJsonSerializerTest.java b/src/test/java/org/folio/linked/data/configuration/json/serialization/RawValueJsonSerializerTest.java index 749a75ce9..bf87f4aa1 100644 --- a/src/test/java/org/folio/linked/data/configuration/json/serialization/RawValueJsonSerializerTest.java +++ b/src/test/java/org/folio/linked/data/configuration/json/serialization/RawValueJsonSerializerTest.java @@ -2,9 +2,6 @@ import static org.mockito.Mockito.verify; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.SerializerProvider; -import java.io.IOException; import org.folio.spring.testing.type.UnitTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -12,6 +9,8 @@ import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.SerializationContext; @UnitTest @ExtendWith(MockitoExtension.class) @@ -22,12 +21,12 @@ class RawValueJsonSerializerTest { @Mock JsonGenerator gen; @Mock - SerializerProvider serializers; + SerializationContext ctx; @Test - void serializeNull_shouldWriteNull() throws IOException { + void serializeNull_shouldWriteNull() { //when - rawValueJsonSerializer.serialize(null, gen, serializers); + rawValueJsonSerializer.serialize(null, gen, ctx); //then verify(gen) @@ -36,9 +35,9 @@ void serializeNull_shouldWriteNull() throws IOException { @ParameterizedTest @ValueSource(strings = {"", " ", "some string"}) - void serializeNonNull_shouldWriteValue(String value) throws IOException { + void serializeNonNull_shouldWriteValue(String value) { //when - rawValueJsonSerializer.serialize(value, gen, serializers); + rawValueJsonSerializer.serialize(value, gen, ctx); //then verify(gen) diff --git a/src/test/java/org/folio/linked/data/e2e/AuthorityAssignmentControllerIT.java b/src/test/java/org/folio/linked/data/e2e/AuthorityAssignmentControllerIT.java index cef4abbd8..3534ad71b 100644 --- a/src/test/java/org/folio/linked/data/e2e/AuthorityAssignmentControllerIT.java +++ b/src/test/java/org/folio/linked/data/e2e/AuthorityAssignmentControllerIT.java @@ -1,5 +1,7 @@ package org.folio.linked.data.e2e; +import static org.folio.linked.data.domain.dto.AssignmentCheckDto.TargetEnum.CREATOR_OF_WORK; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.folio.linked.data.test.TestUtil.loadResourceAsString; import static org.hamcrest.Matchers.equalTo; @@ -8,7 +10,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.ObjectMapper; import org.folio.linked.data.domain.dto.AssignmentCheckDto; import org.folio.linked.data.e2e.base.IntegrationTest; import org.junit.jupiter.params.ParameterizedTest; @@ -28,9 +29,6 @@ class AuthorityAssignmentControllerIT { @Autowired private MockMvc mockMvc; - @Autowired - private ObjectMapper objectMapper; - @ParameterizedTest @CsvSource({ "samples/marc/authority_person.json, true", @@ -47,11 +45,9 @@ void authorityAssignmentCheck(String marcFile, String expectedResponse) throws E .accept(APPLICATION_JSON) .contentType(APPLICATION_JSON) .headers(defaultHeaders(env)) - .content( - objectMapper.writeValueAsString( - new AssignmentCheckDto( - loadResourceAsString(marcFile), - AssignmentCheckDto.TargetEnum.CREATOR_OF_WORK)) + .content(TEST_JSON_MAPPER.writeValueAsString( + new AssignmentCheckDto(loadResourceAsString(marcFile), CREATOR_OF_WORK) + ) ); // when diff --git a/src/test/java/org/folio/linked/data/e2e/ITBase.java b/src/test/java/org/folio/linked/data/e2e/ITBase.java index beb31894d..8c0d7c710 100644 --- a/src/test/java/org/folio/linked/data/e2e/ITBase.java +++ b/src/test/java/org/folio/linked/data/e2e/ITBase.java @@ -33,7 +33,10 @@ public void beforeEach() { if (isStandaloneTest(env)) { cleanResourceTables(jdbcTemplate); } else { - tenantScopedExecutionService.execute(TENANT_ID, () -> cleanResourceTables(jdbcTemplate)); + tenantScopedExecutionService.execute(TENANT_ID, () -> { + cleanResourceTables(jdbcTemplate); + return null; + }); } } } diff --git a/src/test/java/org/folio/linked/data/e2e/ReIndexControllerIT.java b/src/test/java/org/folio/linked/data/e2e/ReIndexControllerIT.java index 57e923bf2..de0bb6c60 100644 --- a/src/test/java/org/folio/linked/data/e2e/ReIndexControllerIT.java +++ b/src/test/java/org/folio/linked/data/e2e/ReIndexControllerIT.java @@ -12,19 +12,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.util.Date; -import lombok.SneakyThrows; import org.folio.linked.data.e2e.base.IntegrationTest; import org.folio.linked.data.model.entity.Resource; -import org.folio.linked.data.repo.ResourceEdgeRepository; import org.folio.linked.data.repo.ResourceRepository; -import org.folio.linked.data.service.tenant.TenantScopedExecutionService; import org.folio.linked.data.test.kafka.KafkaSearchWorkIndexTopicListener; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; -import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.web.servlet.MockMvc; @IntegrationTest @@ -37,15 +33,9 @@ class ReIndexControllerIT extends ITBase { @Autowired private ResourceRepository resourceRepo; @Autowired - private ResourceEdgeRepository resourceEdgeRepository; - @Autowired private Environment env; @Autowired private KafkaSearchWorkIndexTopicListener consumer; - @Autowired - private JdbcTemplate jdbcTemplate; - @Autowired - private TenantScopedExecutionService tenantScopedExecutionService; @BeforeEach @Override @@ -125,7 +115,6 @@ void indexResourceWithIndexDate_andFullIndexRequest() throws Exception { checkKafkaMessageSent(work); } - @SneakyThrows protected void checkKafkaMessageSent(Resource indexed) { if (nonNull(indexed)) { awaitAndAssert(() -> assertTrue(consumer.getMessages() diff --git a/src/test/java/org/folio/linked/data/e2e/base/IntegrationTest.java b/src/test/java/org/folio/linked/data/e2e/base/IntegrationTest.java index abdf42201..151cdcb97 100644 --- a/src/test/java/org/folio/linked/data/e2e/base/IntegrationTest.java +++ b/src/test/java/org/folio/linked/data/e2e/base/IntegrationTest.java @@ -12,9 +12,9 @@ import org.folio.spring.tools.kafka.FolioKafkaProperties; import org.folio.spring.tools.kafka.KafkaAdminService; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.kafka.autoconfigure.KafkaAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; @@ -28,7 +28,7 @@ @ActiveProfiles("test") @org.folio.spring.testing.type.IntegrationTest @ExtendWith(TenantInstallationExtension.class) -@SpringBootTest(classes = {KafkaAdminService.class, KafkaAutoConfiguration.class, - FolioKafkaProperties.class, LinkedDataTopicProperties.class, LinkedDataApplication.class}) +@SpringBootTest(classes = {KafkaAdminService.class, KafkaAutoConfiguration.class, FolioKafkaProperties.class, + LinkedDataTopicProperties.class, LinkedDataApplication.class}) public @interface IntegrationTest { } diff --git a/src/test/java/org/folio/linked/data/e2e/base/TenantInstallationExtension.java b/src/test/java/org/folio/linked/data/e2e/base/TenantInstallationExtension.java index 7e936525c..e05cc6f94 100644 --- a/src/test/java/org/folio/linked/data/e2e/base/TenantInstallationExtension.java +++ b/src/test/java/org/folio/linked/data/e2e/base/TenantInstallationExtension.java @@ -2,7 +2,7 @@ import static java.util.Arrays.asList; import static org.folio.linked.data.test.TestUtil.TENANT_ID; -import static org.folio.linked.data.test.TestUtil.asJsonString; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; import static org.springframework.http.MediaType.APPLICATION_JSON; @@ -33,7 +33,9 @@ public void beforeEach(ExtensionContext extensionContext) { if (!asList(env.getActiveProfiles()).contains(STANDALONE_PROFILE)) { var mockMvc = context.getBean(MockMvc.class); mockMvc.perform(post(TENANT_ENDPOINT_URI, TENANT_ID) - .content(asJsonString(new TenantAttributes().moduleTo(env.getProperty("spring.application.name")))) + .content(TEST_JSON_MAPPER.writeValueAsString( + new TenantAttributes().moduleTo(env.getProperty("spring.application.name")) + )) .headers(defaultHeaders(env)) .contentType(APPLICATION_JSON)) .andExpect(status().isNoContent()); diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/PostResourceIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/PostResourceIT.java index ac9d63bd1..2f6c719a6 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/PostResourceIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/PostResourceIT.java @@ -4,6 +4,7 @@ import static java.util.stream.StreamSupport.stream; import static org.assertj.core.api.Assertions.assertThat; import static org.folio.linked.data.test.TestUtil.STANDALONE_TEST_PROFILE; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; import static org.springframework.http.MediaType.APPLICATION_JSON; @@ -11,8 +12,6 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Set; import java.util.stream.Stream; @@ -29,6 +28,7 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; +import tools.jackson.databind.JsonNode; @IntegrationTest @ActiveProfiles({STANDALONE_PROFILE, STANDALONE_TEST_PROFILE}) @@ -43,8 +43,6 @@ public abstract class PostResourceIT extends ITBase { private Environment env; @Autowired private ResourceTestService resourceService; - @Autowired - private ObjectMapper objectMapper; protected abstract String postPayload(); @@ -83,7 +81,7 @@ void testPostRequest() throws Exception { @SneakyThrows private String getResourceId(ResultActions postResponse) { var postResponseContent = postResponse.andReturn().getResponse().getContentAsString(); - var resourceNode = objectMapper.readTree(postResponseContent).path("resource"); + var resourceNode = TEST_JSON_MAPPER.readTree(postResponseContent).path("resource"); return Stream.of( "http://bibfra.me/vocab/lite/Instance", @@ -92,7 +90,7 @@ private String getResourceId(ResultActions postResponse) { ) .filter(resourceNode::has) .findFirst() - .map(key -> resourceNode.path(key).path("id").asText()) + .map(key -> resourceNode.path(key).path("id").asString()) .orElseThrow(() -> new RuntimeException("No Instance, Work, or Hub node found in response")); } @@ -104,7 +102,7 @@ protected String getProperty(Resource resource, String property) { protected Set getProperties(Resource resource, String property) { return stream(resource.getDoc().get(property).spliterator(), false) - .map(JsonNode::asText) + .map(JsonNode::asString) .collect(toSet()); } diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/hub/creator/HubCreatorIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/hub/creator/HubCreatorIT.java index fed953a42..cfc4a481e 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/hub/creator/HubCreatorIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/hub/creator/HubCreatorIT.java @@ -1,10 +1,10 @@ package org.folio.linked.data.e2e.mappings.hub.creator; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.linked.data.e2e.mappings.PostResourceIT; @@ -20,8 +20,6 @@ class HubCreatorIT extends PostResourceIT { @Autowired private ResourceTestService resourceTestService; - @Autowired - private ObjectMapper objectMapper; @BeforeEach void createAuthority() { @@ -109,11 +107,10 @@ protected void validateGraph(Resource hub) { assertThat(contributor).isEqualTo(sponsoringBody); } - @SneakyThrows private void saveResource(Long id, String label, ResourceTypeDictionary type, String srsId) { var resource = new Resource() .addType(new ResourceTypeEntity().setHash(type.getHash()).setUri(type.getUri())) - .setDoc(objectMapper.readTree("{}")) + .setDoc(TEST_JSON_MAPPER.readTree("{}")) .setLabel(label) .setIdAndRefreshEdges(id); resource.setFolioMetadata(new FolioMetadata(resource).setSrsId(srsId)); diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/instance/identifier/IssnIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/instance/identifier/IssnIT.java index 0b468297c..3cc9b5780 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/instance/identifier/IssnIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/instance/identifier/IssnIT.java @@ -1,19 +1,15 @@ package org.folio.linked.data.e2e.mappings.instance.identifier; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import org.folio.linked.data.e2e.mappings.PostResourceIT; import org.folio.linked.data.model.entity.Resource; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.ResultActions; public class IssnIT extends PostResourceIT { - @Autowired - private ObjectMapper objectMapper; - @Override protected String postPayload() { return """ @@ -52,20 +48,20 @@ protected String postPayload() { protected void validateApiResponse(ResultActions apiResponse) { var responsePayload = apiResponse.andReturn().getResponse().getContentAsString(); - var issnNode = objectMapper.readTree(responsePayload) + var issnNode = TEST_JSON_MAPPER.readTree(responsePayload) .path("resource") .path("http://bibfra.me/vocab/lite/Instance") .path("http://library.link/vocab/map").get(0) .path("http://library.link/identifier/ISSN"); var issnValueNode = issnNode.path("http://bibfra.me/vocab/lite/name").get(0); - assertThat(issnValueNode.asText()).isEqualTo("1234567890"); + assertThat(issnValueNode.asString()).isEqualTo("1234567890"); var statusNode = issnNode.path("http://bibfra.me/vocab/library/status").get(0); var statusLink = statusNode.path("http://bibfra.me/vocab/lite/link").get(0); var statusLabel = statusNode.path("http://bibfra.me/vocab/lite/label").get(0); - assertThat(statusLink.asText()).isEqualTo("http://id.loc.gov/vocabulary/mstatus/current"); - assertThat(statusLabel.asText()).isEqualTo("current"); + assertThat(statusLink.asString()).isEqualTo("http://id.loc.gov/vocabulary/mstatus/current"); + assertThat(statusLabel.asString()).isEqualTo("current"); } @Override diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/instance/note/InstanceNotesIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/instance/note/InstanceNotesIT.java index 6bd87ca41..1a5d2c975 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/instance/note/InstanceNotesIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/instance/note/InstanceNotesIT.java @@ -1,19 +1,16 @@ package org.folio.linked.data.e2e.mappings.instance.note; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.Map; import lombok.SneakyThrows; import org.folio.linked.data.e2e.mappings.PostResourceIT; import org.folio.linked.data.model.entity.Resource; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.ResultActions; public class InstanceNotesIT extends PostResourceIT { - @Autowired - private ObjectMapper objectMapper; @Override protected String postPayload() { @@ -62,7 +59,7 @@ protected String postPayload() { @SneakyThrows protected void validateApiResponse(ResultActions apiResponse) { var responsePayload = apiResponse.andReturn().getResponse().getContentAsString(); - var notesResponse = objectMapper.readTree(responsePayload) + var notesResponse = TEST_JSON_MAPPER.readTree(responsePayload) .path("resource") .path("http://bibfra.me/vocab/lite/Instance") .path("_notes"); @@ -91,8 +88,8 @@ protected void validateApiResponse(ResultActions apiResponse) { var actualNotes = new HashMap<>(); for (var note : notesResponse) { - String type = note.get("type").get(0).asText(); - String value = note.get("value").get(0).asText(); + String type = note.get("type").get(0).asString(); + String value = note.get("value").get(0).asString(); actualNotes.put(type, value); } diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/instance/publicationfrequency/PublicationFrequencyIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/instance/publicationfrequency/PublicationFrequencyIT.java index 305f0440b..aeb317ebb 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/instance/publicationfrequency/PublicationFrequencyIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/instance/publicationfrequency/PublicationFrequencyIT.java @@ -1,19 +1,15 @@ package org.folio.linked.data.e2e.mappings.instance.publicationfrequency; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import org.folio.linked.data.e2e.mappings.PostResourceIT; import org.folio.linked.data.model.entity.Resource; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.ResultActions; public class PublicationFrequencyIT extends PostResourceIT { - @Autowired - private ObjectMapper objectMapper; - @Override protected String postPayload() { return """ @@ -44,16 +40,16 @@ protected String postPayload() { @SneakyThrows protected void validateApiResponse(ResultActions apiResponse) { var responsePayload = apiResponse.andReturn().getResponse().getContentAsString(); - var publicationFrequency = objectMapper.readTree(responsePayload) + var publicationFrequency = TEST_JSON_MAPPER.readTree(responsePayload) .path("resource") .path("http://bibfra.me/vocab/lite/Instance") .path("http://bibfra.me/vocab/library/publicationFrequency").get(0); var labelNode = publicationFrequency.path("http://bibfra.me/vocab/lite/label").get(0); var linkNode = publicationFrequency.path("http://bibfra.me/vocab/lite/link").get(0); var codeNote = publicationFrequency.path("http://bibfra.me/vocab/library/code").get(0); - assertThat(labelNode.asText()).isEqualTo("annual"); - assertThat(linkNode.asText()).isEqualTo("http://id.loc.gov/vocabulary/frequencies/ann"); - assertThat(codeNote.asText()).isEqualTo("a"); + assertThat(labelNode.asString()).isEqualTo("annual"); + assertThat(linkNode.asString()).isEqualTo("http://id.loc.gov/vocabulary/frequencies/ann"); + assertThat(codeNote.asString()).isEqualTo("a"); } @Override diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/work/characteristic/CharacteristicIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/work/characteristic/CharacteristicIT.java index c4a46fa95..fa299525d 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/work/characteristic/CharacteristicIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/work/characteristic/CharacteristicIT.java @@ -1,9 +1,8 @@ package org.folio.linked.data.e2e.mappings.work.characteristic; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -11,8 +10,8 @@ import lombok.SneakyThrows; import org.folio.linked.data.e2e.mappings.PostResourceIT; import org.folio.linked.data.model.entity.Resource; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.ResultActions; +import tools.jackson.core.type.TypeReference; class CharacteristicIT extends PostResourceIT { private static final long BLOG_ID = 4634629703061696745L; @@ -28,9 +27,6 @@ class CharacteristicIT extends PostResourceIT { private static final long REPOSITORY_ID = -4707533701123454052L; private static final long WEBSITE_ID = 2549344889486893314L; - @Autowired - private ObjectMapper objectMapper; - @Override protected String postPayload() { return """ @@ -98,7 +94,7 @@ protected void validateGraph(Resource work) { for (var resource : characteristicResources) { validateResourceType(resource, "http://bibfra.me/vocab/lite/Category"); - var actualDoc = objectMapper.convertValue(resource.getDoc(), new TypeReference>() {}); + var actualDoc = TEST_JSON_MAPPER.convertValue(resource.getDoc(), new TypeReference>() {}); var expectedDoc = expectedCharacteristics.get(resource.getId()); assertThat(actualDoc).isEqualTo(expectedDoc); } @@ -129,12 +125,12 @@ protected void validateApiResponse(ResultActions apiResponse) { .toList(); var responseJson = apiResponse.andReturn().getResponse().getContentAsString(); - var characteristicsNode = objectMapper.readTree(responseJson) + var characteristicsNode = TEST_JSON_MAPPER.readTree(responseJson) .path("resource") .path("http://bibfra.me/vocab/lite/Work") .path("http://bibfra.me/vocab/library/characteristic"); - var actual = objectMapper.convertValue(characteristicsNode, new TypeReference>>() {}); + var actual = TEST_JSON_MAPPER.convertValue(characteristicsNode, new TypeReference>>() {}); assertThat(actual).containsExactlyInAnyOrderElementsOf(expected); } diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/work/creator/WorkCreatorIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/work/creator/WorkCreatorIT.java index 18306988a..80f91682c 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/work/creator/WorkCreatorIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/work/creator/WorkCreatorIT.java @@ -2,10 +2,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.linked.data.e2e.mappings.PostResourceIT; @@ -20,8 +20,6 @@ class WorkCreatorIT extends PostResourceIT { @Autowired private ResourceTestService resourceTestService; - @Autowired - private ObjectMapper objectMapper; @BeforeEach void createAuthority() { @@ -114,11 +112,10 @@ protected void validateApiResponse(ResultActions apiResponse) { .value("http://bibfra.me/vocab/lite/Family")); } - @SneakyThrows private void saveResource(Long id, String label, ResourceTypeDictionary type, String srsId) { var resource = new Resource() .addType(new ResourceTypeEntity().setHash(type.getHash()).setUri(type.getUri())) - .setDoc(objectMapper.readTree("{}")) + .setDoc(TEST_JSON_MAPPER.readTree("{}")) .setLabel(label) .setIdAndRefreshEdges(id); resource.setFolioMetadata(new FolioMetadata(resource).setSrsId(srsId)); diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/work/hub/HubReferenceIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/work/hub/HubReferenceIT.java index 8bfcddd18..344aa5f45 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/work/hub/HubReferenceIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/work/hub/HubReferenceIT.java @@ -3,23 +3,19 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.ld.dictionary.ResourceTypeDictionary.HUB; import static org.folio.linked.data.test.TestUtil.FOLIO_OKAPI_URL; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import org.folio.linked.data.e2e.mappings.PostResourceIT; import org.folio.linked.data.model.entity.Resource; import org.junit.jupiter.api.BeforeEach; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.ResultActions; class HubReferenceIT extends PostResourceIT { public static final Long TEST_HUB_ID = 999L; - @Autowired - private ObjectMapper objectMapper; - @BeforeEach void createAuthority() { saveHub(TEST_HUB_ID); @@ -111,7 +107,7 @@ private void saveHub(Long id) { var hubLabel = "hub label 1"; var resource = new Resource() .addTypes(HUB) - .setDoc(objectMapper.readTree("{\"http://bibfra.me/vocab/lite/label\": [\"%s\"]}".formatted(hubLabel))) + .setDoc(TEST_JSON_MAPPER.readTree("{\"http://bibfra.me/vocab/lite/label\": [\"%s\"]}".formatted(hubLabel))) .setLabel(hubLabel) .setIdAndRefreshEdges(id); resourceTestService.saveGraph(resource); diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/work/language/LanguageIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/work/language/LanguageIT.java index 096b31159..2c628f0d8 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/work/language/LanguageIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/work/language/LanguageIT.java @@ -1,8 +1,8 @@ package org.folio.linked.data.e2e.mappings.work.language; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Map; import java.util.Set; @@ -10,14 +10,10 @@ import org.folio.linked.data.domain.dto.LanguageWithType; import org.folio.linked.data.e2e.mappings.PostResourceIT; import org.folio.linked.data.model.entity.Resource; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.ResultActions; public class LanguageIT extends PostResourceIT { - @Autowired - private ObjectMapper mapper; - @Override protected String postPayload() { return """ @@ -139,14 +135,13 @@ private static Map getExpectedLanguages() { @SneakyThrows private List getActualLanguages(ResultActions apiResponse) { var responseStr = apiResponse.andReturn().getResponse().getContentAsString(); - var languagesNode = mapper.readTree(responseStr) + var languagesNode = TEST_JSON_MAPPER.readTree(responseStr) .path("resource") .path("http://bibfra.me/vocab/lite/Work") .path("_languages"); - return mapper.convertValue( - languagesNode, - mapper.getTypeFactory().constructCollectionType(List.class, LanguageWithType.class) + return TEST_JSON_MAPPER.convertValue(languagesNode, + TEST_JSON_MAPPER.getTypeFactory().constructCollectionType(List.class, LanguageWithType.class) ); } diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/work/note/WorkNotesIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/work/note/WorkNotesIT.java index 0d89a1a93..e821ad467 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/work/note/WorkNotesIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/work/note/WorkNotesIT.java @@ -1,8 +1,8 @@ package org.folio.linked.data.e2e.mappings.work.note; import static org.assertj.core.api.Assertions.assertThat; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -10,14 +10,10 @@ import lombok.SneakyThrows; import org.folio.linked.data.e2e.mappings.PostResourceIT; import org.folio.linked.data.model.entity.Resource; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.ResultActions; public class WorkNotesIT extends PostResourceIT { - @Autowired - private ObjectMapper objectMapper; - @Override protected String postPayload() { return """ @@ -60,16 +56,16 @@ protected void validateApiResponse(ResultActions apiResponse) { ); var responsePayload = apiResponse.andReturn().getResponse().getContentAsString(); - var notes = objectMapper.readTree(responsePayload) + var notes = TEST_JSON_MAPPER.readTree(responsePayload) .path("resource") .path("http://bibfra.me/vocab/lite/Work") .path("_notes"); Map> actualNotes = new HashMap<>(); notes.forEach(note -> { - var value = note.path("value").get(0).asText(); + var value = note.path("value").get(0).asString(); note.path("type").forEach(typeNode -> - actualNotes.computeIfAbsent(value, k -> new HashSet<>()).add(typeNode.asText()) + actualNotes.computeIfAbsent(value, k -> new HashSet<>()).add(typeNode.asString()) ); }); diff --git a/src/test/java/org/folio/linked/data/e2e/mappings/work/partofseries/PartOfSeriesIT.java b/src/test/java/org/folio/linked/data/e2e/mappings/work/partofseries/PartOfSeriesIT.java index 967bbe848..cb562eb64 100644 --- a/src/test/java/org/folio/linked/data/e2e/mappings/work/partofseries/PartOfSeriesIT.java +++ b/src/test/java/org/folio/linked/data/e2e/mappings/work/partofseries/PartOfSeriesIT.java @@ -41,7 +41,7 @@ protected String postPayload() { @Override @SneakyThrows protected void validateApiResponse(ResultActions apiResponse) { - String path = "$.resource['http://bibfra.me/vocab/lite/Work']['http://bibfra.me/vocab/relation/isPartOf'][0]"; + var path = "$.resource['http://bibfra.me/vocab/lite/Work']['http://bibfra.me/vocab/relation/isPartOf'][0]"; apiResponse .andExpect(status().isOk()) .andExpect(jsonPath(path + "['http://bibfra.me/vocab/lite/name'][0]").value("Title 1")) diff --git a/src/test/java/org/folio/linked/data/e2e/rdf/ResourceSubgraphViewIT.java b/src/test/java/org/folio/linked/data/e2e/rdf/ResourceSubgraphViewIT.java index bb50cc915..195936122 100644 --- a/src/test/java/org/folio/linked/data/e2e/rdf/ResourceSubgraphViewIT.java +++ b/src/test/java/org/folio/linked/data/e2e/rdf/ResourceSubgraphViewIT.java @@ -7,8 +7,8 @@ import static org.folio.ld.dictionary.PropertyDictionary.MAIN_TITLE; import static org.folio.ld.dictionary.ResourceTypeDictionary.INSTANCE; import static org.folio.ld.dictionary.ResourceTypeDictionary.PERSON; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.getJsonNode; -import static org.folio.linked.data.test.TestUtil.readTree; import java.util.List; import java.util.Map; @@ -60,9 +60,9 @@ void exportedResourceContainsInventoryId() { var props = amEdge.get().getTarget().getDoc(); assertThat(props).isNotNull(); assertThat(props.has(FOLIO_INVENTORY_ID.getValue())).isTrue(); - assertThat(props.get(FOLIO_INVENTORY_ID.getValue()).get(0).textValue()).isEqualTo(inventoryId); + assertThat(props.get(FOLIO_INVENTORY_ID.getValue()).get(0).stringValue()).isEqualTo(inventoryId); assertThat(props.has(CONTROL_NUMBER.getValue())).isTrue(); - assertThat(props.get(CONTROL_NUMBER.getValue()).get(0).textValue()).isEqualTo(hrId); + assertThat(props.get(CONTROL_NUMBER.getValue()).get(0).stringValue()).isEqualTo(hrId); } private String createInventoriedInstance(String titleStr, String hrid) { @@ -75,7 +75,7 @@ private String createInventoriedInstance(String titleStr, String hrid) { .replace("%TITLE%", titleStr); var title = new Resource() .addTypes(ResourceTypeDictionary.TITLE) - .setDoc(readTree(titleDoc)) + .setDoc(TEST_JSON_MAPPER.readTree(titleDoc)) .setLabel(titleStr); var adminMetadataDoc = """ @@ -89,13 +89,13 @@ private String createInventoriedInstance(String titleStr, String hrid) { .replace("%createdDate%", CREATED_DATE.getValue()); var adminMetadata = new Resource() .addTypes(ResourceTypeDictionary.ANNOTATION) - .setDoc(readTree(adminMetadataDoc)) + .setDoc(TEST_JSON_MAPPER.readTree(adminMetadataDoc)) .setLabel(hrid); var inventoryId = UUID.randomUUID().toString(); var resource = new Resource() .addTypes(INSTANCE) - .setDoc(readTree("{}")) + .setDoc(TEST_JSON_MAPPER.readTree("{}")) .setLabel(titleStr) .setIdAndRefreshEdges(456L); resource.setFolioMetadata(new FolioMetadata(resource).setInventoryId(inventoryId)); diff --git a/src/test/java/org/folio/linked/data/e2e/resource/AuthorityUpdateAndReadWorkIT.java b/src/test/java/org/folio/linked/data/e2e/resource/AuthorityUpdateAndReadWorkIT.java index 267fb33ea..3b0cf89ee 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/AuthorityUpdateAndReadWorkIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/AuthorityUpdateAndReadWorkIT.java @@ -165,6 +165,7 @@ private Resource createWorkAndLinkToAuthority(Resource authority) { resourceEdgeRepository.save(reTitle); resourceEdgeRepository.save(reAuthor); resourceEdgeRepository.save(reCreator); + return null; } ); return work; diff --git a/src/test/java/org/folio/linked/data/e2e/resource/MergeResourcesIT.java b/src/test/java/org/folio/linked/data/e2e/resource/MergeResourcesIT.java index eba5491c7..f590eb51c 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/MergeResourcesIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/MergeResourcesIT.java @@ -4,16 +4,13 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.ID_LCCN; import static org.folio.ld.dictionary.ResourceTypeDictionary.STATUS; import static org.folio.linked.data.test.TestUtil.TENANT_ID; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.cleanResourceTables; import static org.folio.linked.data.test.TestUtil.loadResourceAsString; -import static org.folio.linked.data.test.TestUtil.readTree; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Map; import java.util.Set; -import lombok.SneakyThrows; import org.folio.ld.dictionary.PredicateDictionary; import org.folio.ld.dictionary.PropertyDictionary; import org.folio.ld.dictionary.ResourceTypeDictionary; @@ -31,6 +28,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; +import tools.jackson.databind.JsonNode; @IntegrationTest class MergeResourcesIT { @@ -42,16 +40,16 @@ class MergeResourcesIT { @Autowired private JdbcTemplate jdbcTemplate; @Autowired - private ObjectMapper objectMapper; - @Autowired private TenantScopedExecutionService tenantScopedExecutionService; @MockitoSpyBean private KafkaAdminService kafkaAdminService; @BeforeEach void beforeEach() { - tenantScopedExecutionService.execute(TENANT_ID, () -> - cleanResourceTables(jdbcTemplate) + tenantScopedExecutionService.execute(TENANT_ID, () -> { + cleanResourceTables(jdbcTemplate); + return null; + } ); } @@ -191,31 +189,27 @@ private void assertResourceDoc(String id, JsonNode expected) { assertThat(resource.getDoc()).isEqualTo(expected); } - @SneakyThrows private JsonNode getInitialDoc() { return getDocWithPreferredFlag("samples/json_merge/existing.jsonl", false); } - @SneakyThrows private JsonNode getNewDoc() { return getDocWithPreferredFlag("samples/json_merge/incoming.jsonl", true); } - @SneakyThrows private JsonNode getMergedDoc() { return getDocWithPreferredFlag("samples/json_merge/merged.jsonl", true); } - @SneakyThrows private JsonNode getDocWithPreferredFlag(String docFile, boolean isPreferred) { var preferredJson = """ - { - "http://library.link/vocab/resourcePreferred": [ - "$PREFERRED_FLAG" - ] - } - """.replace("$PREFERRED_FLAG", String.valueOf(isPreferred)); - return JsonUtils.merge(readTree(loadResourceAsString(docFile)), objectMapper.readTree(preferredJson)); + { + "http://library.link/vocab/resourcePreferred": [ + "$PREFERRED_FLAG" + ] + } + """.replace("$PREFERRED_FLAG", String.valueOf(isPreferred)); + return JsonUtils.merge(TEST_JSON_MAPPER.readTree(loadResourceAsString(docFile)), TEST_JSON_MAPPER.readTree(preferredJson)); } private Resource createGraph1toto2() { @@ -242,7 +236,6 @@ private Resource createGraph3toto1to2to5toto4() { return createResource(3L, Map.of(PredicateDictionary.EDITOR, List.of(fp1Resource, fp4Resource))); } - @SneakyThrows private Resource createGraph6toto1toto4to5() { // 6 -> [1, (4 -> 5)] var fp1Resource = createResource(1L, Map.of()).setDoc(getNewDoc()); diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerBaseValidationIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerBaseValidationIT.java index 415d0283f..09ab1bcd1 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerBaseValidationIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerBaseValidationIT.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.linked.data.e2e.resource.ResourceControllerITBase.RESOURCE_URL; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.folio.linked.data.test.TestUtil.loadResourceAsString; import static org.springframework.http.MediaType.APPLICATION_JSON; @@ -10,7 +11,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import org.folio.linked.data.domain.dto.Error; import org.folio.linked.data.domain.dto.ErrorResponse; @@ -19,14 +19,10 @@ import org.folio.linked.data.e2e.base.IntegrationTest; import org.folio.spring.tools.kafka.KafkaAdminService; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; @IntegrationTest class ResourceControllerBaseValidationIT extends ITBase { - - @Autowired - private ObjectMapper objectMapper; @MockitoSpyBean private KafkaAdminService kafkaAdminService; @@ -48,7 +44,7 @@ void createEmptyInstance_shouldReturnBadRequest() throws Exception { .andExpect(content().contentType(APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - var errorResponse = objectMapper.readValue(response, ErrorResponse.class); + var errorResponse = TEST_JSON_MAPPER.readValue(response, ErrorResponse.class); assertThat(errorResponse.getErrors()).containsOnly(expectedError); } @@ -70,7 +66,7 @@ void createEmptyWork_shouldReturnBadRequest() throws Exception { .andExpect(content().contentType(APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - var errorResponse = objectMapper.readValue(response, ErrorResponse.class); + var errorResponse = TEST_JSON_MAPPER.readValue(response, ErrorResponse.class); assertThat(errorResponse.getErrors()).containsOnly(expectedError); } @@ -92,7 +88,7 @@ void updateWithEmptyInstance_shouldReturnBadRequest() throws Exception { .andExpect(content().contentType(APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - var errorResponse = objectMapper.readValue(response, ErrorResponse.class); + var errorResponse = TEST_JSON_MAPPER.readValue(response, ErrorResponse.class); assertThat(errorResponse.getErrors()).containsOnly(expectedError); } @@ -114,7 +110,7 @@ void updateWithEmptyWork_shouldReturnBadRequest() throws Exception { .andExpect(content().contentType(APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - var errorResponse = objectMapper.readValue(response, ErrorResponse.class); + var errorResponse = TEST_JSON_MAPPER.readValue(response, ErrorResponse.class); assertThat(errorResponse.getErrors()).containsOnly(expectedError); } @@ -135,7 +131,7 @@ void createInstanceWithTitleWithoutMainTitle_shouldReturnBadRequest() throws Exc .andExpect(content().contentType(APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - var errorResponse = objectMapper.readValue(response, ErrorResponse.class); + var errorResponse = TEST_JSON_MAPPER.readValue(response, ErrorResponse.class); assertThat(errorResponse.getErrors()) .hasSize(1) .first() diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerIT.java index 8c94eae18..7a66d553f 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerIT.java @@ -7,7 +7,6 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import lombok.SneakyThrows; import org.folio.linked.data.domain.dto.InstanceIngressEvent; import org.folio.linked.data.domain.dto.ResourceIndexEventType; import org.folio.linked.data.e2e.base.IntegrationTest; @@ -43,7 +42,6 @@ public void beforeEach() { inventoryTopicListener.getMessages().clear(); } - @SneakyThrows @Override protected void checkSearchIndexMessage(Long id, ResourceIndexEventType eventType) { awaitAndAssert(() -> diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerITBase.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerITBase.java index 0c8921636..4d74f4e49 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerITBase.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerITBase.java @@ -96,7 +96,7 @@ import static org.folio.linked.data.test.MonographTestUtil.getSubjectFormNotPreferred; import static org.folio.linked.data.test.MonographTestUtil.getSubjectPersonPreferred; import static org.folio.linked.data.test.TestUtil.INSTANCE_WITH_WORK_REF_SAMPLE; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.WORK_WITH_INSTANCE_REF_SAMPLE; import static org.folio.linked.data.test.TestUtil.assertResourceMetadata; import static org.folio.linked.data.test.TestUtil.defaultHeaders; @@ -224,14 +224,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.JsonNode; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; -import lombok.SneakyThrows; import org.folio.ld.dictionary.PredicateDictionary; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.linked.data.domain.dto.InstanceIngressEvent.EventTypeEnum; @@ -253,6 +251,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.web.servlet.ResultActions; +import tools.jackson.databind.JsonNode; abstract class ResourceControllerITBase extends ITBase { @@ -297,7 +296,7 @@ void createInstanceWithWorkRef_shouldSaveEntityCorrectly() throws Exception { .andReturn().getResponse().getContentAsString(); validateInstanceResponse(resultActions, toInstance()); - var resourceResponse = OBJECT_MAPPER.readValue(response, ResourceResponseDto.class); + var resourceResponse = TEST_JSON_MAPPER.readValue(response, ResourceResponseDto.class); var instanceResponse = ((InstanceResponseField) resourceResponse.getResource()).getInstance(); var instanceResource = resourceTestService.getResourceById(instanceResponse.getId(), 4); assertThat(instanceResource.getFolioMetadata().getSource()).isEqualTo(LINKED_DATA); @@ -333,7 +332,7 @@ void createWorkWithInstanceRef_shouldSaveEntityCorrectly() throws Exception { .andReturn().getResponse().getContentAsString(); validateWorkResponse(resultActions, toWork()); - var resourceResponse = OBJECT_MAPPER.readValue(response, ResourceResponseDto.class); + var resourceResponse = TEST_JSON_MAPPER.readValue(response, ResourceResponseDto.class); var id = ((WorkResponseField) resourceResponse.getResource()).getWork().getId(); var workResource = resourceTestService.getResourceById(id, 4); validateWork(workResource, true); @@ -361,7 +360,7 @@ void update_shouldReturnCorrectlyUpdatedInstanceWithWorkRef_deleteOldOne_sendMes .contentType(APPLICATION_JSON) .headers(defaultHeaders(env)) .content( - OBJECT_MAPPER.writeValueAsString(updateDto).replaceAll(WORK_ID_PLACEHOLDER, work.getId().toString()) + TEST_JSON_MAPPER.writeValueAsString(updateDto).replaceAll(WORK_ID_PLACEHOLDER, work.getId().toString()) ); // when @@ -374,13 +373,13 @@ void update_shouldReturnCorrectlyUpdatedInstanceWithWorkRef_deleteOldOne_sendMes .andExpect(content().contentType(APPLICATION_JSON)) .andExpect(jsonPath(toInstance(), notNullValue())) .andReturn().getResponse().getContentAsString(); - var resourceResponse = OBJECT_MAPPER.readValue(response, ResourceResponseDto.class); + var resourceResponse = TEST_JSON_MAPPER.readValue(response, ResourceResponseDto.class); var instanceDto = ((InstanceResponseField) resourceResponse.getResource()).getInstance(); var updatedInstance = resourceTestService.getResourceById(instanceDto.getId(), 1); assertThat(updatedInstance.getId()).isNotNull(); assertThat(updatedInstance.getLabel()).isEqualTo(originalInstance.getLabel()); assertThat(updatedInstance.getTypes().iterator().next().getUri()).isEqualTo(INSTANCE.getUri()); - assertThat(updatedInstance.getDoc().get(DIMENSIONS.getValue()).get(0).asText()).isEqualTo("200 m"); + assertThat(updatedInstance.getDoc().get(DIMENSIONS.getValue()).get(0).asString()).isEqualTo("200 m"); assertThat(updatedInstance.getOutgoingEdges()).hasSize(originalInstance.getOutgoingEdges().size()); var updatedFolioMetadata = updatedInstance.getFolioMetadata(); @@ -421,7 +420,7 @@ void update_shouldReturnCorrectlyUpdatedWorkWithInstanceRef_deleteOldOne_sendMes var updateRequest = put(RESOURCE_URL + "/" + originalWork.getId()) .contentType(APPLICATION_JSON) .headers(defaultHeaders(env)) - .content(OBJECT_MAPPER.writeValueAsString(updateDto) + .content(TEST_JSON_MAPPER.writeValueAsString(updateDto) .replaceAll(INSTANCE_ID_PLACEHOLDER, instance.getId().toString()) ); @@ -436,7 +435,7 @@ void update_shouldReturnCorrectlyUpdatedWorkWithInstanceRef_deleteOldOne_sendMes .andExpect(jsonPath(toWork(), notNullValue())) .andExpect(jsonPath(toInstanceReferenceArray(toWork()), hasSize(1))) .andReturn().getResponse().getContentAsString(); - var resourceResponse = OBJECT_MAPPER.readValue(response, ResourceResponseDto.class); + var resourceResponse = TEST_JSON_MAPPER.readValue(response, ResourceResponseDto.class); var id = ((WorkResponseField) resourceResponse.getResource()).getWork().getId(); var updatedWork = resourceTestService.getResourceById(id, 1); @@ -453,7 +452,7 @@ void update_shouldReturnCorrectlyUpdatedWorkWithInstanceRef_deleteOldOne_sendMes .map(Resource::getDoc) .map(jsonNode -> jsonNode.get(TERM.getValue())) .map(jsonNode -> jsonNode.get(0)) - .map(JsonNode::asText) + .map(JsonNode::asString) ).contains("Russian"); assertThat(updatedWork.getOutgoingEdges()).hasSize(originalWork.getOutgoingEdges().size()); assertThat(updatedWork.getIncomingEdges()).hasSize(originalWork.getIncomingEdges().size()); @@ -478,7 +477,7 @@ void update_shouldReturnCorrectlyUpdateMetadataFields() throws Exception { var response = mockMvc.perform(requestBuilder) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); - var resourceResponse = OBJECT_MAPPER.readValue(response, ResourceResponseDto.class); + var resourceResponse = TEST_JSON_MAPPER.readValue(response, ResourceResponseDto.class); var originalWorkId = ((WorkResponseField) resourceResponse.getResource()).getWork().getId(); var originalWorkResource = resourceTestService.getResourceById(originalWorkId, 4); @@ -499,13 +498,13 @@ void update_shouldReturnCorrectlyUpdateMetadataFields() throws Exception { var updateRequest = put(RESOURCE_URL + "/" + originalWorkId) .contentType(APPLICATION_JSON) .headers(defaultHeadersWithUserId(env, updatedById.toString())) - .content(OBJECT_MAPPER.writeValueAsString(updateDto) + .content(TEST_JSON_MAPPER.writeValueAsString(updateDto) .replaceAll(INSTANCE_ID_PLACEHOLDER, instanceForReference.getId().toString()) ); // then var updatedResponse = mockMvc.perform(updateRequest).andReturn().getResponse().getContentAsString(); - var updatedResourceResponse = OBJECT_MAPPER.readValue(updatedResponse, ResourceResponseDto.class); + var updatedResourceResponse = TEST_JSON_MAPPER.readValue(updatedResponse, ResourceResponseDto.class); var updatedWorkId = ((WorkResponseField) updatedResourceResponse.getResource()).getWork().getId(); var updatedWorkResource = resourceTestService.getResourceById(updatedWorkId, 4); compareResourceMetadataOfOriginalAndUpdated(originalWorkResource, updatedWorkResource, updatedById); @@ -866,13 +865,13 @@ private void validateInstance(Resource instance, boolean validateFullWork) { private void validateLiteral(Resource resource, String field, String value) { assertThat(resource.getDoc().get(field).size()).isEqualTo(1); - assertThat(resource.getDoc().get(field).get(0).asText()).isEqualTo(value); + assertThat(resource.getDoc().get(field).get(0).asString()).isEqualTo(value); } private void validateLiterals(Resource resource, String field, List expectedValues) { var actualValues = resource.getDoc().get(field); assertThat(actualValues.size()).isEqualTo(expectedValues.size()); - assertThat(stream(spliteratorUnknownSize(actualValues.iterator(), ORDERED), false).map(JsonNode::asText).toList()) + assertThat(stream(spliteratorUnknownSize(actualValues.iterator(), ORDERED), false).map(JsonNode::asString).toList()) .hasSameElementsAs(expectedValues); } @@ -882,7 +881,7 @@ private void validatePrimaryTitle(ResourceEdge edge, Resource source) { assertThat(title.getId()).isEqualTo(hashService.hash(title)); assertThat(title.getDoc().size()).isEqualTo(5); assertThat(title.getDoc().get(NON_SORT_NUM.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(NON_SORT_NUM.getValue()).get(0).asText()).isEqualTo("Primary: nonSortNum"); + assertThat(title.getDoc().get(NON_SORT_NUM.getValue()).get(0).asString()).isEqualTo("Primary: nonSortNum"); assertThat(title.getOutgoingEdges()).isEmpty(); } @@ -892,9 +891,9 @@ private void validateParallelTitle(ResourceEdge edge, Resource source) { assertThat(title.getId()).isEqualTo(hashService.hash(title)); assertThat(title.getDoc().size()).isEqualTo(6); assertThat(title.getDoc().get(DATE.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(DATE.getValue()).get(0).asText()).isEqualTo("Parallel: date"); + assertThat(title.getDoc().get(DATE.getValue()).get(0).asString()).isEqualTo("Parallel: date"); assertThat(title.getDoc().get(NOTE.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(NOTE.getValue()).get(0).asText()).isEqualTo("Parallel: noteLabel"); + assertThat(title.getDoc().get(NOTE.getValue()).get(0).asString()).isEqualTo("Parallel: noteLabel"); assertThat(title.getOutgoingEdges()).isEmpty(); } @@ -904,11 +903,11 @@ private void validateVariantTitle(ResourceEdge edge, Resource source) { assertThat(title.getId()).isEqualTo(hashService.hash(title)); assertThat(title.getDoc().size()).isEqualTo(7); assertThat(title.getDoc().get(DATE.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(DATE.getValue()).get(0).asText()).isEqualTo("Variant: date"); + assertThat(title.getDoc().get(DATE.getValue()).get(0).asString()).isEqualTo("Variant: date"); assertThat(title.getDoc().get(VARIANT_TYPE.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(VARIANT_TYPE.getValue()).get(0).asText()).isEqualTo("Variant: variantType"); + assertThat(title.getDoc().get(VARIANT_TYPE.getValue()).get(0).asString()).isEqualTo("Variant: variantType"); assertThat(title.getDoc().get(NOTE.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(NOTE.getValue()).get(0).asText()).isEqualTo("Variant: noteLabel"); + assertThat(title.getDoc().get(NOTE.getValue()).get(0).asString()).isEqualTo("Variant: noteLabel"); assertThat(title.getOutgoingEdges()).isEmpty(); } @@ -921,13 +920,13 @@ private void validateSampleTitleBase(ResourceEdge edge, Resource source, Resourc assertThat(title.getTypes().iterator().next().getUri()).isEqualTo(type.getUri()); assertThat(title.getId()).isEqualTo(hashService.hash(title)); assertThat(title.getDoc().get(PART_NAME.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(PART_NAME.getValue()).get(0).asText()).isEqualTo(prefix + "partName"); + assertThat(title.getDoc().get(PART_NAME.getValue()).get(0).asString()).isEqualTo(prefix + "partName"); assertThat(title.getDoc().get(PART_NUMBER.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(PART_NUMBER.getValue()).get(0).asText()).isEqualTo(prefix + "partNumber"); + assertThat(title.getDoc().get(PART_NUMBER.getValue()).get(0).asString()).isEqualTo(prefix + "partNumber"); assertThat(title.getDoc().get(MAIN_TITLE.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(MAIN_TITLE.getValue()).get(0).asText()).isEqualTo(prefix + "mainTitle"); + assertThat(title.getDoc().get(MAIN_TITLE.getValue()).get(0).asString()).isEqualTo(prefix + "mainTitle"); assertThat(title.getDoc().get(SUBTITLE.getValue()).size()).isEqualTo(1); - assertThat(title.getDoc().get(SUBTITLE.getValue()).get(0).asText()).isEqualTo(prefix + "subTitle"); + assertThat(title.getDoc().get(SUBTITLE.getValue()).get(0).asString()).isEqualTo(prefix + "subTitle"); } private void validateProviderEvent(ResourceEdge edge, Resource source, PredicateDictionary predicate, @@ -942,13 +941,14 @@ private void validateProviderEvent(ResourceEdge edge, Resource source, Predicate assertThat(providerEvent.getId()).isEqualTo(hashService.hash(providerEvent)); assertThat(providerEvent.getDoc().size()).isEqualTo(4); assertThat(providerEvent.getDoc().get(DATE.getValue()).size()).isEqualTo(1); - assertThat(providerEvent.getDoc().get(DATE.getValue()).get(0).asText()).isEqualTo(type + " date"); + assertThat(providerEvent.getDoc().get(DATE.getValue()).get(0).asString()).isEqualTo(type + " date"); assertThat(providerEvent.getDoc().get(NAME.getValue()).size()).isEqualTo(1); - assertThat(providerEvent.getDoc().get(NAME.getValue()).get(0).asText()).isEqualTo(type + " name"); + assertThat(providerEvent.getDoc().get(NAME.getValue()).get(0).asString()).isEqualTo(type + " name"); assertThat(providerEvent.getDoc().get(PROVIDER_DATE.getValue()).size()).isEqualTo(1); - assertThat(providerEvent.getDoc().get(PROVIDER_DATE.getValue()).get(0).asText()).isEqualTo(type + " provider date"); + assertThat(providerEvent.getDoc().get(PROVIDER_DATE.getValue()).get(0).asString()) + .isEqualTo(type + " provider date"); assertThat(providerEvent.getDoc().get(SIMPLE_PLACE.getValue()).size()).isEqualTo(1); - assertThat(providerEvent.getDoc().get(SIMPLE_PLACE.getValue()).get(0).asText()).isEqualTo(type + " simple place"); + assertThat(providerEvent.getDoc().get(SIMPLE_PLACE.getValue()).get(0).asString()).isEqualTo(type + " simple place"); assertThat(providerEvent.getOutgoingEdges()).hasSize(1); validateProviderPlace(providerEvent.getOutgoingEdges().iterator().next(), providerEvent, expectedCode, expectedLabel); @@ -964,11 +964,11 @@ private void validateProviderPlace(ResourceEdge edge, Resource source, String ex assertThat(place.getId()).isEqualTo(hashService.hash(place)); assertThat(place.getDoc().size()).isEqualTo(3); assertThat(place.getDoc().get(CODE.getValue()).size()).isEqualTo(1); - assertThat(place.getDoc().get(CODE.getValue()).get(0).asText()).isEqualTo(expectedCode); + assertThat(place.getDoc().get(CODE.getValue()).get(0).asString()).isEqualTo(expectedCode); assertThat(place.getDoc().get(LABEL.getValue()).size()).isEqualTo(1); - assertThat(place.getDoc().get(LABEL.getValue()).get(0).asText()).isEqualTo(expectedLabel); + assertThat(place.getDoc().get(LABEL.getValue()).get(0).asString()).isEqualTo(expectedLabel); assertThat(place.getDoc().get(LINK.getValue()).size()).isEqualTo(1); - assertThat(place.getDoc().get(LINK.getValue()).get(0).asText()).isEqualTo( + assertThat(place.getDoc().get(LINK.getValue()).get(0).asString()).isEqualTo( "http://id.loc.gov/vocabulary/countries/" + expectedCode); assertThat(place.getOutgoingEdges()).isEmpty(); } @@ -985,7 +985,7 @@ private void validateLccn(ResourceEdge edge, Resource source) { assertThat(lccn.getId()).isEqualTo(hashService.hash(lccn)); assertThat(lccn.getDoc().size()).isEqualTo(1); assertThat(lccn.getDoc().get(NAME.getValue()).size()).isEqualTo(1); - assertThat(lccn.getDoc().get(NAME.getValue()).get(0).asText()).isEqualTo("lccn value"); + assertThat(lccn.getDoc().get(NAME.getValue()).get(0).asString()).isEqualTo("lccn value"); assertThat(lccn.getOutgoingEdges()).hasSize(1); validateStatus(lccn.getOutgoingEdges().iterator().next(), lccn, "lccn"); } @@ -1003,9 +1003,9 @@ private void validateIsbn(ResourceEdge edge, Resource source) { assertThat(isbn.getId()).isEqualTo(hashService.hash(isbn)); assertThat(isbn.getDoc().size()).isEqualTo(2); assertThat(isbn.getDoc().get(NAME.getValue()).size()).isEqualTo(1); - assertThat(isbn.getDoc().get(NAME.getValue()).get(0).asText()).isEqualTo("isbn value"); + assertThat(isbn.getDoc().get(NAME.getValue()).get(0).asString()).isEqualTo("isbn value"); assertThat(isbn.getDoc().get(QUALIFIER.getValue()).size()).isEqualTo(1); - assertThat(isbn.getDoc().get(QUALIFIER.getValue()).get(0).asText()).isEqualTo("isbn qualifier"); + assertThat(isbn.getDoc().get(QUALIFIER.getValue()).get(0).asString()).isEqualTo("isbn qualifier"); assertThat(isbn.getOutgoingEdges()).hasSize(1); validateStatus(isbn.getOutgoingEdges().iterator().next(), isbn, "isbn"); } @@ -1023,9 +1023,9 @@ private void validateIan(ResourceEdge edge, Resource source) { assertThat(ian.getId()).isEqualTo(hashService.hash(ian)); assertThat(ian.getDoc().size()).isEqualTo(2); assertThat(ian.getDoc().get(NAME.getValue()).size()).isEqualTo(1); - assertThat(ian.getDoc().get(NAME.getValue()).get(0).asText()).isEqualTo("ian value"); + assertThat(ian.getDoc().get(NAME.getValue()).get(0).asString()).isEqualTo("ian value"); assertThat(ian.getDoc().get(QUALIFIER.getValue()).size()).isEqualTo(1); - assertThat(ian.getDoc().get(QUALIFIER.getValue()).get(0).asText()).isEqualTo("ian qualifier"); + assertThat(ian.getDoc().get(QUALIFIER.getValue()).get(0).asString()).isEqualTo("ian qualifier"); assertThat(ian.getOutgoingEdges()).isEmpty(); } @@ -1042,9 +1042,9 @@ private void validateOtherId(ResourceEdge edge, Resource source) { assertThat(otherId.getId()).isEqualTo(hashService.hash(otherId)); assertThat(otherId.getDoc().size()).isEqualTo(2); assertThat(otherId.getDoc().get(NAME.getValue()).size()).isEqualTo(1); - assertThat(otherId.getDoc().get(NAME.getValue()).get(0).asText()).isEqualTo("otherId value"); + assertThat(otherId.getDoc().get(NAME.getValue()).get(0).asString()).isEqualTo("otherId value"); assertThat(otherId.getDoc().get(QUALIFIER.getValue()).size()).isEqualTo(1); - assertThat(otherId.getDoc().get(QUALIFIER.getValue()).get(0).asText()).isEqualTo("otherId qualifier"); + assertThat(otherId.getDoc().get(QUALIFIER.getValue()).get(0).asString()).isEqualTo("otherId qualifier"); assertThat(otherId.getOutgoingEdges()).isEmpty(); } @@ -1058,9 +1058,9 @@ private void validateStatus(ResourceEdge edge, Resource source, String prefix) { assertThat(status.getId()).isEqualTo(hashService.hash(status)); assertThat(status.getDoc().size()).isEqualTo(2); assertThat(status.getDoc().get(LINK.getValue()).size()).isEqualTo(1); - assertThat(status.getDoc().get(LINK.getValue()).get(0).asText()).isEqualTo("http://id/" + prefix); + assertThat(status.getDoc().get(LINK.getValue()).get(0).asString()).isEqualTo("http://id/" + prefix); assertThat(status.getDoc().get(LABEL.getValue()).size()).isEqualTo(1); - assertThat(status.getDoc().get(LABEL.getValue()).get(0).asText()).isEqualTo(prefix + " status value"); + assertThat(status.getDoc().get(LABEL.getValue()).get(0).asString()).isEqualTo(prefix + " status value"); assertThat(status.getOutgoingEdges()).isEmpty(); } @@ -1115,9 +1115,9 @@ private void validateAccessLocation(ResourceEdge edge, Resource source) { assertThat(locator.getId()).isEqualTo(hashService.hash(locator)); assertThat(locator.getDoc().size()).isEqualTo(2); assertThat(locator.getDoc().get(LINK.getValue()).size()).isEqualTo(1); - assertThat(locator.getDoc().get(LINK.getValue()).get(0).asText()).isEqualTo("accessLocation value"); + assertThat(locator.getDoc().get(LINK.getValue()).get(0).asString()).isEqualTo("accessLocation value"); assertThat(locator.getDoc().get(NOTE.getValue()).size()).isEqualTo(1); - assertThat(locator.getDoc().get(NOTE.getValue()).get(0).asText()).isEqualTo("accessLocation note"); + assertThat(locator.getDoc().get(NOTE.getValue()).get(0).asString()).isEqualTo("accessLocation note"); assertThat(locator.getOutgoingEdges()).isEmpty(); } @@ -1365,7 +1365,7 @@ private void validateCopyrightDate(ResourceEdge edge, Resource source) { assertThat(copyrightEvent.getId()).isEqualTo(hashService.hash(copyrightEvent)); assertThat(copyrightEvent.getDoc().size()).isEqualTo(1); assertThat(copyrightEvent.getDoc().get(DATE.getValue()).size()).isEqualTo(1); - assertThat(copyrightEvent.getDoc().get(DATE.getValue()).get(0).asText()).isEqualTo("copyright date value"); + assertThat(copyrightEvent.getDoc().get(DATE.getValue()).get(0).asString()).isEqualTo("copyright date value"); assertThat(copyrightEvent.getOutgoingEdges()).isEmpty(); } @@ -1381,7 +1381,7 @@ private void validateSubject(ResourceEdge edge, assertThat(types).containsOnly(CONCEPT.getUri(), expectedSubject.getTypes().iterator().next().getUri()); assertThat(subjectConcept.getLabel()).isEqualTo(expectedConcept.getLabel()); assertThat(subjectConcept.getDoc().size()).isEqualTo(1); - validateLiteral(subjectConcept, NAME.getValue(), expectedConcept.getDoc().get(NAME.getValue()).get(0).asText()); + validateLiteral(subjectConcept, NAME.getValue(), expectedConcept.getDoc().get(NAME.getValue()).get(0).asString()); assertThat(subjectConcept.getOutgoingEdges()).hasSize(1); var subjectEdge = subjectConcept.getOutgoingEdges().iterator().next(); validateResourceEdge(subjectEdge, subjectConcept, expectedSubject, FOCUS.getUri()); @@ -1422,14 +1422,13 @@ private Resource saveResource(Long id, String label, ResourceTypeDictionary type return resourceTestService.saveGraph(resource); } - @SneakyThrows private Resource createResource(Long id, String label, String doc, ResourceTypeDictionary... types) { var resource = new Resource(); Arrays.stream(types) .map(t -> new ResourceTypeEntity().setHash(t.getHash()).setUri(t.getUri())) .forEach(resource::addType); resource.setLabel(label); - resource.setDoc(OBJECT_MAPPER.readTree(doc)); + resource.setDoc(TEST_JSON_MAPPER.readTree(doc)); resource.setIdAndRefreshEdges(id); return resource; } diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerImportMarcIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerImportMarcIT.java index 63b7a9c6f..784bc3ea6 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerImportMarcIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerImportMarcIT.java @@ -1,6 +1,6 @@ package org.folio.linked.data.e2e.resource; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.awaitAndAssert; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -9,9 +9,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.UUID; -import lombok.SneakyThrows; import org.folio.linked.data.e2e.ITBase; import org.folio.linked.data.e2e.base.IntegrationTest; import org.folio.linked.data.integration.rest.srs.SrsClient; @@ -31,8 +29,6 @@ @IntegrationTest @SpringBootTest(classes = {KafkaProducerTestConfiguration.class}) class ResourceControllerImportMarcIT extends ITBase { - private final ObjectMapper mapper = OBJECT_MAPPER; - @MockitoBean private SrsClient srsClient; @Autowired @@ -86,7 +82,7 @@ void shouldImportMarc() throws Exception { when(srsClient.getSourceStorageInstanceRecordById(instanceId)) - .thenReturn(ResponseEntity.ok(mapper.readValue(sampleSrsResponse, Record.class))); + .thenReturn(ResponseEntity.ok(TEST_JSON_MAPPER.readValue(sampleSrsResponse, Record.class))); var requestBuilder = post("/linked-data/inventory-instance/{inventoryId}/import", instanceId) .contentType(APPLICATION_JSON) @@ -98,7 +94,7 @@ void shouldImportMarc() throws Exception { .getResponse() .getContentAsString(); - var resourceId = mapper.readTree(payload).get("id").asText(); + var resourceId = TEST_JSON_MAPPER.readTree(payload).get("id").asString(); awaitAndAssert( () -> assertTrue( @@ -125,28 +121,25 @@ void shouldImportMarc() throws Exception { ); } - @SneakyThrows private boolean isExpectedInventoryMessage(String message, String resourceId) { - var root = mapper.readTree(message); - return root.get("eventType").asText().equals("UPDATE_INSTANCE") - && root.get("eventPayload").get("sourceType").asText().equals("LINKED_DATA") - && root.get("eventPayload").get("linkedDataId").asText().equals(resourceId) + var root = TEST_JSON_MAPPER.readTree(message); + return root.get("eventType").asString().equals("UPDATE_INSTANCE") + && root.get("eventPayload").get("sourceType").asString().equals("LINKED_DATA") + && root.get("eventPayload").get("linkedDataId").asString().equals(resourceId) && message.contains("in00000000001"); } - @SneakyThrows private boolean isExpectedSearchWorkMessage(String message) { - var root = mapper.readTree(message); - return root.get("type").asText().equals("UPDATE") - && root.get("resourceName").asText().equals("linked-data-work") + var root = TEST_JSON_MAPPER.readTree(message); + return root.get("type").asString().equals("UPDATE") + && root.get("resourceName").asString().equals("linked-data-work") && message.contains("ResourceControllerImportMarcIT - Testing instance"); } - @SneakyThrows private boolean isExpectedHubIndexMessage(String message) { - var root = mapper.readTree(message); - return root.get("type").asText().equals("CREATE") - && root.get("resourceName").asText().equals("linked-data-hub") - && root.get("new").get("label").asText().contains("Person name. Title"); + var root = TEST_JSON_MAPPER.readTree(message); + return root.get("type").asString().equals("CREATE") + && root.get("resourceName").asString().equals("linked-data-hub") + && root.get("new").get("label").asString().contains("Person name. Title"); } } diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerLccnPatternValidationIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerLccnPatternValidationIT.java index bc79cb2c5..abfc5d318 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerLccnPatternValidationIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerLccnPatternValidationIT.java @@ -8,7 +8,7 @@ import static org.folio.linked.data.test.MonographTestUtil.getSampleWork; import static org.folio.linked.data.test.MonographTestUtil.setCurrentStatus; import static org.folio.linked.data.test.TestUtil.INSTANCE_WITH_WORK_REF_SAMPLE; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.folio.linked.data.test.TestUtil.getSampleInstanceDtoMap; import static org.folio.linked.data.test.resource.ResourceSpecUtil.createSpecRules; @@ -95,7 +95,7 @@ void update_shouldReturn400_ifLccnIsInvalid() throws Exception { .contentType(APPLICATION_JSON) .headers(defaultHeaders(env)) .content( - OBJECT_MAPPER.writeValueAsString(updateDto).replaceAll(WORK_ID_PLACEHOLDER, work.getId().toString()) + TEST_JSON_MAPPER.writeValueAsString(updateDto).replaceAll(WORK_ID_PLACEHOLDER, work.getId().toString()) ); when(searchClient.searchInstances(any())) .thenReturn(new ResponseEntity<>(new SearchResponseTotalOnly().totalRecords(0L), HttpStatus.OK)); diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerLccnUniquenessValidationIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerLccnUniquenessValidationIT.java index 5e91a16e9..2b06b5532 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerLccnUniquenessValidationIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerLccnUniquenessValidationIT.java @@ -7,7 +7,7 @@ import static org.folio.linked.data.test.MonographTestUtil.getSampleWork; import static org.folio.linked.data.test.MonographTestUtil.setCurrentStatus; import static org.folio.linked.data.test.TestUtil.INSTANCE_WITH_WORK_REF_SAMPLE; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.folio.linked.data.test.TestUtil.getSampleInstanceDtoMap; import static org.folio.linked.data.test.resource.ResourceUtils.setExistingResourcesIds; @@ -93,7 +93,7 @@ void update_shouldReturn400_ifLccnIsNotUnique() throws Exception { .contentType(APPLICATION_JSON) .headers(defaultHeaders(env)) .content( - OBJECT_MAPPER.writeValueAsString(updateDto).replaceAll(WORK_ID_PLACEHOLDER, work.getId().toString()) + TEST_JSON_MAPPER.writeValueAsString(updateDto).replaceAll(WORK_ID_PLACEHOLDER, work.getId().toString()) .replace("lccn value", "nn0123456789") ); var query = "(lccn==\"nn0123456789\") and (staffSuppress <> \"true\" and discoverySuppress <> \"true\")" diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerPostHubIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerPostHubIT.java index 7e96d7119..21ffa7597 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerPostHubIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerPostHubIT.java @@ -2,6 +2,7 @@ import static org.folio.linked.data.domain.dto.ResourceIndexEventType.CREATE; import static org.folio.linked.data.e2e.resource.ResourceControllerITBase.RESOURCE_URL; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.awaitAndAssert; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -11,7 +12,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.ObjectMapper; import org.folio.linked.data.domain.dto.ResourceIndexEventType; import org.folio.linked.data.e2e.ITBase; import org.folio.linked.data.e2e.base.IntegrationTest; @@ -31,8 +31,6 @@ class ResourceControllerPostHubIT extends ITBase { private MockMvc mockMvc; @Autowired private KafkaSearchHubIndexTopicListener searchIndexTopicListener; - @Autowired - private ObjectMapper objectMapper; @BeforeEach @Override @@ -73,11 +71,11 @@ void shouldCreateHubAndEmitSearchIndexEvent() throws Exception { .andReturn().getResponse() .getContentAsString(); - var hubIdStr = objectMapper.readTree(responseJson) + var hubIdStr = TEST_JSON_MAPPER.readTree(responseJson) .path("resource") .path("http://bibfra.me/vocab/lite/Hub") .path("id") - .asText(); + .asString(); checkSearchIndexMessage(Long.parseLong(hubIdStr), CREATE); checkIndexDate(hubIdStr); } diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerPutHubIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerPutHubIT.java index 0ac5153bf..e355fb549 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerPutHubIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerPutHubIT.java @@ -3,6 +3,7 @@ import static org.folio.linked.data.domain.dto.ResourceIndexEventType.CREATE; import static org.folio.linked.data.domain.dto.ResourceIndexEventType.DELETE; import static org.folio.linked.data.e2e.resource.ResourceControllerITBase.RESOURCE_URL; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.awaitAndAssert; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -12,7 +13,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.ObjectMapper; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.linked.data.domain.dto.ResourceIndexEventType; import org.folio.linked.data.e2e.ITBase; @@ -36,8 +36,6 @@ class ResourceControllerPutHubIT extends ITBase { @Autowired private KafkaSearchHubIndexTopicListener searchIndexTopicListener; @Autowired - private ObjectMapper objectMapper; - @Autowired private ResourceRepository resourceRepository; @BeforeEach @@ -84,11 +82,11 @@ void shouldUpdateHubAndEmitSearchIndexEvents() throws Exception { .andReturn().getResponse() .getContentAsString(); - var hubIdStr = objectMapper.readTree(responseJson) + var hubIdStr = TEST_JSON_MAPPER.readTree(responseJson) .path("resource") .path("http://bibfra.me/vocab/lite/Hub") .path("id") - .asText(); + .asString(); checkSearchIndexMessage(existingHub.getId(), DELETE); checkSearchIndexMessage(Long.parseLong(hubIdStr), CREATE); checkIndexDate(hubIdStr); diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerSrsIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerSrsIT.java index c7f5ff343..f04447f98 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerSrsIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerSrsIT.java @@ -1,7 +1,7 @@ package org.folio.linked.data.e2e.resource; import static org.folio.linked.data.e2e.resource.ResourceControllerITBase.RESOURCE_URL; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; @@ -12,7 +12,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.ObjectMapper; import org.folio.linked.data.e2e.ITBase; import org.folio.linked.data.e2e.base.IntegrationTest; import org.junit.jupiter.api.Test; @@ -21,8 +20,6 @@ @IntegrationTest class ResourceControllerSrsIT extends ITBase { - private final ObjectMapper objectMapper = OBJECT_MAPPER; - @Test void createWorkWithInstanceRef_shouldCreateAuthorityFromSrs() throws Exception { var existingSrsId = "srs_id_0001"; @@ -42,7 +39,7 @@ void createWorkWithInstanceRef_shouldCreateAuthorityFromSrs() throws Exception { .andExpect(content().contentType(APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - var creatorResourceId = objectMapper.readTree(resp) + var creatorResourceId = TEST_JSON_MAPPER.readTree(resp) .path("resource") .path("http://bibfra.me/vocab/lite/Work") .path("_creatorReference").get(0) diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateAndMergeWorksIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateAndMergeWorksIT.java index a1abaaf0e..db75a5bdb 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateAndMergeWorksIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateAndMergeWorksIT.java @@ -2,19 +2,17 @@ import static org.folio.linked.data.e2e.resource.ResourceControllerITBase.RESOURCE_URL; import static org.folio.linked.data.test.MonographTestUtil.getWork; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.awaitAndAssert; import static org.folio.linked.data.test.TestUtil.defaultHeaders; -import static org.folio.linked.data.test.TestUtil.readTree; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashSet; import java.util.Map; import java.util.Set; -import lombok.SneakyThrows; import org.folio.ld.dictionary.PredicateDictionary; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.linked.data.domain.dto.InstanceIngressEvent; @@ -46,8 +44,6 @@ class ResourceControllerUpdateAndMergeWorksIT extends ITBase { @Autowired private ResourceTestService resourceTestService; @Autowired - private ObjectMapper objectMapper; - @Autowired private KafkaInventoryTopicListener inventoryTopicListener; @Autowired private KafkaSearchWorkIndexTopicListener searchWorkIndexTopicListener; @@ -165,11 +161,11 @@ private Resource getInstance(Resource work) { .replace("%TITLE%", titleStr); var title = new Resource() .addTypes(ResourceTypeDictionary.TITLE) - .setDoc(readTree(titleDoc)) + .setDoc(TEST_JSON_MAPPER.readTree(titleDoc)) .setLabel(titleStr); var instance = new Resource() .addTypes(ResourceTypeDictionary.INSTANCE) - .setDoc(readTree("{}")) + .setDoc(TEST_JSON_MAPPER.readTree("{}")) .setLabel(titleStr); instance.addOutgoingEdge(new ResourceEdge(instance, title, PredicateDictionary.TITLE)); @@ -181,9 +177,8 @@ private Resource getInstance(Resource work) { return instance; } - @SneakyThrows private T parse(String json, Class clazz) { - return objectMapper.readValue(json, clazz); + return TEST_JSON_MAPPER.readValue(json, clazz); } private boolean isExpectedSearchEvents(Set events, long deletedWorkId, long createdWorkId) { @@ -212,7 +207,7 @@ private boolean isSearchDeleteEvent(ResourceIndexEvent event, Long deletedWorkId private LinkedDataWork getWorkFromEvent(ResourceIndexEvent event) { var data = (Map) event.getNew(); - return objectMapper.convertValue(data, LinkedDataWork.class); + return TEST_JSON_MAPPER.convertValue(data, LinkedDataWork.class); } private boolean isExpectedInventoryEvents(Set inventoryEventList) { diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateInstanceIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateInstanceIT.java index 625791dfe..41cf8c594 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateInstanceIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateInstanceIT.java @@ -4,17 +4,14 @@ import static org.folio.linked.data.e2e.resource.ResourceControllerITBase.RESOURCE_URL; import static org.folio.linked.data.test.MonographTestUtil.getWork; import static org.folio.linked.data.test.TestUtil.STANDALONE_TEST_PROFILE; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultHeaders; -import static org.folio.linked.data.test.TestUtil.readTree; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.SneakyThrows; import org.folio.ld.dictionary.PredicateDictionary; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.linked.data.e2e.ITBase; @@ -29,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; +import tools.jackson.databind.JsonNode; @IntegrationTest @SpringBootTest() @@ -38,8 +36,6 @@ class ResourceControllerUpdateInstanceIT extends ITBase { private ResourceTestService resourceTestService; @Autowired private RawMarcRepository rawMarcRepository; - @Autowired - private ObjectMapper objectMapper; @Test void update_should_reject_if_instance_with_same_id_exists_and_connected_to_different_work() throws Exception { @@ -149,9 +145,8 @@ void update_should_retain_unmapped_marc_records() throws Exception { .isEqualTo(unmappedMarc); } - @SneakyThrows private long getInstanceId(String postResponse) { - JsonNode rootNode = objectMapper.readTree(postResponse); + JsonNode rootNode = TEST_JSON_MAPPER.readTree(postResponse); return rootNode .path("resource") .path("http://bibfra.me/vocab/lite/Instance") @@ -168,11 +163,11 @@ private Resource getInstance(Resource work, String titleStr) { .replace("%TITLE%", titleStr); var title = new Resource() .addTypes(ResourceTypeDictionary.TITLE) - .setDoc(readTree(titleDoc)) + .setDoc(TEST_JSON_MAPPER.readTree(titleDoc)) .setLabel(titleStr); var instance = new Resource() .addTypes(ResourceTypeDictionary.INSTANCE) - .setDoc(readTree("{}")) + .setDoc(TEST_JSON_MAPPER.readTree("{}")) .setLabel(titleStr); instance.addOutgoingEdge(new ResourceEdge(instance, title, PredicateDictionary.TITLE)); diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateWorkIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateWorkIT.java index 90b90ab50..668e651c9 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateWorkIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceControllerUpdateWorkIT.java @@ -11,18 +11,15 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.PERSON; import static org.folio.ld.dictionary.ResourceTypeDictionary.WORK; import static org.folio.linked.data.e2e.resource.ResourceControllerITBase.RESOURCE_URL; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.awaitAndAssert; import static org.folio.linked.data.test.TestUtil.defaultHeaders; -import static org.folio.linked.data.test.TestUtil.readTree; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.SneakyThrows; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.linked.data.domain.dto.InstanceIngressEvent; import org.folio.linked.data.e2e.ITBase; @@ -39,6 +36,7 @@ import org.marc4j.marc.DataField; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import tools.jackson.databind.JsonNode; @IntegrationTest @SpringBootTest(classes = {KafkaProducerTestConfiguration.class}) @@ -46,8 +44,6 @@ class ResourceControllerUpdateWorkIT extends ITBase { @Autowired private ResourceTestService resourceTestService; @Autowired - private ObjectMapper objectMapper; - @Autowired private KafkaInventoryTopicListener inventoryTopicListener; @Autowired private MarcReaderProcessor marcReader; @@ -138,7 +134,7 @@ private String getWorkRequestDto(String label, Long personId, Long instanceId) { private Resource getWork(String label) { var title = new Resource() .addTypes(ResourceTypeDictionary.TITLE) - .setDoc(readTree(""" + .setDoc(TEST_JSON_MAPPER.readTree(""" { "http://bibfra.me/vocab/library/mainTitle": ["%s"] } @@ -146,7 +142,7 @@ private Resource getWork(String label) { .setLabel(label); var work = new Resource() .addTypes(WORK, BOOKS) - .setDoc(readTree("{}")) + .setDoc(TEST_JSON_MAPPER.readTree("{}")) .setLabel(label); work.addOutgoingEdge(new ResourceEdge(work, title, TITLE)); @@ -160,7 +156,7 @@ private Resource getWork(String label) { private Resource getInstance(Resource work) { var title = new Resource() .addTypes(ResourceTypeDictionary.TITLE) - .setDoc(readTree(""" + .setDoc(TEST_JSON_MAPPER.readTree(""" { "http://bibfra.me/vocab/library/mainTitle": ["simple_instance"] } @@ -168,7 +164,7 @@ private Resource getInstance(Resource work) { .setLabel("simple_instance"); var instance = new Resource() .addTypes(INSTANCE) - .setDoc(readTree("{}")) + .setDoc(TEST_JSON_MAPPER.readTree("{}")) .setLabel("simple_instance"); instance.addOutgoingEdge(new ResourceEdge(instance, title, TITLE)); @@ -183,7 +179,7 @@ private Resource getInstance(Resource work) { private Resource getPerson() { var person = new Resource() .addTypes(PERSON) - .setDoc(readTree(""" + .setDoc(TEST_JSON_MAPPER.readTree(""" { "http://bibfra.me/vocab/lite/name": ["Person name"] } @@ -192,7 +188,7 @@ private Resource getPerson() { var lccn = new Resource() .addTypes(ID_LCCN, IDENTIFIER) - .setDoc(readTree(""" + .setDoc(TEST_JSON_MAPPER.readTree(""" { "http://bibfra.me/vocab/lite/link": ["n123456789"] } @@ -208,9 +204,8 @@ private Resource getPerson() { return person; } - @SneakyThrows private T parse(String json, Class clazz) { - return objectMapper.readValue(json, clazz); + return TEST_JSON_MAPPER.readValue(json, clazz); } private boolean isExpectedEvent(String eventStr, long linkedDataId) { @@ -245,7 +240,7 @@ private org.folio.ld.dictionary.model.Resource performGetGraph(Long resourceId) var response = mockMvc.perform(requestBuilder) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); - return objectMapper.readValue(response, org.folio.ld.dictionary.model.Resource.class); + return TEST_JSON_MAPPER.readValue(response, org.folio.ld.dictionary.model.Resource.class); } private JsonNode putResource(Long resourceId, String dto) throws Exception { @@ -256,6 +251,6 @@ private JsonNode putResource(Long resourceId, String dto) throws Exception { var response = mockMvc.perform(updateRequest) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); - return objectMapper.readTree(response); + return TEST_JSON_MAPPER.readTree(response); } } diff --git a/src/test/java/org/folio/linked/data/e2e/resource/ResourceGraphControllerIT.java b/src/test/java/org/folio/linked/data/e2e/resource/ResourceGraphControllerIT.java index 08dee808a..65b068049 100644 --- a/src/test/java/org/folio/linked/data/e2e/resource/ResourceGraphControllerIT.java +++ b/src/test/java/org/folio/linked/data/e2e/resource/ResourceGraphControllerIT.java @@ -6,6 +6,7 @@ import static org.folio.ld.dictionary.PropertyDictionary.PROVIDER_DATE; import static org.folio.ld.dictionary.PropertyDictionary.SIMPLE_PLACE; import static org.folio.ld.dictionary.ResourceTypeDictionary.PROVIDER_EVENT; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultHeaders; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.springframework.http.MediaType.APPLICATION_JSON; @@ -13,14 +14,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.fasterxml.jackson.databind.ObjectMapper; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.Set; import org.folio.ld.dictionary.model.Resource; import org.folio.linked.data.e2e.ITBase; import org.folio.linked.data.e2e.base.IntegrationTest; -import org.folio.linked.data.service.tenant.TenantScopedExecutionService; import org.folio.linked.data.test.MonographTestUtil; import org.folio.linked.data.test.resource.ResourceTestService; import org.folio.spring.tools.kafka.KafkaAdminService; @@ -40,10 +39,6 @@ class ResourceGraphControllerIT extends ITBase { private Environment env; @Autowired private MockMvc mockMvc; - @Autowired - private ObjectMapper objectMapper; - @Autowired - private TenantScopedExecutionService tenantScopedExecutionService; @MockitoSpyBean private KafkaAdminService kafkaAdminService; @@ -62,13 +57,13 @@ void getResourceGraphById_shouldReturnResourceGraph() throws Exception { .andReturn().getResponse().getContentAsString(); // then - var providerEventModel = objectMapper.readValue(providerEventResponse, Resource.class); + var providerEventModel = TEST_JSON_MAPPER.readValue(providerEventResponse, Resource.class); assertNotNull(providerEventModel.getId()); assertThat(providerEventModel.getTypes()).isEqualTo(Set.of(PROVIDER_EVENT)); - assertThat(providerEventModel.getDoc().get(NAME.getValue()).get(0).asText()).isEqualTo("production name"); - assertThat(providerEventModel.getDoc().get(PROVIDER_DATE.getValue()).get(0).asText()) + assertThat(providerEventModel.getDoc().get(NAME.getValue()).get(0).asString()).isEqualTo("production name"); + assertThat(providerEventModel.getDoc().get(PROVIDER_DATE.getValue()).get(0).asString()) .isEqualTo("production provider date"); - assertThat(providerEventModel.getDoc().get(SIMPLE_PLACE.getValue()).get(0).asText()) + assertThat(providerEventModel.getDoc().get(SIMPLE_PLACE.getValue()).get(0).asString()) .isEqualTo("production simple place"); assertThat(providerEventModel.getIncomingEdges()).isEmpty(); assertThat(providerEventModel.getOutgoingEdges()).hasSize(1); @@ -79,7 +74,7 @@ void getResourceGraphById_shouldReturnResourceGraph() throws Exception { .andExpect(status().isOk()) .andExpect(content().contentType(APPLICATION_JSON)) .andReturn().getResponse().getContentAsString(); - var providerPlaceModel = objectMapper.readValue(providerPlaceResponse, Resource.class); + var providerPlaceModel = TEST_JSON_MAPPER.readValue(providerPlaceResponse, Resource.class); assertThat(providerPlaceModel.getOutgoingEdges()).isEmpty(); assertThat(providerPlaceModel.getIncomingEdges()).hasSize(1); var providerPlaceSourceEdge = providerPlaceModel.getIncomingEdges().iterator().next(); diff --git a/src/test/java/org/folio/linked/data/integration/kafka/listener/InventoryInstanceEventListenerIT.java b/src/test/java/org/folio/linked/data/integration/kafka/listener/InventoryInstanceEventListenerIT.java index 8de2b8d2b..1540aec36 100644 --- a/src/test/java/org/folio/linked/data/integration/kafka/listener/InventoryInstanceEventListenerIT.java +++ b/src/test/java/org/folio/linked/data/integration/kafka/listener/InventoryInstanceEventListenerIT.java @@ -1,6 +1,7 @@ package org.folio.linked.data.integration.kafka.listener; import static org.folio.linked.data.test.TestUtil.TENANT_ID; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.awaitAndAssert; import static org.folio.linked.data.test.kafka.KafkaEventsTestDataFixture.getInventoryInstanceEventSampleProducerRecord; import static org.folio.spring.integration.XOkapiHeaders.TENANT; @@ -9,8 +10,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.kafka.common.header.internals.RecordHeader; import org.folio.linked.data.domain.dto.InventoryInstanceEvent; import org.folio.linked.data.domain.dto.ResourceIndexEventType; @@ -29,9 +28,6 @@ class InventoryInstanceEventListenerIT { @Autowired private KafkaTemplate eventKafkaTemplate; - @Autowired - private ObjectMapper objectMapper; - @MockitoSpyBean private InventoryInstanceEventHandler inventoryInstanceDomainEventHandler; @@ -50,14 +46,14 @@ void shouldConsumeInventoryInstanceEvent() { // then awaitAndAssert(() -> verify(inventoryInstanceDomainEventHandler) - .handle(objectMapper.readValue(eventProducerRecord.value(), InventoryInstanceEvent.class), null)); + .handle(TEST_JSON_MAPPER.readValue(eventProducerRecord.value(), InventoryInstanceEvent.class), null)); } @Test - void shouldRetryIfErrorOccurs() throws JsonProcessingException { + void shouldRetryIfErrorOccurs() { // given var eventProducerRecord = getInventoryInstanceEventSampleProducerRecord(); - var event = objectMapper.readValue(eventProducerRecord.value(), InventoryInstanceEvent.class); + var event = TEST_JSON_MAPPER.readValue(eventProducerRecord.value(), InventoryInstanceEvent.class); var expectedEvent = new InventoryInstanceEvent() .id(event.getId()) ._new(event.getNew()) diff --git a/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/InventoryInstanceEventHandlerIT.java b/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/InventoryInstanceEventHandlerIT.java index b55c6d2ea..9e1c694ed 100644 --- a/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/InventoryInstanceEventHandlerIT.java +++ b/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/InventoryInstanceEventHandlerIT.java @@ -41,6 +41,7 @@ void clean() { kafkaSearchWorkIndexTopicListener.getMessages().clear(); folioMetadataRepository.deleteAll(); resourceRepository.deleteAll(); + return null; } ); } diff --git a/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/InventoryInstanceEventHandlerTest.java b/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/InventoryInstanceEventHandlerTest.java index ee98299e4..30b3ff7aa 100644 --- a/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/InventoryInstanceEventHandlerTest.java +++ b/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/InventoryInstanceEventHandlerTest.java @@ -1,14 +1,12 @@ package org.folio.linked.data.integration.kafka.listener.handler; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Optional; import org.folio.linked.data.domain.dto.InventoryInstanceEvent; import org.folio.linked.data.domain.dto.ResourceIndexEventType; @@ -28,9 +26,6 @@ @ExtendWith(MockitoExtension.class) class InventoryInstanceEventHandlerTest { - private static final ObjectMapper MAPPER = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - @Mock private WorkUpdateMessageSender workUpdateMessageSender; @Mock @@ -134,10 +129,6 @@ private InventoryInstanceEvent getEventWithChangesInSuppressFlags() { private InventoryInstanceEvent getEvent() { var eventSource = TestUtil.loadResourceAsString("samples/inventoryInstanceEvent.json"); - try { - return MAPPER.readValue(eventSource, InventoryInstanceEvent.class); - } catch (JsonProcessingException e) { - throw new IllegalArgumentException(e); - } + return TEST_JSON_MAPPER.readValue(eventSource, InventoryInstanceEvent.class); } } diff --git a/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/LdImportOutputEventHandlerIT.java b/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/LdImportOutputEventHandlerIT.java index 25ddf69d6..0380db255 100644 --- a/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/LdImportOutputEventHandlerIT.java +++ b/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/LdImportOutputEventHandlerIT.java @@ -11,7 +11,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import java.util.ArrayList; -import lombok.SneakyThrows; import org.apache.kafka.clients.producer.ProducerRecord; import org.folio.linked.data.e2e.base.IntegrationTest; import org.folio.linked.data.mapper.ResourceModelMapper; @@ -49,7 +48,10 @@ static void beforeAll(@Autowired KafkaAdminService kafkaAdminService) { @BeforeEach void clean() { - tenantScopedExecutionService.execute(TENANT_ID, () -> cleanResourceTables(jdbcTemplate)); + tenantScopedExecutionService.execute(TENANT_ID, () -> { + cleanResourceTables(jdbcTemplate); + return null; + }); importResultListener.clear(); } @@ -84,7 +86,6 @@ void incomingLdImportEvent_shouldBeHandledCorrectly() { assertThat(eventResult.getFailedResources()).isEmpty(); } - @SneakyThrows private ProducerRecord getImportOutputEventProducerRecord() { var headers = new ArrayList<>(defaultKafkaHeaders()); var topic = getTenantTopicName(LD_IMPORT_OUTPUT_TOPIC, TENANT_ID); diff --git a/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/SourceRecordDomainEventHandlerIT.java b/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/SourceRecordDomainEventHandlerIT.java index cb6a8438a..3cb9ead81 100644 --- a/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/SourceRecordDomainEventHandlerIT.java +++ b/src/test/java/org/folio/linked/data/integration/kafka/listener/handler/SourceRecordDomainEventHandlerIT.java @@ -97,6 +97,7 @@ void clean() { () -> { cleanResourceTables(jdbcTemplate); kafkaSearchWorkIndexTopicListener.getMessages().clear(); + return null; } ); } @@ -156,10 +157,10 @@ void shouldSaveAdminMetadataOutOfMarcBibSourceRecordDomainEvent() { assertThat(adminMetadataDoc).hasSize(2); assertThat(adminMetadataDoc.has(CONTROL_NUMBER.getValue())).isTrue(); assertThat(adminMetadataDoc.get(CONTROL_NUMBER.getValue())).hasSize(1); - assertThat(adminMetadataDoc.get(CONTROL_NUMBER.getValue()).get(0).asText()).isEqualTo("#880524405##"); + assertThat(adminMetadataDoc.get(CONTROL_NUMBER.getValue()).get(0).asString()).isEqualTo("#880524405##"); assertThat(adminMetadataDoc.has(CREATED_DATE.getValue())).isTrue(); assertThat(adminMetadataDoc.get(CREATED_DATE.getValue())).hasSize(1); - assertThat(adminMetadataDoc.get(CREATED_DATE.getValue()).get(0).asText()).isEqualTo("2019-06-07"); + assertThat(adminMetadataDoc.get(CREATED_DATE.getValue()).get(0).asString()).isEqualTo("2019-06-07"); verifyNoInteractions(instanceIngressMessageProducer); } diff --git a/src/test/java/org/folio/linked/data/integration/rest/configuration/ConfigurationClientCacheIT.java b/src/test/java/org/folio/linked/data/integration/rest/configuration/ConfigurationClientCacheIT.java index 6f99952bc..cc81782dd 100644 --- a/src/test/java/org/folio/linked/data/integration/rest/configuration/ConfigurationClientCacheIT.java +++ b/src/test/java/org/folio/linked/data/integration/rest/configuration/ConfigurationClientCacheIT.java @@ -2,11 +2,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.linked.data.test.TestUtil.TENANT_ID; -import static org.folio.linked.data.test.TestUtil.executeAsyncWithContext; import static org.folio.linked.data.util.Constants.Cache.SETTINGS_ENTRIES; import org.folio.linked.data.e2e.base.IntegrationTest; -import org.folio.spring.tools.context.ExecutionContextBuilder; +import org.folio.linked.data.service.tenant.TenantScopedExecutionService; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -18,12 +17,10 @@ class ConfigurationClientCacheIT { @Autowired private ConfigurationService configurationService; - - @Autowired - private ExecutionContextBuilder contextBuilder; - @Autowired private CacheManager cacheManager; + @Autowired + private TenantScopedExecutionService tenantScopedExecutionService; @BeforeEach void setUp() { @@ -41,7 +38,7 @@ void shouldNotShareCacheAcrossTenants() { var tenant1 = TENANT_ID; // when - populate cache for tenant1 - executeAsyncWithContext(contextBuilder, tenant1, () -> configurationService.getFolioHost()); + tenantScopedExecutionService.execute(tenant1, () -> configurationService.getFolioHost()); // Verify tenant1 has cache entry var cache = cacheManager.getCache(SETTINGS_ENTRIES); @@ -58,7 +55,7 @@ void shouldNotShareCacheAcrossTenants() { assertThat(tenant2CacheValue).isNull(); // when - make call for tenant2 - executeAsyncWithContext(contextBuilder, tenant2, () -> configurationService.getFolioHost()); + tenantScopedExecutionService.execute(tenant2, () -> configurationService.getFolioHost()); // then - now tenant2 should have its own cache entry assertThat(cache.get(tenant2CacheKey)).isNotNull(); diff --git a/src/test/java/org/folio/linked/data/integration/rest/search/SearchServiceFolioTest.java b/src/test/java/org/folio/linked/data/integration/rest/search/SearchServiceFolioTest.java index 3e31ccaef..b5adf6870 100644 --- a/src/test/java/org/folio/linked/data/integration/rest/search/SearchServiceFolioTest.java +++ b/src/test/java/org/folio/linked/data/integration/rest/search/SearchServiceFolioTest.java @@ -7,7 +7,6 @@ import static org.mockito.Mockito.when; import static org.springframework.http.HttpStatus.OK; -import feign.FeignException; import java.util.List; import java.util.stream.Stream; import org.folio.linked.data.domain.dto.AuthorityItem; @@ -25,6 +24,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.ResponseEntity; import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.client.HttpClientErrorException; @UnitTest @ExtendWith(MockitoExtension.class) @@ -55,11 +55,11 @@ void setUp() { @Test void shouldReturnZeroTotalRecords_ifSearchClientThrowsNotFound() { // given - when(searchClient.searchInstances(any())).thenThrow(FeignException.NotFound.class); + when(searchClient.searchInstances(any())).thenThrow(HttpClientErrorException.NotFound.class); var lccn = List.of(""); // expect - assertThrows(FeignException.NotFound.class, () -> + assertThrows(HttpClientErrorException.NotFound.class, () -> searchService.countInstancesByLccnExcludingSuppressedAndId(lccn, "")); } diff --git a/src/test/java/org/folio/linked/data/integration/rest/settings/SettingsClientCacheIT.java b/src/test/java/org/folio/linked/data/integration/rest/settings/SettingsClientCacheIT.java index 20ced3e81..c073d3140 100644 --- a/src/test/java/org/folio/linked/data/integration/rest/settings/SettingsClientCacheIT.java +++ b/src/test/java/org/folio/linked/data/integration/rest/settings/SettingsClientCacheIT.java @@ -2,11 +2,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.linked.data.test.TestUtil.TENANT_ID; -import static org.folio.linked.data.test.TestUtil.executeAsyncWithContext; import static org.folio.linked.data.util.Constants.Cache.SETTINGS_ENTRIES; import org.folio.linked.data.e2e.base.IntegrationTest; -import org.folio.spring.tools.context.ExecutionContextBuilder; +import org.folio.linked.data.service.tenant.TenantScopedExecutionService; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -18,12 +17,10 @@ class SettingsClientCacheIT { @Autowired private SettingsClient settingsClient; - - @Autowired - private ExecutionContextBuilder contextBuilder; - @Autowired private CacheManager cacheManager; + @Autowired + private TenantScopedExecutionService tenantScopedExecutionService; @BeforeEach void setUp() { @@ -42,7 +39,7 @@ void shouldNotShareCacheAcrossTenants() { var query = "key==test.setting"; // when - populate cache for tenant1 - executeAsyncWithContext(contextBuilder, tenant1, () -> settingsClient.getEntries(query)); + tenantScopedExecutionService.execute(tenant1, () -> settingsClient.getEntries(query)); // Verify tenant1 has cache entry var cache = cacheManager.getCache(SETTINGS_ENTRIES); @@ -59,7 +56,7 @@ void shouldNotShareCacheAcrossTenants() { assertThat(tenant2CacheValue).isNull(); // when - make call for tenant2 - executeAsyncWithContext(contextBuilder, tenant2, () -> settingsClient.getEntries(query)); + tenantScopedExecutionService.execute(tenant2, () -> settingsClient.getEntries(query)); // then - now tenant2 should have its own cache entry assertThat(cache.get(tenant2CacheKey)).isNotNull(); diff --git a/src/test/java/org/folio/linked/data/integration/rest/specification/SpecClientCacheIT.java b/src/test/java/org/folio/linked/data/integration/rest/specification/SpecClientCacheIT.java index 7832cb7dc..ff0b8517c 100644 --- a/src/test/java/org/folio/linked/data/integration/rest/specification/SpecClientCacheIT.java +++ b/src/test/java/org/folio/linked/data/integration/rest/specification/SpecClientCacheIT.java @@ -2,12 +2,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.linked.data.test.TestUtil.TENANT_ID; -import static org.folio.linked.data.test.TestUtil.executeAsyncWithContext; import static org.folio.linked.data.util.Constants.Cache.SPEC_RULES; import java.util.UUID; import org.folio.linked.data.e2e.base.IntegrationTest; -import org.folio.spring.tools.context.ExecutionContextBuilder; +import org.folio.linked.data.service.tenant.TenantScopedExecutionService; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -19,12 +18,10 @@ class SpecClientCacheIT { @Autowired private SpecClient specClient; - - @Autowired - private ExecutionContextBuilder contextBuilder; - @Autowired private CacheManager cacheManager; + @Autowired + private TenantScopedExecutionService tenantScopedExecutionService; @BeforeEach void setUp() { @@ -43,7 +40,7 @@ void shouldNotShareCacheAcrossTenants() { var specId = UUID.fromString("bbb1f951-1f30-52e5-b827-557766551002"); // when - populate cache for tenant1 - executeAsyncWithContext(contextBuilder, tenant1, () -> specClient.getSpecRules(specId)); + tenantScopedExecutionService.execute(tenant1, () -> specClient.getSpecRules(specId)); // Verify tenant1 has cache entry var cache = cacheManager.getCache(SPEC_RULES); @@ -60,7 +57,7 @@ void shouldNotShareCacheAcrossTenants() { assertThat(tenant2CacheValue).isNull(); // when - make call for tenant2 - executeAsyncWithContext(contextBuilder, tenant2, () -> specClient.getSpecRules(specId)); + tenantScopedExecutionService.execute(tenant2, () -> specClient.getSpecRules(specId)); // then - now tenant2 should have its own cache entry assertThat(cache.get(tenant2CacheKey)).isNotNull(); diff --git a/src/test/java/org/folio/linked/data/integration/rest/specification/SpecProviderFolioTest.java b/src/test/java/org/folio/linked/data/integration/rest/specification/SpecProviderFolioTest.java index 3ceaead53..8d85725c3 100644 --- a/src/test/java/org/folio/linked/data/integration/rest/specification/SpecProviderFolioTest.java +++ b/src/test/java/org/folio/linked/data/integration/rest/specification/SpecProviderFolioTest.java @@ -6,7 +6,6 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; -import feign.FeignException; import java.util.List; import org.folio.rspec.domain.dto.SpecificationDto; import org.folio.rspec.domain.dto.SpecificationDtoCollection; @@ -19,6 +18,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpClientErrorException; @UnitTest @ExtendWith(MockitoExtension.class) @@ -49,7 +49,7 @@ void shouldReturn_specRules_whenSpecificationStorageIsAvailable() { @Test void shouldReturn_emptyList_whenSpecificationStorageIsNotAvailable() { //given - when(client.getBibMarcSpecs()).thenThrow(FeignException.class); + when(client.getBibMarcSpecs()).thenThrow(HttpClientErrorException.TooManyRequests.class); //expect assertEquals(emptyList(), specProvider.getSpecRules()); diff --git a/src/test/java/org/folio/linked/data/mapper/dto/ResourceMarcViewDtoMapperTest.java b/src/test/java/org/folio/linked/data/mapper/dto/ResourceMarcViewDtoMapperTest.java index 70f0427c3..e90cc10eb 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/ResourceMarcViewDtoMapperTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/ResourceMarcViewDtoMapperTest.java @@ -2,8 +2,8 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.folio.ld.dictionary.ResourceTypeDictionary.PROVIDER_EVENT; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.databind.ObjectMapper; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.List; @@ -49,7 +49,7 @@ private Resource generateTestResource() { return new Resource() .setIdAndRefreshEdges(3856321131L) .setTypes(Set.of(new ResourceTypeEntity().setUri(PROVIDER_EVENT.getUri()))) - .setDoc(new ObjectMapper().valueToTree(Map.of( + .setDoc(TEST_JSON_MAPPER.valueToTree(Map.of( "http://bibfra.me/vocab/lite/name", List.of("name $ 2023"), "http://bibfra.me/vocab/lite/providerDate", List.of("1981"), "http://bibfra.me/vocab/lite/place", List.of("Alaska"))) diff --git a/src/test/java/org/folio/linked/data/mapper/dto/ResourceSubgraphViewMapperTest.java b/src/test/java/org/folio/linked/data/mapper/dto/ResourceSubgraphViewMapperTest.java index 54e52df73..8a9b7e33b 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/ResourceSubgraphViewMapperTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/ResourceSubgraphViewMapperTest.java @@ -56,7 +56,7 @@ void fromJson_validJson_returnsDto() { var resource = result.get(); assertThat(resource.getId()).isEqualTo(123L); assertThat(resource.getLabel()).isEqualTo("test label"); - assertThat(resource.getDoc().get("key1").get(0).asText()).isEqualTo("value1"); + assertThat(resource.getDoc().get("key1").get(0).asString()).isEqualTo("value1"); assertThat(resource.getTypes()).containsExactly(INSTANCE); assertThat(resource.getOutgoingEdges()).hasSize(1); var edge1 = resource.getOutgoingEdges().iterator().next(); @@ -65,7 +65,7 @@ void fromJson_validJson_returnsDto() { var nested = edge1.getTarget(); assertThat(nested.getId()).isEqualTo(456L); assertThat(nested.getLabel()).isEqualTo("nested label"); - assertThat(nested.getDoc().get("nestedKey").get(0).asText()).isEqualTo("nestedValue"); + assertThat(nested.getDoc().get("nestedKey").get(0).asString()).isEqualTo("nestedValue"); assertThat(nested.getTypes()).containsExactly(TITLE); assertThat(nested.getOutgoingEdges()).isEmpty(); } diff --git a/src/test/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapperTest.java b/src/test/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapperTest.java index 3d02b87e6..1b9fdf58a 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapperTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/resource/base/CoreMapperTest.java @@ -1,6 +1,6 @@ package org.folio.linked.data.mapper.dto.resource.base; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.randomLong; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -12,9 +12,6 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.TextNode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -30,8 +27,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.databind.node.StringNode; @UnitTest @ExtendWith(MockitoExtension.class) @@ -39,8 +36,6 @@ class CoreMapperTest { @InjectMocks private CoreMapperImpl coreMapper; - @Spy - private ObjectMapper objectMapper = OBJECT_MAPPER; @Mock private SingleResourceMapper singleResourceMapper; @@ -76,7 +71,7 @@ void toDtoWithEdges_shouldThrowNpe_ifGivenDtoClassIsNull(@Mock Resource resource } @Test - void toJson_shouldReturnCorrectJsonNodeFromMap() throws JsonProcessingException { + void toJson_shouldReturnCorrectJsonNodeFromMap() { // given var map = new HashMap>(); map.put("key1", List.of("value1.1", "value1.2")); @@ -86,7 +81,7 @@ void toJson_shouldReturnCorrectJsonNodeFromMap() throws JsonProcessingException var jsonNode = coreMapper.toJson(map); // then - assertThat(OBJECT_MAPPER.writeValueAsString(jsonNode), + assertThat(TEST_JSON_MAPPER.writeValueAsString(jsonNode), is("{\"key1\":[\"value1.1\",\"value1.2\"],\"key2\":[\"value2.1\",\"value2.2\"]}")); } @@ -178,9 +173,9 @@ void addOutgoingEdges_shouldAddMappedEdgesToResource_ifGivenDtoListIsNotEmpty() var predicate = PredicateDictionary.MAP; var parent = InstanceResponse.class; var source = new Resource(); - var expectedTarget1 = new Resource().setDoc(new TextNode("1")).setIdAndRefreshEdges(111L); + var expectedTarget1 = new Resource().setDoc(new StringNode("1")).setIdAndRefreshEdges(111L); doReturn(expectedTarget1).when(singleResourceMapper).toEntity(dto1, parent, predicate, source); - var expectedTarget2 = new Resource().setDoc(new TextNode("2")).setIdAndRefreshEdges(222L); + var expectedTarget2 = new Resource().setDoc(new StringNode("2")).setIdAndRefreshEdges(222L); doReturn(expectedTarget2).when(singleResourceMapper).toEntity(dto2, parent, predicate, source); var dtoList = List.of(dto1, dto2); diff --git a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/NoteMapperTest.java b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/NoteMapperTest.java index be0a06fca..7c2d32feb 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/NoteMapperTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/NoteMapperTest.java @@ -5,10 +5,9 @@ import static org.folio.ld.dictionary.PropertyDictionary.ISSUANCE_NOTE; import static org.folio.ld.dictionary.PropertyDictionary.NOTE; import static org.folio.ld.dictionary.PropertyDictionary.WITH_NOTE; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.util.ResourceUtils.putProperty; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -19,11 +18,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import tools.jackson.databind.JsonNode; @UnitTest class NoteMapperTest { - - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private final NoteMapper noteMapper = new NoteMapper(); private static Stream provideDocAndExpectedNotes() { @@ -40,7 +38,7 @@ private static Stream provideDocAndExpectedNotes() { createNote(List.of(NOTE.getValue()), "general note")) ), Arguments.of( - OBJECT_MAPPER.convertValue(Map.of(), JsonNode.class), + TEST_JSON_MAPPER.convertValue(Map.of(), JsonNode.class), List.of() ) ); @@ -103,7 +101,7 @@ void putNotes_shouldAddNotesToMap(List notes, Map> ex private static JsonNode createDocWithoutNotes() { var map = new HashMap>(); putProperty(map, DIMENSIONS, List.of("dimensions")); - return OBJECT_MAPPER.convertValue(map, JsonNode.class); + return TEST_JSON_MAPPER.convertValue(map, JsonNode.class); } private static JsonNode createDocWithNotes() { @@ -111,7 +109,7 @@ private static JsonNode createDocWithNotes() { putProperty(map, DIMENSIONS, List.of("dimensions")); putProperty(map, NOTE, List.of("general note")); putProperty(map, ISSUANCE_NOTE, List.of("issuance note", "another issuance note")); - return OBJECT_MAPPER.convertValue(map, JsonNode.class); + return TEST_JSON_MAPPER.convertValue(map, JsonNode.class); } private static Note createNote(List types, String value) { diff --git a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/CarrierMapperUnitTest.java b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/CarrierMapperUnitTest.java index a9802d455..49f8aea94 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/CarrierMapperUnitTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/CarrierMapperUnitTest.java @@ -4,9 +4,8 @@ import static org.folio.ld.dictionary.PropertyDictionary.CODE; import static org.folio.ld.dictionary.PropertyDictionary.LINK; import static org.folio.ld.dictionary.PropertyDictionary.TERM; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Map; import org.folio.linked.data.configuration.ErrorResponseConfig; @@ -21,15 +20,14 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import tools.jackson.core.type.TypeReference; @SpringBootTest(classes = CarrierMapperUnit.class) -@Import({CoreMapperImpl.class, ObjectMapper.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) +@Import({CoreMapperImpl.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) @UnitTest class CarrierMapperUnitTest { @Autowired private CarrierMapperUnit carrierMapperUnit; - @Autowired - private ObjectMapper objectMapper; @MockitoBean private HashService hashService; @@ -48,7 +46,7 @@ void toEntity_shouldDeriveMarcCodeFromLink() { var resource = carrierMapperUnit.toEntity(category, new Resource()); // then - Map> props = objectMapper.convertValue(resource.getDoc(), new TypeReference<>() { + Map> props = TEST_JSON_MAPPER.convertValue(resource.getDoc(), new TypeReference<>() { }); assertThat(props.get(LINK.getValue())).hasSize(1).contains(expectedLink); assertThat(props.get(TERM.getValue())).hasSize(1).contains(expectedTerm); diff --git a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/ContentMapperUnitTest.java b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/ContentMapperUnitTest.java index e1555be6c..2e6e762f5 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/ContentMapperUnitTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/ContentMapperUnitTest.java @@ -7,9 +7,8 @@ import static org.folio.ld.dictionary.PropertyDictionary.LINK; import static org.folio.ld.dictionary.PropertyDictionary.TERM; import static org.folio.ld.dictionary.ResourceTypeDictionary.CATEGORY_SET; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Map; import org.folio.linked.data.configuration.ErrorResponseConfig; @@ -25,15 +24,14 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import tools.jackson.core.type.TypeReference; @SpringBootTest(classes = ContentMapperUnit.class) -@Import({CoreMapperImpl.class, ObjectMapper.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) +@Import({CoreMapperImpl.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) @UnitTest class ContentMapperUnitTest { @Autowired private ContentMapperUnit contentMapperUnit; - @Autowired - private ObjectMapper objectMapper; @MockitoBean private HashService hashService; @@ -52,7 +50,7 @@ void toEntity_shouldDeriveMarcCodeFromLink() { var resource = contentMapperUnit.toEntity(category, new Resource()); // then - Map> props = objectMapper.convertValue(resource.getDoc(), new TypeReference<>() { + Map> props = TEST_JSON_MAPPER.convertValue(resource.getDoc(), new TypeReference<>() { }); assertThat(props.get(LINK.getValue())).hasSize(1).contains(expectedLink); assertThat(props.get(TERM.getValue())).hasSize(1).contains(expectedTerm); @@ -75,7 +73,7 @@ void toEntity_shouldCreateCategorySet() { .extracting(ResourceTypeEntity::getUri) .containsExactly(CATEGORY_SET.getUri()); - Map> targetProps = objectMapper.convertValue(target.getDoc(), new TypeReference<>() { + Map> targetProps = TEST_JSON_MAPPER.convertValue(target.getDoc(), new TypeReference<>() { }); assertThat(targetProps.get(LINK.getValue())) .hasSize(1) diff --git a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/GovernmentPublicationMapperUnitTest.java b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/GovernmentPublicationMapperUnitTest.java index 278505ef6..bd5d382b3 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/GovernmentPublicationMapperUnitTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/GovernmentPublicationMapperUnitTest.java @@ -4,9 +4,8 @@ import static org.folio.ld.dictionary.PropertyDictionary.CODE; import static org.folio.ld.dictionary.PropertyDictionary.LINK; import static org.folio.ld.dictionary.PropertyDictionary.TERM; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Map; import org.folio.linked.data.configuration.ErrorResponseConfig; @@ -22,15 +21,14 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import tools.jackson.core.type.TypeReference; @SpringBootTest(classes = GovernmentPublicationMapperUnit.class) -@Import({CoreMapperImpl.class, ObjectMapper.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) +@Import({CoreMapperImpl.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) @UnitTest class GovernmentPublicationMapperUnitTest { @Autowired private GovernmentPublicationMapperUnit governmentPublicationMapperUnit; - @Autowired - private ObjectMapper objectMapper; @MockitoBean private HashService hashService; @@ -52,7 +50,7 @@ void toEntity_shouldDeriveMarcCodeFromLink(String linkSuffix, String expectedMar var resource = governmentPublicationMapperUnit.toEntity(category, new Resource()); // then - Map> props = objectMapper.convertValue(resource.getDoc(), new TypeReference<>() { + Map> props = TEST_JSON_MAPPER.convertValue(resource.getDoc(), new TypeReference<>() { }); assertThat(props.get(LINK.getValue())).hasSize(1).contains(expectedLink); assertThat(props.get(TERM.getValue())).hasSize(1).contains(expectedTerm); diff --git a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/MediaMapperUnitTest.java b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/MediaMapperUnitTest.java index fc4ea9a44..4864b123a 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/MediaMapperUnitTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/MediaMapperUnitTest.java @@ -4,9 +4,8 @@ import static org.folio.ld.dictionary.PropertyDictionary.CODE; import static org.folio.ld.dictionary.PropertyDictionary.LINK; import static org.folio.ld.dictionary.PropertyDictionary.TERM; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Map; import org.folio.linked.data.configuration.ErrorResponseConfig; @@ -21,15 +20,14 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import tools.jackson.core.type.TypeReference; @SpringBootTest(classes = MediaMapperUnit.class) -@Import({CoreMapperImpl.class, ObjectMapper.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) +@Import({CoreMapperImpl.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) @UnitTest class MediaMapperUnitTest { @Autowired private MediaMapperUnit mediaMapperUnit; - @Autowired - private ObjectMapper objectMapper; @MockitoBean private HashService hashService; @@ -48,7 +46,7 @@ void toEntity_shouldDeriveMarcCodeFromLink() { var resource = mediaMapperUnit.toEntity(category, new Resource()); // then - Map> props = objectMapper.convertValue(resource.getDoc(), new TypeReference<>() { + Map> props = TEST_JSON_MAPPER.convertValue(resource.getDoc(), new TypeReference<>() { }); assertThat(props.get(LINK.getValue())).hasSize(1).contains(expectedLink); assertThat(props.get(TERM.getValue())).hasSize(1).contains(expectedTerm); diff --git a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/TargetAudienceMapperUnitTest.java b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/TargetAudienceMapperUnitTest.java index 5dc702199..237f0a853 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/TargetAudienceMapperUnitTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/category/TargetAudienceMapperUnitTest.java @@ -7,9 +7,8 @@ import static org.folio.ld.dictionary.PropertyDictionary.LINK; import static org.folio.ld.dictionary.PropertyDictionary.TERM; import static org.folio.ld.dictionary.ResourceTypeDictionary.CATEGORY_SET; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Map; import org.folio.linked.data.configuration.ErrorResponseConfig; @@ -27,15 +26,14 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import tools.jackson.core.type.TypeReference; @SpringBootTest(classes = TargetAudienceMapperUnit.class) -@Import({CoreMapperImpl.class, ObjectMapper.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) +@Import({CoreMapperImpl.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) @UnitTest class TargetAudienceMapperUnitTest { @Autowired private TargetAudienceMapperUnit targetAudienceMapperUnit; - @Autowired - private ObjectMapper objectMapper; @MockitoBean private HashService hashService; @@ -63,7 +61,7 @@ void toEntity_shouldDeriveMarcCodeFromLink(String linkSuffix, String expectedMar var resource = targetAudienceMapperUnit.toEntity(category, new Resource()); // then - Map> props = objectMapper.convertValue(resource.getDoc(), new TypeReference<>() { + Map> props = TEST_JSON_MAPPER.convertValue(resource.getDoc(), new TypeReference<>() { }); assertThat(props.get(LINK.getValue())).hasSize(1).contains(expectedLink); assertThat(props.get(TERM.getValue())).hasSize(1).contains(expectedTerm); @@ -86,7 +84,7 @@ void toEntity_shouldCreateCategorySet() { .extracting(ResourceTypeEntity::getUri) .containsExactly(CATEGORY_SET.getUri()); - Map> targetProps = objectMapper.convertValue(target.getDoc(), new TypeReference<>() { + Map> targetProps = TEST_JSON_MAPPER.convertValue(target.getDoc(), new TypeReference<>() { }); assertThat(targetProps.get(LINK.getValue())) .hasSize(1) diff --git a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/place/OriginPlaceMapperUnitTest.java b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/place/OriginPlaceMapperUnitTest.java index d8519c1de..56c618b63 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/place/OriginPlaceMapperUnitTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/place/OriginPlaceMapperUnitTest.java @@ -4,9 +4,8 @@ import static org.folio.ld.dictionary.PropertyDictionary.CODE; import static org.folio.ld.dictionary.PropertyDictionary.LINK; import static org.folio.ld.dictionary.PropertyDictionary.NAME; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.Map; import org.folio.linked.data.configuration.ErrorResponseConfig; @@ -21,16 +20,15 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import tools.jackson.core.type.TypeReference; @SpringBootTest(classes = OriginPlaceMapperUnit.class) -@Import({CoreMapperImpl.class, ObjectMapper.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) +@Import({CoreMapperImpl.class, RequestProcessingExceptionBuilder.class, ErrorResponseConfig.class}) @UnitTest class OriginPlaceMapperUnitTest { @Autowired private OriginPlaceMapperUnit originPlaceMapperUnit; - @Autowired - private ObjectMapper objectMapper; @MockitoBean private HashService hashService; @@ -49,7 +47,7 @@ void toEntity_shouldDeriveMarcCodeFromLink() { var resource = originPlaceMapperUnit.toEntity(place, new Resource()); //then - var props = objectMapper.convertValue(resource.getDoc(), new TypeReference>>() {}); + var props = TEST_JSON_MAPPER.convertValue(resource.getDoc(), new TypeReference>>() {}); assertThat(props.get(CODE.getValue())).hasSize(1).contains(expectedMarcCode); assertThat(props.get(LINK.getValue())).hasSize(1).contains(expectedLink); assertThat(props.get(NAME.getValue())).hasSize(1).contains(expectedName); diff --git a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/reference/SubjectMapperUnitTest.java b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/reference/SubjectMapperUnitTest.java index 1abf97414..aef7bb25b 100644 --- a/src/test/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/reference/SubjectMapperUnitTest.java +++ b/src/test/java/org/folio/linked/data/mapper/dto/resource/common/work/sub/reference/SubjectMapperUnitTest.java @@ -8,11 +8,10 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.PERSON; import static org.folio.ld.dictionary.ResourceTypeDictionary.PLACE; import static org.folio.ld.dictionary.ResourceTypeDictionary.TOPIC; -import static org.folio.linked.data.test.TestUtil.readTree; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; import java.util.List; import org.folio.linked.data.domain.dto.Reference; import org.folio.linked.data.domain.dto.WorkResponse; @@ -27,6 +26,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.databind.node.JsonNodeFactory; @UnitTest @ExtendWith(MockitoExtension.class) @@ -58,7 +58,7 @@ void toEntity_wrapsWithConcept_whenSubjectIsNotOfTypeConcept() { // then assertThat(result).isNotNull(); assertThat(result.getDoc().has("http://library.link/vocab/resourcePreferred")).isFalse(); - assertThat(result.getDoc().get("http://bibfra.me/vocab/lite/name").get(0).asText()).isEqualTo(name); + assertThat(result.getDoc().get("http://bibfra.me/vocab/lite/name").get(0).asString()).isEqualTo(name); assertThat(result.getTypes().stream().map(ResourceTypeEntity::getUri)).contains(CONCEPT.getUri()); assertThat(result.getOutgoingEdges()) .hasSize(1) @@ -91,7 +91,7 @@ void toDto_shouldConvertResourceToDto() { var label = "label string"; var id = 1L; var resource = new Resource() - .setDoc(readTree(""" + .setDoc(TEST_JSON_MAPPER.readTree(""" { "http://library.link/vocab/resourcePreferred": ["true"] } @@ -118,7 +118,7 @@ void toDto_preferredFlagShouldBeFalse_whenResourceHasSubFocusEdge() { var focus = new Resource() .setLabel("John Doe") .addTypes(PERSON) - .setDoc(readTree(""" + .setDoc(TEST_JSON_MAPPER.readTree(""" { "http://library.link/vocab/resourcePreferred": ["true"] } @@ -127,7 +127,7 @@ void toDto_preferredFlagShouldBeFalse_whenResourceHasSubFocusEdge() { var subFocus = new Resource() .setLabel("Childhood") .addTypes(TOPIC) - .setDoc(readTree(""" + .setDoc(TEST_JSON_MAPPER.readTree(""" { "http://library.link/vocab/resourcePreferred": ["true"] } @@ -155,7 +155,7 @@ void toDto_shouldFetchPreferredFlagFromFocus_whenResourceHasNoSubFocusEdges() { var focus = new Resource() .setLabel("John Doe") .addTypes(PERSON) - .setDoc(readTree(""" + .setDoc(TEST_JSON_MAPPER.readTree(""" { "http://library.link/vocab/resourcePreferred": ["true"] } diff --git a/src/test/java/org/folio/linked/data/mapper/kafka/search/HubSearchMessageMapperTest.java b/src/test/java/org/folio/linked/data/mapper/kafka/search/HubSearchMessageMapperTest.java index dd6c2c6f5..b2dab68c3 100644 --- a/src/test/java/org/folio/linked/data/mapper/kafka/search/HubSearchMessageMapperTest.java +++ b/src/test/java/org/folio/linked/data/mapper/kafka/search/HubSearchMessageMapperTest.java @@ -1,9 +1,8 @@ package org.folio.linked.data.mapper.kafka.search; import static org.assertj.core.api.Assertions.assertThat; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.stream.Stream; import org.folio.linked.data.domain.dto.LinkedDataHub; import org.folio.linked.data.model.entity.Resource; @@ -16,7 +15,6 @@ @UnitTest class HubSearchMessageMapperTest { private final HubSearchMessageMapper mapper = new HubSearchMessageMapperImpl(); - private final ObjectMapper objectMapper = OBJECT_MAPPER; @ParameterizedTest @MethodSource("linkAndExpectedOriginalId") @@ -25,7 +23,7 @@ void testToIndex_extractsOriginalIdFromLink(String link, String expectedOriginal var resource = new Resource() .setIdAndRefreshEdges(123L) .setLabel("Test Hub") - .setDoc(objectMapper.readTree(String.format(""" + .setDoc(TEST_JSON_MAPPER.readTree(String.format(""" { "http://bibfra.me/vocab/lite/link": [ "%s" ] } diff --git a/src/test/java/org/folio/linked/data/mapper/kafka/search/WorkSearchMessageMapperTest.java b/src/test/java/org/folio/linked/data/mapper/kafka/search/WorkSearchMessageMapperTest.java index e73ed06d4..50b421b1d 100644 --- a/src/test/java/org/folio/linked/data/mapper/kafka/search/WorkSearchMessageMapperTest.java +++ b/src/test/java/org/folio/linked/data/mapper/kafka/search/WorkSearchMessageMapperTest.java @@ -131,7 +131,7 @@ void toIndex_shouldReturnCorrectlyMappedIndex_fromWork() { } private static String contributorName(Resource contributor) { - return contributor.getDoc().get(NAME.getValue()).get(0).textValue(); + return contributor.getDoc().get(NAME.getValue()).get(0).stringValue(); } private Resource getInstance(Long id, Resource work) { @@ -206,7 +206,7 @@ private void validateInstance(LinkedDataInstanceOnly instanceIndex, Resource ins assertThat(instanceIndex.getPublications().getFirst().getName()).isEqualTo("publication name"); assertThat(instanceIndex.getEditionStatements()).hasSize(1); assertThat(instanceIndex.getEditionStatements().getFirst()) - .isEqualTo(instance.getDoc().get(EDITION.getValue()).get(0).asText()); + .isEqualTo(instance.getDoc().get(EDITION.getValue()).get(0).asString()); } private void assertTitle(LinkedDataTitle titleInner, String value, LinkedDataTitle.TypeEnum type) { diff --git a/src/test/java/org/folio/linked/data/service/hub/HubServiceImplTest.java b/src/test/java/org/folio/linked/data/service/hub/HubServiceImplTest.java index 9fa2c5788..fc9e0da36 100644 --- a/src/test/java/org/folio/linked/data/service/hub/HubServiceImplTest.java +++ b/src/test/java/org/folio/linked/data/service/hub/HubServiceImplTest.java @@ -3,12 +3,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.folio.ld.dictionary.PropertyDictionary.LINK; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.fasterxml.jackson.databind.ObjectMapper; import org.folio.linked.data.domain.dto.ResourceResponseDto; import org.folio.linked.data.exception.RequestProcessingException; import org.folio.linked.data.mapper.dto.resource.hub.HubMapperUnit; @@ -38,9 +38,8 @@ void previewHub_shouldDownloadAndConvertHub() { // given var hubUri = "https://example.com/hub.json"; var resource = new Resource(); - var objectMapper = new ObjectMapper(); - var doc = objectMapper.createObjectNode(); - var linkArray = objectMapper.createArrayNode().add(hubUri); + var doc = TEST_JSON_MAPPER.createObjectNode(); + var linkArray = TEST_JSON_MAPPER.createArrayNode().add(hubUri); doc.set(LINK.getValue(), linkArray); resource.setDoc(doc); var expectedResponse = new ResourceResponseDto(); diff --git a/src/test/java/org/folio/linked/data/service/profile/ProfileServiceCacheIT.java b/src/test/java/org/folio/linked/data/service/profile/ProfileServiceCacheIT.java index 68da5646f..e2cc6a325 100644 --- a/src/test/java/org/folio/linked/data/service/profile/ProfileServiceCacheIT.java +++ b/src/test/java/org/folio/linked/data/service/profile/ProfileServiceCacheIT.java @@ -2,14 +2,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.linked.data.test.TestUtil.TENANT_ID; -import static org.folio.linked.data.test.TestUtil.executeAsyncWithContext; -import static org.folio.linked.data.test.TestUtil.executeWithContext; import static org.folio.linked.data.util.Constants.Cache.PROFILES; import org.folio.linked.data.e2e.base.IntegrationTest; import org.folio.linked.data.model.entity.Profile; import org.folio.linked.data.repo.ProfileRepository; import org.folio.linked.data.repo.ResourceTypeRepository; +import org.folio.linked.data.service.tenant.TenantScopedExecutionService; import org.folio.spring.tools.context.ExecutionContextBuilder; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -24,18 +23,16 @@ class ProfileServiceCacheIT { @Autowired private ProfileService profileService; - @Autowired private ProfileRepository profileRepository; - @Autowired private ResourceTypeRepository resourceTypeRepository; - @Autowired private ExecutionContextBuilder contextBuilder; - @Autowired private CacheManager cacheManager; + @Autowired + private TenantScopedExecutionService tenantScopedExecutionService; @BeforeEach void setUp() { @@ -53,13 +50,13 @@ void shouldNotShareCacheAcrossTenants() { // given var tenant1 = TENANT_ID; var profileId = TEST_PROFILE_ID; - executeAsyncWithContext(contextBuilder, tenant1, () -> createTestProfile(profileId, "Tenant1 Profile")); + tenantScopedExecutionService.execute(tenant1, () -> createTestProfile(profileId, "Tenant1 Profile")); // Clear cache to ensure fresh start clearCache(); // when - populate cache for tenant1 - var profile1 = executeWithContext(contextBuilder, tenant1, () -> profileService.getProfileById(profileId)); + var profile1 = tenantScopedExecutionService.execute(tenant1, () -> profileService.getProfileById(profileId)); // Verify tenant1 has cache entry var cache = cacheManager.getCache(PROFILES); @@ -80,10 +77,10 @@ void shouldNotShareCacheAcrossTenants() { // then - tenant2 should not have any cached value yet assertThat(tenant2CacheValue).isNull(); // Create profile for tenant2 - executeAsyncWithContext(contextBuilder, tenant2, () -> createTestProfile(profileId, "Tenant2 Profile")); + tenantScopedExecutionService.execute(tenant2, () -> createTestProfile(profileId, "Tenant2 Profile")); // when - make call for tenant2 - var profile2 = executeWithContext(contextBuilder, tenant2, () -> profileService.getProfileById(profileId)); + var profile2 = tenantScopedExecutionService.execute(tenant2, () -> profileService.getProfileById(profileId)); // then - now tenant2 should have its own cache entry assertThat(cache.get(tenant2CacheKey)).isNotNull(); @@ -97,7 +94,7 @@ void shouldNotShareCacheAcrossTenants() { assertThat(cache.get(tenant2CacheKey)).isNotNull(); } - private void createTestProfile(int id, String name) { + private Profile createTestProfile(int id, String name) { // Get existing resource type (Work type exists in test data) var resourceType = resourceTypeRepository.findByUri("http://bibfra.me/vocab/lite/Work"); if (resourceType == null) { @@ -110,13 +107,19 @@ private void createTestProfile(int id, String name) { .setResourceType(resourceType) .setValue("{\"profile\": \"" + name + "\"}"); - profileRepository.save(profile); + return profileRepository.save(profile); } private void cleanupTestProfiles() { // Delete profile with same ID from both tenant schemas - executeAsyncWithContext(contextBuilder, TENANT_ID, () -> profileRepository.deleteById(TEST_PROFILE_ID)); - executeAsyncWithContext(contextBuilder, "another_tenant", () -> profileRepository.deleteById(TEST_PROFILE_ID)); + tenantScopedExecutionService.execute(TENANT_ID, () -> { + profileRepository.deleteById(TEST_PROFILE_ID); + return null; + }); + tenantScopedExecutionService.execute("another_tenant", () -> { + profileRepository.deleteById(TEST_PROFILE_ID); + return null; + }); } private void clearCache() { diff --git a/src/test/java/org/folio/linked/data/service/profile/ProfileSettingsServiceImplTest.java b/src/test/java/org/folio/linked/data/service/profile/ProfileSettingsServiceImplTest.java index 615779ea6..bff1b42ca 100644 --- a/src/test/java/org/folio/linked/data/service/profile/ProfileSettingsServiceImplTest.java +++ b/src/test/java/org/folio/linked/data/service/profile/ProfileSettingsServiceImplTest.java @@ -3,24 +3,16 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.linked.data.test.TestUtil.emptyRequestProcessingException; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Optional; import java.util.UUID; -import lombok.SneakyThrows; -import org.folio.linked.data.domain.dto.CustomProfileSettings; import org.folio.linked.data.domain.dto.CustomProfileSettingsRequestDto; import org.folio.linked.data.exception.RequestProcessingException; import org.folio.linked.data.exception.RequestProcessingExceptionBuilder; import org.folio.linked.data.model.entity.Profile; -import org.folio.linked.data.model.entity.ProfileSettings; -import org.folio.linked.data.model.entity.pk.ProfileSettingsPk; import org.folio.linked.data.repo.ProfileRepository; import org.folio.linked.data.repo.ProfileSettingsRepository; import org.folio.spring.FolioExecutionContext; @@ -45,8 +37,6 @@ class ProfileSettingsServiceImplTest { private RequestProcessingExceptionBuilder exceptionBuilder; @Mock private FolioExecutionContext executionContext; - @Mock - private ObjectMapper objectMapper; @Test void getProfileSettings_shouldThrowNotFound_ifNoSuchProfile() { @@ -85,33 +75,6 @@ void getProfileSettings_shouldReturnInactiveSettings_ifNoSuchSettings() { assertThat(settings.getChildren()).isNull(); } - @SneakyThrows - @Test - void getProfileSettings_shouldReturnInactiveSettings_ifMalformedSettingsExist() { - // given - var userId = UUID.randomUUID(); - doReturn(userId).when(executionContext).getUserId(); - var id = 1; - var profile = new Profile(); - profile.setId(id); - when(profileRepository.findById(id)).thenReturn(Optional.of(profile)); - var profileSettings = new ProfileSettings(); - profileSettings.setId(new ProfileSettingsPk(userId, id)); - profileSettings.setProfile(profile); - profileSettings.setSettings("{"); - when(profileSettingsRepository.getByIdUserIdAndIdProfileId(userId, id)) - .thenReturn(Optional.of(profileSettings)); - doThrow(new JsonProcessingException(""){}) - .when(objectMapper).readValue("{", CustomProfileSettings.class); - - // when - var settings = profileSettingsService.getProfileSettings(id); - - // then - assertThat(settings.getActive()).isFalse(); - assertThat(settings.getChildren()).isNull(); - } - @Test void setProfileSettings_shouldThrowNotFound_ifNoSuchProfile() { // given @@ -132,29 +95,4 @@ void setProfileSettings_shouldThrowNotFound_ifNoSuchProfile() { assertThat(thrown.getMessage()).isEmpty(); } - @Test - @SneakyThrows - void setProfileSettings_shouldThrowGeneralError_ifBadInput() { - // given - var userId = UUID.randomUUID(); - doReturn(userId).when(executionContext).getUserId(); - var id = 1; - var profile = new Profile(); - profile.setId(id); - when(profileRepository.findById(id)).thenReturn(Optional.of(profile)); - var settings = new CustomProfileSettingsRequestDto(false, null); - when(exceptionBuilder.badRequestException(anyString(), anyString())) - .thenReturn(emptyRequestProcessingException()); - doThrow(new JsonProcessingException(""){}) - .when(objectMapper).writeValueAsString(any()); - - // when - var thrown = assertThrows(RequestProcessingException.class, - () -> profileSettingsService.setProfileSettings(id, settings)); - - // then - assertThat(thrown.getClass()).isEqualTo(RequestProcessingException.class); - assertThat(thrown.getMessage()).isEmpty(); - } - } diff --git a/src/test/java/org/folio/linked/data/service/rdf/RdfImportServiceTest.java b/src/test/java/org/folio/linked/data/service/rdf/RdfImportServiceTest.java index 54f96b573..9ce26e905 100644 --- a/src/test/java/org/folio/linked/data/service/rdf/RdfImportServiceTest.java +++ b/src/test/java/org/folio/linked/data/service/rdf/RdfImportServiceTest.java @@ -2,7 +2,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; -import static org.folio.linked.data.test.TestUtil.readTree; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; @@ -221,10 +221,10 @@ void importRdfUrl_shouldConvertJsonToResourcesWithoutSaving() { var rdfUrl = "https://example.com/resource-123.json"; var entity1 = new org.folio.linked.data.model.entity.Resource() .setIdAndRefreshEdges(1L) - .setDoc(readTree("{\"http://bibfra.me/vocab/lite/link\":[\"" + rdfUrl + "\"]}")); + .setDoc(JSON_MAPPER.readTree("{\"http://bibfra.me/vocab/lite/link\":[\"" + rdfUrl + "\"]}")); var entity2 = new org.folio.linked.data.model.entity.Resource() .setIdAndRefreshEdges(2L) - .setDoc(readTree("{\"http://bibfra.me/vocab/lite/link\":[\"https://example.com/resource-456.json\"]}")); + .setDoc(JSON_MAPPER.readTree("{\"http://bibfra.me/vocab/lite/link\":[\"https://example.com/resource-456.json\"]}")); when(httpClient.downloadString(rdfUrl)).thenReturn(rdfJson); when(rdf4LdService.mapBibframe2RdfToLd(any(InputStream.class), eq("application/ld+json"))) .thenReturn(Set.of(resource1, resource2)); @@ -254,7 +254,7 @@ void importRdfUrl_shouldSaveResources_whenSaveIsTrue() { var resource = new Resource().setId(1L); var entity = new org.folio.linked.data.model.entity.Resource() .setIdAndRefreshEdges(1L) - .setDoc(readTree("{\"http://bibfra.me/vocab/lite/link\":[\"" + rdfUrl + "\"]}")); + .setDoc(JSON_MAPPER.readTree("{\"http://bibfra.me/vocab/lite/link\":[\"" + rdfUrl + "\"]}")); when(httpClient.downloadString(rdfUrl)).thenReturn(rdfJson); when(rdf4LdService.mapBibframe2RdfToLd(any(InputStream.class), eq("application/ld+json"))) .thenReturn(Set.of(resource)); diff --git a/src/test/java/org/folio/linked/data/service/resource/ResourceServiceImplTest.java b/src/test/java/org/folio/linked/data/service/resource/ResourceServiceImplTest.java index fa286daa3..87df6cec0 100644 --- a/src/test/java/org/folio/linked/data/service/resource/ResourceServiceImplTest.java +++ b/src/test/java/org/folio/linked/data/service/resource/ResourceServiceImplTest.java @@ -15,7 +15,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.util.List; import java.util.Optional; import java.util.UUID; import org.folio.linked.data.domain.dto.InstanceField; @@ -83,7 +82,7 @@ class ResourceServiceImplTest { @Test void create_shouldPersistMappedResourceAndPublishResourceCreatedEvent() { // given - var request = new ResourceRequestDto().resource(new InstanceField().instance(new InstanceRequest(3, List.of()))); + var request = new ResourceRequestDto().resource(new InstanceField().instance(new InstanceRequest(3))); var work = new Resource().addTypes(WORK).setIdAndRefreshEdges(555L); when(resourceDtoMapper.toEntity(request)).thenReturn(work); var expectedResponse = new ResourceResponseDto(); @@ -105,9 +104,7 @@ void create_shouldPersistMappedResourceAndPublishResourceCreatedEvent_forResourc // given var profileId = 12; var request = new ResourceRequestDto().resource( - new WorkField().work( - new WorkRequest(2, List.of()).profileId(profileId) - ) + new WorkField().work(new WorkRequest(2).profileId(profileId)) ); var work = new Resource().addTypes(WORK).setIdAndRefreshEdges(444L); when(resourceDtoMapper.toEntity(request)).thenReturn(work); @@ -129,7 +126,7 @@ void create_shouldPersistMappedResourceAndPublishResourceCreatedEvent_forResourc @Test void create_shouldNotPersistResourceAndThrowAlreadyExists_forExistedResource() { // given - var request = new ResourceRequestDto().resource(new InstanceField().instance(new InstanceRequest(3, List.of()))); + var request = new ResourceRequestDto().resource(new InstanceField().instance(new InstanceRequest(3))); var mapped = new Resource().setIdAndRefreshEdges(12345L); when(resourceDtoMapper.toEntity(request)).thenReturn(mapped); when(resourceRepo.existsById(mapped.getId())).thenReturn(true); @@ -218,7 +215,7 @@ void getResourceIdByInventoryId_shouldThrowRequestProcessingException_ifNoEntity void update_shouldSaveUpdatedResourceAndSendResourceUpdatedEvent_forResourceWithSameId() { // given var id = randomLong(); - var workDto = new ResourceRequestDto().resource(new WorkField().work(new WorkRequest(2, List.of()))); + var workDto = new ResourceRequestDto().resource(new WorkField().work(new WorkRequest(2))); var oldWork = new Resource().setIdAndRefreshEdges(id).addTypes(WORK).setLabel("oldWork"); when(resourceRepo.findById(id)).thenReturn(Optional.of(oldWork)); var work = new Resource().setIdAndRefreshEdges(id).setLabel("saved").addTypes(WORK); @@ -254,9 +251,7 @@ void update_shouldSaveUpdatedResourceAndSendReplaceEvent_forResourceWithDifferen when(resourceRepo.findById(oldId)).thenReturn(Optional.of(oldInstance)); var mapped = new Resource().setIdAndRefreshEdges(newId).setLabel("mapped"); var instanceDto = new ResourceRequestDto().resource( - new InstanceField().instance( - new InstanceRequest(3, List.of()).profileId(profileId) - ) + new InstanceField().instance(new InstanceRequest(3).profileId(profileId)) ); when(resourceDtoMapper.toEntity(instanceDto)).thenReturn(mapped); var persisted = new Resource().setIdAndRefreshEdges(newId).setLabel("saved"); diff --git a/src/test/java/org/folio/linked/data/service/resource/copy/ResourceCopyServiceImplTest.java b/src/test/java/org/folio/linked/data/service/resource/copy/ResourceCopyServiceImplTest.java index 8d8337cc5..894f4852a 100644 --- a/src/test/java/org/folio/linked/data/service/resource/copy/ResourceCopyServiceImplTest.java +++ b/src/test/java/org/folio/linked/data/service/resource/copy/ResourceCopyServiceImplTest.java @@ -3,21 +3,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.ld.dictionary.ResourceTypeDictionary.INSTANCE; import static org.folio.ld.dictionary.ResourceTypeDictionary.WORK; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.junit.jupiter.params.provider.Arguments.arguments; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; + import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Stream; import org.folio.linked.data.model.entity.Resource; import org.folio.linked.data.model.entity.ResourceTypeEntity; @@ -28,10 +20,11 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import tools.jackson.core.type.TypeReference; +import tools.jackson.databind.JsonNode; @ExtendWith(MockitoExtension.class) @UnitTest @@ -42,8 +35,6 @@ class ResourceCopyServiceImplTest { @Mock private ResourceEdgeService resourceEdgeService; - @Mock - private ObjectMapper objectMapper; @Test void copyEdgesAndProperties_shouldRetainUnmappedMarc_whenUpdatedResourceIsInstance() { @@ -69,18 +60,21 @@ void copyEdgesAndProperties_shouldNotCopyProperties_whenOldResourceDoesNotHaveDo service.copyEdgesAndProperties(old, updated); // then - verifyNoInteractions(objectMapper); verify(resourceEdgeService).copyOutgoingEdges(old, updated); } private static Stream dataProvider() { return Stream.of( - arguments(new Resource() - .addType(new ResourceTypeEntity().setUri(INSTANCE.getUri())).setDoc(new ArrayNode(new JsonNodeFactory(true))), - new Resource(), getOldInstanceDoc(), getUpdatedInstanceDoc()), - arguments(new Resource() - .addType(new ResourceTypeEntity().setUri(WORK.getUri())).setDoc(new ArrayNode(new JsonNodeFactory(true))), - new Resource(), getOldWorkDoc(), getUpdatedWorkDoc()) + arguments( + createResourceWithDoc(INSTANCE.getUri(), getOldInstanceDoc()), + new Resource(), + getUpdatedInstanceDoc() + ), + arguments( + createResourceWithDoc(WORK.getUri(), getOldWorkDoc()), + new Resource(), + getUpdatedWorkDoc() + ) ); } @@ -88,22 +82,25 @@ private static Stream dataProvider() { @MethodSource("dataProvider") void copyEdgesAndProperties_shouldRetainProperties_thatAreNotSupportedOnUi(Resource old, Resource updated, - HashMap> fromDoc, - HashMap> expectedDoc) - throws JsonProcessingException { - // given - when(objectMapper.treeToValue(eq(old.getDoc()), any(TypeReference.class))).thenReturn(fromDoc); - + Map> expectedDoc) { // when service.copyEdgesAndProperties(old, updated); // then - var docCaptor = ArgumentCaptor.forClass(HashMap.class); - verify(objectMapper).convertValue(docCaptor.capture(), eq(JsonNode.class)); - assertThat(docCaptor.getValue()).isEqualTo(expectedDoc); + var actualDoc = TEST_JSON_MAPPER.treeToValue(updated.getDoc(), + new TypeReference>>() {} + ); + assertThat(actualDoc).isEqualTo(expectedDoc); verify(resourceEdgeService).copyOutgoingEdges(old, updated); } + private static Resource createResourceWithDoc(String typeUri, HashMap> doc) { + JsonNode docNode = TEST_JSON_MAPPER.convertValue(doc, JsonNode.class); + return new Resource() + .addType(new ResourceTypeEntity().setUri(typeUri)) + .setDoc(docNode); + } + private static HashMap> getOldInstanceDoc() { var doc = getUpdatedInstanceDoc(); doc.put("http://bibfra.me/vocab/lite/note", List.of("generalNote")); diff --git a/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceIT.java b/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceIT.java index 38402833c..ec868945c 100644 --- a/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceIT.java +++ b/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceIT.java @@ -2,11 +2,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.ld.dictionary.PredicateDictionary.REPLACED_BY; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.util.ResourceUtils.isPreferred; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Set; -import lombok.SneakyThrows; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.ld.dictionary.model.FolioMetadata; import org.folio.ld.dictionary.model.Resource; @@ -21,21 +20,18 @@ class ResourceMarcAuthorityServiceIT { @Autowired private ResourceMarcAuthorityService resourceMarcAuthorityService; @Autowired - private ObjectMapper objectMapper; - @Autowired private ResourceTestService resourceTestService; @Autowired private FolioMetadataRepository folioMetadataRepository; @Test - @SneakyThrows void testAuthorityPreferenceToggle_when_authority_is_reverted_back_to_original_state() { var srsId = "src_id_01"; // save version 1 of the authority var v1Resource = new Resource() .setId(1L) - .setDoc(objectMapper.readTree("{}")) + .setDoc(TEST_JSON_MAPPER.readTree("{}")) .setTypes(Set.of(ResourceTypeDictionary.PERSON)) .setLabel("label_01") .setFolioMetadata(new FolioMetadata().setSrsId(srsId)); diff --git a/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceImplTest.java b/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceImplTest.java index cd335f4f4..df926ca61 100644 --- a/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceImplTest.java +++ b/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcAuthorityServiceImplTest.java @@ -8,7 +8,6 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.CONCEPT; import static org.folio.ld.dictionary.ResourceTypeDictionary.PERSON; import static org.folio.ld.dictionary.ResourceTypeDictionary.WORK; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; import static org.folio.linked.data.test.TestUtil.emptyRequestProcessingException; import static org.folio.linked.data.test.TestUtil.randomLong; import static org.folio.linked.data.test.TestUtil.randomString; @@ -18,8 +17,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.fasterxml.jackson.databind.ObjectMapper; -import feign.FeignException; import java.util.List; import java.util.Map; import java.util.Optional; @@ -46,11 +43,11 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.context.ApplicationEventPublisher; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpClientErrorException; @UnitTest @ExtendWith(MockitoExtension.class) @@ -75,8 +72,6 @@ class ResourceMarcAuthorityServiceImplTest { private SrsClient srsClient; @Mock private RequestProcessingExceptionBuilder exceptionBuilder; - @Spy - private ObjectMapper objectMapper = OBJECT_MAPPER; @Test void importResourceFromSrs_shouldImportAuthorityFromSrs() { @@ -104,8 +99,7 @@ void importResourceFromSrs_shouldImportAuthorityFromSrs() { void importResourceFromSrs_shouldThrowNotFound_ifRecordNotExistsInSrs() { // given var id = "123"; - when(srsClient.getAuthorityBySrsId(id)) - .thenThrow(FeignException.NotFound.class); + when(srsClient.getAuthorityBySrsId(id)).thenThrow(HttpClientErrorException.NotFound.class); when(exceptionBuilder.notFoundSourceRecordException(any(), any())).thenReturn(emptyRequestProcessingException()); // then @@ -178,8 +172,8 @@ void saveMarcAuthority_shouldNotReplaceOldAuthority_ifNewAuthorityHasDifferentTy // then assertThat(actualId).isEqualTo(newAuthority.getId()); assertThat(newAuthority.getOutgoingEdges()).isEmpty(); - assertThat(newAuthority.getDoc().get(RESOURCE_PREFERRED.getValue()).get(0).textValue()).isEqualTo("true"); - assertThat(existedAuthority.getDoc().get(RESOURCE_PREFERRED.getValue()).get(0).textValue()).isEqualTo("false"); + assertThat(newAuthority.getDoc().get(RESOURCE_PREFERRED.getValue()).get(0).stringValue()).isEqualTo("true"); + assertThat(existedAuthority.getDoc().get(RESOURCE_PREFERRED.getValue()).get(0).stringValue()).isEqualTo("false"); } @Test @@ -206,11 +200,11 @@ void saveMarcAuthority_shouldCreateNewAuthorityVersionAndMarkOldAsObsolete_ifGiv // then assertThat(result).isEqualTo(id); assertThat(existed.isActive()).isFalse(); - assertThat(existed.getDoc().get(RESOURCE_PREFERRED.getValue()).get(0).textValue()).isEqualTo("false"); + assertThat(existed.getDoc().get(RESOURCE_PREFERRED.getValue()).get(0).stringValue()).isEqualTo("false"); assertThat(existed.getFolioMetadata()).isNull(); verify(resourceGraphService).saveMergingGraph(mapped); verify(applicationEventPublisher).publishEvent(new ResourceReplacedEvent(existed, mapped.getId())); - assertThat(mapped.getDoc().get(RESOURCE_PREFERRED.getValue()).get(0).textValue()).isEqualTo("true"); + assertThat(mapped.getDoc().get(RESOURCE_PREFERRED.getValue()).get(0).stringValue()).isEqualTo("true"); assertThat(mapped.getIncomingEdges()).contains(new ResourceEdge(existed, mapped, REPLACED_BY)); } diff --git a/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcBibServiceImplTest.java b/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcBibServiceImplTest.java index 61ed59ce0..c6a5b295b 100644 --- a/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcBibServiceImplTest.java +++ b/src/test/java/org/folio/linked/data/service/resource/marc/ResourceMarcBibServiceImplTest.java @@ -7,7 +7,7 @@ import static org.folio.linked.data.model.entity.ResourceSource.LINKED_DATA; import static org.folio.linked.data.test.MonographTestUtil.getSampleInstanceResource; import static org.folio.linked.data.test.MonographTestUtil.getSampleWork; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.emptyRequestProcessingException; import static org.folio.linked.data.test.TestUtil.random; import static org.folio.linked.data.test.TestUtil.randomLong; @@ -17,9 +17,6 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import feign.FeignException; import java.util.Map; import java.util.Optional; import java.util.UUID; @@ -59,6 +56,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpClientErrorException; @UnitTest @ExtendWith(MockitoExtension.class) @@ -86,8 +84,6 @@ class ResourceMarcBibServiceImplTest { @Mock private ResourceGraphService resourceGraphService; @Mock - private ObjectMapper objectMapper = OBJECT_MAPPER; - @Mock private SrsClient srsClient; @Mock private RequestProcessingExceptionBuilder exceptionBuilder; @@ -197,7 +193,7 @@ void checkMarcBibImportableToGraph_shouldThrowRequestProcessingException() { //given var inventoryId = UUID.randomUUID().toString(); when(srsClient.getSourceStorageInstanceRecordById(inventoryId)) - .thenThrow(FeignException.NotFound.class); + .thenThrow(HttpClientErrorException.NotFound.class); when(exceptionBuilder.notFoundSourceRecordException(anyString(), anyString())) .thenReturn(emptyRequestProcessingException()); @@ -207,17 +203,16 @@ void checkMarcBibImportableToGraph_shouldThrowRequestProcessingException() { } @Test - void getResourcePreviewByInventoryId_shouldReturn_resourceResponseDto() throws JsonProcessingException { + void getResourcePreviewByInventoryId_shouldReturn_resourceResponseDto() { //given var inventoryId = UUID.randomUUID().toString(); var marcRecord = createRecord('a', 'm'); - var marcJson = ""; + var marcJson = TEST_JSON_MAPPER.writeValueAsString(marcRecord.getParsedRecord().getContent()); var resourceModel = new org.folio.ld.dictionary.model.Resource(); var resourceEntity = new Resource(); var resourceDto = new ResourceResponseDto(); when(srsClient.getSourceStorageInstanceRecordById(inventoryId)) .thenReturn(new ResponseEntity<>(marcRecord, HttpStatusCode.valueOf(200))); - when(objectMapper.writeValueAsString(marcRecord.getParsedRecord().getContent())).thenReturn(marcJson); when(marcBib2ldMapper.fromMarcJson(marcJson)).thenReturn(Optional.of(resourceModel)); when(resourceModelMapper.toEntity(resourceModel)).thenReturn(resourceEntity); when(resourceDtoMapper.toDto(resourceEntity)).thenReturn(resourceDto); @@ -234,7 +229,7 @@ void getResourcePreviewByInventoryId_shouldThrowRequestProcessingException() { // given var inventoryId = UUID.randomUUID().toString(); when(srsClient.getSourceStorageInstanceRecordById(inventoryId)) - .thenThrow(FeignException.NotFound.class); + .thenThrow(HttpClientErrorException.NotFound.class); when(exceptionBuilder.notFoundSourceRecordException(anyString(), anyString())) .thenReturn(emptyRequestProcessingException()); @@ -244,11 +239,11 @@ void getResourcePreviewByInventoryId_shouldThrowRequestProcessingException() { } @Test - void importMarcRecord_shouldCreateResource() throws JsonProcessingException { + void importMarcRecord_shouldCreateResource() { //given var inventoryId = UUID.randomUUID().toString(); var marcRecord = createRecord('a', 'm'); - var marcJson = ""; + var marcJson = TEST_JSON_MAPPER.writeValueAsString(marcRecord.getParsedRecord().getContent()); var unmappedMarc = "{}"; var resourceId = 1L; var srsId = UUID.randomUUID().toString(); @@ -264,7 +259,6 @@ void importMarcRecord_shouldCreateResource() throws JsonProcessingException { var saveGraphResult = new SaveGraphResult(resourceEntity); when(srsClient.getSourceStorageInstanceRecordById(inventoryId)) .thenReturn(new ResponseEntity<>(marcRecord, HttpStatusCode.valueOf(200))); - when(objectMapper.writeValueAsString(marcRecord.getParsedRecord().getContent())).thenReturn(marcJson); when(marcBib2ldMapper.fromMarcJson(marcJson)).thenReturn(Optional.of(resourceModel)); when(resourceModelMapper.toEntity(resourceModelCaptor.capture())).thenReturn(resourceEntity); when(resourceRepo.existsById(resourceId)).thenReturn(false); @@ -291,7 +285,7 @@ void importMarcRecord_shouldThrowRequestProcessingException() { //given var inventoryId = UUID.randomUUID().toString(); when(srsClient.getSourceStorageInstanceRecordById(inventoryId)) - .thenThrow(FeignException.NotFound.class); + .thenThrow(HttpClientErrorException.NotFound.class); when(exceptionBuilder.notFoundSourceRecordException(anyString(), anyString())) .thenReturn(emptyRequestProcessingException()); @@ -301,12 +295,11 @@ void importMarcRecord_shouldThrowRequestProcessingException() { } @Test - void importMarcRecord_shouldThrowAlreadyExistsException_whenResourceWithSameIdExists() - throws JsonProcessingException { + void importMarcRecord_shouldThrowAlreadyExistsException_whenResourceWithSameIdExists() { //given var inventoryId = UUID.randomUUID().toString(); var marcRecord = createRecord('a', 'm'); - var marcJson = ""; + var marcJson = TEST_JSON_MAPPER.writeValueAsString(marcRecord.getParsedRecord().getContent()); var resourceId = 1L; var resourceModel = new org.folio.ld.dictionary.model.Resource() .setId(resourceId) @@ -314,7 +307,6 @@ void importMarcRecord_shouldThrowAlreadyExistsException_whenResourceWithSameIdEx when(srsClient.getSourceStorageInstanceRecordById(inventoryId)) .thenReturn(new ResponseEntity<>(marcRecord, HttpStatusCode.valueOf(200))); - when(objectMapper.writeValueAsString(marcRecord.getParsedRecord().getContent())).thenReturn(marcJson); when(marcBib2ldMapper.fromMarcJson(marcJson)).thenReturn(Optional.of(resourceModel)); when(resourceRepo.existsById(resourceId)).thenReturn(true); when(exceptionBuilder.alreadyExistsException(anyString(), anyString())) @@ -326,12 +318,11 @@ void importMarcRecord_shouldThrowAlreadyExistsException_whenResourceWithSameIdEx } @Test - void importMarcRecord_shouldThrowAlreadyExistsException_whenResourceWithSameSrsIdExists() - throws JsonProcessingException { + void importMarcRecord_shouldThrowAlreadyExistsException_whenResourceWithSameSrsIdExists() { //given var inventoryId = UUID.randomUUID().toString(); var marcRecord = createRecord('a', 'm'); - var marcJson = ""; + var marcJson = TEST_JSON_MAPPER.writeValueAsString(marcRecord.getParsedRecord().getContent()); var resourceId = 1L; var srsId = UUID.randomUUID().toString(); var resourceModel = new org.folio.ld.dictionary.model.Resource() @@ -340,7 +331,6 @@ void importMarcRecord_shouldThrowAlreadyExistsException_whenResourceWithSameSrsI when(srsClient.getSourceStorageInstanceRecordById(inventoryId)) .thenReturn(new ResponseEntity<>(marcRecord, HttpStatusCode.valueOf(200))); - when(objectMapper.writeValueAsString(marcRecord.getParsedRecord().getContent())).thenReturn(marcJson); when(marcBib2ldMapper.fromMarcJson(marcJson)).thenReturn(Optional.of(resourceModel)); when(resourceRepo.existsById(resourceId)).thenReturn(false); when(folioMetadataRepo.existsBySrsId(srsId)).thenReturn(true); diff --git a/src/test/java/org/folio/linked/data/test/MonographTestUtil.java b/src/test/java/org/folio/linked/data/test/MonographTestUtil.java index 8737d9796..a985e5355 100644 --- a/src/test/java/org/folio/linked/data/test/MonographTestUtil.java +++ b/src/test/java/org/folio/linked/data/test/MonographTestUtil.java @@ -90,9 +90,9 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.WORK; import static org.folio.linked.data.model.entity.ResourceSource.LINKED_DATA; import static org.folio.linked.data.test.TestUtil.RESOURCE_MODEL_MAPPER; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.getJsonNode; import static org.folio.linked.data.test.TestUtil.randomLong; -import static org.folio.linked.data.test.TestUtil.readTree; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -679,11 +679,11 @@ public static Resource getWork(String titleStr, HashService hashService) { .replace("%SUMMARY_NOTE%", titleStr + "_summary_note"); var title = new Resource() .addTypes(ResourceTypeDictionary.TITLE) - .setDoc(readTree(titleDoc)) + .setDoc(TEST_JSON_MAPPER.readTree(titleDoc)) .setLabel(titleStr); var work = new Resource() .addTypes(WORK, BOOKS) - .setDoc(readTree(workDoc)) + .setDoc(TEST_JSON_MAPPER.readTree(workDoc)) .setLabel(titleStr); work.addOutgoingEdge(new ResourceEdge(work, title, TITLE)); diff --git a/src/test/java/org/folio/linked/data/test/TestUtil.java b/src/test/java/org/folio/linked/data/test/TestUtil.java index 242b1bfff..c363f492f 100644 --- a/src/test/java/org/folio/linked/data/test/TestUtil.java +++ b/src/test/java/org/folio/linked/data/test/TestUtil.java @@ -12,6 +12,7 @@ import static org.folio.ld.dictionary.PropertyDictionary.RESOURCE_PREFERRED; import static org.folio.linked.data.service.lccn.LccnResourceService.LccnResourceSearchResult; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; import static org.folio.spring.integration.XOkapiHeaders.TENANT; import static org.folio.spring.integration.XOkapiHeaders.URL; import static org.folio.spring.integration.XOkapiHeaders.USER_ID; @@ -23,9 +24,6 @@ import static org.testcontainers.shaded.org.awaitility.Durations.ONE_HUNDRED_MILLISECONDS; import static org.testcontainers.shaded.org.awaitility.Durations.TWO_MINUTES; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -39,12 +37,10 @@ import org.apache.commons.io.IOUtils; import org.apache.kafka.common.header.internals.RecordHeader; import org.folio.linked.data.configuration.ErrorResponseConfig; -import org.folio.linked.data.configuration.json.ObjectMapperConfig; import org.folio.linked.data.domain.dto.IdentifierFieldResponse; import org.folio.linked.data.domain.dto.ResourceResponseField; import org.folio.linked.data.domain.dto.TitleFieldResponseTitleInner; import org.folio.linked.data.exception.RequestProcessingException; -import org.folio.linked.data.exception.RequestProcessingExceptionBuilder; import org.folio.linked.data.mapper.ResourceModelMapper; import org.folio.linked.data.mapper.ResourceModelMapperImpl; import org.folio.linked.data.model.entity.Resource; @@ -52,9 +48,6 @@ import org.folio.linked.data.test.json.IdentifierFieldResponseDeserializer; import org.folio.linked.data.test.json.ResourceResponseFieldDeserializer; import org.folio.linked.data.test.json.TitleFieldResponseDeserializer; -import org.folio.spring.FolioExecutionContext; -import org.folio.spring.scope.FolioExecutionContextSetter; -import org.folio.spring.tools.context.ExecutionContextBuilder; import org.jeasy.random.EasyRandom; import org.jeasy.random.EasyRandomParameters; import org.springframework.core.env.Environment; @@ -63,6 +56,9 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.jdbc.JdbcTestUtils; import org.testcontainers.shaded.org.awaitility.core.ThrowingRunnable; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.json.JsonMapper; +import tools.jackson.databind.module.SimpleModule; @UtilityClass public class TestUtil { @@ -72,9 +68,12 @@ public class TestUtil { public static final String RECORD_DOMAIN_EVENT_TOPIC = "srs.source_records"; public static final String INVENTORY_INSTANCE_EVENT_TOPIC = "inventory.instance"; public static final String LD_IMPORT_OUTPUT_TOPIC = "linked_data_import.output"; - public static final RequestProcessingExceptionBuilder EMPTY_EXCEPTION_BUILDER - = new RequestProcessingExceptionBuilder(new ErrorResponseConfig()); - public static final ObjectMapper OBJECT_MAPPER = new ObjectMapperConfig().objectMapper(EMPTY_EXCEPTION_BUILDER); + public static final JsonMapper TEST_JSON_MAPPER = JSON_MAPPER.rebuild() + .addModule(new SimpleModule() + .addDeserializer(ResourceResponseField.class, new ResourceResponseFieldDeserializer()) + .addDeserializer(TitleFieldResponseTitleInner.class, new TitleFieldResponseDeserializer()) + .addDeserializer(IdentifierFieldResponse.class, new IdentifierFieldResponseDeserializer())) + .build(); public static final String INSTANCE_WITH_WORK_REF_SAMPLE = loadResourceAsString("samples/instance_and_work_ref.json"); public static final String WORK_WITH_INSTANCE_REF_SAMPLE = loadResourceAsString("samples/work_and_instance_ref.json"); public static final ResourceModelMapper RESOURCE_MODEL_MAPPER = new ResourceModelMapperImpl(); @@ -83,26 +82,11 @@ public class TestUtil { private static final EasyRandom GENERATOR = new EasyRandom(PARAMETERS); static { - OBJECT_MAPPER.registerModule(new SimpleModule() - .addDeserializer(ResourceResponseField.class, new ResourceResponseFieldDeserializer()) - .addDeserializer(TitleFieldResponseTitleInner.class, new TitleFieldResponseDeserializer()) - .addDeserializer(IdentifierFieldResponse.class, new IdentifierFieldResponseDeserializer()) - ); PARAMETERS.excludeField(named("id")); PARAMETERS.randomizationDepth(3); PARAMETERS.scanClasspathForConcreteTypes(true); } - @SneakyThrows - public static String asJsonString(Object value) { - return OBJECT_MAPPER.writeValueAsString(value); - } - - @SneakyThrows - public static JsonNode readTree(String value) { - return OBJECT_MAPPER.readTree(value); - } - public static HttpHeaders defaultHeaders(Environment env) { var httpHeaders = new HttpHeaders(); if (!isStandaloneTest(env)) { @@ -136,14 +120,12 @@ public static String loadResourceAsString(String resourceName) { return IOUtils.toString(is, StandardCharsets.UTF_8); } - @SneakyThrows public static Map getSampleInstanceDtoMap() { - return OBJECT_MAPPER.readValue(INSTANCE_WITH_WORK_REF_SAMPLE, Map.class); + return TEST_JSON_MAPPER.readValue(INSTANCE_WITH_WORK_REF_SAMPLE, Map.class); } - @SneakyThrows public static Map getSampleWorkDtoMap() { - return OBJECT_MAPPER.readValue(WORK_WITH_INSTANCE_REF_SAMPLE, Map.class); + return TEST_JSON_MAPPER.readValue(WORK_WITH_INSTANCE_REF_SAMPLE, Map.class); } public static T random(Class clazz) { @@ -159,7 +141,7 @@ public static Long randomLong() { } public static JsonNode getJsonNode(Map map) { - return OBJECT_MAPPER.convertValue(map, JsonNode.class); + return TEST_JSON_MAPPER.convertValue(map, JsonNode.class); } public static void awaitAndAssert(ThrowingRunnable throwingRunnable) { @@ -235,29 +217,4 @@ public static LccnResourceSearchResult getLccnResourceSearchResult(String resour ); } - public static T executeWithContext(ExecutionContextBuilder contextBuilder, String tenantId, - java.util.concurrent.Callable callable) { - var context = buildContext(contextBuilder, tenantId); - try (@SuppressWarnings("unused") var fex = new FolioExecutionContextSetter(context)) { - return callable.call(); - } catch (Exception e) { - throw new RuntimeException("Failed to execute with context", e); - } - } - - public static void executeAsyncWithContext(ExecutionContextBuilder contextBuilder, String tenantId, - Runnable runnable) { - var context = buildContext(contextBuilder, tenantId); - try (@SuppressWarnings("unused") var fex = new FolioExecutionContextSetter(context)) { - runnable.run(); - } - } - - private static FolioExecutionContext buildContext(ExecutionContextBuilder contextBuilder, String tenantId) { - var okapiUrl = getProperty(FOLIO_OKAPI_URL); - return contextBuilder.builder() - .withTenantId(tenantId) - .withOkapiUrl(okapiUrl) - .build(); - } } diff --git a/src/test/java/org/folio/linked/data/test/config/TestCacheConfig.java b/src/test/java/org/folio/linked/data/test/config/TestCacheConfig.java new file mode 100644 index 000000000..7b20e5734 --- /dev/null +++ b/src/test/java/org/folio/linked/data/test/config/TestCacheConfig.java @@ -0,0 +1,15 @@ +package org.folio.linked.data.test.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.cache.CacheManager; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class TestCacheConfig { + + @Bean + public CacheManager cacheManager() { + return new ConcurrentMapCacheManager(); + } +} diff --git a/src/test/java/org/folio/linked/data/test/json/IdentifierFieldResponseDeserializer.java b/src/test/java/org/folio/linked/data/test/json/IdentifierFieldResponseDeserializer.java index 34dc4aca4..0108e85bf 100644 --- a/src/test/java/org/folio/linked/data/test/json/IdentifierFieldResponseDeserializer.java +++ b/src/test/java/org/folio/linked/data/test/json/IdentifierFieldResponseDeserializer.java @@ -4,12 +4,7 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.ID_ISBN; import static org.folio.ld.dictionary.ResourceTypeDictionary.ID_LCCN; import static org.folio.ld.dictionary.ResourceTypeDictionary.ID_UNKNOWN; -import static org.folio.linked.data.test.TestUtil.EMPTY_EXCEPTION_BUILDER; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import java.io.IOException; import java.util.Map; import org.folio.linked.data.domain.dto.IanFieldResponse; import org.folio.linked.data.domain.dto.IdentifierFieldResponse; @@ -17,8 +12,11 @@ import org.folio.linked.data.domain.dto.LccnFieldResponse; import org.folio.linked.data.domain.dto.OtherIdFieldResponse; import org.folio.linked.data.util.DtoDeserializer; +import tools.jackson.core.JsonParser; +import tools.jackson.databind.DeserializationContext; +import tools.jackson.databind.ValueDeserializer; -public class IdentifierFieldResponseDeserializer extends JsonDeserializer { +public class IdentifierFieldResponseDeserializer extends ValueDeserializer { private static final Map> IDENDTITY_MAP = Map.of( ID_LCCN.getUri(), LccnFieldResponse.class, @@ -27,11 +25,11 @@ public class IdentifierFieldResponseDeserializer extends JsonDeserializer dtoDeserializer = - new DtoDeserializer<>(IdentifierFieldResponse.class, IDENDTITY_MAP, EMPTY_EXCEPTION_BUILDER); + new DtoDeserializer<>(IdentifierFieldResponse.class, IDENDTITY_MAP); @Override - public IdentifierFieldResponse deserialize(JsonParser jp, DeserializationContext dc) throws IOException { - return dtoDeserializer.deserialize(jp); + public IdentifierFieldResponse deserialize(JsonParser jp, DeserializationContext dc) { + return dtoDeserializer.deserialize(jp, dc); } } diff --git a/src/test/java/org/folio/linked/data/test/json/ResourceResponseFieldDeserializer.java b/src/test/java/org/folio/linked/data/test/json/ResourceResponseFieldDeserializer.java index 04c280bdd..a0dd89827 100644 --- a/src/test/java/org/folio/linked/data/test/json/ResourceResponseFieldDeserializer.java +++ b/src/test/java/org/folio/linked/data/test/json/ResourceResponseFieldDeserializer.java @@ -1,29 +1,26 @@ package org.folio.linked.data.test.json; -import static org.folio.linked.data.test.TestUtil.EMPTY_EXCEPTION_BUILDER; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import java.io.IOException; import java.util.Map; import org.folio.ld.dictionary.ResourceTypeDictionary; import org.folio.linked.data.domain.dto.InstanceResponseField; import org.folio.linked.data.domain.dto.ResourceResponseField; import org.folio.linked.data.domain.dto.WorkResponseField; import org.folio.linked.data.util.DtoDeserializer; +import tools.jackson.core.JsonParser; +import tools.jackson.databind.DeserializationContext; +import tools.jackson.databind.ValueDeserializer; -public class ResourceResponseFieldDeserializer extends JsonDeserializer { +public class ResourceResponseFieldDeserializer extends ValueDeserializer { private static final Map> IDENDTITY_MAP = Map.of( ResourceTypeDictionary.INSTANCE.getUri(), InstanceResponseField.class, ResourceTypeDictionary.WORK.getUri(), WorkResponseField.class ); private final DtoDeserializer dtoDeserializer = - new DtoDeserializer<>(ResourceResponseField.class, IDENDTITY_MAP, EMPTY_EXCEPTION_BUILDER); + new DtoDeserializer<>(ResourceResponseField.class, IDENDTITY_MAP); @Override - public ResourceResponseField deserialize(JsonParser jp, DeserializationContext dc) throws IOException { - return dtoDeserializer.deserialize(jp); + public ResourceResponseField deserialize(JsonParser jp, DeserializationContext dc) { + return dtoDeserializer.deserialize(jp, dc); } } diff --git a/src/test/java/org/folio/linked/data/test/json/TitleFieldResponseDeserializer.java b/src/test/java/org/folio/linked/data/test/json/TitleFieldResponseDeserializer.java index 2e19fc150..611445ba8 100644 --- a/src/test/java/org/folio/linked/data/test/json/TitleFieldResponseDeserializer.java +++ b/src/test/java/org/folio/linked/data/test/json/TitleFieldResponseDeserializer.java @@ -3,30 +3,28 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.PARALLEL_TITLE; import static org.folio.ld.dictionary.ResourceTypeDictionary.TITLE; import static org.folio.ld.dictionary.ResourceTypeDictionary.VARIANT_TITLE; -import static org.folio.linked.data.test.TestUtil.EMPTY_EXCEPTION_BUILDER; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import java.io.IOException; import java.util.Map; import org.folio.linked.data.domain.dto.ParallelTitleFieldResponse; import org.folio.linked.data.domain.dto.PrimaryTitleFieldResponse; import org.folio.linked.data.domain.dto.TitleFieldResponseTitleInner; import org.folio.linked.data.domain.dto.VariantTitleFieldResponse; import org.folio.linked.data.util.DtoDeserializer; +import tools.jackson.core.JsonParser; +import tools.jackson.databind.DeserializationContext; +import tools.jackson.databind.ValueDeserializer; -public class TitleFieldResponseDeserializer extends JsonDeserializer { +public class TitleFieldResponseDeserializer extends ValueDeserializer { private static final Map> IDENDTITY_MAP = Map.of( TITLE.getUri(), PrimaryTitleFieldResponse.class, PARALLEL_TITLE.getUri(), ParallelTitleFieldResponse.class, VARIANT_TITLE.getUri(), VariantTitleFieldResponse.class ); private final DtoDeserializer dtoDeserializer = - new DtoDeserializer<>(TitleFieldResponseTitleInner.class, IDENDTITY_MAP, EMPTY_EXCEPTION_BUILDER); + new DtoDeserializer<>(TitleFieldResponseTitleInner.class, IDENDTITY_MAP); @Override - public TitleFieldResponseTitleInner deserialize(JsonParser jp, DeserializationContext dc) throws IOException { - return dtoDeserializer.deserialize(jp); + public TitleFieldResponseTitleInner deserialize(JsonParser jp, DeserializationContext dc) { + return dtoDeserializer.deserialize(jp, dc); } } diff --git a/src/test/java/org/folio/linked/data/test/kafka/KafkaEventsTestDataFixture.java b/src/test/java/org/folio/linked/data/test/kafka/KafkaEventsTestDataFixture.java index af405e890..932c35ae2 100644 --- a/src/test/java/org/folio/linked/data/test/kafka/KafkaEventsTestDataFixture.java +++ b/src/test/java/org/folio/linked/data/test/kafka/KafkaEventsTestDataFixture.java @@ -3,15 +3,14 @@ import static org.folio.linked.data.domain.dto.SourceRecordDomainEvent.EventTypeEnum; import static org.folio.linked.data.domain.dto.SourceRecordType.MARC_BIB; import static org.folio.linked.data.test.TestUtil.INVENTORY_INSTANCE_EVENT_TOPIC; -import static org.folio.linked.data.test.TestUtil.OBJECT_MAPPER; import static org.folio.linked.data.test.TestUtil.RECORD_DOMAIN_EVENT_TOPIC; import static org.folio.linked.data.test.TestUtil.TENANT_ID; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.test.TestUtil.defaultKafkaHeaders; import static org.folio.spring.tools.kafka.KafkaUtils.getTenantTopicName; import java.util.ArrayList; import java.util.Map; -import lombok.SneakyThrows; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.header.internals.RecordHeader; import org.folio.linked.data.domain.dto.ParsedRecord; @@ -37,13 +36,12 @@ public static ProducerRecord getSrsDomainEventSampleProducerReco return new ProducerRecord(topic, 0, "1", value, headers); } - @SneakyThrows public static ProducerRecord getSrsDomainEventProducerRecord(String id, String marc, EventTypeEnum type, SourceRecordType recordType) { var topic = getTenantTopicName(RECORD_DOMAIN_EVENT_TOPIC, TENANT_ID); - var value = OBJECT_MAPPER.writeValueAsString(Map.of( + var value = TEST_JSON_MAPPER.writeValueAsString(Map.of( "id", id, "eventType", type, "eventPayload", new SourceRecord().parsedRecord(new ParsedRecord(marc)) diff --git a/src/test/java/org/folio/linked/data/test/kafka/KafkaImportResultTopicListener.java b/src/test/java/org/folio/linked/data/test/kafka/KafkaImportResultTopicListener.java index 8259c23b6..1e7b5215d 100644 --- a/src/test/java/org/folio/linked/data/test/kafka/KafkaImportResultTopicListener.java +++ b/src/test/java/org/folio/linked/data/test/kafka/KafkaImportResultTopicListener.java @@ -1,13 +1,12 @@ package org.folio.linked.data.test.kafka; +import static org.folio.linked.data.test.TestUtil.TEST_JSON_MAPPER; import static org.folio.linked.data.util.Constants.STANDALONE_PROFILE; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import lombok.Getter; import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.folio.linked.data.domain.dto.ImportResultEvent; @@ -21,14 +20,12 @@ @RequiredArgsConstructor @Profile("!" + STANDALONE_PROFILE) public class KafkaImportResultTopicListener { - private final ObjectMapper objectMapper; private final List messages = new CopyOnWriteArrayList<>(); @KafkaListener(topics = "${test.topic.ld-import-result}") - @SneakyThrows public void receive(ConsumerRecord consumerRecord) { log.info("received consumerRecord = [{}]", consumerRecord.toString()); - var result = objectMapper.readValue(consumerRecord.value().toString(), ImportResultEvent.class); + var result = TEST_JSON_MAPPER.readValue(consumerRecord.value().toString(), ImportResultEvent.class); messages.add(result); } diff --git a/src/test/java/org/folio/linked/data/util/ImportUtilsTest.java b/src/test/java/org/folio/linked/data/util/ImportUtilsTest.java index df0506361..ee138c5e9 100644 --- a/src/test/java/org/folio/linked/data/util/ImportUtilsTest.java +++ b/src/test/java/org/folio/linked/data/util/ImportUtilsTest.java @@ -6,7 +6,6 @@ import static org.folio.linked.data.util.ImportUtils.Status.UPDATED; import java.util.stream.Stream; -import lombok.SneakyThrows; import org.folio.ld.dictionary.model.Resource; import org.folio.linked.data.domain.dto.ResourceWithLineNumber; import org.folio.spring.testing.type.UnitTest; @@ -54,7 +53,6 @@ void toRdfMediaType_shouldReturnUpdatedMediaType(String original, String expecte @ParameterizedTest @MethodSource("resources") - @SneakyThrows void importReportToCsv_shouldGenerateCsv(ImportUtils.ImportedResource res, String expected) { var report = new ImportUtils.ImportReport(); report.addImport(res); diff --git a/src/test/java/org/folio/linked/data/util/JsonUtilsTest.java b/src/test/java/org/folio/linked/data/util/JsonUtilsTest.java index 8a5d81b07..a683940a3 100644 --- a/src/test/java/org/folio/linked/data/util/JsonUtilsTest.java +++ b/src/test/java/org/folio/linked/data/util/JsonUtilsTest.java @@ -2,16 +2,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.folio.linked.data.test.TestUtil.loadResourceAsString; +import static org.folio.linked.data.util.JsonUtils.JSON_MAPPER; import static org.folio.linked.data.util.JsonUtils.merge; import static org.folio.linked.data.util.JsonUtils.writeValueAsString; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; import java.util.Map; import java.util.Optional; import java.util.stream.Stream; @@ -20,12 +16,13 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import tools.jackson.databind.JsonNode; +import tools.jackson.databind.node.JsonNodeFactory; +import tools.jackson.databind.node.ObjectNode; @UnitTest class JsonUtilsTest { - private static final ObjectMapper MAPPER = new ObjectMapper(); - private static Stream jsonObjects() { return Stream.of( Arguments.of("{\"key\":\"value\"}", "{\"key\":\"value\"}"), @@ -35,19 +32,18 @@ private static Stream jsonObjects() { @ParameterizedTest @MethodSource("jsonObjects") void writeValueAsString_shouldReturnCorrectString(Object obj, String expected) { - assertThat(writeValueAsString(obj, MAPPER)).isEqualTo(expected); + assertThat(writeValueAsString(obj)).isEqualTo(expected); } @Test - void merge_shouldReturnModifiedIncoming() throws JsonProcessingException { + void merge_shouldReturnModifiedIncoming() { var existing = loadResourceAsString("samples/json_merge/existing.jsonl"); var incoming = loadResourceAsString("samples/json_merge/incoming.jsonl"); var merged = loadResourceAsString("samples/json_merge/merged.jsonl"); - var result = merge(MAPPER.readTree(existing), MAPPER.readTree(incoming)); - assertThat(result).isEqualTo(MAPPER.readTree(merged)); + var result = merge(JSON_MAPPER.readTree(existing), JSON_MAPPER.readTree(incoming)); + assertThat(result).isEqualTo(JSON_MAPPER.readTree(merged)); } - @ParameterizedTest @MethodSource("hasElementByJsonPathArguments") void hasElementByJsonPath_shouldReturnCorrectBoolean(String jsonPath, boolean expected) { @@ -69,7 +65,7 @@ void testGetProperty() { // then assertTrue(result.isPresent()); - assertThat(result.get().asText()).isEqualTo("testValue"); + assertThat(result.get().asString()).isEqualTo("testValue"); } @Test @@ -94,7 +90,7 @@ void testSetProperty() { JsonUtils.setProperty(node, "newProperty", value); // then - assertThat(node.get("newProperty").asText()).isEqualTo("newValue"); + assertThat(node.get("newProperty").asString()).isEqualTo("newValue"); } @Test @@ -108,7 +104,7 @@ void testSetProperty_Overwrite() { JsonUtils.setProperty(node, "existingProperty", value); // then - assertThat(node.get("existingProperty").asText()).isEqualTo("newValue"); + assertThat(node.get("existingProperty").asString()).isEqualTo("newValue"); } static Stream hasElementByJsonPathArguments() { diff --git a/src/test/java/org/folio/linked/data/util/ResourceUtilsTest.java b/src/test/java/org/folio/linked/data/util/ResourceUtilsTest.java index 6251b9300..d741c602f 100644 --- a/src/test/java/org/folio/linked/data/util/ResourceUtilsTest.java +++ b/src/test/java/org/folio/linked/data/util/ResourceUtilsTest.java @@ -9,7 +9,6 @@ import static org.folio.ld.dictionary.ResourceTypeDictionary.PERSON; import static org.folio.ld.dictionary.ResourceTypeDictionary.WORK; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.google.common.collect.Lists; import java.util.List; import java.util.UUID; @@ -22,6 +21,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import tools.jackson.databind.node.JsonNodeFactory; @UnitTest class ResourceUtilsTest { @@ -260,7 +260,7 @@ void copyWithoutPreferred_returnsUnchangedCopy_whenDocDoesNotContainPreferred() // then assertThat(result).isNotNull(); assertThat(result.has("otherProperty")).isTrue(); - assertThat(result.get("otherProperty").asText()).isEqualTo("value"); + assertThat(result.get("otherProperty").asString()).isEqualTo("value"); } @Test @@ -277,7 +277,7 @@ void addProperty_createsDocAndSetsArrayValue() { var node = resource.getDoc().get(LABEL.getValue()); assertThat(node).isNotNull(); assertThat(node.isArray()).isTrue(); - assertThat(node.get(0).asText()).isEqualTo(labelText); + assertThat(node.get(0).asString()).isEqualTo(labelText); } @Test diff --git a/src/test/java/org/folio/linked/data/validation/dto/LccnUniquenessValidatorTest.java b/src/test/java/org/folio/linked/data/validation/dto/LccnUniquenessValidatorTest.java index 56b2d227a..81b5fb815 100644 --- a/src/test/java/org/folio/linked/data/validation/dto/LccnUniquenessValidatorTest.java +++ b/src/test/java/org/folio/linked/data/validation/dto/LccnUniquenessValidatorTest.java @@ -196,12 +196,12 @@ void shouldReturnFalse_ifResourceNotExistsInReposButExistsInSearch() { } private InstanceRequest createInstanceRequest(IdentifierRequest lccnRequest) { - return new InstanceRequest(3, List.of()) + return new InstanceRequest(3) .addMapItem(new LccnField().lccn(lccnRequest)); } private InstanceRequest createInstanceRequest() { - return new InstanceRequest(3, List.of()); + return new InstanceRequest(3); } private IdentifierRequest createLccnRequest() { diff --git a/src/test/resources/mappings/configurations.json b/src/test/resources/mappings/configurations.json index 38ac6441e..e29bd6daa 100644 --- a/src/test/resources/mappings/configurations.json +++ b/src/test/resources/mappings/configurations.json @@ -3,7 +3,7 @@ { "request": { "method": "GET", - "url": "/configurations/entries?query=module==USERSBL%20and%20code==FOLIO_HOST", + "url": "/configurations/entries?query=module%3D%3DUSERSBL%20and%20code%3D%3DFOLIO_HOST", "headers": { "X-Okapi-Tenant": { "equalTo": "test_tenant" @@ -21,7 +21,7 @@ { "request": { "method": "GET", - "url": "/configurations/entries?query=module==USERSBL%20and%20code==FOLIO_HOST", + "url": "/configurations/entries?query=module%3D%3DUSERSBL%20and%20code%3D%3DFOLIO_HOST", "headers": { "X-Okapi-Tenant": { "equalTo": "another_tenant"