From c95c680f27589612f9db3abe2d79989ff478fb52 Mon Sep 17 00:00:00 2001 From: Kevin_T <596823919@qq.com> Date: Wed, 1 Dec 2021 19:40:17 +0800 Subject: [PATCH] refactor: optimize code --- .../CapaConfigurationProperties.java | 54 +++++++++++++++++++ .../configstore/CapaConfigStoreBuilder.java | 2 +- .../rxcloud/capa/component/http/CapaHttp.java | 30 +++++------ ...-component-configuration-common.properties | 2 + sdk-infrastructure/pom.xml | 7 +++ .../capa/infrastructure/CapaProperties.java | 48 ++++++++++------- .../serializer/ObjectSerializer.java | 21 +++++--- .../capa/infrastructure/utils/SpiUtils.java | 1 + .../capa-infrastructure-mixer.properties | 3 +- .../capa/spi/demo/http/DemoCapaHttp.java | 17 +++--- .../resources/capa-component-log.properties | 1 + .../rxcloud/capa/spi/http/CapaHttpSpi.java | 17 +++--- .../capa/spi/http/CapaSerializeHttpSpi.java | 37 ++++++++++--- .../spi/http/CapaSerializeHttpSpiTest.java | 17 +++--- 14 files changed, 178 insertions(+), 79 deletions(-) create mode 100644 sdk-component/src/main/java/group/rxcloud/capa/component/CapaConfigurationProperties.java create mode 100644 sdk-component/src/main/resources/sample/capa-component-configuration-common.properties diff --git a/sdk-component/src/main/java/group/rxcloud/capa/component/CapaConfigurationProperties.java b/sdk-component/src/main/java/group/rxcloud/capa/component/CapaConfigurationProperties.java new file mode 100644 index 0000000..e4bdf42 --- /dev/null +++ b/sdk-component/src/main/java/group/rxcloud/capa/component/CapaConfigurationProperties.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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 group.rxcloud.capa.component; + +import group.rxcloud.capa.infrastructure.CapaProperties; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Properties; + +/** + * Capa configuration component common properties. + */ +public interface CapaConfigurationProperties { + + abstract class Settings { + + private static List storeNames = Collections.singletonList(""); + + private static final String CONFIGURATION_COMPONENT_STORE_NAMES = "CONFIGURATION_COMPONENT_STORE_NAMES"; + + static { + Properties properties = CapaProperties.COMPONENT_PROPERTIES_SUPPLIER.apply("configuration-common"); + + String storeNames = properties.getProperty(CONFIGURATION_COMPONENT_STORE_NAMES, ""); + if (storeNames != null) { + String[] split = storeNames.split(","); + Settings.storeNames = Arrays.asList((split)); + } + } + + public static List getStoreNames() { + return storeNames; + } + + private Settings() { + } + } +} diff --git a/sdk-component/src/main/java/group/rxcloud/capa/component/configstore/CapaConfigStoreBuilder.java b/sdk-component/src/main/java/group/rxcloud/capa/component/configstore/CapaConfigStoreBuilder.java index c12e3c8..3fd2c9e 100644 --- a/sdk-component/src/main/java/group/rxcloud/capa/component/configstore/CapaConfigStoreBuilder.java +++ b/sdk-component/src/main/java/group/rxcloud/capa/component/configstore/CapaConfigStoreBuilder.java @@ -81,7 +81,7 @@ public CapaConfigStore build() { * @return Instance of {@link CapaConfigStore} implementor */ private CapaConfigStore buildCapaConfigStore() { - // TODO: 2021/11/30 build multi component + // TODO: 2021/11/30 build multi component by storeName // load spi capa config store impl return CapaClassLoader.loadComponentClassObj( "configuration", diff --git a/sdk-component/src/main/java/group/rxcloud/capa/component/http/CapaHttp.java b/sdk-component/src/main/java/group/rxcloud/capa/component/http/CapaHttp.java index 65c7a72..f43a0aa 100644 --- a/sdk-component/src/main/java/group/rxcloud/capa/component/http/CapaHttp.java +++ b/sdk-component/src/main/java/group/rxcloud/capa/component/http/CapaHttp.java @@ -93,14 +93,13 @@ public CapaHttp(OkHttpClient httpClient, CapaObjectSerializer objectSerializer) * @param type The Type needed as return for the call. * @return Asynchronous response */ - public Mono> invokeApi( - String httpMethod, - String[] pathSegments, - Map> urlParameters, - Object requestData, - Map headers, - Context context, - TypeRef type) { + public Mono> invokeApi(String httpMethod, + String[] pathSegments, + Map> urlParameters, + Object requestData, + Map headers, + Context context, + TypeRef type) { // fromCallable() is needed so the invocation does not happen early, causing a hot mono. return Mono.fromCallable(() -> doInvokeApi(httpMethod, pathSegments, urlParameters, requestData, headers, context, type)) .flatMap(f -> Mono.fromFuture(f)); @@ -119,14 +118,13 @@ public Mono> invokeApi( * @param type The Type needed as return for the call. * @return CompletableFuture for Response. */ - protected abstract CompletableFuture> doInvokeApi( - String httpMethod, - String[] pathSegments, - Map> urlParameters, - Object requestData, - Map headers, - Context context, - TypeRef type); + protected abstract CompletableFuture> doInvokeApi(String httpMethod, + String[] pathSegments, + Map> urlParameters, + Object requestData, + Map headers, + Context context, + TypeRef type); /** * Shutdown call is not necessary for OkHttpClient. diff --git a/sdk-component/src/main/resources/sample/capa-component-configuration-common.properties b/sdk-component/src/main/resources/sample/capa-component-configuration-common.properties new file mode 100644 index 0000000..37b0dd6 --- /dev/null +++ b/sdk-component/src/main/resources/sample/capa-component-configuration-common.properties @@ -0,0 +1,2 @@ +# configuration component store names +CONFIGURATION_COMPONENT_STORE_NAMES=apollo,aws.appconfig \ No newline at end of file diff --git a/sdk-infrastructure/pom.xml b/sdk-infrastructure/pom.xml index 17a1891..4c17bbb 100644 --- a/sdk-infrastructure/pom.xml +++ b/sdk-infrastructure/pom.xml @@ -31,6 +31,7 @@ SDK infrastructure for Capa + 0.10.4 1.0.1-RELEASE 1.39.0 2.12.4 @@ -71,6 +72,12 @@ vrml-error ${vrml.version} + + + io.vavr + vavr + ${vavr.version} + diff --git a/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/CapaProperties.java b/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/CapaProperties.java index c47bdc0..c2a4243 100644 --- a/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/CapaProperties.java +++ b/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/CapaProperties.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; +import io.vavr.Function2; import java.io.IOException; import java.io.InputStream; @@ -36,7 +37,9 @@ import static group.rxcloud.capa.infrastructure.CapaConstants.Properties.CAPA_COMPONENT_PROPERTIES_PREFIX; import static group.rxcloud.capa.infrastructure.CapaConstants.Properties.CAPA_INFRASTRUCTURE_PROPERTIES_PREFIX; import static group.rxcloud.capa.infrastructure.CapaConstants.Properties.CAPA_PROPERTIES_SUFFIX; -import static group.rxcloud.capa.infrastructure.Module.OBJECT_MAPPER; +import static group.rxcloud.capa.infrastructure.InnerModule.FILE_CACHE_MAP; +import static group.rxcloud.capa.infrastructure.InnerModule.loadCapaConfig; +import static group.rxcloud.capa.infrastructure.InnerModule.loadCapaProperties; /** * Global properties for Capa's SDK, using Supplier so they are dynamically resolved. @@ -65,15 +68,10 @@ public abstract class CapaProperties { = () -> DEFAULT_HTTP_CLIENT_READTIMEOUTSECONDS; /** - * Capa's properties cache map. - */ - private static final Map PROPERTIES_MAP = new ConcurrentHashMap<>(); - - /** - * Capa's infrastructure properties. + * Capa's infrastructure properties supplier. */ public static final Function INFRASTRUCTURE_PROPERTIES_SUPPLIER - = (infrastructureDomain) -> (Properties) PROPERTIES_MAP.computeIfAbsent(infrastructureDomain, + = (infrastructureDomain) -> (Properties) FILE_CACHE_MAP.computeIfAbsent(infrastructureDomain, s -> { final String fileName = CAPA_INFRASTRUCTURE_PROPERTIES_PREFIX + infrastructureDomain.toLowerCase() @@ -82,10 +80,10 @@ public abstract class CapaProperties { }); /** - * Capa's component properties. + * Capa's component properties supplier. */ public static final Function COMPONENT_PROPERTIES_SUPPLIER - = (componentDomain) -> (Properties) PROPERTIES_MAP.computeIfAbsent(componentDomain, + = (componentDomain) -> (Properties) FILE_CACHE_MAP.computeIfAbsent(componentDomain, s -> { final String fileName = CAPA_COMPONENT_PROPERTIES_PREFIX + componentDomain.toLowerCase() @@ -93,7 +91,26 @@ public abstract class CapaProperties { return loadCapaProperties(fileName); }); - private static Properties loadCapaProperties(final String fileName) { + /** + * Capa's config file supplier. + */ + public static final Function2 CONFIG_FILE_SUPPLIER + = (fileName, clazz) -> FILE_CACHE_MAP.computeIfAbsent(fileName, + s -> loadCapaConfig(s, clazz)); +} + +interface InnerModule { + + /** + * Capa's file cache map. + */ + Map FILE_CACHE_MAP = new ConcurrentHashMap<>(); + + ObjectMapper OBJECT_MAPPER = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setSerializationInclusion(JsonInclude.Include.NON_NULL); + + static Properties loadCapaProperties(final String fileName) { Objects.requireNonNull(fileName, "fileName not found."); try (InputStream in = CapaProperties.class.getResourceAsStream(fileName)) { InputStreamReader inputStreamReader = new InputStreamReader(in, StandardCharsets.UTF_8); @@ -105,7 +122,7 @@ private static Properties loadCapaProperties(final String fileName) { } } - public static T loadCapaConfig(final String fileName, Class configClazz) { + static T loadCapaConfig(final String fileName, Class configClazz) { Objects.requireNonNull(fileName, "fileName not found."); try (InputStream in = configClazz.getResourceAsStream(fileName)) { InputStreamReader inputStreamReader = new InputStreamReader(in, StandardCharsets.UTF_8); @@ -117,10 +134,3 @@ public static T loadCapaConfig(final String fileName, Class configClazz) } } } - -interface Module { - - ObjectMapper OBJECT_MAPPER = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setSerializationInclusion(JsonInclude.Include.NON_NULL); -} diff --git a/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/serializer/ObjectSerializer.java b/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/serializer/ObjectSerializer.java index 28ff972..3f84b49 100644 --- a/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/serializer/ObjectSerializer.java +++ b/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/serializer/ObjectSerializer.java @@ -47,6 +47,13 @@ public class ObjectSerializer { protected ObjectSerializer() { } + /** + * Hook method for custom object mapper. + */ + protected ObjectMapper getObjectMapper() { + return OBJECT_MAPPER; + } + /** * Serializes a given state object into byte array. * @@ -74,7 +81,7 @@ public byte[] serialize(Object state) throws IOException { } // Not string, not primitive, so it is a complex type: we use JSON for that. - return OBJECT_MAPPER.writeValueAsBytes(state); + return getObjectMapper().writeValueAsBytes(state); } /** @@ -87,7 +94,7 @@ public byte[] serialize(Object state) throws IOException { * @throws IOException In case content cannot be deserialized. */ public T deserialize(byte[] content, TypeRef type) throws IOException { - return deserialize(content, OBJECT_MAPPER.constructType(type.getType())); + return deserialize(content, getObjectMapper().constructType(type.getType())); } /** @@ -100,7 +107,7 @@ public T deserialize(byte[] content, TypeRef type) throws IOException { * @throws IOException In case content cannot be deserialized. */ public T deserialize(byte[] content, Class clazz) throws IOException { - return deserialize(content, OBJECT_MAPPER.constructType(clazz)); + return deserialize(content, getObjectMapper().constructType(clazz)); } private T deserialize(byte[] content, JavaType javaType) throws IOException { @@ -138,7 +145,7 @@ private T deserialize(byte[] content, JavaType javaType) throws IOException } } - return OBJECT_MAPPER.readValue(content, javaType); + return getObjectMapper().readValue(content, javaType); } /** @@ -149,7 +156,7 @@ private T deserialize(byte[] content, JavaType javaType) throws IOException * @throws IOException In case content cannot be parsed. */ public JsonNode parseNode(byte[] content) throws IOException { - return OBJECT_MAPPER.readTree(content); + return getObjectMapper().readTree(content); } /** @@ -161,7 +168,7 @@ public JsonNode parseNode(byte[] content) throws IOException { * @return Result as corresponding type. * @throws IOException if cannot deserialize primitive time. */ - private static T deserializePrimitives(byte[] content, JavaType javaType) throws IOException { + private T deserializePrimitives(byte[] content, JavaType javaType) throws IOException { if ((content == null) || (content.length == 0)) { if (javaType.hasRawClass(boolean.class)) { return (T) Boolean.FALSE; @@ -198,6 +205,6 @@ private static T deserializePrimitives(byte[] content, JavaType javaType) th return null; } - return OBJECT_MAPPER.readValue(content, javaType); + return getObjectMapper().readValue(content, javaType); } } diff --git a/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/utils/SpiUtils.java b/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/utils/SpiUtils.java index 89b02ac..e89f426 100644 --- a/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/utils/SpiUtils.java +++ b/sdk-infrastructure/src/main/java/group/rxcloud/capa/infrastructure/utils/SpiUtils.java @@ -38,6 +38,7 @@ /** * Load class and create instance from config file. + * TODO move to {@link CapaProperties} */ public final class SpiUtils { diff --git a/sdk-infrastructure/src/main/resources/sample/capa-infrastructure-mixer.properties b/sdk-infrastructure/src/main/resources/sample/capa-infrastructure-mixer.properties index 105ef32..79fe141 100644 --- a/sdk-infrastructure/src/main/resources/sample/capa-infrastructure-mixer.properties +++ b/sdk-infrastructure/src/main/resources/sample/capa-infrastructure-mixer.properties @@ -1 +1,2 @@ -# optional \ No newline at end of file +# optional +group.rxcloud.capa.infrastructure.hook.Mixer$MixerProvider=your-spi-class-path \ No newline at end of file diff --git a/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/http/DemoCapaHttp.java b/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/http/DemoCapaHttp.java index 0f93d72..8e14a28 100644 --- a/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/http/DemoCapaHttp.java +++ b/sdk-spi-demo/src/main/java/group/rxcloud/capa/spi/demo/http/DemoCapaHttp.java @@ -48,15 +48,14 @@ public DemoCapaHttp(OkHttpClient httpClient, CapaObjectSerializer objectSerializ } @Override - protected CompletableFuture> invokeSpiApi( - String appId, - String method, - Object requestData, - String httpMethod, - Map headers, - Map> urlParameters, - TypeRef type, - RpcServiceOptions rpcServiceOptions) { + protected CompletableFuture> invokeSpiApi(String appId, + String method, + Object requestData, + String httpMethod, + Map headers, + Map> urlParameters, + TypeRef type, + RpcServiceOptions rpcServiceOptions) { DemoRpcServiceOptions demoRpcServiceOptions = (DemoRpcServiceOptions) rpcServiceOptions; logger.info("[DemoCapaHttp.invokeSpiApi] rpcServiceOptions[{}]", demoRpcServiceOptions); diff --git a/sdk-spi-demo/src/main/resources/capa-component-log.properties b/sdk-spi-demo/src/main/resources/capa-component-log.properties index 2b10f8d..795f59b 100644 --- a/sdk-spi-demo/src/main/resources/capa-component-log.properties +++ b/sdk-spi-demo/src/main/resources/capa-component-log.properties @@ -1,2 +1,3 @@ +# log component group.rxcloud.capa.component.log.agent.CapaLog4jAppenderAgent$CapaLog4jAppender=group.rxcloud.capa.spi.demo.log.DemoLog4jAppender group.rxcloud.capa.component.log.agent.CapaLogbackAppenderAgent$CapaLogbackAppender=group.rxcloud.capa.spi.demo.log.DemoLogbackAppender \ No newline at end of file diff --git a/sdk-spi/src/main/java/group/rxcloud/capa/spi/http/CapaHttpSpi.java b/sdk-spi/src/main/java/group/rxcloud/capa/spi/http/CapaHttpSpi.java index 711b514..6d37d7d 100644 --- a/sdk-spi/src/main/java/group/rxcloud/capa/spi/http/CapaHttpSpi.java +++ b/sdk-spi/src/main/java/group/rxcloud/capa/spi/http/CapaHttpSpi.java @@ -150,13 +150,12 @@ protected RpcServiceOptions getRpcServiceOptions(String appId) { * @param rpcServiceOptions the rpc service options * @return the async completable future */ - protected abstract CompletableFuture> invokeSpiApi( - String appId, - String method, - Object requestData, - String httpMethod, - Map headers, - Map> urlParameters, - TypeRef type, - RpcServiceOptions rpcServiceOptions); + protected abstract CompletableFuture> invokeSpiApi(String appId, + String method, + Object requestData, + String httpMethod, + Map headers, + Map> urlParameters, + TypeRef type, + RpcServiceOptions rpcServiceOptions); } diff --git a/sdk-spi/src/main/java/group/rxcloud/capa/spi/http/CapaSerializeHttpSpi.java b/sdk-spi/src/main/java/group/rxcloud/capa/spi/http/CapaSerializeHttpSpi.java index 1a92894..f434590 100644 --- a/sdk-spi/src/main/java/group/rxcloud/capa/spi/http/CapaSerializeHttpSpi.java +++ b/sdk-spi/src/main/java/group/rxcloud/capa/spi/http/CapaSerializeHttpSpi.java @@ -74,17 +74,33 @@ protected byte[] getRequestWithSerialize(Object requestData) { requestData, e); } throw new CapaException(CapaErrorContext.PARAMETER_RPC_REQUEST_SERIALIZE_ERROR, - "Request Type: " + requestData.getClass().getName()); + "Request Type: " + requestData.getClass().getName() + ", Error: " + e.getMessage()); } catch (Exception e) { if (logger.isWarnEnabled()) { logger.warn("[CapaSerializeHttpSpi] serialize rpc request[{}] error", requestData, e); } throw new CapaException(CapaErrorContext.PARAMETER_RPC_REQUEST_SERIALIZE_ERROR, - "Request Type: " + requestData.getClass().getName(), e); + "Request Type: " + requestData.getClass().getName() + ", Error: " + e.getMessage(), e); } } + /** + * Gets request content type. + * + * @param headers the headers with custom content type + * @return the request content type + */ + protected String getRequestContentType(Map headers) { + if (headers != null) { + String contentType = headers.get(Metadata.CONTENT_TYPE); + if (contentType != null) { + return contentType; + } + } + return this.objectSerializer.getContentType(); + } + /** * Gets request body with byte[] serialize. * @@ -93,12 +109,12 @@ protected byte[] getRequestWithSerialize(Object requestData) { * @return the request body with byte[] serialize */ protected RequestBody getRequestBodyWithSerialize(Object requestData, Map headers) { - final String contentType = headers != null - ? headers.get(Metadata.CONTENT_TYPE) - : null; + final String contentType = getRequestContentType(headers); + final MediaType mediaType = contentType == null ? MEDIA_TYPE_APPLICATION_JSON : MediaType.get(contentType); + RequestBody body; if (requestData == null) { body = mediaType.equals(MEDIA_TYPE_APPLICATION_JSON) @@ -128,6 +144,11 @@ protected Headers getRequestHeaderWithParams(Map headersParams) /** * Http async call + * + * @param the type parameter + * @param request the request + * @param type the type + * @return the completable future */ protected CompletableFuture> doAsyncInvoke0(Request request, TypeRef type) { CompletableFuture> future = new CompletableFuture<>(); @@ -149,7 +170,7 @@ protected CompletableFuture> doAsyncInvoke0(Request request, * Gets response body with byte[] deserialize. * * @param the type parameter - * @param type the type + * @param type the response type * @param httpResponse the http response * @return the response body with byte[] deserialize */ @@ -166,14 +187,14 @@ protected HttpResponse getResponseBodyWithDeserialize(TypeRef type, Ht httpResponseStatusCode, httpResponseHeaders, httpResponseBody, type, e); } throw new CapaException(CapaErrorContext.PARAMETER_RPC_RESPONSE_DESERIALIZE_ERROR, - "Response Type: " + type, e); + "Response Type: " + type.getType().getTypeName() + ", Error: " + e.getMessage(), e); } catch (Exception e) { if (logger.isWarnEnabled()) { logger.warn("[CapaSerializeHttpSpi] deserialize rpc statusCode[{}] headers[{}] response[{}] type[{}] error", httpResponseStatusCode, httpResponseHeaders, httpResponseBody, type, e); } throw new CapaException(CapaErrorContext.PARAMETER_RPC_RESPONSE_DESERIALIZE_ERROR, - "Response Type: " + type, e); + "Response Type: " + type.getType().getTypeName() + ", Error: " + e.getMessage(), e); } } diff --git a/sdk-spi/src/test/java/group/rxcloud/capa/spi/http/CapaSerializeHttpSpiTest.java b/sdk-spi/src/test/java/group/rxcloud/capa/spi/http/CapaSerializeHttpSpiTest.java index b8dafe3..5041c86 100644 --- a/sdk-spi/src/test/java/group/rxcloud/capa/spi/http/CapaSerializeHttpSpiTest.java +++ b/sdk-spi/src/test/java/group/rxcloud/capa/spi/http/CapaSerializeHttpSpiTest.java @@ -292,15 +292,14 @@ public TestCapaSerializeHttpSpi(OkHttpClient httpClient, CapaObjectSerializer ob } @Override - protected CompletableFuture> invokeSpiApi( - String appId, - String method, - Object requestData, - String httpMethod, - Map headers, - Map> urlParameters, - TypeRef type, - RpcServiceOptions rpcServiceOptions) { + protected CompletableFuture> invokeSpiApi(String appId, + String method, + Object requestData, + String httpMethod, + Map headers, + Map> urlParameters, + TypeRef type, + RpcServiceOptions rpcServiceOptions) { return CompletableFuture.supplyAsync( () -> { return new HttpResponse<>(null, null, 200);