Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SCB-2060]fix nocas configuration not properly handle yaml and proper… #1911

Merged
merged 1 commit into from Aug 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions demo/demo-jaxrs/jaxrs-client/pom.xml
Expand Up @@ -45,6 +45,13 @@
<groupId>org.apache.servicecomb</groupId>
<artifactId>provider-pojo</artifactId>
</dependency>
<!-- can be added in local test -->
<!-- This jar will add an environment version={project.version}, and may cause spring boot application
startup fail -->
<!-- <dependency>-->
<!-- <groupId>org.apache.servicecomb</groupId>-->
<!-- <artifactId>config-nacos</artifactId>-->
<!-- </dependency>-->
</dependencies>

<properties>
Expand Down
@@ -0,0 +1,118 @@
/*
* 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 org.apache.servicecomb.demo.jaxrs.client;

import java.util.Arrays;

import org.apache.servicecomb.config.inject.InjectProperties;
import org.apache.servicecomb.config.inject.InjectProperty;
import org.apache.servicecomb.core.BootListener;
import org.apache.servicecomb.core.SCBEngine;
import org.apache.servicecomb.demo.TestMgr;
import org.springframework.stereotype.Component;

@Component
public class TestDynamicConfig implements BootListener {

@InjectProperties(prefix = "jaxrstest.jaxrsclient")
public class Configuration {
/*
* 方法的 prefix 属性值 "override" 会覆盖标注在类定义的 @InjectProperties
* 注解的 prefix 属性值。
*
* keys属性可以为一个字符串数组,下标越小优先级越高。
*
* 这里会按照如下顺序的属性名称查找配置属性,直到找到已被配置的配置属性,则停止查找:
* 1) jaxrstest.jaxrsclient.override.high
* 2) jaxrstest.jaxrsclient.override.low
*
* 测试用例:
* jaxrstest.jaxrsclient.override.high: hello high
* jaxrstest.jaxrsclient.override.low: hello low
* 预期:
* hello high
*/
@InjectProperty(prefix = "jaxrstest.jaxrsclient.override", keys = {"high", "low"})
public String strValue;

/**
* keys支持通配符,并在可以在将配置属性注入的时候指定通配符的代入对象。
*
* 测试用例:
* jaxrstest.jaxrsclient.k.value: 3
* 预期:
* 3
*/
@InjectProperty(keys = "${key}.value")
public int intValue;

/**
* 通配符的代入对象可以是一个字符串List,优先级遵循数组元素下标越小优先级越高策略。
*
* 测试用例:
* jaxrstest.jaxrsclient.l1-1: 3.0
* jaxrstest.jaxrsclient.l1-2: 2.0
*
* 预期:
* 3.0
*/
@InjectProperty(keys = "${full-list}")
public float floatValue;

/**
* keys属性也支持多个通配符,优先级如下:首先通配符的优先级从左到右递减,
* 然后如果通配符被代入List,遵循List中元素index越小优先级越高策略。
*
* 测试用例:
* jaxrstest.jaxrsclient.low-1.a.high-1.b: 1
* jaxrstest.jaxrsclient.low-1.a.high-2.b: 2
* jaxrstest.jaxrsclient.low-2.a.high-1.b: 3
* jaxrstest.jaxrsclient.low-2.a.high-2.b: 4
* 预期:
* 1
*/
@InjectProperty(keys = "${low-list}.a.${high-list}.b")
public long longValue;

/**
* 可以通过注解的defaultValue属性指定默认值。如果字段未关联任何配置属性,
* 定义的默认值会生效,否则默认值会被覆盖。
*
* 测试用例:
* 预期:
* abc
*/
@InjectProperty(defaultValue = "abc")
public String strDef;
}

