Skip to content

Commit

Permalink
refactor: split TypeManager interface and Jackson implementation (#4111)
Browse files Browse the repository at this point in the history
  • Loading branch information
ndr-brt authored Apr 15, 2024
1 parent e4e71b9 commit b303638
Show file tree
Hide file tree
Showing 78 changed files with 378 additions and 233 deletions.
11 changes: 6 additions & 5 deletions core/common/connector-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ dependencies {
api(project(":spi:common:transform-spi"))
api(project(":spi:common:validator-spi"))

implementation(project(":core:common:lib:http-lib"))
implementation(project(":core:common:lib:json-lib"))
implementation(project(":core:common:lib:keys-lib"))
implementation(project(":core:common:lib:policy-engine-lib"))
implementation(project(":core:common:lib:util-lib"))
implementation(project(":core:common:lib:query-lib"))
implementation(project(":core:common:lib:state-machine-lib"))
implementation(project(":core:common:lib:transform-lib"))
implementation(project(":core:common:lib:util-lib"))
implementation(project(":core:common:lib:validator-lib"))
implementation(project(":core:common:lib:state-machine-lib"))
implementation(project(":core:common:lib:query-lib"))
implementation(project(":core:common:lib:http-lib"))
implementation(project(":core:common:lib:keys-lib"))

implementation(libs.bouncyCastle.bcpkixJdk18on)
implementation(libs.nimbus.jwt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.edc.connector.core.message.RemoteMessageDispatcherRegistryImpl;
import org.eclipse.edc.connector.core.validator.DataAddressValidatorRegistryImpl;
import org.eclipse.edc.connector.core.validator.JsonObjectValidatorRegistryImpl;
import org.eclipse.edc.json.JacksonTypeManager;
import org.eclipse.edc.policy.engine.PolicyEngineImpl;
import org.eclipse.edc.policy.engine.RuleBindingRegistryImpl;
import org.eclipse.edc.policy.engine.ScopeFilter;
Expand Down Expand Up @@ -93,7 +94,7 @@ public void prepare() {
@Provider
public TypeManager typeManager() {
if (typeManager == null) {
typeManager = new TypeManager();
typeManager = new JacksonTypeManager();
}
return typeManager;
}
Expand Down
3 changes: 2 additions & 1 deletion core/common/junit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ dependencies {

api(project(":spi:common:core-spi"))
api(project(":core:common:boot"))
api(project(":core:common:lib:util-lib"))
api(project(":core:common:lib:http-lib"))
api(project(":core:common:lib:json-lib"))
api(project(":core:common:lib:util-lib"))

implementation(project(":spi:common:http-spi"))
implementation(libs.okhttp)
Expand Down
1 change: 1 addition & 0 deletions core/common/lib/http-lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ dependencies {
implementation(libs.okhttp)
implementation(libs.dnsOverHttps)

testImplementation(project(":core:common:lib:json-lib"))
testImplementation(project(":core:common:lib:util-lib"))

testFixturesImplementation(libs.mockito.core)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import okhttp3.Request;
import okhttp3.Response;
import org.eclipse.edc.http.spi.EdcHttpClient;
import org.eclipse.edc.json.JacksonTypeManager;
import org.eclipse.edc.spi.result.Result;
import org.eclipse.edc.spi.types.TypeManager;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -54,7 +55,7 @@ class EdcHttpClientImplTest {

private final int port = getFreePort();

private final TypeManager typeManager = new TypeManager();
private final TypeManager typeManager = new JacksonTypeManager();
private ClientAndServer server;

@NotNull
Expand Down
1 change: 1 addition & 0 deletions core/common/lib/json-ld-lib/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
api(libs.jakartaJson)
api(libs.jackson.datatype.jakarta.jsonp)
api(libs.titaniumJsonLd)
implementation(libs.jackson.datatype.jsr310)

implementation(project(":spi:common:core-spi"))
implementation(project(":spi:common:json-ld-spi"))
Expand Down
23 changes: 23 additions & 0 deletions core/common/lib/json-lib/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

plugins {
`java-library`
}

dependencies {
api(project(":spi:common:core-spi"))

implementation(libs.jackson.datatype.jsr310)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.edc.json;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.eclipse.edc.spi.EdcException;
import org.eclipse.edc.spi.types.TypeManager;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


public class JacksonTypeManager implements TypeManager {
final ObjectMapper defaultMapper;

/**
* Concurrent support is not needed since this map is only populated a boot, which is single-threaded.
*/
final Map<String, ObjectMapper> objectMappers = new HashMap<>();

/**
* Default constructor.
*/
public JacksonTypeManager() {
defaultMapper = new ObjectMapper();
defaultMapper.registerModule(new JavaTimeModule()); // configure ISO 8601 time de/serialization
defaultMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); // serialize dates in ISO 8601 format
defaultMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

registerContext("default", defaultMapper);
}

@Override
public ObjectMapper getMapper() {
return defaultMapper;
}

@Override
@NotNull
public ObjectMapper getMapper(String key) {
return objectMappers.computeIfAbsent(key, k -> defaultMapper.copy());
}

@Override
public void registerContext(String key, ObjectMapper mapper) {
objectMappers.put(key, mapper);
}

@Override
public void registerTypes(Class<?>... type) {
objectMappers.values().forEach(m -> m.registerSubtypes(type));
}

@Override
public void registerTypes(NamedType... type) {
objectMappers.values().forEach(m -> m.registerSubtypes(type));
}

@Override
public void registerTypes(String key, Class<?>... type) {
getMapper(key).registerSubtypes(type);
}

@Override
public void registerTypes(String key, NamedType... type) {
getMapper(key).registerSubtypes(type);
}

@Override
public <T> void registerSerializer(String key, Class<T> type, JsonSerializer<T> serializer) {
var module = new SimpleModule();
module.addSerializer(type, serializer);
getMapper(key).registerModule(module);
}

@Override
public <T> void registerSerializer(Class<T> type, JsonSerializer<T> serializer) {
var module = new SimpleModule();
module.addSerializer(type, serializer);
getMapper().registerModule(module);
}

@Override
public <T> T readValue(String input, TypeReference<T> typeReference) {
try {
return getMapper().readValue(input, typeReference);
} catch (IOException e) {
throw new EdcException(e);
}
}

@Override
public <T> T readValue(String input, Class<T> type) {
try {
return getMapper().readValue(input, type);
} catch (IOException e) {
throw new EdcException(e);
}
}

@Override
public <T> T readValue(byte[] bytes, Class<T> type) {
try {
return getMapper().readValue(bytes, type);
} catch (IOException e) {
throw new EdcException(e);
}
}

@Override
public String writeValueAsString(Object value) {
try {
return getMapper().writeValueAsString(value);
} catch (IOException e) {
throw new EdcException(e);
}
}

@Override
public byte[] writeValueAsBytes(Object value) {
try {
return getMapper().writeValueAsBytes(value);
} catch (IOException e) {
throw new EdcException(e);
}
}

@Override
public String writeValueAsString(Object value, TypeReference<?> reference) {
try {
return getMapper().writerFor(reference).writeValueAsString(value);
} catch (IOException e) {
throw new EdcException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Microsoft Corporation
* Copyright (c) 2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
Expand All @@ -8,11 +8,11 @@
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Microsoft Corporation - initial API and implementation
* Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation
*
*/

package org.eclipse.edc.spi.types;
package org.eclipse.edc.json;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
Expand All @@ -26,19 +26,20 @@

import static org.assertj.core.api.Assertions.assertThat;

class TypeManagerTest {
class JacksonTypeManagerTest {

private final JacksonTypeManager typeManager = new JacksonTypeManager();

@Test
void verifySerialization() throws JsonProcessingException {
var manager = new TypeManager();
manager.registerSerializer("foo", Bar.class, new JsonSerializer<>() {
typeManager.registerSerializer("foo", Bar.class, new JsonSerializer<>() {
@Override
public void serialize(Bar value, JsonGenerator generator, SerializerProvider serializers) throws IOException {
generator.writeString(value.toString());
}
});

var fooMapper = manager.getMapper("foo");
var fooMapper = typeManager.getMapper("foo");
assertThat(fooMapper).isNotNull();

var result = fooMapper.writeValueAsString(new Bar());
Expand All @@ -47,11 +48,10 @@ public void serialize(Bar value, JsonGenerator generator, SerializerProvider ser

@Test
void decorateExample() throws JsonProcessingException {
var manager = new TypeManager();
var fooMapper = manager.getMapper("foo");
var fooMapper = typeManager.getMapper("foo");

manager.registerSerializer("foo", Bar.class, new DecoratingSerializer<>(Bar.class));
manager.registerSerializer("foo", Baz.class, new DecoratingSerializer<>(Baz.class));
typeManager.registerSerializer("foo", Bar.class, new DecoratingSerializer<>(Bar.class));
typeManager.registerSerializer("foo", Baz.class, new DecoratingSerializer<>(Baz.class));

var baz = new Baz();
baz.setName("name");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

package org.eclipse.edc.connector.controlplane.contract.policy;

import org.eclipse.edc.json.JacksonTypeManager;
import org.eclipse.edc.policy.model.Permission;
import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.spi.types.TypeManager;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -25,7 +25,7 @@

class PolicyEqualityTest {

private final PolicyEquality comparator = new PolicyEquality(new TypeManager());
private final PolicyEquality comparator = new PolicyEquality(new JacksonTypeManager());

@Test
void emptyPoliciesAreEqual() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public abstract class JerseyIntegrationTestBase {
var config = new JettyConfiguration(null, null);
config.portMapping(new PortMapping("test", port, "/"));
jetty = new JettyService(config, monitor);
var jerseyService = new JerseyRestService(jetty, new TypeManager(), mock(JerseyConfiguration.class), monitor);
var jerseyService = new JerseyRestService(jetty, new JacksonTypeManager(), mock(JerseyConfiguration.class), monitor);
jetty.start();
jerseyService.registerResource("test", controller());
jerseyService.start();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.edc.json.JacksonTypeManager;
import org.eclipse.edc.spi.EdcException;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.types.TypeManager;
import org.eclipse.edc.web.jetty.JettyConfiguration;
import org.eclipse.edc.web.jetty.JettyService;
import org.eclipse.edc.web.jetty.PortMapping;
Expand Down Expand Up @@ -231,7 +231,7 @@ private void startJetty(PortMapping... mapping) {
var config = new JettyConfiguration(null, null);
Arrays.stream(mapping).forEach(config::portMapping);
jettyService = new JettyService(config, monitor);
jerseyRestService = new JerseyRestService(jettyService, new TypeManager(), JerseyConfiguration.Builder.newInstance().build(), monitor);
jerseyRestService = new JerseyRestService(jettyService, new JacksonTypeManager(), JerseyConfiguration.Builder.newInstance().build(), monitor);
jettyService.start();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
package org.eclipse.edc.web.jersey.testfixtures;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.edc.json.JacksonTypeManager;
import org.eclipse.edc.jsonld.util.JacksonJsonLd;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.types.TypeManager;
import org.eclipse.edc.web.jersey.JerseyConfiguration;
import org.eclipse.edc.web.jersey.JerseyRestService;
import org.eclipse.edc.web.jersey.providers.jsonld.ObjectMapperProvider;
Expand Down Expand Up @@ -46,7 +46,7 @@ final void startJetty() {
var config = new JettyConfiguration(null, null);
config.portMapping(new PortMapping("test", port, "/"));
jetty = new JettyService(config, monitor);
var jerseyService = new JerseyRestService(jetty, new TypeManager(), mock(JerseyConfiguration.class), monitor);
var jerseyService = new JerseyRestService(jetty, new JacksonTypeManager(), mock(JerseyConfiguration.class), monitor);
jerseyService.registerResource("test", new ObjectMapperProvider(objectMapper));
jerseyService.registerResource("test", controller());
var additionalResource = additionalResource();
Expand Down
Loading

0 comments on commit b303638

Please sign in to comment.