From 1024e45ddec0375b0db361719fd014263ef1bba7 Mon Sep 17 00:00:00 2001 From: Enrico Risa Date: Fri, 17 Jan 2025 16:05:47 +0100 Subject: [PATCH] fix: add deterministic ObjectMapper for JSON-LD --- .../edc/jsonld/util/JacksonJsonLd.java | 1 + .../http/api/DspCatalogApiExtension.java | 5 +- .../DspCatalogTransformExtension.java | 7 +- .../DspApiConfigurationExtension.java | 9 +- .../dsp/http/DspHttpCoreExtension.java | 2 +- .../JsonLdRemoteMessageSerializerImpl.java | 10 +- .../JsonLdResponseBodyDeserializer.java | 9 +- ...JsonLdRemoteMessageSerializerImplTest.java | 2 +- .../JsonLdResponseBodyDeserializerTest.java | 2 +- .../http/api/DspNegotiationApiExtension.java | 5 +- ...DspNegotiationHttpDispatcherExtension.java | 2 +- .../api/DspTransferProcessApiExtension.java | 5 +- ...DspTransferProcessDispatcherExtension.java | 2 +- .../DspTransferProcessTransformExtension.java | 4 +- .../ControlApiConfigurationExtension.java | 7 +- .../ManagementApiConfigurationExtension.java | 12 +- .../jwt/JwtPresentationVerifier.java | 9 +- .../jwt/JwtPresentationVerifierTest.java | 2 +- .../linkeddata/LdpVerifier.java | 13 +- .../linkeddata/LdpVerifierTest.java | 2 +- .../edc/web/jersey/JerseyRestService.java | 2 +- .../testfixtures/RestControllerTestBase.java | 2 +- .../jsonld/JerseyJsonLdInterceptor.java | 11 +- .../jsonld/ObjectMapperProvider.java | 10 +- .../jsonld/JerseyJsonLdInterceptorTest.java | 2 +- .../core/IdentityAndTrustExtension.java | 28 ++--- .../DefaultCredentialServiceClient.java | 14 +-- .../DefaultCredentialServiceClientTest.java | 115 +++++++++--------- .../MultiFormatPresentationVerifierTest.java | 4 +- .../ContractDefinitionApiExtension.java | 13 +- .../policy/PolicyDefinitionApiExtension.java | 20 +-- .../DataPlaneSelectorApiExtension.java | 12 +- .../DataPlaneSelectorApiExtensionTest.java | 3 +- .../DataPlaneSelectorClientExtension.java | 4 +- .../RemoteDataPlaneSelectorService.java | 11 +- .../DataPlaneSelectorClientExtensionTest.java | 4 +- .../DataplaneSelectorControlApiExtension.java | 10 +- ...aplaneSelectorControlApiExtensionTest.java | 4 +- .../api/DataPlaneSignalingApiExtension.java | 16 ++- .../client/DataPlaneSignalingClient.java | 11 +- .../DataPlaneSignalingClientExtension.java | 3 +- ...laneSignalingClientTransformExtension.java | 3 +- .../client/DataPlaneSignalingClientTest.java | 8 +- ...SignalingClientTransformExtensionTest.java | 4 +- 44 files changed, 225 insertions(+), 199 deletions(-) diff --git a/core/common/lib/json-ld-lib/src/main/java/org/eclipse/edc/jsonld/util/JacksonJsonLd.java b/core/common/lib/json-ld-lib/src/main/java/org/eclipse/edc/jsonld/util/JacksonJsonLd.java index fd5a66aa8be..387d9c636e7 100644 --- a/core/common/lib/json-ld-lib/src/main/java/org/eclipse/edc/jsonld/util/JacksonJsonLd.java +++ b/core/common/lib/json-ld-lib/src/main/java/org/eclipse/edc/jsonld/util/JacksonJsonLd.java @@ -36,6 +36,7 @@ public void setupModule(SetupContext context) { } }; mapper.registerModule(module); + mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); return mapper; } } diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtension.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtension.java index 79d2bfb9b74..64e7691a702 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtension.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-http-api/src/main/java/org/eclipse/edc/protocol/dsp/catalog/http/api/DspCatalogApiExtension.java @@ -92,14 +92,13 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var jsonLdMapper = typeManager.getMapper(JSON_LD); registerValidators(DSP_NAMESPACE_V_08); registerValidators(DSP_NAMESPACE_V_2024_1); webService.registerResource(ApiContext.PROTOCOL, new DspCatalogApiController(service, dspRequestHandler, continuationTokenManager(monitor, DSP_TRANSFORMER_CONTEXT_V_08, DSP_NAMESPACE_V_08))); webService.registerResource(ApiContext.PROTOCOL, new DspCatalogApiController20241(service, dspRequestHandler, continuationTokenManager(monitor, DSP_TRANSFORMER_CONTEXT_V_2024_1, DSP_NAMESPACE_V_2024_1))); - webService.registerDynamicResource(ApiContext.PROTOCOL, DspCatalogApiController.class, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, DSP_SCOPE_V_08)); - webService.registerDynamicResource(ApiContext.PROTOCOL, DspCatalogApiController20241.class, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, DSP_SCOPE_V_2024_1)); + webService.registerDynamicResource(ApiContext.PROTOCOL, DspCatalogApiController.class, new JerseyJsonLdInterceptor(jsonLd, () -> typeManager.getMapper(JSON_LD), DSP_SCOPE_V_08)); + webService.registerDynamicResource(ApiContext.PROTOCOL, DspCatalogApiController20241.class, new JerseyJsonLdInterceptor(jsonLd, () -> typeManager.getMapper(JSON_LD), DSP_SCOPE_V_2024_1)); dataServiceRegistry.register(DataService.Builder.newInstance() .endpointDescription("dspace:connector") diff --git a/data-protocols/dsp/dsp-catalog/dsp-catalog-transform/src/main/java/org/eclipse/edc/protocol/dsp/catalog/transform/DspCatalogTransformExtension.java b/data-protocols/dsp/dsp-catalog/dsp-catalog-transform/src/main/java/org/eclipse/edc/protocol/dsp/catalog/transform/DspCatalogTransformExtension.java index 3c55c99f7cd..a821f1d26f3 100644 --- a/data-protocols/dsp/dsp-catalog/dsp-catalog-transform/src/main/java/org/eclipse/edc/protocol/dsp/catalog/transform/DspCatalogTransformExtension.java +++ b/data-protocols/dsp/dsp-catalog/dsp-catalog-transform/src/main/java/org/eclipse/edc/protocol/dsp/catalog/transform/DspCatalogTransformExtension.java @@ -29,7 +29,6 @@ import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; @@ -64,16 +63,14 @@ public String name() { } @Override - public void initialize(ServiceExtensionContext context) { + public void prepare() { var mapper = typeManager.getMapper(JSON_LD); registerV08Transformers(mapper); registerV2024Transformers(mapper); - + registerTransformers(DSP_TRANSFORMER_CONTEXT_V_08, DSP_NAMESPACE_V_08, mapper); registerTransformers(DSP_TRANSFORMER_CONTEXT_V_2024_1, DSP_NAMESPACE_V_2024_1, mapper); - - } private void registerTransformers(String version, JsonLdNamespace namespace, ObjectMapper mapper) { diff --git a/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java b/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java index bb5f57d4a47..3673aaad9b8 100644 --- a/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java +++ b/data-protocols/dsp/dsp-http-api-configuration/src/main/java/org/eclipse/edc/protocol/dsp/http/api/configuration/DspApiConfigurationExtension.java @@ -118,14 +118,17 @@ public void initialize(ServiceExtensionContext context) { var dspWebhookAddress = ofNullable(callbackAddress).orElseGet(() -> format("http://%s:%s%s", hostname.get(), portMapping.port(), portMapping.path())); context.registerService(ProtocolWebhook.class, () -> dspWebhookAddress); - var jsonLdMapper = typeManager.getMapper(JSON_LD); - // registers ns for DSP scope registerNamespaces(DSP_SCOPE_V_08, DSP_NAMESPACE_V_08); registerNamespaces(DSP_SCOPE_V_2024_1, DSP_NAMESPACE_V_2024_1); - webService.registerResource(ApiContext.PROTOCOL, new ObjectMapperProvider(jsonLdMapper)); + webService.registerResource(ApiContext.PROTOCOL, new ObjectMapperProvider(() -> typeManager.getMapper(JSON_LD))); + + } + + @Override + public void prepare() { var mapper = typeManager.getMapper(JSON_LD); mapper.registerSubtypes(AtomicConstraint.class, LiteralExpression.class); diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/DspHttpCoreExtension.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/DspHttpCoreExtension.java index 4a128f6e018..88e02c17a1e 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/DspHttpCoreExtension.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/DspHttpCoreExtension.java @@ -150,7 +150,7 @@ public DspRequestHandler dspRequestHandler() { @Provider public JsonLdRemoteMessageSerializer jsonLdRemoteMessageSerializer() { - return new JsonLdRemoteMessageSerializerImpl(dspTransformerRegistry(), typeManager.getMapper(JSON_LD), jsonLdService, dspProtocolParser(), DSP_SCOPE); + return new JsonLdRemoteMessageSerializerImpl(dspTransformerRegistry(), () -> typeManager.getMapper(JSON_LD), jsonLdService, dspProtocolParser(), DSP_SCOPE); } @Provider diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImpl.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImpl.java index 6f046700d71..6a9c36954c7 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImpl.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImpl.java @@ -25,6 +25,8 @@ import org.eclipse.edc.spi.types.domain.message.RemoteMessage; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; +import java.util.function.Supplier; + import static java.lang.String.format; import static java.lang.String.join; import static org.eclipse.edc.protocol.dsp.spi.type.DspConstants.DSP_CONTEXT_SEPARATOR; @@ -34,16 +36,16 @@ */ public class JsonLdRemoteMessageSerializerImpl implements JsonLdRemoteMessageSerializer { - private final ObjectMapper mapper; + private final Supplier mapperSupplier; private final JsonLd jsonLdService; private final String scopePrefix; private final DspProtocolTypeTransformerRegistry dspTransformerRegistry; private final DspProtocolParser protocolParser; public JsonLdRemoteMessageSerializerImpl(DspProtocolTypeTransformerRegistry dspTransformerRegistry, - ObjectMapper mapper, JsonLd jsonLdService, DspProtocolParser protocolParser, String scopePrefix) { + Supplier mapperSupplier, JsonLd jsonLdService, DspProtocolParser protocolParser, String scopePrefix) { this.dspTransformerRegistry = dspTransformerRegistry; - this.mapper = mapper; + this.mapperSupplier = mapperSupplier; this.jsonLdService = jsonLdService; this.scopePrefix = scopePrefix; this.protocolParser = protocolParser; @@ -73,7 +75,7 @@ public String serialize(RemoteMessage message) { var compacted = protocolParser.parse(message.getProtocol()) .compose(protocol -> jsonLdService.compact(transformResult.getContent(), scopePrefix + DSP_CONTEXT_SEPARATOR + protocol.version())); if (compacted.succeeded()) { - return mapper.writeValueAsString(compacted.getContent()); + return mapperSupplier.get().writeValueAsString(compacted.getContent()); } throw new EdcException("Failed to compact JSON-LD: " + compacted.getFailureDetail()); } diff --git a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializer.java b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializer.java index 082a8b522fe..8be5b6c7dad 100644 --- a/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializer.java +++ b/data-protocols/dsp/dsp-http-core/src/main/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializer.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.util.function.Function; +import java.util.function.Supplier; import static java.lang.String.format; import static java.lang.String.join; @@ -35,13 +36,13 @@ */ public class JsonLdResponseBodyDeserializer implements DspHttpResponseBodyExtractor { private final Class type; - private final ObjectMapper objectMapper; + private final Supplier objectMapperSupplier; private final JsonLd jsonLd; private final DspProtocolTypeTransformerRegistry dspTransformerRegistry; - public JsonLdResponseBodyDeserializer(Class type, ObjectMapper objectMapper, JsonLd jsonLd, DspProtocolTypeTransformerRegistry dspTransformerRegistry) { + public JsonLdResponseBodyDeserializer(Class type, Supplier objectMapperSupplier, JsonLd jsonLd, DspProtocolTypeTransformerRegistry dspTransformerRegistry) { this.type = type; - this.objectMapper = objectMapper; + this.objectMapperSupplier = objectMapperSupplier; this.jsonLd = jsonLd; this.dspTransformerRegistry = dspTransformerRegistry; } @@ -49,7 +50,7 @@ public JsonLdResponseBodyDeserializer(Class type, ObjectMapper objectMapper, @Override public T extractBody(ResponseBody responseBody, String protocol) { try { - var jsonObject = objectMapper.readValue(responseBody.byteStream(), JsonObject.class); + var jsonObject = objectMapperSupplier.get().readValue(responseBody.byteStream(), JsonObject.class); var transformerRegistryResult = dspTransformerRegistry.forProtocol(protocol); if (transformerRegistryResult.failed()) { throw new EdcException(format("Failed to extract body: %s", join(", ", transformerRegistryResult.getFailureMessages()))); diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImplTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImplTest.java index dab5ef16e88..5656ee70017 100644 --- a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImplTest.java +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdRemoteMessageSerializerImplTest.java @@ -56,7 +56,7 @@ void setUp() { var jsonLdService = new TitaniumJsonLd(mock(Monitor.class)); jsonLdService.registerNamespace("schema", "http://schema/"); //needed for compaction when(registry.forContext(DSP_TRANSFORMER_CONTEXT_V_08)).thenReturn(registry); - serializer = new JsonLdRemoteMessageSerializerImpl(dspTransformerRegistry, mapper, jsonLdService, protocolParser, "scope"); + serializer = new JsonLdRemoteMessageSerializerImpl(dspTransformerRegistry, () -> mapper, jsonLdService, protocolParser, "scope"); when(message.getProtocol()).thenReturn(DATASPACE_PROTOCOL_HTTP); } diff --git a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializerTest.java b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializerTest.java index 16357da73bf..090b8213522 100644 --- a/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializerTest.java +++ b/data-protocols/dsp/dsp-http-core/src/test/java/org/eclipse/edc/protocol/dsp/http/serialization/JsonLdResponseBodyDeserializerTest.java @@ -52,7 +52,7 @@ class JsonLdResponseBodyDeserializerTest { private final TypeTransformerRegistry transformerRegistry = mock(); private final DspProtocolTypeTransformerRegistry dspTransformerRegistry = mock(); private final JsonLdResponseBodyDeserializer bodyExtractor = - new JsonLdResponseBodyDeserializer<>(Object.class, objectMapper, jsonLd, dspTransformerRegistry); + new JsonLdResponseBodyDeserializer<>(Object.class, () -> objectMapper, jsonLd, dspTransformerRegistry); @BeforeEach diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/DspNegotiationApiExtension.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/DspNegotiationApiExtension.java index 7f49640d9b0..ab8349383cc 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/DspNegotiationApiExtension.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-api/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/api/DspNegotiationApiExtension.java @@ -83,15 +83,14 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var jsonLdMapper = typeManager.getMapper(JSON_LD); registerValidators(DSP_NAMESPACE_V_08); registerValidators(DSP_NAMESPACE_V_2024_1); webService.registerResource(ApiContext.PROTOCOL, new DspNegotiationApiController(protocolService, dspRequestHandler)); webService.registerResource(ApiContext.PROTOCOL, new DspNegotiationApiController20241(protocolService, dspRequestHandler)); - webService.registerDynamicResource(ApiContext.PROTOCOL, DspNegotiationApiController.class, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, DSP_SCOPE_V_08)); - webService.registerDynamicResource(ApiContext.PROTOCOL, DspNegotiationApiController20241.class, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, DSP_SCOPE_V_2024_1)); + webService.registerDynamicResource(ApiContext.PROTOCOL, DspNegotiationApiController.class, new JerseyJsonLdInterceptor(jsonLd, () -> typeManager.getMapper(JSON_LD), DSP_SCOPE_V_08)); + webService.registerDynamicResource(ApiContext.PROTOCOL, DspNegotiationApiController20241.class, new JerseyJsonLdInterceptor(jsonLd, () -> typeManager.getMapper(JSON_LD), DSP_SCOPE_V_2024_1)); versionRegistry.register(V_2024_1); versionRegistry.register(V_08); diff --git a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/dispatcher/DspNegotiationHttpDispatcherExtension.java b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/dispatcher/DspNegotiationHttpDispatcherExtension.java index 6af7bf789b6..c7295df8e71 100644 --- a/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/dispatcher/DspNegotiationHttpDispatcherExtension.java +++ b/data-protocols/dsp/dsp-negotiation/dsp-negotiation-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/negotiation/http/dispatcher/DspNegotiationHttpDispatcherExtension.java @@ -68,7 +68,7 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { var contractNegotiationAckDeserializer = new JsonLdResponseBodyDeserializer<>( - ContractNegotiationAck.class, typeManager.getMapper(JSON_LD), jsonLd, dspTransformerRegistry); + ContractNegotiationAck.class, () -> typeManager.getMapper(JSON_LD), jsonLd, dspTransformerRegistry); messageDispatcher.registerMessage( ContractAgreementMessage.class, diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/DspTransferProcessApiExtension.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/DspTransferProcessApiExtension.java index 7405509b882..0a319f699a5 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/DspTransferProcessApiExtension.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-api/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/api/DspTransferProcessApiExtension.java @@ -71,15 +71,14 @@ public class DspTransferProcessApiExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { - var jsonLdMapper = typeManager.getMapper(JSON_LD); registerValidators(DSP_NAMESPACE_V_08); registerValidators(DSP_NAMESPACE_V_2024_1); webService.registerResource(ApiContext.PROTOCOL, new DspTransferProcessApiController(transferProcessProtocolService, dspRequestHandler)); webService.registerResource(ApiContext.PROTOCOL, new DspTransferProcessApiController20241(transferProcessProtocolService, dspRequestHandler)); - webService.registerDynamicResource(ApiContext.PROTOCOL, DspTransferProcessApiController.class, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, DSP_SCOPE_V_08)); - webService.registerDynamicResource(ApiContext.PROTOCOL, DspTransferProcessApiController20241.class, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, DSP_SCOPE_V_2024_1)); + webService.registerDynamicResource(ApiContext.PROTOCOL, DspTransferProcessApiController.class, new JerseyJsonLdInterceptor(jsonLd, () -> typeManager.getMapper(JSON_LD), DSP_SCOPE_V_08)); + webService.registerDynamicResource(ApiContext.PROTOCOL, DspTransferProcessApiController20241.class, new JerseyJsonLdInterceptor(jsonLd, () -> typeManager.getMapper(JSON_LD), DSP_SCOPE_V_2024_1)); versionRegistry.register(V_2024_1); versionRegistry.register(V_08); diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/dispatcher/DspTransferProcessDispatcherExtension.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/dispatcher/DspTransferProcessDispatcherExtension.java index 6fadce273d0..9b739f0febc 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/dispatcher/DspTransferProcessDispatcherExtension.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-http-dispatcher/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/http/dispatcher/DspTransferProcessDispatcherExtension.java @@ -80,7 +80,7 @@ public void initialize(ServiceExtensionContext context) { messageDispatcher.registerMessage( TransferRequestMessage.class, new PostDspHttpRequestFactory<>(remoteMessageSerializer, dspProtocolParser, m -> BASE_PATH + TRANSFER_INITIAL_REQUEST), - new JsonLdResponseBodyDeserializer<>(TransferProcessAck.class, typeManager.getMapper(JSON_LD), jsonLd, dspTransformerRegistry) + new JsonLdResponseBodyDeserializer<>(TransferProcessAck.class, () -> typeManager.getMapper(JSON_LD), jsonLd, dspTransformerRegistry) ); messageDispatcher.registerMessage( TransferCompletionMessage.class, diff --git a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/DspTransferProcessTransformExtension.java b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/DspTransferProcessTransformExtension.java index 29a9ac83edc..897c5d721a0 100644 --- a/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/DspTransferProcessTransformExtension.java +++ b/data-protocols/dsp/dsp-transfer-process/dsp-transfer-process-transform/src/main/java/org/eclipse/edc/protocol/dsp/transferprocess/transform/DspTransferProcessTransformExtension.java @@ -39,7 +39,6 @@ import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; @@ -71,7 +70,7 @@ public String name() { } @Override - public void initialize(ServiceExtensionContext context) { + public void prepare() { var objectMapper = typeManager.getMapper(JSON_LD); registerV08transformers(); @@ -80,7 +79,6 @@ public void initialize(ServiceExtensionContext context) { registerTransformers(DSP_TRANSFORMER_CONTEXT_V_2024_1, DSP_NAMESPACE_V_2024_1, objectMapper); } - private void registerTransformers(String version, JsonLdNamespace namespace, ObjectMapper objectMapper) { var builderFactory = Json.createBuilderFactory(Map.of()); diff --git a/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java b/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java index 8b7abd429e7..a57aa763525 100644 --- a/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java +++ b/extensions/common/api/control-api-configuration/src/main/java/org/eclipse/edc/connector/api/control/configuration/ControlApiConfigurationExtension.java @@ -97,7 +97,6 @@ public String name() { public void initialize(ServiceExtensionContext context) { var portMapping = new PortMapping(ApiContext.CONTROL, apiConfiguration.port(), apiConfiguration.path()); portMappingRegistry.register(portMapping); - var jsonLdMapper = typeManager.getMapper(JSON_LD); context.registerService(ControlApiUrl.class, controlApiUrl(context, portMapping)); jsonLd.registerNamespace(EDC_PREFIX, EDC_NAMESPACE, CONTROL_SCOPE); @@ -107,8 +106,8 @@ public void initialize(ServiceExtensionContext context) { var authenticationRequestFilter = new AuthenticationRequestFilter(authenticationRegistry, "control-api"); webService.registerResource(ApiContext.CONTROL, authenticationRequestFilter); - webService.registerResource(ApiContext.CONTROL, new ObjectMapperProvider(jsonLdMapper)); - webService.registerResource(ApiContext.CONTROL, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, CONTROL_SCOPE)); + webService.registerResource(ApiContext.CONTROL, new ObjectMapperProvider(() -> typeManager.getMapper(JSON_LD))); + webService.registerResource(ApiContext.CONTROL, new JerseyJsonLdInterceptor(jsonLd, () -> typeManager.getMapper(JSON_LD), CONTROL_SCOPE)); registerVersionInfo(getClass().getClassLoader()); } @@ -129,7 +128,7 @@ private void registerVersionInfo(ClassLoader resourceClassLoader) { private ControlApiUrl controlApiUrl(ServiceExtensionContext context, PortMapping config) { var callbackAddress = ofNullable(controlEndpoint).orElseGet(() -> format("http://%s:%s%s", hostname.get(), config.port(), config.path())); - + try { var url = URI.create(callbackAddress); return () -> url; diff --git a/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java b/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java index 822aa0e8c85..c89ab00053a 100644 --- a/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java +++ b/extensions/common/api/management-api-configuration/src/main/java/org/eclipse/edc/connector/api/management/configuration/ManagementApiConfigurationExtension.java @@ -135,9 +135,15 @@ public void initialize(ServiceExtensionContext context) { jsonLd.registerNamespace(ODRL_PREFIX, ODRL_SCHEMA, MANAGEMENT_SCOPE); } + webService.registerResource(ApiContext.MANAGEMENT, new ObjectMapperProvider(() -> typeManager.getMapper(JSON_LD))); + webService.registerResource(ApiContext.MANAGEMENT, new JerseyJsonLdInterceptor(jsonLd, () -> typeManager.getMapper(JSON_LD), MANAGEMENT_SCOPE)); + + registerVersionInfo(getClass().getClassLoader()); + } + + @Override + public void prepare() { var jsonLdMapper = typeManager.getMapper(JSON_LD); - webService.registerResource(ApiContext.MANAGEMENT, new ObjectMapperProvider(jsonLdMapper)); - webService.registerResource(ApiContext.MANAGEMENT, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, MANAGEMENT_SCOPE)); var managementApiTransformerRegistry = transformerRegistry.forContext(MANAGEMENT_API_CONTEXT); @@ -159,8 +165,6 @@ public void initialize(ServiceExtensionContext context) { var managementApiTransformerRegistryV4Alpha = managementApiTransformerRegistry.forContext(MANAGEMENT_API_V_4_ALPHA); managementApiTransformerRegistryV4Alpha.register(new JsonObjectFromPolicyTransformer(factory, participantIdMapper, true)); - - registerVersionInfo(getClass().getClassLoader()); } private void registerVersionInfo(ClassLoader resourceClassLoader) { diff --git a/extensions/common/crypto/jwt-verifiable-credentials/src/main/java/org/eclipse/edc/verifiablecredentials/jwt/JwtPresentationVerifier.java b/extensions/common/crypto/jwt-verifiable-credentials/src/main/java/org/eclipse/edc/verifiablecredentials/jwt/JwtPresentationVerifier.java index 8f82f3deef0..0ea20cd6aeb 100644 --- a/extensions/common/crypto/jwt-verifiable-credentials/src/main/java/org/eclipse/edc/verifiablecredentials/jwt/JwtPresentationVerifier.java +++ b/extensions/common/crypto/jwt-verifiable-credentials/src/main/java/org/eclipse/edc/verifiablecredentials/jwt/JwtPresentationVerifier.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.function.Supplier; /** * Computes the cryptographic integrity of a VerifiablePresentation when it's represented as JWT. Internally, for the actual @@ -68,7 +69,7 @@ public class JwtPresentationVerifier implements CredentialVerifier { public static final String VERIFIABLE_CREDENTIAL_JSON_KEY = "verifiableCredential"; public static final String VP_CLAIM = "vp"; public static final String VC_CLAIM = "vc"; - private final ObjectMapper objectMapper; + private final Supplier objectMapperSupplier; private final TokenValidationService tokenValidationService; private final TokenValidationRulesRegistry tokenValidationRulesRegistry; private final PublicKeyResolver publicKeyResolver; @@ -76,8 +77,8 @@ public class JwtPresentationVerifier implements CredentialVerifier { /** * Verifies the JWT presentation by checking the cryptographic integrity. */ - public JwtPresentationVerifier(ObjectMapper objectMapper, TokenValidationService tokenValidationService, TokenValidationRulesRegistry tokenValidationRulesRegistry, PublicKeyResolver publicKeyResolver) { - this.objectMapper = objectMapper; + public JwtPresentationVerifier(Supplier objectMapperSupplier, TokenValidationService tokenValidationService, TokenValidationRulesRegistry tokenValidationRulesRegistry, PublicKeyResolver publicKeyResolver) { + this.objectMapperSupplier = objectMapperSupplier; this.tokenValidationService = tokenValidationService; this.tokenValidationRulesRegistry = tokenValidationRulesRegistry; this.publicKeyResolver = publicKeyResolver; @@ -177,7 +178,7 @@ private List extractCredentials(Object credentialsObject) { if (credentialsObject instanceof Collection) { return ((Collection) credentialsObject).stream().map(obj -> { try { - return (obj instanceof String) ? obj.toString() : objectMapper.writeValueAsString(obj); + return (obj instanceof String) ? obj.toString() : objectMapperSupplier.get().writeValueAsString(obj); } catch (JsonProcessingException e) { throw new RuntimeException(e); } diff --git a/extensions/common/crypto/jwt-verifiable-credentials/src/test/java/org/eclipse/edc/verifiablecredentials/jwt/JwtPresentationVerifierTest.java b/extensions/common/crypto/jwt-verifiable-credentials/src/test/java/org/eclipse/edc/verifiablecredentials/jwt/JwtPresentationVerifierTest.java index 539edeabfa5..afb6f3c3430 100644 --- a/extensions/common/crypto/jwt-verifiable-credentials/src/test/java/org/eclipse/edc/verifiablecredentials/jwt/JwtPresentationVerifierTest.java +++ b/extensions/common/crypto/jwt-verifiable-credentials/src/test/java/org/eclipse/edc/verifiablecredentials/jwt/JwtPresentationVerifierTest.java @@ -68,7 +68,7 @@ class JwtPresentationVerifierTest { private final TokenValidationService tokenValidationService = new TokenValidationServiceImpl(); private final TokenValidationRulesRegistry ruleRegistry = new TokenValidationRulesRegistryImpl(); private final ObjectMapper mapper = JacksonJsonLd.createObjectMapper(); - private final JwtPresentationVerifier verifier = new JwtPresentationVerifier(mapper, tokenValidationService, ruleRegistry, publicKeyResolverMock); + private final JwtPresentationVerifier verifier = new JwtPresentationVerifier(() -> mapper, tokenValidationService, ruleRegistry, publicKeyResolverMock); private ECKey vpSigningKey; private ECKey vcSigningKey; diff --git a/extensions/common/crypto/ldp-verifiable-credentials/src/main/java/org/eclipse/edc/verifiablecredentials/linkeddata/LdpVerifier.java b/extensions/common/crypto/ldp-verifiable-credentials/src/main/java/org/eclipse/edc/verifiablecredentials/linkeddata/LdpVerifier.java index a332f43c7e0..76f97abab49 100644 --- a/extensions/common/crypto/ldp-verifiable-credentials/src/main/java/org/eclipse/edc/verifiablecredentials/linkeddata/LdpVerifier.java +++ b/extensions/common/crypto/ldp-verifiable-credentials/src/main/java/org/eclipse/edc/verifiablecredentials/linkeddata/LdpVerifier.java @@ -52,6 +52,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.function.Supplier; import static org.eclipse.edc.spi.result.Result.failure; import static org.eclipse.edc.spi.result.Result.success; @@ -59,7 +60,7 @@ public class LdpVerifier implements CredentialVerifier { private JsonLd jsonLd; - private ObjectMapper jsonLdMapper; + private Supplier jsonLdMapperSupplier; private SignatureSuiteRegistry suiteRegistry; private Map params; private Collection methodResolvers = new ArrayList<>(List.of(new HttpMethodResolver())); @@ -71,7 +72,7 @@ private LdpVerifier() { @Override public boolean canHandle(String rawInput) { - try (var parser = jsonLdMapper.createParser(rawInput)) { + try (var parser = jsonLdMapperSupplier.get().createParser(rawInput)) { parser.nextToken(); return true; } catch (IOException e) { @@ -90,7 +91,7 @@ public boolean canHandle(String rawInput) { public Result verify(String rawInput, VerifierContext verifierContext) { JsonObject jo; try { - jo = jsonLdMapper.readValue(rawInput, JsonObject.class); + jo = jsonLdMapperSupplier.get().readValue(rawInput, JsonObject.class); } catch (JsonProcessingException e) { return failure("Failed to parse JSON: %s".formatted(e.toString())); } @@ -333,8 +334,8 @@ public Builder methodResolver(MethodResolver resolver) { return this; } - public Builder objectMapper(ObjectMapper mapper) { - this.verifier.jsonLdMapper = mapper; + public Builder objectMapperSupplier(Supplier objectMapperSupplier) { + this.verifier.jsonLdMapperSupplier = objectMapperSupplier; return this; } @@ -360,7 +361,7 @@ public Builder loader(DocumentLoader loader) { public LdpVerifier build() { Objects.requireNonNull(this.verifier.jsonLd, "Must have a JsonLD service!"); - Objects.requireNonNull(this.verifier.jsonLdMapper, "Must have an ObjectMapper!"); + Objects.requireNonNull(this.verifier.jsonLdMapperSupplier, "Must have an ObjectMapper!"); Objects.requireNonNull(this.verifier.suiteRegistry, "Must have a Signature registry!"); return this.verifier; } diff --git a/extensions/common/crypto/ldp-verifiable-credentials/src/test/java/org/eclipse/edc/verifiablecredentials/linkeddata/LdpVerifierTest.java b/extensions/common/crypto/ldp-verifiable-credentials/src/test/java/org/eclipse/edc/verifiablecredentials/linkeddata/LdpVerifierTest.java index a8ebcce825e..56a1c58dc04 100644 --- a/extensions/common/crypto/ldp-verifiable-credentials/src/test/java/org/eclipse/edc/verifiablecredentials/linkeddata/LdpVerifierTest.java +++ b/extensions/common/crypto/ldp-verifiable-credentials/src/test/java/org/eclipse/edc/verifiablecredentials/linkeddata/LdpVerifierTest.java @@ -82,7 +82,7 @@ void setUp() throws URISyntaxException { ldpVerifier = LdpVerifier.Builder.newInstance() .signatureSuites(suiteRegistry) .jsonLd(jsonLd) - .objectMapper(mapper) + .objectMapperSupplier(() -> mapper) .methodResolvers(List.of(mockDidResolver)) .loader(testDocLoader) .build(); diff --git a/extensions/common/http/jersey-core/src/main/java/org/eclipse/edc/web/jersey/JerseyRestService.java b/extensions/common/http/jersey-core/src/main/java/org/eclipse/edc/web/jersey/JerseyRestService.java index 030ac2db959..4034d5d8c1e 100644 --- a/extensions/common/http/jersey-core/src/main/java/org/eclipse/edc/web/jersey/JerseyRestService.java +++ b/extensions/common/http/jersey-core/src/main/java/org/eclipse/edc/web/jersey/JerseyRestService.java @@ -101,7 +101,7 @@ private void registerContext(String contextAlias, List controllers) { // In order to use instances with Jersey, the controller types must be registered along with an {@link AbstractBinder} that maps those types to the instances. resourceConfig.registerClasses(controllers.stream().map(Object::getClass).collect(toSet())); resourceConfig.registerInstances(new Binder(controllers)); - resourceConfig.registerInstances(new ObjectMapperProvider(typeManager.getMapper())); + resourceConfig.registerInstances(new ObjectMapperProvider(typeManager::getMapper)); resourceConfig.registerInstances(new EdcApiExceptionMapper()); resourceConfig.registerInstances(new UnexpectedExceptionMapper(monitor)); resourceConfig.registerInstances(new DynamicResourceFeature(dynamicResourcesForContext)); diff --git a/extensions/common/http/jersey-core/src/testFixtures/java/org/eclipse/edc/web/jersey/testfixtures/RestControllerTestBase.java b/extensions/common/http/jersey-core/src/testFixtures/java/org/eclipse/edc/web/jersey/testfixtures/RestControllerTestBase.java index 3a7a382397a..fbf968bfb38 100644 --- a/extensions/common/http/jersey-core/src/testFixtures/java/org/eclipse/edc/web/jersey/testfixtures/RestControllerTestBase.java +++ b/extensions/common/http/jersey-core/src/testFixtures/java/org/eclipse/edc/web/jersey/testfixtures/RestControllerTestBase.java @@ -49,7 +49,7 @@ final void startJetty() { portMappings.register(new PortMapping("test", port, "/")); jetty = new JettyService(config, monitor, portMappings); var jerseyService = new JerseyRestService(jetty, new JacksonTypeManager(), mock(JerseyConfiguration.class), monitor); - jerseyService.registerResource("test", new ObjectMapperProvider(objectMapper)); + jerseyService.registerResource("test", new ObjectMapperProvider(() -> objectMapper)); jerseyService.registerResource("test", controller()); var additionalResource = additionalResource(); if (additionalResource != null) { diff --git a/extensions/common/http/lib/jersey-providers-lib/src/main/java/org/eclipse/edc/web/jersey/providers/jsonld/JerseyJsonLdInterceptor.java b/extensions/common/http/lib/jersey-providers-lib/src/main/java/org/eclipse/edc/web/jersey/providers/jsonld/JerseyJsonLdInterceptor.java index d0f47e0a40f..d8d8d4a90d7 100644 --- a/extensions/common/http/lib/jersey-providers-lib/src/main/java/org/eclipse/edc/web/jersey/providers/jsonld/JerseyJsonLdInterceptor.java +++ b/extensions/common/http/lib/jersey-providers-lib/src/main/java/org/eclipse/edc/web/jersey/providers/jsonld/JerseyJsonLdInterceptor.java @@ -29,19 +29,20 @@ import java.io.ByteArrayInputStream; import java.io.IOException; +import java.util.function.Supplier; import static jakarta.json.stream.JsonCollectors.toJsonArray; @Provider public class JerseyJsonLdInterceptor implements ReaderInterceptor, WriterInterceptor { private final JsonLd jsonLd; - private final ObjectMapper objectMapper; + private final Supplier objectMapper; private final String scope; - public JerseyJsonLdInterceptor(JsonLd jsonLd, ObjectMapper objectMapper, String scope) { + public JerseyJsonLdInterceptor(JsonLd jsonLd, Supplier objectMapperSupplier, String scope) { this.jsonLd = jsonLd; - this.objectMapper = objectMapper; + this.objectMapper = objectMapperSupplier; this.scope = scope; } @@ -50,12 +51,12 @@ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOExceptio if (context.getType().equals(JsonObject.class)) { var bytes = context.getInputStream().readAllBytes(); if (bytes.length > 0) { - var jsonObject = objectMapper.readValue(bytes, JsonObject.class); + var jsonObject = objectMapper.get().readValue(bytes, JsonObject.class); var expanded = jsonLd.expand(jsonObject) .orElseThrow(f -> new BadRequestException("Failed to expand JsonObject: " + f.getFailureDetail())); - var expandedBytes = objectMapper.writeValueAsBytes(expanded); + var expandedBytes = objectMapper.get().writeValueAsBytes(expanded); context.setInputStream(new ByteArrayInputStream(expandedBytes)); } } diff --git a/extensions/common/http/lib/jersey-providers-lib/src/main/java/org/eclipse/edc/web/jersey/providers/jsonld/ObjectMapperProvider.java b/extensions/common/http/lib/jersey-providers-lib/src/main/java/org/eclipse/edc/web/jersey/providers/jsonld/ObjectMapperProvider.java index bcb06d22e63..4fd6d92ff33 100644 --- a/extensions/common/http/lib/jersey-providers-lib/src/main/java/org/eclipse/edc/web/jersey/providers/jsonld/ObjectMapperProvider.java +++ b/extensions/common/http/lib/jersey-providers-lib/src/main/java/org/eclipse/edc/web/jersey/providers/jsonld/ObjectMapperProvider.java @@ -17,20 +17,22 @@ import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.ws.rs.ext.ContextResolver; +import java.util.function.Supplier; + /** * Provides an ObjectMapper to be used for parsing incoming requests. A custom ObjectMapper that supports the * Jakarta JSON API is required to allow JsonObject as a controller parameter. */ public class ObjectMapperProvider implements ContextResolver { - private final ObjectMapper objectMapper; + private final Supplier objectMapperSupplier; - public ObjectMapperProvider(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; + public ObjectMapperProvider(Supplier objectMapperSupplier) { + this.objectMapperSupplier = objectMapperSupplier; } @Override public ObjectMapper getContext(Class type) { - return objectMapper; + return objectMapperSupplier.get(); } } diff --git a/extensions/common/http/lib/jersey-providers-lib/src/test/java/org/eclipse/edc/web/jersey/providers/jsonld/JerseyJsonLdInterceptorTest.java b/extensions/common/http/lib/jersey-providers-lib/src/test/java/org/eclipse/edc/web/jersey/providers/jsonld/JerseyJsonLdInterceptorTest.java index 84b9997a35f..c8dbf769f41 100644 --- a/extensions/common/http/lib/jersey-providers-lib/src/test/java/org/eclipse/edc/web/jersey/providers/jsonld/JerseyJsonLdInterceptorTest.java +++ b/extensions/common/http/lib/jersey-providers-lib/src/test/java/org/eclipse/edc/web/jersey/providers/jsonld/JerseyJsonLdInterceptorTest.java @@ -44,7 +44,7 @@ class JerseyJsonLdInterceptorTest extends RestControllerTestBase { private static final String SCOPE = "scope"; private final JsonLd jsonLd = mock(); - private final JerseyJsonLdInterceptor interceptor = new JerseyJsonLdInterceptor(jsonLd, objectMapper, SCOPE); + private final JerseyJsonLdInterceptor interceptor = new JerseyJsonLdInterceptor(jsonLd, () -> objectMapper, SCOPE); @Test void expansion_shouldSucceed_whenInputIsJsonObject() { diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtension.java b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtension.java index 621af09c73c..56016378886 100644 --- a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtension.java +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/IdentityAndTrustExtension.java @@ -78,20 +78,15 @@ public class IdentityAndTrustExtension implements ServiceExtension { public static final long DEFAULT_REVOCATION_CACHE_VALIDITY_MILLIS = 15 * 60 * 1000L; + public static final String DCP_SELF_ISSUED_TOKEN_CONTEXT = "dcp-si"; + public static final String JSON_2020_SIGNATURE_SUITE = "JsonWebSignature2020"; + public static final long DEFAULT_CLEANUP_PERIOD_SECONDS = 60; @Setting(description = "Validity period of cached StatusList2021 credential entries in milliseconds.", defaultValue = DEFAULT_REVOCATION_CACHE_VALIDITY_MILLIS + "", key = "edc.iam.credential.revocation.cache.validity") private long revocationCacheValidity; - @Setting(description = "DID of this connector", key = "edc.iam.issuer.id") private String issuerId; - @Setting(description = "The period of the JTI entry reaper thread in seconds", defaultValue = DEFAULT_CLEANUP_PERIOD_SECONDS + "", key = "edc.sql.store.jti.cleanup.period") private long reaperCleanupPeriod; - - public static final String DCP_SELF_ISSUED_TOKEN_CONTEXT = "dcp-si"; - public static final String JSON_2020_SIGNATURE_SUITE = "JsonWebSignature2020"; - public static final long DEFAULT_CLEANUP_PERIOD_SECONDS = 60; - - @Inject private SecureTokenService secureTokenService; @@ -159,9 +154,6 @@ public void initialize(ServiceExtensionContext context) { // add all rules for validating VerifiableCredential JWTs rulesRegistry.addRule(JWT_VC_TOKEN_CONTEXT, new HasSubjectRule()); - // TODO move in a separated extension? - signatureSuiteRegistry.register(JSON_2020_SIGNATURE_SUITE, new Jws2020SignatureSuite(typeManager.getMapper(JSON_LD))); - try { jsonLd.registerCachedDocument(STATUSLIST_2021_URL, getClass().getClassLoader().getResource("statuslist2021.json").toURI()); @@ -187,6 +179,12 @@ public void shutdown() { jtiEntryReaperThread.cancel(true); } + @Override + public void prepare() { + // TODO move in a separated extension? + signatureSuiteRegistry.register(JSON_2020_SIGNATURE_SUITE, new Jws2020SignatureSuite(typeManager.getMapper(JSON_LD))); + } + @Provider public IdentityService createIdentityService(ServiceExtensionContext context) { var credentialServiceUrlResolver = new DidCredentialServiceUrlResolver(didResolverRegistry); @@ -204,7 +202,7 @@ public IdentityService createIdentityService(ServiceExtensionContext context) { public CredentialServiceClient getCredentialServiceClient(ServiceExtensionContext context) { if (credentialServiceClient == null) { credentialServiceClient = new DefaultCredentialServiceClient(httpClient, Json.createBuilderFactory(Map.of()), - typeManager.getMapper(JSON_LD), typeTransformerRegistry, jsonLd, context.getMonitor()); + () -> typeManager.getMapper(JSON_LD), typeTransformerRegistry, jsonLd, context.getMonitor()); } return credentialServiceClient; } @@ -212,13 +210,11 @@ public CredentialServiceClient getCredentialServiceClient(ServiceExtensionContex @Provider public PresentationVerifier createPresentationVerifier(ServiceExtensionContext context) { if (presentationVerifier == null) { - var mapper = typeManager.getMapper(JSON_LD); - - var jwtVerifier = new JwtPresentationVerifier(mapper, tokenValidationService, rulesRegistry, didPublicKeyResolver); + var jwtVerifier = new JwtPresentationVerifier(() -> typeManager.getMapper(JSON_LD), tokenValidationService, rulesRegistry, didPublicKeyResolver); var ldpVerifier = LdpVerifier.Builder.newInstance() .signatureSuites(signatureSuiteRegistry) .jsonLd(jsonLd) - .objectMapper(mapper) + .objectMapperSupplier(() -> typeManager.getMapper(JSON_LD)) .methodResolver(new DidMethodResolver(didResolverRegistry)) .build(); diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClient.java b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClient.java index fcc285f928f..8e9e7558a44 100644 --- a/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClient.java +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/main/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClient.java @@ -15,7 +15,6 @@ package org.eclipse.edc.iam.identitytrust.core.defaults; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.json.JsonBuilderFactory; import jakarta.json.JsonObject; @@ -42,6 +41,7 @@ import java.io.IOException; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import java.util.stream.Collectors; import static org.eclipse.edc.spi.result.Result.failure; @@ -51,15 +51,15 @@ public class DefaultCredentialServiceClient implements CredentialServiceClient { public static final String PRESENTATION_ENDPOINT = "/presentations/query"; private final EdcHttpClient httpClient; private final JsonBuilderFactory jsonFactory; - private final ObjectMapper objectMapper; + private final Supplier objectMapperSupplier; private final TypeTransformerRegistry transformerRegistry; private final JsonLd jsonLd; private final Monitor monitor; - public DefaultCredentialServiceClient(EdcHttpClient httpClient, JsonBuilderFactory jsonFactory, ObjectMapper jsonLdMapper, TypeTransformerRegistry transformerRegistry, JsonLd jsonLd, Monitor monitor) { + public DefaultCredentialServiceClient(EdcHttpClient httpClient, JsonBuilderFactory jsonFactory, Supplier objectMapperSupplier, TypeTransformerRegistry transformerRegistry, JsonLd jsonLd, Monitor monitor) { this.httpClient = httpClient; this.jsonFactory = jsonFactory; - this.objectMapper = jsonLdMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); + this.objectMapperSupplier = objectMapperSupplier; this.transformerRegistry = transformerRegistry; this.jsonLd = jsonLd; this.monitor = monitor; @@ -72,7 +72,7 @@ public Result> requestPresentation(String var url = credentialServiceBaseUrl + PRESENTATION_ENDPOINT; try { - var requestJson = objectMapper.writeValueAsString(query); + var requestJson = objectMapperSupplier.get().writeValueAsString(query); var request = new Request.Builder() .post(RequestBody.create(requestJson, MediaType.parse("application/json"))) .url(url) @@ -87,7 +87,7 @@ public Result> requestPresentation(String } if (response.isSuccessful() && response.body() != null) { - var presentationResponse = objectMapper.readValue(body, JsonObject.class); + var presentationResponse = objectMapperSupplier.get().readValue(body, JsonObject.class); return parseResponse(presentationResponse); } return failure("Presentation Query failed: HTTP %s, message: %s".formatted(response.code(), body)); @@ -130,7 +130,7 @@ private Result parseVpToken(Object vpObj) { } private Result parseLdpVp(Object vpObj) { - var jsonObj = objectMapper.convertValue(vpObj, JsonObject.class); + var jsonObj = objectMapperSupplier.get().convertValue(vpObj, JsonObject.class); var rawStr = jsonObj.toString(); return jsonLd.expand(jsonObj) diff --git a/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClientTest.java b/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClientTest.java index 29b47aa11fa..12fbc90753f 100644 --- a/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClientTest.java +++ b/extensions/common/iam/identity-trust/identity-trust-core/src/test/java/org/eclipse/edc/iam/identitytrust/core/defaults/DefaultCredentialServiceClientTest.java @@ -55,7 +55,6 @@ import java.util.Objects; import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.edc.jsonld.util.JacksonJsonLd.createObjectMapper; import static org.eclipse.edc.junit.testfixtures.TestUtils.getResourceFileContentAsString; import static org.eclipse.edc.spi.result.Result.success; import static org.mockito.ArgumentMatchers.any; @@ -75,6 +74,17 @@ class DefaultCredentialServiceClientTest { private DefaultCredentialServiceClient client; private TypeTransformerRegistry transformerRegistry; + private static VerifiableCredential.Builder createCredential() { + return VerifiableCredential.Builder.newInstance() + .issuer(new Issuer("test-issuer", Map.of())) + .type("VerifiableCredential") + .issuanceDate(Instant.now()) + .credentialSubject(CredentialSubject.Builder.newInstance() + .id("test-subject") + .claim("foo", "bar") + .build()); + } + @BeforeEach void setup() { transformerRegistry = mock(TypeTransformerRegistry.class); @@ -85,7 +95,7 @@ void setup() { var jsonLdMock = mock(JsonLd.class); when(jsonLdMock.expand(any())).thenAnswer(a -> success(a.getArgument(0))); client = new DefaultCredentialServiceClient(httpClientMock, Json.createBuilderFactory(Map.of()), - createObjectMapper(), transformerRegistry, jsonLdMock, mock()); + JacksonJsonLd::createObjectMapper, transformerRegistry, jsonLdMock, mock()); } @Test @@ -102,6 +112,51 @@ void requestPresentation_sendScopes() throws IOException { verify(httpClientMock).execute(argThat((r) -> containsScope(r, scopes))); } + @SuppressWarnings("unchecked") + private boolean containsScope(Request request, List scopes) { + + try (var buffer = new Buffer()) { + Objects.requireNonNull(request.body()).writeTo(buffer); + var body = mapper.readValue(buffer.inputStream(), new TypeReference>() { + + }); + var requestScopes = (Collection) body.get("scope"); + + return requestScopes.containsAll(scopes); + + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private VerifiablePresentation.Builder createPresentation() { + return VerifiablePresentation.Builder.newInstance() + .type("VerifiablePresentation") + .credential(createCredential().build()); + } + + private Result presentationResponse(InvocationOnMock args) { + try { + var response = mapper.readValue(args.getArgument(0, JsonObject.class).toString(), PresentationResponseMessage.class); + return Result.success(response); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + private Response response(int code, String body) { + return new Response.Builder() + .request(mock()) + .protocol(Protocol.HTTP_2) + .code(code) // status code + .message("") + .body(ResponseBody.create( + body, + MediaType.get("application/json; charset=utf-8") + )) + .build(); + } + @Nested class VcDataModel11 { @Test @@ -257,61 +312,5 @@ void requestPresentation_noCredentials() throws IOException { } } - @SuppressWarnings("unchecked") - private boolean containsScope(Request request, List scopes) { - - try (var buffer = new Buffer()) { - Objects.requireNonNull(request.body()).writeTo(buffer); - var body = mapper.readValue(buffer.inputStream(), new TypeReference>() { - - }); - var requestScopes = (Collection) body.get("scope"); - - return requestScopes.containsAll(scopes); - - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private VerifiablePresentation.Builder createPresentation() { - return VerifiablePresentation.Builder.newInstance() - .type("VerifiablePresentation") - .credential(createCredential().build()); - } - - private static VerifiableCredential.Builder createCredential() { - return VerifiableCredential.Builder.newInstance() - .issuer(new Issuer("test-issuer", Map.of())) - .type("VerifiableCredential") - .issuanceDate(Instant.now()) - .credentialSubject(CredentialSubject.Builder.newInstance() - .id("test-subject") - .claim("foo", "bar") - .build()); - } - - private Result presentationResponse(InvocationOnMock args) { - try { - var response = mapper.readValue(args.getArgument(0, JsonObject.class).toString(), PresentationResponseMessage.class); - return Result.success(response); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - private Response response(int code, String body) { - return new Response.Builder() - .request(mock()) - .protocol(Protocol.HTTP_2) - .code(code) // status code - .message("") - .body(ResponseBody.create( - body, - MediaType.get("application/json; charset=utf-8") - )) - .build(); - } - } \ No newline at end of file diff --git a/extensions/common/iam/identity-trust/identity-trust-service/src/test/java/org/eclipse/edc/iam/identitytrust/service/verification/MultiFormatPresentationVerifierTest.java b/extensions/common/iam/identity-trust/identity-trust-service/src/test/java/org/eclipse/edc/iam/identitytrust/service/verification/MultiFormatPresentationVerifierTest.java index d2f789bb0d7..9185eac095c 100644 --- a/extensions/common/iam/identity-trust/identity-trust-service/src/test/java/org/eclipse/edc/iam/identitytrust/service/verification/MultiFormatPresentationVerifierTest.java +++ b/extensions/common/iam/identity-trust/identity-trust-service/src/test/java/org/eclipse/edc/iam/identitytrust/service/verification/MultiFormatPresentationVerifierTest.java @@ -116,10 +116,10 @@ void setup() { var ldpVerifier = LdpVerifier.Builder.newInstance() .signatureSuites(SIGNATURE_SUITE_REGISTRY) .jsonLd(jsonLd) - .objectMapper(MAPPER) + .objectMapperSupplier(() -> MAPPER) .build(); - var jwtPresentationVerifier = new JwtPresentationVerifier(MAPPER, tokenValidationService, mock(), publicKeyResolverMock); + var jwtPresentationVerifier = new JwtPresentationVerifier(() -> MAPPER, tokenValidationService, mock(), publicKeyResolverMock); multiFormatVerifier = new MultiFormatPresentationVerifier(MY_OWN_DID, jwtPresentationVerifier, ldpVerifier); } diff --git a/extensions/control-plane/api/management-api/contract-definition-api/src/main/java/org/eclipse/edc/connector/controlplane/api/management/contractdefinition/ContractDefinitionApiExtension.java b/extensions/control-plane/api/management-api/contract-definition-api/src/main/java/org/eclipse/edc/connector/controlplane/api/management/contractdefinition/ContractDefinitionApiExtension.java index 71cc9391a2a..3b19af18a64 100644 --- a/extensions/control-plane/api/management-api/contract-definition-api/src/main/java/org/eclipse/edc/connector/controlplane/api/management/contractdefinition/ContractDefinitionApiExtension.java +++ b/extensions/control-plane/api/management-api/contract-definition-api/src/main/java/org/eclipse/edc/connector/controlplane/api/management/contractdefinition/ContractDefinitionApiExtension.java @@ -68,10 +68,7 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var jsonFactory = Json.createBuilderFactory(Map.of()); - var mapper = typeManager.getMapper(JSON_LD); - transformerRegistry.register(new JsonObjectFromContractDefinitionTransformer(jsonFactory, mapper)); - transformerRegistry.register(new JsonObjectToContractDefinitionTransformer()); + validatorRegistry.register(CONTRACT_DEFINITION_TYPE, ContractDefinitionValidator.instance(criterionOperatorRegistry)); @@ -79,4 +76,12 @@ public void initialize(ServiceExtensionContext context) { webService.registerResource(ApiContext.MANAGEMENT, new ContractDefinitionApiV3Controller(managementApiTransformerRegistry, service, context.getMonitor(), validatorRegistry)); } + + @Override + public void prepare() { + var jsonFactory = Json.createBuilderFactory(Map.of()); + var mapper = typeManager.getMapper(JSON_LD); + transformerRegistry.register(new JsonObjectFromContractDefinitionTransformer(jsonFactory, mapper)); + transformerRegistry.register(new JsonObjectToContractDefinitionTransformer()); + } } diff --git a/extensions/control-plane/api/management-api/policy-definition-api/src/main/java/org/eclipse/edc/connector/controlplane/api/management/policy/PolicyDefinitionApiExtension.java b/extensions/control-plane/api/management-api/policy-definition-api/src/main/java/org/eclipse/edc/connector/controlplane/api/management/policy/PolicyDefinitionApiExtension.java index 29e74df099d..c419da3786d 100644 --- a/extensions/control-plane/api/management-api/policy-definition-api/src/main/java/org/eclipse/edc/connector/controlplane/api/management/policy/PolicyDefinitionApiExtension.java +++ b/extensions/control-plane/api/management-api/policy-definition-api/src/main/java/org/eclipse/edc/connector/controlplane/api/management/policy/PolicyDefinitionApiExtension.java @@ -69,14 +69,7 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { - var jsonBuilderFactory = Json.createBuilderFactory(Map.of()); var managementApiTransformerRegistry = transformerRegistry.forContext("management-api"); - var mapper = typeManager.getMapper(JSON_LD); - managementApiTransformerRegistry.register(new JsonObjectToPolicyEvaluationPlanRequestTransformer()); - managementApiTransformerRegistry.register(new JsonObjectToPolicyDefinitionTransformer()); - managementApiTransformerRegistry.register(new JsonObjectFromPolicyDefinitionTransformer(jsonBuilderFactory, mapper)); - managementApiTransformerRegistry.register(new JsonObjectFromPolicyValidationResultTransformer(jsonBuilderFactory)); - managementApiTransformerRegistry.register(new JsonObjectFromPolicyEvaluationPlanTransformer(jsonBuilderFactory)); validatorRegistry.register(EDC_POLICY_DEFINITION_TYPE, PolicyDefinitionValidator.instance()); validatorRegistry.register(EDC_POLICY_EVALUATION_PLAN_REQUEST_TYPE, PolicyEvaluationPlanRequestValidator.instance()); @@ -85,4 +78,17 @@ public void initialize(ServiceExtensionContext context) { webService.registerResource(ApiContext.MANAGEMENT, new PolicyDefinitionApiV3Controller(monitor, managementApiTransformerRegistry, service, validatorRegistry)); webService.registerResource(ApiContext.MANAGEMENT, new PolicyDefinitionApiV31AlphaController(monitor, managementApiTransformerRegistry, service, validatorRegistry)); } + + @Override + public void prepare() { + var managementApiTransformerRegistry = transformerRegistry.forContext("management-api"); + var jsonBuilderFactory = Json.createBuilderFactory(Map.of()); + + var mapper = typeManager.getMapper(JSON_LD); + managementApiTransformerRegistry.register(new JsonObjectToPolicyEvaluationPlanRequestTransformer()); + managementApiTransformerRegistry.register(new JsonObjectToPolicyDefinitionTransformer()); + managementApiTransformerRegistry.register(new JsonObjectFromPolicyDefinitionTransformer(jsonBuilderFactory, mapper)); + managementApiTransformerRegistry.register(new JsonObjectFromPolicyValidationResultTransformer(jsonBuilderFactory)); + managementApiTransformerRegistry.register(new JsonObjectFromPolicyEvaluationPlanTransformer(jsonBuilderFactory)); + } } diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtension.java b/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtension.java index 3928592a3f8..80de77f19ed 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtension.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtension.java @@ -51,15 +51,21 @@ public class DataPlaneSelectorApiExtension implements ServiceExtension { @Override public void initialize(ServiceExtensionContext context) { var managementApiTransformerRegistry = transformerRegistry.forContext("management-api"); + var managementApiTransformerRegistryV3 = managementApiTransformerRegistry.forContext("v3"); + + webservice.registerResource(ApiContext.MANAGEMENT, new DataplaneSelectorApiV3Controller(selectionService, managementApiTransformerRegistryV3)); + webservice.registerResource(ApiContext.MANAGEMENT, new DataplaneSelectorApiV4Controller(selectionService, managementApiTransformerRegistry)); + } + + @Override + public void prepare() { + var managementApiTransformerRegistry = transformerRegistry.forContext("management-api"); // V4 managementApiTransformerRegistry.register(new JsonObjectFromDataPlaneInstanceTransformer(createBuilderFactory(Map.of()), typeManager.getMapper(JSON_LD))); - webservice.registerResource(ApiContext.MANAGEMENT, new DataplaneSelectorApiV4Controller(selectionService, managementApiTransformerRegistry)); // V3 var managementApiTransformerRegistryV3 = managementApiTransformerRegistry.forContext("v3"); managementApiTransformerRegistryV3.register(new JsonObjectFromDataPlaneInstanceV3Transformer(createBuilderFactory(Map.of()), typeManager.getMapper(JSON_LD))); - webservice.registerResource(ApiContext.MANAGEMENT, new DataplaneSelectorApiV3Controller(selectionService, managementApiTransformerRegistryV3)); - } } diff --git a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtensionTest.java b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtensionTest.java index bab00058d37..6292a8328ad 100644 --- a/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtensionTest.java +++ b/extensions/data-plane-selector/data-plane-selector-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorApiExtensionTest.java @@ -69,9 +69,8 @@ void setUp(ServiceExtensionContext context, ObjectFactory factory) { @Test void shouldRegisterManagementContext() { - var config = ConfigFactory.fromMap(Collections.emptyMap()); - extension.initialize(contextWithConfig(config)); + extension.prepare(); verify(managementApiTransformerRegistry).register(isA(JsonObjectFromDataPlaneInstanceTransformer.class)); } diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java index b6a3c652143..8ebe4411fc6 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtension.java @@ -64,7 +64,7 @@ public String name() { } @Override - public void initialize(ServiceExtensionContext context) { + public void prepare() { var builderFactory = Json.createBuilderFactory(emptyMap()); var objectMapper = typeManager.getMapper(JSON_LD); typeTransformerRegistry.register(new JsonObjectFromDataPlaneInstanceTransformer(builderFactory, objectMapper)); @@ -76,7 +76,7 @@ public void initialize(ServiceExtensionContext context) { @Provider public DataPlaneSelectorService dataPlaneSelectorService(ServiceExtensionContext context) { - return new RemoteDataPlaneSelectorService(httpClient, selectorApiUrl, typeManager.getMapper(JSON_LD), typeTransformerRegistry, + return new RemoteDataPlaneSelectorService(httpClient, selectorApiUrl, () -> typeManager.getMapper(JSON_LD), typeTransformerRegistry, selectionStrategy, jsonLd); } } diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorService.java b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorService.java index 00e83af70fe..48054e88869 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorService.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/main/java/org/eclipse/edc/connector/dataplane/selector/RemoteDataPlaneSelectorService.java @@ -36,6 +36,7 @@ import java.util.List; import java.util.Optional; +import java.util.function.Supplier; import static jakarta.json.Json.createObjectBuilder; import static okhttp3.internal.Util.EMPTY_REQUEST; @@ -51,17 +52,17 @@ public class RemoteDataPlaneSelectorService implements DataPlaneSelectorService private static final String SELECT_PATH = "/select"; private final ControlApiHttpClient httpClient; private final String url; - private final ObjectMapper mapper; + private final Supplier objectMapperSupplier; private final TypeTransformerRegistry typeTransformerRegistry; private final String selectionStrategy; private final JsonLd jsonLd; - public RemoteDataPlaneSelectorService(ControlApiHttpClient controlClient, String url, ObjectMapper mapper, + public RemoteDataPlaneSelectorService(ControlApiHttpClient controlClient, String url, Supplier objectMapperSupplier, TypeTransformerRegistry typeTransformerRegistry, String selectionStrategy, JsonLd jsonLd) { this.httpClient = controlClient; this.url = url; - this.mapper = mapper; + this.objectMapperSupplier = objectMapperSupplier; this.typeTransformerRegistry = typeTransformerRegistry; this.selectionStrategy = selectionStrategy; this.jsonLd = jsonLd; @@ -145,7 +146,7 @@ public ServiceResult findById(String id) { private ServiceResult toJsonObject(String it) { try { - return ServiceResult.success(mapper.readValue(it, JsonObject.class)); + return ServiceResult.success(objectMapperSupplier.get().readValue(it, JsonObject.class)); } catch (JsonProcessingException e) { return ServiceResult.unexpected("Cannot deserialize response body as JsonObject"); } @@ -153,7 +154,7 @@ private ServiceResult toJsonObject(String it) { private ServiceResult toJsonArray(String it) { try { - return ServiceResult.success(mapper.readValue(it, JsonArray.class)); + return ServiceResult.success(objectMapperSupplier.get().readValue(it, JsonArray.class)); } catch (JsonProcessingException e) { return ServiceResult.unexpected("Cannot deserialize response body as JsonObject"); } diff --git a/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java b/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java index ddb31fa2405..1aabea9ad50 100644 --- a/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java +++ b/extensions/data-plane-selector/data-plane-selector-client/src/test/java/org/eclipse/edc/connector/dataplane/selector/DataPlaneSelectorClientExtensionTest.java @@ -66,8 +66,8 @@ void dataPlaneSelectorService_shouldThrowException_whenUrlNotConfigured(ServiceE } @Test - void initialize_shouldRegisterTransformer(DataPlaneSelectorClientExtension extension, ServiceExtensionContext context) { - extension.initialize(context); + void prepare_shouldRegisterTransformer(DataPlaneSelectorClientExtension extension) { + extension.prepare(); verify(typeTransformerRegistry).register(isA(JsonObjectFromDataPlaneInstanceTransformer.class)); } diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtension.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtension.java index 7c86cc90b55..ff5714b1314 100644 --- a/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtension.java +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/main/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtension.java @@ -70,6 +70,13 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { validatorRegistry.register(DATAPLANE_INSTANCE_TYPE, DataPlaneInstanceValidator.instance()); + + var controller = new DataplaneSelectorControlApiController(validatorRegistry, typeTransformerRegistry, dataPlaneSelectorService, clock); + webService.registerResource(ApiContext.CONTROL, controller); + } + + @Override + public void prepare() { var objectMapper = typeManager.getMapper(JSON_LD); typeTransformerRegistry.register(new JsonObjectToDataPlaneInstanceTransformer()); @@ -77,8 +84,5 @@ public void initialize(ServiceExtensionContext context) { typeTransformerRegistry.register(new JsonObjectToDataAddressTransformer()); typeTransformerRegistry.register(new JsonValueToGenericTypeTransformer(objectMapper)); typeTransformerRegistry.register(new JsonObjectFromDataPlaneInstanceTransformer(createBuilderFactory(Map.of()), objectMapper)); - - var controller = new DataplaneSelectorControlApiController(validatorRegistry, typeTransformerRegistry, dataPlaneSelectorService, clock); - webService.registerResource(ApiContext.CONTROL, controller); } } diff --git a/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtensionTest.java b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtensionTest.java index 47c74e6d88d..5e13e9bd023 100644 --- a/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtensionTest.java +++ b/extensions/data-plane-selector/data-plane-selector-control-api/src/test/java/org/eclipse/edc/connector/dataplane/selector/control/api/DataplaneSelectorControlApiExtensionTest.java @@ -63,8 +63,8 @@ void shouldRegisterValidator(DataplaneSelectorControlApiExtension extension, Ser } @Test - void shouldRegisterTransformers(DataplaneSelectorControlApiExtension extension, ServiceExtensionContext context) { - extension.initialize(context); + void shouldRegisterTransformers(DataplaneSelectorControlApiExtension extension) { + extension.prepare(); verify(typeTransformerRegistry).register(isA(JsonObjectToDataPlaneInstanceTransformer.class)); verify(typeTransformerRegistry).register(isA(JsonObjectFromDataPlaneInstanceTransformer.class)); diff --git a/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlaneSignalingApiExtension.java b/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlaneSignalingApiExtension.java index 2c83596744c..eb18015a8ec 100644 --- a/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlaneSignalingApiExtension.java +++ b/extensions/data-plane/data-plane-signaling/data-plane-signaling-api/src/main/java/org/eclipse/edc/connector/dataplane/api/DataPlaneSignalingApiExtension.java @@ -58,6 +58,16 @@ public String name() { @Override public void initialize(ServiceExtensionContext context) { + var signalingApiTypeTransformerRegistry = transformerRegistry.forContext("signaling-api"); + + var controller = new DataPlaneSignalingApiController(signalingApiTypeTransformerRegistry, + dataPlaneManager, context.getMonitor().withPrefix("SignalingAPI")); + + webService.registerResource(ApiContext.CONTROL, controller); + } + + @Override + public void prepare() { var factory = Json.createBuilderFactory(Map.of()); var jsonLdMapper = typeManager.getMapper(JSON_LD); @@ -68,11 +78,5 @@ public void initialize(ServiceExtensionContext context) { signalingApiTypeTransformerRegistry.register(new JsonObjectToDataAddressDspaceTransformer()); signalingApiTypeTransformerRegistry.register(new JsonObjectFromDataFlowResponseMessageTransformer(factory)); signalingApiTypeTransformerRegistry.register(new JsonObjectFromDataAddressDspaceTransformer(factory, jsonLdMapper)); - - var controller = new DataPlaneSignalingApiController(signalingApiTypeTransformerRegistry, - dataPlaneManager, context.getMonitor().withPrefix("SignalingAPI")); - - webService.registerResource(ApiContext.CONTROL, controller); } - } diff --git a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClient.java b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClient.java index f1a2f16ec1f..41dc1483e24 100644 --- a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClient.java +++ b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClient.java @@ -38,6 +38,7 @@ import java.io.IOException; import java.util.Optional; +import java.util.function.Supplier; import static java.lang.String.format; import static org.eclipse.edc.spi.response.ResponseStatus.FATAL_ERROR; @@ -54,15 +55,15 @@ public class DataPlaneSignalingClient implements DataPlaneClient { private final JsonLd jsonLd; private final String jsonLdScope; - private final ObjectMapper mapper; + private final Supplier objectMapperSupplier; public DataPlaneSignalingClient(ControlApiHttpClient httpClient, TypeTransformerRegistry transformerRegistry, JsonLd jsonLd, String jsonLdScope, - ObjectMapper mapper, DataPlaneInstance dataPlane) { + Supplier objectMapperSupplier, DataPlaneInstance dataPlane) { this.httpClient = httpClient; this.transformerRegistry = transformerRegistry; this.jsonLd = jsonLd; this.jsonLdScope = jsonLdScope; - this.mapper = mapper; + this.objectMapperSupplier = objectMapperSupplier; this.dataPlane = dataPlane; } @@ -131,7 +132,7 @@ private StatusResult handleStartResponse(String respons private StatusResult deserializeStartMessage(String responseBody) { try { - var jsonObject = mapper.readValue(responseBody, JsonObject.class); + var jsonObject = objectMapperSupplier.get().readValue(responseBody, JsonObject.class); var result = jsonLd.expand(jsonObject) .compose(expanded -> transformerRegistry.transform(expanded, DataFlowResponseMessage.class)); if (result.succeeded()) { @@ -151,7 +152,7 @@ private Result compact(JsonObject object) { private Result serializeMessage(Object message) { try { - return Result.success(mapper.writeValueAsString(message)); + return Result.success(objectMapperSupplier.get().writeValueAsString(message)); } catch (JsonProcessingException e) { return Result.failure(e.getMessage()); } diff --git a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientExtension.java b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientExtension.java index aa42ad92e4f..681adad988a 100644 --- a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientExtension.java +++ b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientExtension.java @@ -74,11 +74,10 @@ public DataPlaneClientFactory dataPlaneClientFactory(ServiceExtensionContext con jsonLd.registerNamespace(DSPACE_PREFIX, DSPACE_SCHEMA, CONTROL_CLIENT_SCOPE); jsonLd.registerNamespace(VOCAB, EDC_NAMESPACE, CONTROL_CLIENT_SCOPE); - var mapper = typeManager.getMapper(JSON_LD); context.getMonitor().debug(() -> "Using remote Data Plane client."); Objects.requireNonNull(httpClient, "To use remote Data Plane client, a ControlApiHttpClient instance must be registered"); var signalingApiTypeTransformerRegistry = transformerRegistry.forContext("signaling-api"); - return instance -> new DataPlaneSignalingClient(httpClient, signalingApiTypeTransformerRegistry, jsonLd, CONTROL_CLIENT_SCOPE, mapper, + return instance -> new DataPlaneSignalingClient(httpClient, signalingApiTypeTransformerRegistry, jsonLd, CONTROL_CLIENT_SCOPE, () -> typeManager.getMapper(JSON_LD), instance); } } diff --git a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTransformExtension.java b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTransformExtension.java index b237224321c..8706021b84d 100644 --- a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTransformExtension.java +++ b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/main/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTransformExtension.java @@ -22,7 +22,6 @@ import org.eclipse.edc.runtime.metamodel.annotation.Extension; import org.eclipse.edc.runtime.metamodel.annotation.Inject; import org.eclipse.edc.spi.system.ServiceExtension; -import org.eclipse.edc.spi.system.ServiceExtensionContext; import org.eclipse.edc.spi.types.TypeManager; import org.eclipse.edc.transform.spi.TypeTransformerRegistry; import org.eclipse.edc.transform.transformer.dspace.from.JsonObjectFromDataAddressDspaceTransformer; @@ -52,7 +51,7 @@ public String name() { } @Override - public void initialize(ServiceExtensionContext context) { + public void prepare() { var mapper = typeManager.getMapper(JSON_LD); var factory = Json.createBuilderFactory(Map.of()); diff --git a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/test/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTest.java b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/test/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTest.java index c506ef792f4..d22b6d05fb5 100644 --- a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/test/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTest.java +++ b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/test/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTest.java @@ -99,7 +99,7 @@ class DataPlaneSignalingClientTest { private final ControlApiHttpClient httpClient = new ControlApiHttpClientImpl(testHttpClient(), mock()); private final DataPlaneClient dataPlaneClient = new DataPlaneSignalingClient(httpClient, TRANSFORMER_REGISTRY, - JSON_LD, CONTROL_CLIENT_SCOPE, MAPPER, instance); + JSON_LD, CONTROL_CLIENT_SCOPE, () -> MAPPER, instance); @BeforeAll public static void setUp() { @@ -183,7 +183,7 @@ void verifyReturnFatalErrorIfReceiveErrorInResponse() throws JsonProcessingExcep void verifyReturnFatalErrorIfTransformFails() { var flowRequest = createDataFlowRequest(); TypeTransformerRegistry registry = mock(); - var dataPlaneClient = new DataPlaneSignalingClient(httpClient, registry, JSON_LD, CONTROL_CLIENT_SCOPE, MAPPER, instance); + var dataPlaneClient = new DataPlaneSignalingClient(httpClient, registry, JSON_LD, CONTROL_CLIENT_SCOPE, () -> MAPPER, instance); when(registry.transform(any(), any())).thenReturn(Result.failure("Transform Failure")); @@ -316,7 +316,7 @@ void shouldFail_whenConflictResponse() { @Test void verifyReturnFatalErrorIfTransformFails() { TypeTransformerRegistry registry = mock(); - var dataPlaneClient = new DataPlaneSignalingClient(httpClient, registry, JSON_LD, CONTROL_CLIENT_SCOPE, MAPPER, instance); + var dataPlaneClient = new DataPlaneSignalingClient(httpClient, registry, JSON_LD, CONTROL_CLIENT_SCOPE, () -> MAPPER, instance); when(registry.transform(any(), any())).thenReturn(Result.failure("Transform Failure")); @@ -359,7 +359,7 @@ void shouldFail_whenConflictResponse() { @Test void verifyReturnFatalErrorIfTransformFails() { TypeTransformerRegistry registry = mock(); - var dataPlaneClient = new DataPlaneSignalingClient(httpClient, registry, JSON_LD, CONTROL_CLIENT_SCOPE, MAPPER, instance); + var dataPlaneClient = new DataPlaneSignalingClient(httpClient, registry, JSON_LD, CONTROL_CLIENT_SCOPE, () -> MAPPER, instance); when(registry.transform(any(), any())).thenReturn(Result.failure("Transform Failure")); diff --git a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/test/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTransformExtensionTest.java b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/test/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTransformExtensionTest.java index 68ed2230294..b00f8771086 100644 --- a/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/test/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTransformExtensionTest.java +++ b/extensions/data-plane/data-plane-signaling/data-plane-signaling-client/src/test/java/org/eclipse/edc/connector/dataplane/client/DataPlaneSignalingClientTransformExtensionTest.java @@ -43,8 +43,8 @@ void setUp(ServiceExtensionContext context) { } @Test - void verifyTransformerRegistry(DataPlaneSignalingClientTransformExtension extension, ServiceExtensionContext context) { - extension.initialize(context); + void verifyTransformerRegistry(DataPlaneSignalingClientTransformExtension extension) { + extension.prepare(); verify(signalingRegistry).register(isA(JsonObjectFromDataFlowSuspendMessageTransformer.class)); verify(signalingRegistry).register(isA(JsonObjectFromDataFlowTerminateMessageTransformer.class));