public void onAfterRegistry(BootEvent event) {
Configuration configuration = SCBEngine.getInstance().getPriorityPropertyManager()
.createConfigObject(Configuration.class,
"key", "k",
"low-list", Arrays.asList("low-1", "low-2"),
"high-list", Arrays.asList("high-1", "high-2"),
"full-list", Arrays.asList("l1-1", "l1-2")
);
TestMgr.check(configuration.strValue, "hello high");
TestMgr.check(configuration.intValue, 3);
TestMgr.check(configuration.floatValue, 3.0);
TestMgr.check(configuration.longValue, 1);
TestMgr.check(configuration.strDef, "abc");
}
}
@@ -0,0 +1,55 @@
/*
* 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 org.apache.servicecomb.demo.jaxrs.client;

import java.util.HashMap;
import java.util.Map;

import org.apache.servicecomb.core.provider.consumer.InvokerUtils;
import org.apache.servicecomb.demo.CategorizedTestCase;
import org.apache.servicecomb.demo.TestMgr;
import org.apache.servicecomb.demo.server.User;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.type.TypeReference;

@Component
public class TestInvokerUtils implements CategorizedTestCase {
private static final String SERVICE_NAME = "jaxrs";

private static final String SCHEMA_ID = "codeFirst";

public void testAllTransport() throws Exception {
testCodeFirstJaxrs();
}

// invoke CodeFirstJaxrs
private void testCodeFirstJaxrs() {
Map<String, Object> swaggerArguments = new HashMap<>();
Map<String, User> userMap = new HashMap<>();
User user = new User();
user.setName("hello");
userMap.put("user", user);
swaggerArguments.put("userMap", userMap);
TypeReference<Map<String, User>> type = new TypeReference<Map<String, User>>() {
};
Map<String, User> result = InvokerUtils.syncInvoke(SERVICE_NAME, SCHEMA_ID, "testUserMap", swaggerArguments,
type.getType());
TestMgr.check(result.get("user").getName(), userMap.get("user").getName());
}
}
Expand Up @@ -42,4 +42,30 @@ servicecomb:
sayHello:
timeout: 30000
add:
timeout: 1000
timeout: 1000

# test configurations. you can choose any implementation. default using local.

# using nacos configuration
# nacos:
# serverAddr: http://127.0.0.1:8848
# group: jaxrstest
# dataId: jaxrsclient
# namespace: public
# contentType: properties # can be properties, yaml, raw. If using raw, property [group].[dataId]=value.
# addPrefix: false # if true [group].[dataId] will added as properties/yaml items prefix. Will not influence raw.

# for integration test not install any config server
jaxrstest:
jaxrsclient:
override.high: hello high
override.low: hello low
k.value: 3
l1-1: 3.0
l1-2: 2.0
low-1.a.high-1.b: 1
low-1.a.high-2.b: 2
low-2.a.high-1.b: 3
low-2.a.high-2.b: 4

# test configurations.
Expand Up @@ -17,13 +17,11 @@

package org.apache.servicecomb.config.kie.client;

import java.io.StringReader;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
Expand All @@ -34,10 +32,9 @@
import org.apache.servicecomb.config.kie.model.KVDoc;
import org.apache.servicecomb.config.kie.model.KVResponse;
import org.apache.servicecomb.config.kie.model.ValueType;
import org.apache.servicecomb.config.parser.Parser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ByteArrayResource;

public class KieUtil {

Expand Down Expand Up @@ -109,32 +106,15 @@ public static Map<String, Object> getConfigByLabel(KVResponse resp) {
return resultMap;
}

public static Map<String, String> processValueType(KVDoc kvDoc) {
public static Map<String, Object> processValueType(KVDoc kvDoc) {
ValueType valueType = parseValueType(kvDoc.getValueType());

Properties properties = new Properties();
Map<String, String> kvMap = new HashMap<>();
try {
if (valueType == (ValueType.YAML) || valueType == (ValueType.YML)) {
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
yamlFactory.setResources(new ByteArrayResource(kvDoc.getValue().getBytes()));
properties = yamlFactory.getObject();
} else if (valueType == (ValueType.PROPERTIES)) {
properties.load(new StringReader(kvDoc.getValue()));
} else if (valueType == (ValueType.TEXT) || valueType == (ValueType.STRING)) {
kvMap.put(kvDoc.getKey(), kvDoc.getValue());
return kvMap;
} else {
// ValueType.JSON
kvMap.put(kvDoc.getKey(), kvDoc.getValue());
return kvMap;
}
kvMap = toMap(kvDoc.getKey(), properties);
return kvMap;
} catch (Exception e) {
LOGGER.error("read config failed", e);
if (valueType == (ValueType.YAML) || valueType == (ValueType.YML)) {
return Parser.findParser(Parser.CONTENT_TYPE_YAML).parse(kvDoc.getValue(), kvDoc.getKey(), true);
} else if (valueType == (ValueType.PROPERTIES)) {
return Parser.findParser(Parser.CONTENT_TYPE_PROPERTIES).parse(kvDoc.getValue(), kvDoc.getKey(), true);
} else {
return Parser.findParser(Parser.CONTENT_TYPE_RAW).parse(kvDoc.getValue(), kvDoc.getKey(), true);
}
return Collections.emptyMap();
}

private static ValueType parseValueType(String valueType) {
Expand Down
Expand Up @@ -29,7 +29,7 @@ public void test_processValueType() {
KVDoc kvDoc = new KVDoc();
kvDoc.setKey("hello");
kvDoc.setValue("world");
Map<String, String> result = KieUtil.processValueType(kvDoc);
Map<String, Object> result = KieUtil.processValueType(kvDoc);
Assert.assertEquals("world", result.get("hello"));

kvDoc.setValueType("text");
Expand Down
41 changes: 3 additions & 38 deletions dynamic-config/config-nacos/README.md
@@ -1,40 +1,5 @@
#config-nacos
How to use:
1.Download base model from http://start.servicecomb.io and add maven dependence:
# Dynamic configurations implementation with [Nacos](https://github.com/alibaba/nacos)

<dependency>
<groupId>org.apache.servicecomb</groupId>
<artifactId>config-nacos</artifactId>
<version>${project.version}</version>
</dependency>
Read [developers guide](https://docs.servicecomb.io/java-chassis/zh_CN/config/general-config/)
for details.

2.Start nacos console model(git url:https://github.com/alibaba/nacos) ,both account and password is "nacos",after that add properties(example):
Data ID: example
Group: DEFAULT_GROUP
JSON:
{
"nacos":"666"
}

3.In base model,add info in microservice.yaml:
nacos:
config:
serverAddr: 127.0.0.1:8848
dataId: example
group: DEFAULT_GROUP

4.Then add blow code and start base model,you will get properties(If properties on nacos has changed, you can also get new value):
@RestSchema(schemaId = "nacos")
@RequestMapping(path = "/")
public class NacosImpl {
/**
**get properties from nacos
*/
@GetMapping(path = "/config")
@Responsebody
public String config() throws Exception{
final String config = DynamicPropertyFactory.getInstance()
.getStringProperty("nacos","").getValue();
return JSON.toJSONString(config);
}
}
Expand Up @@ -47,16 +47,14 @@ public class NacosConfigurationSourceImpl implements ConfigCenterConfigurationSo

private List<WatchedUpdateListener> listeners = new CopyOnWriteArrayList<>();

private static final String SERVER_ADDR = "nacos.config.serverAddr";

public NacosConfigurationSourceImpl() {
}

private final UpdateHandler updateHandler = new UpdateHandler();

@Override
public boolean isValidSource(Configuration localConfiguration) {
if (localConfiguration.getProperty(SERVER_ADDR) == null) {
if (localConfiguration.getProperty(NacosConfig.SERVER_ADDR) == null) {
LOGGER.warn("Nacos configuration source is not configured!");
return false;
}
Expand Down