diff --git a/dice/pom.xml b/dice/pom.xml index 09616eca..02e4d08d 100644 --- a/dice/pom.xml +++ b/dice/pom.xml @@ -53,7 +53,7 @@ - com.fasterxml.jackson.module + tools.jackson.module jackson-module-kotlin diff --git a/dice/src/main/kotlin/com/embabel/dice/agent/DiscoveryTools.kt b/dice/src/main/kotlin/com/embabel/dice/agent/DiscoveryTools.kt index ae898528..d60efc7e 100644 --- a/dice/src/main/kotlin/com/embabel/dice/agent/DiscoveryTools.kt +++ b/dice/src/main/kotlin/com/embabel/dice/agent/DiscoveryTools.kt @@ -18,6 +18,7 @@ package com.embabel.dice.agent import com.embabel.agent.api.annotation.LlmTool import com.embabel.agent.api.tool.Tool import com.embabel.agent.core.ContextId +import com.embabel.dice.agent.DiscoveryTools.Companion.asTools import com.embabel.dice.projection.lineage.ProjectionRecordStore import com.embabel.dice.projection.memory.CollectorRunner import com.embabel.dice.query.discovery.CollectorDryRunDto @@ -25,8 +26,8 @@ import com.embabel.dice.query.discovery.DiscoveryQuery import com.embabel.dice.query.discovery.ProjectionHealthDto import com.embabel.dice.query.discovery.RetrievalMode import com.embabel.dice.query.discovery.RetrievalRouter -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import org.slf4j.LoggerFactory +import tools.jackson.module.kotlin.jacksonObjectMapper /** * LLM-invocable tools exposing the discovery surface — proposition query, graph path, why-explain, diff --git a/dice/src/main/kotlin/com/embabel/dice/agent/Memory.kt b/dice/src/main/kotlin/com/embabel/dice/agent/Memory.kt index 8220e706..7c15e3d7 100644 --- a/dice/src/main/kotlin/com/embabel/dice/agent/Memory.kt +++ b/dice/src/main/kotlin/com/embabel/dice/agent/Memory.kt @@ -27,8 +27,8 @@ import com.embabel.dice.proposition.Proposition import com.embabel.dice.proposition.PropositionQuery import com.embabel.dice.proposition.PropositionRepository import com.embabel.dice.proposition.PropositionStatus -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import org.slf4j.LoggerFactory +import tools.jackson.module.kotlin.jacksonObjectMapper import java.util.function.UnaryOperator /** diff --git a/dice/src/main/kotlin/com/embabel/dice/proposition/store/JsonFilePropositionRepository.kt b/dice/src/main/kotlin/com/embabel/dice/proposition/store/JsonFilePropositionRepository.kt index 6665dbe6..79f7e654 100644 --- a/dice/src/main/kotlin/com/embabel/dice/proposition/store/JsonFilePropositionRepository.kt +++ b/dice/src/main/kotlin/com/embabel/dice/proposition/store/JsonFilePropositionRepository.kt @@ -24,9 +24,9 @@ import com.embabel.dice.proposition.PropositionQuery import com.embabel.dice.proposition.PropositionRepository import com.embabel.dice.proposition.PropositionStatus import com.embabel.dice.proposition.PropositionStoreType -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import com.fasterxml.jackson.module.kotlin.readValue import org.slf4j.LoggerFactory +import tools.jackson.module.kotlin.jacksonObjectMapper +import tools.jackson.module.kotlin.readValue import java.nio.file.Files import java.nio.file.Path import java.nio.file.StandardCopyOption @@ -55,7 +55,7 @@ class JsonFilePropositionRepository @JvmOverloads constructor( private val logger = LoggerFactory.getLogger(JsonFilePropositionRepository::class.java) - private val mapper = jacksonObjectMapper().findAndRegisterModules() + private val mapper = jacksonObjectMapper() private val propositions = ConcurrentHashMap() private val embeddings = ConcurrentHashMap() diff --git a/dice/src/main/kotlin/com/embabel/dice/web/rest/PropositionPipelineController.kt b/dice/src/main/kotlin/com/embabel/dice/web/rest/PropositionPipelineController.kt index a129e153..8394ed76 100644 --- a/dice/src/main/kotlin/com/embabel/dice/web/rest/PropositionPipelineController.kt +++ b/dice/src/main/kotlin/com/embabel/dice/web/rest/PropositionPipelineController.kt @@ -33,15 +33,15 @@ import com.embabel.dice.pipeline.ChunkPropositionResult import com.embabel.dice.pipeline.PropositionPipeline import com.embabel.dice.proposition.PropositionRepository import com.embabel.dice.proposition.revision.RevisionResult -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import com.fasterxml.jackson.module.kotlin.readValue import org.slf4j.LoggerFactory import org.springframework.boot.autoconfigure.condition.ConditionalOnBean import org.springframework.http.MediaType import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* import org.springframework.web.multipart.MultipartFile +import tools.jackson.databind.ObjectMapper +import tools.jackson.module.kotlin.jacksonObjectMapper +import tools.jackson.module.kotlin.readValue /** * REST controller that runs the proposition extraction pipeline over text or uploaded files. diff --git a/dice/src/test/kotlin/com/embabel/dice/common/GateDiceEventSerializationTest.kt b/dice/src/test/kotlin/com/embabel/dice/common/GateDiceEventSerializationTest.kt index c8591200..a426c688 100644 --- a/dice/src/test/kotlin/com/embabel/dice/common/GateDiceEventSerializationTest.kt +++ b/dice/src/test/kotlin/com/embabel/dice/common/GateDiceEventSerializationTest.kt @@ -19,14 +19,13 @@ import com.embabel.agent.core.ContextId import com.embabel.dice.proposition.EntityMention import com.embabel.dice.proposition.MentionRole import com.embabel.dice.proposition.Proposition -import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import com.fasterxml.jackson.module.kotlin.registerKotlinModule import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertInstanceOf import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test +import tools.jackson.databind.DeserializationFeature +import tools.jackson.databind.ObjectMapper +import tools.jackson.module.kotlin.jacksonMapperBuilder /** * The gate-decision events are declared on a `@JsonTypeInfo(use = CLASS)` interface, which is the @@ -40,10 +39,9 @@ class GateDiceEventSerializationTest { // (the @JsonTypeInfo discriminator on the DiceEvent interface) without coupling to the // nested Proposition type's own serialization shape, which carries a derived getter // (contextIdValue) that has no matching constructor parameter. - private val mapper: ObjectMapper = ObjectMapper() - .registerKotlinModule() - .registerModule(JavaTimeModule()) - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + private val mapper: ObjectMapper = jacksonMapperBuilder() + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .build() private fun proposition(): Proposition = Proposition( contextId = ContextId("ctx"), diff --git a/dice/src/test/kotlin/com/embabel/dice/proposition/PropositionJacksonRoundTripTest.kt b/dice/src/test/kotlin/com/embabel/dice/proposition/PropositionJacksonRoundTripTest.kt index 08b56abf..d624cbd8 100644 --- a/dice/src/test/kotlin/com/embabel/dice/proposition/PropositionJacksonRoundTripTest.kt +++ b/dice/src/test/kotlin/com/embabel/dice/proposition/PropositionJacksonRoundTripTest.kt @@ -16,12 +16,9 @@ package com.embabel.dice.proposition import com.embabel.agent.core.ContextId -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test - -// A real consumer registers modules (incl. JSR-310 for the Instant fields) on its mapper; -// findAndRegisterModules() picks up jackson-datatype-jsr310 from the classpath. +import tools.jackson.module.kotlin.jacksonObjectMapper /** * Verifies that a [Proposition] round-trips cleanly through JSON. The class exposes computed @@ -32,7 +29,7 @@ import org.junit.jupiter.api.Test */ class PropositionJacksonRoundTripTest { - private val mapper = jacksonObjectMapper().findAndRegisterModules() + private val mapper = jacksonObjectMapper() @Test fun `a Proposition round-trips through JSON preserving its core fields`() { diff --git a/dice/src/test/kotlin/com/embabel/dice/provenance/SourceLocatorTest.kt b/dice/src/test/kotlin/com/embabel/dice/provenance/SourceLocatorTest.kt index 46253a08..8fdd8d38 100644 --- a/dice/src/test/kotlin/com/embabel/dice/provenance/SourceLocatorTest.kt +++ b/dice/src/test/kotlin/com/embabel/dice/provenance/SourceLocatorTest.kt @@ -15,13 +15,13 @@ */ package com.embabel.dice.provenance -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import com.fasterxml.jackson.module.kotlin.readValue import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNotEquals import org.junit.jupiter.api.Assertions.assertThrows import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test +import tools.jackson.module.kotlin.jacksonObjectMapper +import tools.jackson.module.kotlin.readValue class SourceLocatorTest { diff --git a/dice/src/test/kotlin/com/embabel/dice/support/EntitiesTest.kt b/dice/src/test/kotlin/com/embabel/dice/support/EntitiesTest.kt index 5ef927af..f1e88553 100644 --- a/dice/src/test/kotlin/com/embabel/dice/support/EntitiesTest.kt +++ b/dice/src/test/kotlin/com/embabel/dice/support/EntitiesTest.kt @@ -16,7 +16,7 @@ package com.embabel.dice.support import com.embabel.dice.text2graph.support.Entities -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import tools.jackson.module.kotlin.jacksonObjectMapper import org.junit.jupiter.api.Test class EntitiesTest { diff --git a/dice/src/test/kotlin/com/embabel/dice/web/rest/DiscoveryControllerTest.kt b/dice/src/test/kotlin/com/embabel/dice/web/rest/DiscoveryControllerTest.kt index b44ab35a..fad5deac 100644 --- a/dice/src/test/kotlin/com/embabel/dice/web/rest/DiscoveryControllerTest.kt +++ b/dice/src/test/kotlin/com/embabel/dice/web/rest/DiscoveryControllerTest.kt @@ -26,28 +26,27 @@ import com.embabel.dice.proposition.MentionRole import com.embabel.dice.proposition.Proposition import com.embabel.dice.proposition.PropositionRepository import com.embabel.dice.proposition.store.InMemoryPropositionRepository -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import com.fasterxml.jackson.module.kotlin.KotlinModule import org.junit.jupiter.api.Assertions.assertDoesNotThrow import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter +import org.springframework.http.MediaType +import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.test.web.servlet.setup.MockMvcBuilders +import tools.jackson.databind.json.JsonMapper +import tools.jackson.module.kotlin.kotlinModule import java.time.Instant import kotlin.reflect.KClass import kotlin.reflect.KType import kotlin.reflect.full.functions import kotlin.reflect.jvm.javaMethod -import org.springframework.http.MediaType /** * Opt-in and leak-free contract for the discovery REST surface, plus the cross-tier signature gate @@ -82,16 +81,17 @@ class DiscoveryControllerTest { @BeforeEach fun setUp() { repository = TestPropositionRepository() - val objectMapper = ObjectMapper() - .registerModule(KotlinModule.Builder().build()) - .registerModule(JavaTimeModule()) + val objectMapper = JsonMapper.builder() + .addModule(kotlinModule()) + .findAndAddModules() + .build() val controller = DiscoveryController( store = repository, projectionRecordStore = emptyRecordStore, collectorRunner = noopCollectorRunner, ) mockMvc = MockMvcBuilders.standaloneSetup(controller) - .setMessageConverters(MappingJackson2HttpMessageConverter(objectMapper)) + .setMessageConverters(JacksonJsonHttpMessageConverter(objectMapper)) .build() } @@ -192,16 +192,17 @@ class DiscoveryControllerTest { override fun delete(id: String): Boolean = false override fun count(): Int = 0 } - val objectMapper = ObjectMapper() - .registerModule(KotlinModule.Builder().build()) - .registerModule(JavaTimeModule()) + val objectMapper = JsonMapper.builder() + .addModule(kotlinModule()) + .findAndAddModules() + .build() val controller = DiscoveryController( store = failingStore, projectionRecordStore = emptyRecordStore, collectorRunner = noopCollectorRunner, ) val mvc = MockMvcBuilders.standaloneSetup(controller) - .setMessageConverters(MappingJackson2HttpMessageConverter(objectMapper)) + .setMessageConverters(JacksonJsonHttpMessageConverter(objectMapper)) .build() mvc.perform( diff --git a/dice/src/test/kotlin/com/embabel/dice/web/rest/MemoryControllerTest.kt b/dice/src/test/kotlin/com/embabel/dice/web/rest/MemoryControllerTest.kt index f6f646b0..83957bc3 100644 --- a/dice/src/test/kotlin/com/embabel/dice/web/rest/MemoryControllerTest.kt +++ b/dice/src/test/kotlin/com/embabel/dice/web/rest/MemoryControllerTest.kt @@ -19,23 +19,19 @@ import com.embabel.agent.core.ContextId import com.embabel.agent.rag.service.RetrievableIdentifier import com.embabel.common.core.types.SimilarityResult import com.embabel.common.core.types.TextSimilaritySearchRequest -import com.embabel.dice.proposition.EntityMention -import com.embabel.dice.proposition.MentionRole -import com.embabel.dice.proposition.Proposition -import com.embabel.dice.proposition.PropositionRepository -import com.embabel.dice.proposition.PropositionStatus -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import com.fasterxml.jackson.module.kotlin.KotlinModule +import com.embabel.dice.proposition.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.springframework.http.MediaType -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter +import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.* +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.test.web.servlet.setup.MockMvcBuilders +import tools.jackson.databind.json.JsonMapper +import tools.jackson.module.kotlin.kotlinModule import java.util.concurrent.ConcurrentHashMap /** @@ -89,22 +85,23 @@ class MemoryControllerTest { private lateinit var mockMvc: MockMvc private lateinit var propositionRepository: TestPropositionRepository - private lateinit var objectMapper: ObjectMapper + private lateinit var objectMapper: JsonMapper @BeforeEach fun setUp() { propositionRepository = TestPropositionRepository() - objectMapper = ObjectMapper() - .registerModule(KotlinModule.Builder().build()) - .registerModule(JavaTimeModule()) + objectMapper = JsonMapper.builder() + .addModule(kotlinModule()) + .findAndAddModules() + .build() val controller = MemoryController( propositionRepository = propositionRepository, ) mockMvc = MockMvcBuilders.standaloneSetup(controller) - .setMessageConverters(MappingJackson2HttpMessageConverter(objectMapper)) + .setMessageConverters(JacksonJsonHttpMessageConverter(objectMapper)) .build() } diff --git a/dice/src/test/kotlin/com/embabel/dice/web/rest/PropositionPipelineControllerTest.kt b/dice/src/test/kotlin/com/embabel/dice/web/rest/PropositionPipelineControllerTest.kt index 1df89616..1dcfa00e 100644 --- a/dice/src/test/kotlin/com/embabel/dice/web/rest/PropositionPipelineControllerTest.kt +++ b/dice/src/test/kotlin/com/embabel/dice/web/rest/PropositionPipelineControllerTest.kt @@ -17,32 +17,29 @@ package com.embabel.dice.web.rest import com.embabel.agent.core.ContextId import com.embabel.agent.core.DataDictionary +import com.embabel.agent.rag.ingestion.ContentChunker +import com.embabel.agent.rag.ingestion.HierarchicalContentReader +import com.embabel.agent.rag.model.Chunk +import com.embabel.agent.rag.model.NavigableDocument import com.embabel.dice.common.EntityResolver import com.embabel.dice.common.NewEntity import com.embabel.dice.common.Resolutions import com.embabel.dice.common.SuggestedEntity import com.embabel.dice.common.resolver.AlwaysCreateEntityResolver import com.embabel.dice.common.support.InMemorySchemaRegistry -import com.embabel.agent.rag.ingestion.ContentChunker -import com.embabel.agent.rag.ingestion.HierarchicalContentReader -import com.embabel.agent.rag.model.Chunk -import com.embabel.agent.rag.model.NavigableDocument import com.embabel.dice.pipeline.ChunkPropositionResult import com.embabel.dice.pipeline.PropositionPipeline import com.embabel.dice.pipeline.PropositionResults import com.embabel.dice.proposition.* import com.embabel.dice.proposition.revision.RevisionResult import com.fasterxml.jackson.annotation.JsonClassDescription -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import com.fasterxml.jackson.module.kotlin.KotlinModule import io.mockk.every import io.mockk.mockk import io.mockk.verify import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.springframework.http.MediaType -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter +import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter import org.springframework.mock.web.MockMultipartFile import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart @@ -50,6 +47,8 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.test.web.servlet.setup.MockMvcBuilders +import tools.jackson.databind.json.JsonMapper +import tools.jackson.module.kotlin.kotlinModule /** * Contract tests for the proposition extraction REST controller. @@ -64,7 +63,7 @@ class PropositionPipelineControllerTest { private lateinit var propositionPipeline: PropositionPipeline private lateinit var entityResolver: EntityResolver private lateinit var schemaRegistry: InMemorySchemaRegistry - private lateinit var objectMapper: ObjectMapper + private lateinit var objectMapper: JsonMapper @JsonClassDescription("A composer of music") data class Composer(val id: String, val name: String) @@ -80,9 +79,10 @@ class PropositionPipelineControllerTest { val schema = DataDictionary.fromClasses("test", Composer::class.java, Work::class.java) schemaRegistry = InMemorySchemaRegistry(schema) - objectMapper = ObjectMapper() - .registerModule(KotlinModule.Builder().build()) - .registerModule(JavaTimeModule()) + objectMapper = JsonMapper.builder() + .addModule(kotlinModule()) + .findAndAddModules() + .build() val controller = PropositionPipelineController( propositionPipeline = propositionPipeline, @@ -92,7 +92,7 @@ class PropositionPipelineControllerTest { ) mockMvc = MockMvcBuilders.standaloneSetup(controller) - .setMessageConverters(MappingJackson2HttpMessageConverter(objectMapper)) + .setMessageConverters(JacksonJsonHttpMessageConverter(objectMapper)) .build() } @@ -306,7 +306,7 @@ class PropositionPipelineControllerTest { contentChunker = chunker, ) val mvc = MockMvcBuilders.standaloneSetup(fileController) - .setMessageConverters(MappingJackson2HttpMessageConverter(objectMapper)) + .setMessageConverters(JacksonJsonHttpMessageConverter(objectMapper)) .build() mvc.perform(