From 9794677241adedbece5dccf0be6db6d2ba676002 Mon Sep 17 00:00:00 2001 From: Jonas Konrad Date: Wed, 10 Jan 2024 21:39:32 +0100 Subject: [PATCH] Use ObjectMapper from context (#768) --- gradle/libs.versions.toml | 4 +- .../netty/ManagedNettyHttpProvider.java | 26 ++++++++++-- .../httpclient/netty/NettyHttpClient.java | 5 +++ .../httpclient/netty/NettyHttpRequest.java | 5 +-- .../httpclient/netty/NettyHttpResponse.java | 10 +++-- .../serde/OciSdkMicronautSerializer.java | 41 +++++++++++-------- .../serde/OciSerdeConfiguration.java | 31 ++++++++++++++ .../serde/OciSerializationConfiguration.java | 32 +++++++++++++++ .../httpclient/netty/ManagedTest.java | 8 ++-- ...ityResourcePrincipalsFederationClient.java | 2 +- 10 files changed, 129 insertions(+), 35 deletions(-) create mode 100644 oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSerdeConfiguration.java create mode 100644 oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSerializationConfiguration.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 67db0dc6d..c47c7000b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -micronaut = "4.2.0" +micronaut = "4.2.2" micronaut-platform = "4.1.6" micronaut-docs = "2.0.0" fn = '1.0.180' @@ -25,7 +25,7 @@ micronaut-kotlin = "4.1.0" micronaut-micrometer = "5.2.0" micronaut-reactor = "3.1.0" micronaut-rxjava2 = "2.1.0" -micronaut-serde = "2.4.0" +micronaut-serde = "2.7.0" micronaut-servlet = "4.2.1" micronaut-sql = "5.2.0" micronaut-test = "4.1.0" diff --git a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/ManagedNettyHttpProvider.java b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/ManagedNettyHttpProvider.java index 3c9340a90..d4d7fbf5f 100644 --- a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/ManagedNettyHttpProvider.java +++ b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/ManagedNettyHttpProvider.java @@ -23,7 +23,10 @@ import io.micronaut.http.client.annotation.Client; import io.micronaut.json.JsonMapper; import io.micronaut.oraclecloud.serde.OciSdkMicronautSerializer; +import io.micronaut.oraclecloud.serde.OciSerdeConfiguration; +import io.micronaut.oraclecloud.serde.OciSerializationConfiguration; import io.micronaut.scheduling.TaskExecutors; +import io.micronaut.serde.ObjectMapper; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; @@ -47,10 +50,26 @@ public class ManagedNettyHttpProvider implements HttpProvider { final JsonMapper jsonMapper; @Inject - public ManagedNettyHttpProvider(@Client(id = SERVICE_ID) HttpClient mnHttpClient, @Named(TaskExecutors.BLOCKING) ExecutorService ioExecutor, JsonMapper jsonMapper) { + public ManagedNettyHttpProvider( + @Client(id = SERVICE_ID) HttpClient mnHttpClient, + @Named(TaskExecutors.BLOCKING) ExecutorService ioExecutor, + ObjectMapper jsonMapper, + OciSerdeConfiguration ociSerdeConfiguration, + OciSerializationConfiguration ociSerializationConfiguration + ) { this.mnHttpClient = mnHttpClient; this.ioExecutor = ioExecutor; - this.jsonMapper = jsonMapper; + this.jsonMapper = jsonMapper.cloneWithConfiguration(ociSerdeConfiguration, ociSerializationConfiguration, null); + } + + // for OKE + public ManagedNettyHttpProvider( + HttpClient mnHttpClient, + ExecutorService ioExecutor + ) { + this.mnHttpClient = mnHttpClient; + this.ioExecutor = ioExecutor; + this.jsonMapper = OciSdkMicronautSerializer.getDefaultObjectMapper(); } @Override @@ -60,7 +79,6 @@ public HttpClientBuilder newBuilder() { @Override public Serializer getSerializer() { - // todo: use serializer from context - return OciSdkMicronautSerializer.getDefaultSerializer(); + return new OciSdkMicronautSerializer(jsonMapper); } } diff --git a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpClient.java b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpClient.java index 62957d445..dfb840855 100644 --- a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpClient.java +++ b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpClient.java @@ -26,6 +26,8 @@ import io.micronaut.http.client.DefaultHttpClientConfiguration; import io.micronaut.http.client.netty.ConnectionManager; import io.micronaut.http.client.netty.DefaultHttpClient; +import io.micronaut.json.JsonMapper; +import io.micronaut.oraclecloud.serde.OciSdkMicronautSerializer; import io.netty.buffer.ByteBufAllocator; import java.io.Closeable; @@ -58,6 +60,7 @@ final class NettyHttpClient implements HttpClient { final Closeable upstreamHttpClient; final ConnectionManager connectionManager; final DefaultHttpClient.RequestKey requestKey; + final JsonMapper jsonMapper; static { ClientConfiguration cfg = ClientConfiguration.builder().build(); @@ -81,6 +84,7 @@ final class NettyHttpClient implements HttpClient { } mnClient = new DefaultHttpClient((URI) null, cfg); blockingIoExecutor = Executors.newCachedThreadPool(); + jsonMapper = OciSdkMicronautSerializer.getDefaultObjectMapper(); } else { hasContext = true; for (Map.Entry, Object> entry : builder.properties.entrySet()) { @@ -90,6 +94,7 @@ final class NettyHttpClient implements HttpClient { } mnClient = (DefaultHttpClient) builder.managedProvider.mnHttpClient; blockingIoExecutor = builder.managedProvider.ioExecutor; + jsonMapper = builder.managedProvider.jsonMapper; } upstreamHttpClient = mnClient; connectionManager = mnClient.connectionManager(); diff --git a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpRequest.java b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpRequest.java index a3e7101ef..de7bf7ee4 100644 --- a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpRequest.java +++ b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpRequest.java @@ -20,7 +20,6 @@ import com.oracle.bmc.http.client.Method; import com.oracle.bmc.http.client.RequestInterceptor; import io.micronaut.http.client.netty.ConnectionManager; -import io.micronaut.oraclecloud.serde.OciSdkMicronautSerializer; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.Unpooled; @@ -127,7 +126,7 @@ public HttpRequest body(Object body) { // anything but String String json; try { - json = OciSdkMicronautSerializer.getDefaultObjectMapper().writeValueAsString(body); + json = client.jsonMapper.writeValueAsString(body); } catch (IOException e) { throw new IllegalArgumentException("Unable to process JSON body", e); } @@ -382,7 +381,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) { skipLast = true; } } else { - future.complete(new NettyHttpResponse(response, limitedBufferingBodyHandler, undecidedBodyHandler, offloadExecutor)); + future.complete(new NettyHttpResponse(client.jsonMapper, response, limitedBufferingBodyHandler, undecidedBodyHandler, offloadExecutor)); ctx.pipeline().remove(this); } diff --git a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpResponse.java b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpResponse.java index 94d7b3cd7..cb7e1718a 100644 --- a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpResponse.java +++ b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/httpclient/netty/NettyHttpResponse.java @@ -17,7 +17,7 @@ import com.oracle.bmc.http.client.HttpResponse; import io.micronaut.core.type.Argument; -import io.micronaut.oraclecloud.serde.OciSdkMicronautSerializer; +import io.micronaut.json.JsonMapper; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufInputStream; @@ -33,12 +33,14 @@ import java.util.function.Function; final class NettyHttpResponse implements HttpResponse { + private final JsonMapper jsonMapper; private final io.netty.handler.codec.http.HttpResponse nettyResponse; private final LimitedBufferingBodyHandler limitedBufferingBodyHandler; private final UndecidedBodyHandler undecidedBodyHandler; private final Executor offloadExecutor; - NettyHttpResponse(io.netty.handler.codec.http.HttpResponse nettyResponse, LimitedBufferingBodyHandler limitedBufferingBodyHandler, UndecidedBodyHandler undecidedBodyHandler, Executor offloadExecutor) { + NettyHttpResponse(JsonMapper jsonMapper, io.netty.handler.codec.http.HttpResponse nettyResponse, LimitedBufferingBodyHandler limitedBufferingBodyHandler, UndecidedBodyHandler undecidedBodyHandler, Executor offloadExecutor) { + this.jsonMapper = jsonMapper; this.nettyResponse = nettyResponse; this.limitedBufferingBodyHandler = limitedBufferingBodyHandler; this.undecidedBodyHandler = undecidedBodyHandler; @@ -98,7 +100,7 @@ public CompletionStage body(Class type) { return null; } - return OciSdkMicronautSerializer.getDefaultObjectMapper().readValue(new ByteBufInputStream(buf), type); + return jsonMapper.readValue(new ByteBufInputStream(buf), type); } catch (IOException e) { throw new CompletionException(e); } finally { @@ -112,7 +114,7 @@ public CompletionStage> listBody(Class type) { Argument> listArgument = Argument.listOf(type); return thenApply(bodyAsBuffer(), buf -> { try { - return OciSdkMicronautSerializer.getDefaultObjectMapper().readValue(new ByteBufInputStream(buf), listArgument); + return jsonMapper.readValue(new ByteBufInputStream(buf), listArgument); } catch (IOException e) { throw new CompletionException(e); } finally { diff --git a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSdkMicronautSerializer.java b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSdkMicronautSerializer.java index 26c5102f9..5e29fa8e4 100644 --- a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSdkMicronautSerializer.java +++ b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSdkMicronautSerializer.java @@ -24,6 +24,7 @@ import com.oracle.bmc.http.internal.ResponseHelper; import com.oracle.bmc.model.RegionSchema; import io.micronaut.core.annotation.Internal; +import io.micronaut.json.JsonMapper; import io.micronaut.serde.ObjectMapper; import io.micronaut.serde.annotation.SerdeImport; import io.micronaut.serde.config.annotation.SerdeConfig; @@ -48,27 +49,13 @@ @SerdeImport(OkeResourcePrincipalSessionToken.class) public final class OciSdkMicronautSerializer implements Serializer { - private static final Map DEFAULT_MAPPER_CONFIG = Map.of( - "micronaut.serde.writeDatesAsTimestamps", false, - "micronaut.serde.write-binary-as-array", false, - "micronaut.serde.serialization.inclusion", SerdeConfig.SerInclude.NON_NULL - ); - - private static final ObjectMapper DEFAULT_MAPPER = ObjectMapper.create( - DEFAULT_MAPPER_CONFIG, - "io.micronaut.oraclecloud.serde.filter", - "io.micronaut.oraclecloud.serde.serializers" - ); - - private static final Serializer DEFAULT_SERIALIZER = new OciSdkMicronautSerializer(DEFAULT_MAPPER); - - private final ObjectMapper objectMapper; + private final JsonMapper objectMapper; /** * Create Serializer from micronaut serde {@link ObjectMapper}. * @param objectMapper the object mapper */ - public OciSdkMicronautSerializer(ObjectMapper objectMapper) { + public OciSdkMicronautSerializer(JsonMapper objectMapper) { this.objectMapper = objectMapper; } @@ -91,13 +78,31 @@ public String writeValueAsString(Object o) throws IOException { * @return The implementation of object mapper configured for oci java sdk */ public static ObjectMapper getDefaultObjectMapper() { - return DEFAULT_MAPPER; + return UnmanagedSerializerHolder.DEFAULT_MAPPER; } /** * @return The implementation of serializer configured for oci java sdk */ public static Serializer getDefaultSerializer() { - return DEFAULT_SERIALIZER; + return UnmanagedSerializerHolder.DEFAULT_SERIALIZER; + } + + private static class UnmanagedSerializerHolder { + // only initialize if necessary + + private static final Map DEFAULT_MAPPER_CONFIG = Map.of( + "micronaut.serde.writeDatesAsTimestamps", false, + "micronaut.serde.write-binary-as-array", false, + "micronaut.serde.serialization.inclusion", SerdeConfig.SerInclude.NON_NULL + ); + + private static final ObjectMapper DEFAULT_MAPPER = ObjectMapper.create( + DEFAULT_MAPPER_CONFIG, + "io.micronaut.oraclecloud.serde.filter", + "io.micronaut.oraclecloud.serde.serializers" + ); + + private static final Serializer DEFAULT_SERIALIZER = new OciSdkMicronautSerializer(DEFAULT_MAPPER); } } diff --git a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSerdeConfiguration.java b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSerdeConfiguration.java new file mode 100644 index 000000000..faca569a6 --- /dev/null +++ b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSerdeConfiguration.java @@ -0,0 +1,31 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.oraclecloud.serde; + +import io.micronaut.context.annotation.Bean; +import io.micronaut.context.annotation.ConfigurationProperties; +import io.micronaut.core.annotation.Internal; +import io.micronaut.core.bind.annotation.Bindable; +import io.micronaut.serde.config.SerdeConfiguration; + +@ConfigurationProperties("oci.serde") +@Bean(typed = OciSerdeConfiguration.class) +@Internal +public interface OciSerdeConfiguration extends SerdeConfiguration { + @Override + @Bindable(defaultValue = "false") + boolean isWriteBinaryAsArray(); +} diff --git a/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSerializationConfiguration.java b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSerializationConfiguration.java new file mode 100644 index 000000000..d9b6e5fa2 --- /dev/null +++ b/oraclecloud-httpclient-netty/src/main/java/io/micronaut/oraclecloud/serde/OciSerializationConfiguration.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017-2024 original authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micronaut.oraclecloud.serde; + +import io.micronaut.context.annotation.Bean; +import io.micronaut.context.annotation.ConfigurationProperties; +import io.micronaut.core.annotation.Internal; +import io.micronaut.core.bind.annotation.Bindable; +import io.micronaut.serde.config.SerializationConfiguration; +import io.micronaut.serde.config.annotation.SerdeConfig; + +@ConfigurationProperties("oci.serde.serialization") +@Bean(typed = OciSerializationConfiguration.class) +@Internal +public interface OciSerializationConfiguration extends SerializationConfiguration { + @Bindable(defaultValue = "NON_NULL") + @Override + SerdeConfig.SerInclude getInclusion(); +} diff --git a/oraclecloud-httpclient-netty/src/test/java/io/micronaut/oraclecloud/httpclient/netty/ManagedTest.java b/oraclecloud-httpclient-netty/src/test/java/io/micronaut/oraclecloud/httpclient/netty/ManagedTest.java index 6cebb2f31..42b3a643f 100644 --- a/oraclecloud-httpclient-netty/src/test/java/io/micronaut/oraclecloud/httpclient/netty/ManagedTest.java +++ b/oraclecloud-httpclient-netty/src/test/java/io/micronaut/oraclecloud/httpclient/netty/ManagedTest.java @@ -10,8 +10,10 @@ import io.micronaut.context.annotation.Requires; import io.micronaut.http.client.HttpClient; import io.micronaut.http.client.annotation.Client; -import io.micronaut.json.JsonMapper; +import io.micronaut.oraclecloud.serde.OciSerdeConfiguration; +import io.micronaut.oraclecloud.serde.OciSerializationConfiguration; import io.micronaut.scheduling.TaskExecutors; +import io.micronaut.serde.ObjectMapper; import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import jakarta.inject.Inject; import jakarta.inject.Named; @@ -43,8 +45,8 @@ public void managedClientUsesManagedProvider() { public static class MockProvider extends ManagedNettyHttpProvider { int buildersCreated = 0; - public MockProvider(@Client(id = SERVICE_ID) HttpClient mnHttpClient, @Named(TaskExecutors.BLOCKING) ExecutorService ioExecutor, JsonMapper jsonMapper) { - super(mnHttpClient, ioExecutor, jsonMapper); + public MockProvider(@Client(id = SERVICE_ID) HttpClient mnHttpClient, @Named(TaskExecutors.BLOCKING) ExecutorService ioExecutor, ObjectMapper jsonMapper, OciSerdeConfiguration ociSerdeConfiguration, OciSerializationConfiguration ociSerializationConfiguration) { + super(mnHttpClient, ioExecutor, jsonMapper, ociSerdeConfiguration, ociSerializationConfiguration); } @Override diff --git a/oraclecloud-oke-workload-identity/src/main/java/io/micronaut/oraclecloud/oke/workload/identity/MicronautOkeWorkloadIdentityResourcePrincipalsFederationClient.java b/oraclecloud-oke-workload-identity/src/main/java/io/micronaut/oraclecloud/oke/workload/identity/MicronautOkeWorkloadIdentityResourcePrincipalsFederationClient.java index 60af98821..f3c603aec 100644 --- a/oraclecloud-oke-workload-identity/src/main/java/io/micronaut/oraclecloud/oke/workload/identity/MicronautOkeWorkloadIdentityResourcePrincipalsFederationClient.java +++ b/oraclecloud-oke-workload-identity/src/main/java/io/micronaut/oraclecloud/oke/workload/identity/MicronautOkeWorkloadIdentityResourcePrincipalsFederationClient.java @@ -171,7 +171,7 @@ protected HttpClient makeClient(String endpoint, RequestSigner requestSigner) { return null; } - HttpClientBuilder rptBuilder = new ManagedNettyHttpProvider(defaultHttpClient(), Executors.newCachedThreadPool(), JsonMapper.createDefault()) + HttpClientBuilder rptBuilder = new ManagedNettyHttpProvider(defaultHttpClient(), Executors.newCachedThreadPool()) .newBuilder() .baseUri(URI.create(endpoint)) .registerRequestInterceptor(