2.7.8 Rlease (#6398)

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService

* 2.7.8 service introspection (#6300)

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService

* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* 2.7.8 service introspection update (#6308)

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert the MetadataReport

* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event

* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure

Deprecated List :

- NacosMetadataReport
- ZookeeperMetadataReport

* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory

* Polish apache/dubbo#6315 : Bugfix

* Polish apache/dubbo#6315 : Bugfix

* 2.7.8 service introspection (#6317)

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert the MetadataReport

* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure

Deprecated List :

- NacosMetadataReport
- ZookeeperMetadataReport

* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory

* Polish apache/dubbo#6315 : Bugfix

* Polish apache/dubbo#6315 : Bugfix

* Polish apache/dubbo#6315 : Correct words

* Polish apache/dubbo#6333 : [Refactor] Using mandatory implementation of Service Instance registration instead of the event

* Polish apache/dubbo#6336 : [Refactor] org.apache.dubbo.metadata.ServiceNameMapping

* 2.7.8 service introspection (#6337)

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert the MetadataReport

* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure

Deprecated List :

- NacosMetadataReport
- ZookeeperMetadataReport

* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory

* Polish apache/dubbo#6315 : Bugfix

* Polish apache/dubbo#6315 : Bugfix

* Polish apache/dubbo#6315 : Correct words

* Polish apache/dubbo#6333 : [Refactor] Using mandatory implementation of Service Instance registration instead of the event

* Polish apache/dubbo#6336 : [Refactor] org.apache.dubbo.metadata.ServiceNameMapping

* Polish apache/dubbo#6170 : [Feature] Introducing the externalized configuration for ServiceNameMapping

* Polish apache/dubbo#6342 : [Enhancement] Introducing the composite ServiceNameMapping

* Refactor

* Polish apache/dubbo#6172 : [Feature] Adding the "services" attribute methods into @DubboReference

* Polish apache/dubbo#6173 : [Feature] Adding the "services" attribute into <dubbo:reference> element

* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services

* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services

* Polish apache/dubbo#6252

* Polish apache/dubbo#6356 & apache/dubbo#6171

* Polish apache/dubbo#6356 & apache/dubbo#6171

* Polish apache/dubbo#6224 : Filter chain was not invoked with local calls since v2.7.6

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* 2.7.8 service introspection (#6366)

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert the MetadataReport

* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure

Deprecated List :

- NacosMetadataReport
- ZookeeperMetadataReport

* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory

* Polish apache/dubbo#6315 : Bugfix

* Polish apache/dubbo#6315 : Bugfix

* Polish apache/dubbo#6315 : Correct words

* Polish apache/dubbo#6333 : [Refactor] Using mandatory implementation of Service Instance registration instead of the event

* Polish apache/dubbo#6336 : [Refactor] org.apache.dubbo.metadata.ServiceNameMapping

* Polish apache/dubbo#6170 : [Feature] Introducing the externalized configuration for ServiceNameMapping

* Polish apache/dubbo#6342 : [Enhancement] Introducing the composite ServiceNameMapping

* Refactor

* Polish apache/dubbo#6172 : [Feature] Adding the "services" attribute methods into @DubboReference

* Polish apache/dubbo#6173 : [Feature] Adding the "services" attribute into <dubbo:reference> element

* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services

* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services

* Polish apache/dubbo#6252

* Polish apache/dubbo#6356 & apache/dubbo#6171

* Polish apache/dubbo#6356 & apache/dubbo#6171

* Polish apache/dubbo#6224 : Filter chain was not invoked with local calls since v2.7.6

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : Adding META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* 2.7.8 Test Cases (#6384)

* Polish apache/dubbo#6152

* Polish apache/dubbo#6174 : [Enhancement] Registering the common beans for Spring XML meta-configuration

* Polish apache/dubbo#6174 : Fixing the test-cases

* Polish apache/dubbo#6174 : Fixing the test-cases

* Add the test-case for multiple services with MethodConfigs

* Fixed the test-cases

* 2.7.8 Dev (#6386)

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection

* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"

This reverts commit 91989cae50.

* Revert the MetadataReport

* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug

* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure

Deprecated List :

- NacosMetadataReport
- ZookeeperMetadataReport

* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration

* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory

* Polish apache/dubbo#6315 : Bugfix

* Polish apache/dubbo#6315 : Bugfix

* Polish apache/dubbo#6315 : Correct words

* sync wait netty server to finish shutdown (#6281)

* Polish apache/dubbo#6333 : [Refactor] Using mandatory implementation of Service Instance registration instead of the event

* maybe we can remove null judge in this case (#6321)

* update

* update

* Polish apache/dubbo#6336 : [Refactor] org.apache.dubbo.metadata.ServiceNameMapping

* Polish apache/dubbo#6170 : [Feature] Introducing the externalized configuration for ServiceNameMapping

* Polish apache/dubbo#6342 : [Enhancement] Introducing the composite ServiceNameMapping

* Refactor

* fix method name typo in JValidator.java (#6344)

* [Dubbo-6340]fix application cannot exit when use consul registry (#6341)

* fix application cannot exit when use consul registry

* make consul registry suppor ACL (#6313)

* make consul registry suppor ACL

* Polish apache/dubbo#6172 : [Feature] Adding the "services" attribute methods into @DubboReference

* Polish apache/dubbo#6173 : [Feature] Adding the "services" attribute into <dubbo:reference> element

* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services

* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services

* fix publish null value when use consul config center (#6351)

* fix publish null value when use consul config center

* Polish apache/dubbo#6252

* Polish apache/dubbo#6356 & apache/dubbo#6171

* Polish apache/dubbo#6356 & apache/dubbo#6171

* Polish apache/dubbo#6224 : Filter chain was not invoked with local calls since v2.7.6

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : Adding META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter

* fix the priority of ListenableRouter were not effective (#6148)

fixes #4822

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* when the url is generic, the log level should be info (#6363)

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* fix NPE when check=false is set and provider is empty. (#6376)

fixes #6228

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* fix #6306.  support TypeBuilder sort (#6365)

* fix #6306. support TypeBuilder sort

* fix #6306. support TypeBuilder sort

* fix #6306. support TypeBuilder sort

* remove unused import

* add license for test file

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* enhance ClusterInvoker & ExtensionLoader (#6343)

- Introduce ClusterInvoker to better support multiple registries subscription
- Wrapper sort and enable/disable
- some small fixes

* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring

* Fixed the test-cases

Co-authored-by: tswstarplanet <tswstarplanet@apache.org>
Co-authored-by: Nine <nine.yang.coding@gmail.com>
Co-authored-by: 陈哈哈 <chenyongjia365@outlook.com>
Co-authored-by: luoning810 <18311333766@163.com>
Co-authored-by: cvictory <shenglicao2@gmail.com>
Co-authored-by: ken.lj <ken.lj.hz@gmail.com>

* Fixes the issue of merging code in Github

* Polish apache/dubbo#6389 : [Issue] Resolving the issues with ConsulServiceDiscovery

* Fixes the test-cases

* Fixes the test-cases

* Fixes the test-cases

Co-authored-by: tswstarplanet <tswstarplanet@apache.org>
Co-authored-by: Nine <nine.yang.coding@gmail.com>
Co-authored-by: 陈哈哈 <chenyongjia365@outlook.com>
Co-authored-by: luoning810 <18311333766@163.com>
Co-authored-by: cvictory <shenglicao2@gmail.com>
Co-authored-by: ken.lj <ken.lj.hz@gmail.com>
This commit is contained in:
Mercy Ma 2020-07-02 17:08:09 +08:00 committed by GitHub
parent 51361d535d
commit 4aaaea43ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
193 changed files with 6868 additions and 3160 deletions

View File

@ -981,6 +981,14 @@
</resource>
</transformer>
<!-- @since 2.7.8 -->
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>
META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
</resource>
</transformer>
</transformers>
<filters>
<filter>

View File

@ -27,9 +27,9 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
/**
* Configurator. (SPI, Prototype, ThreadSafe)

View File

@ -35,10 +35,12 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
@ -55,6 +57,8 @@ import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.common.convert.Converter.convertIfPossible;
import static org.apache.dubbo.common.utils.StringUtils.isBlank;
/**
* URL - Uniform Resource Locator (Immutable, ThreadSafe)
@ -566,6 +570,24 @@ class URL implements Serializable {
return parameters;
}
/**
* Get the parameters to be selected(filtered)
*
* @param nameToSelect the {@link Predicate} to select the parameter name
* @return non-null {@link Map}
* @since 2.7.8
*/
public Map<String, String> getParameters(Predicate<String> nameToSelect) {
Map<String, String> selectedParameters = new LinkedHashMap<>();
for (Map.Entry<String, String> entry : getParameters().entrySet()) {
String name = entry.getKey();
if (nameToSelect.test(name)) {
selectedParameters.put(name, entry.getValue());
}
}
return Collections.unmodifiableMap(selectedParameters);
}
public Map<String, Map<String, String>> getMethodParameters() {
return methodParameters;
}
@ -601,6 +623,41 @@ class URL implements Serializable {
return Arrays.asList(strArray);
}
/**
* Get parameter
*
* @param key the key of parameter
* @param valueType the type of parameter value
* @param <T> the type of parameter value
* @return get the parameter if present, or <code>null</code>
* @since 2.7.8
*/
public <T> T getParameter(String key, Class<T> valueType) {
return getParameter(key, valueType, null);
}
/**
* Get parameter
*
* @param key the key of parameter
* @param valueType the type of parameter value
* @param defaultValue the default value if parameter is absent
* @param <T> the type of parameter value
* @return get the parameter if present, or <code>defaultValue</code> will be used.
* @since 2.7.8
*/
public <T> T getParameter(String key, Class<T> valueType, T defaultValue) {
String value = getParameter(key);
T result = null;
if (!isBlank(value)) {
result = convertIfPossible(value, valueType);
}
if (result == null) {
result = defaultValue;
}
return result;
}
private Map<String, Number> getNumbers() {
// concurrent initialization is tolerant
if (numbers == null) {
@ -1415,7 +1472,7 @@ class URL implements Serializable {
private void append(StringBuilder target, String parameterName, boolean first) {
String parameterValue = this.getParameter(parameterName);
if (!StringUtils.isBlank(parameterValue)) {
if (!isBlank(parameterValue)) {
if (!first) {
target.append(":");
}

View File

@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.NamedThreadFactory;
import org.apache.dubbo.common.utils.StringUtils;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
@ -27,6 +28,9 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
/**
* The abstract implementation of {@link DynamicConfiguration}
*
@ -47,6 +51,20 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
*/
public static final String THREAD_POOL_KEEP_ALIVE_TIME_PARAM_NAME = PARAM_NAME_PREFIX + "thread-pool.keep-alive-time";
/**
* The parameter name of group for config-center
*
* @since 2.7.8
*/
public static final String GROUP_PARAM_NAME = PARAM_NAME_PREFIX + GROUP_KEY;
/**
* The parameter name of timeout for config-center
*
* @since 2.7.8
*/
public static final String TIMEOUT_PARAM_NAME = PARAM_NAME_PREFIX + TIMEOUT_KEY;
public static final int DEFAULT_THREAD_POOL_SIZE = 1;
/**
@ -64,28 +82,31 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
*/
private final ThreadPoolExecutor workersThreadPool;
public AbstractDynamicConfiguration() {
this(DEFAULT_THREAD_POOL_PREFIX, DEFAULT_THREAD_POOL_SIZE, DEFAULT_THREAD_POOL_KEEP_ALIVE_TIME);
}
private final String group;
private final long timeout;
public AbstractDynamicConfiguration(URL url) {
this(getThreadPoolPrefixName(url), getThreadPoolSize(url), getThreadPoolKeepAliveTime(url));
this(getThreadPoolPrefixName(url), getThreadPoolSize(url), getThreadPoolKeepAliveTime(url), getGroup(url),
getTimeout(url));
}
public AbstractDynamicConfiguration(String threadPoolPrefixName,
int threadPoolSize,
long keepAliveTime) {
long keepAliveTime,
String group,
long timeout) {
this.workersThreadPool = initWorkersThreadPool(threadPoolPrefixName, threadPoolSize, keepAliveTime);
this.group = group;
this.timeout = timeout;
}
@Override
public void addListener(String key, String group, ConfigurationListener listener) {
}
@Override
public void removeListener(String key, String group, ConfigurationListener listener) {
}
@Override
@ -107,6 +128,29 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
}
}
@Override
public boolean removeConfig(String key, String group) {
return execute(() -> doRemoveConfig(key, group), -1L);
}
/**
* @return the default group
* @since 2.7.8
*/
@Override
public String getDefaultGroup() {
return getGroup();
}
/**
* @return the default timeout
* @since 2.7.8
*/
@Override
public long getDefaultTimeout() {
return getTimeout();
}
/**
* Get the content of configuration in the specified key and group
*
@ -124,6 +168,17 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
*/
protected abstract void doClose() throws Exception;
/**
* Remove the config in the specified key and group
*
* @param key the key
* @param group the group
* @return If successful, return <code>true</code>, or <code>false</code>
* @throws Exception
* @since 2.7.8
*/
protected abstract boolean doRemoveConfig(String key, String group) throws Exception;
/**
* Executes the {@link Runnable} with the specified timeout
*
@ -181,7 +236,7 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
int threadPoolSize,
long keepAliveTime) {
return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, keepAliveTime,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory(threadPoolPrefixName));
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory(threadPoolPrefixName, true));
}
protected static String getThreadPoolPrefixName(URL url) {
@ -216,4 +271,36 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
}
return defaultValue;
}
protected String getGroup() {
return group;
}
protected long getTimeout() {
return timeout;
}
/**
* Get the group from {@link URL the specified connection URL}
*
* @param url {@link URL the specified connection URL}
* @return non-null
* @since 2.7.8
*/
protected static String getGroup(URL url) {
String group = getParameter(url, GROUP_PARAM_NAME, null);
return StringUtils.isBlank(group) ? getParameter(url, GROUP_KEY, DEFAULT_GROUP) : group;
}
/**
* Get the timeout from {@link URL the specified connection URL}
*
* @param url {@link URL the specified connection URL}
* @return non-null
* @since 2.7.8
*/
protected static long getTimeout(URL url) {
return getParameter(url, TIMEOUT_PARAM_NAME, -1L);
}
}

View File

@ -35,7 +35,7 @@ public abstract class AbstractDynamicConfigurationFactory implements DynamicConf
@Override
public final DynamicConfiguration getDynamicConfiguration(URL url) {
String key = url == null ? DEFAULT_KEY : url.getAddress();
String key = url == null ? DEFAULT_KEY : url.toServiceString();
return dynamicConfigurations.computeIfAbsent(key, k -> createDynamicConfiguration(url));
}

View File

@ -232,4 +232,14 @@ public interface DynamicConfiguration extends Configuration, AutoCloseable {
static String getRuleKey(URL url) {
return url.getColonSeparatedKey();
}
/**
* @param key the key to represent a configuration
* @param group the group where the key belongs to
* @return <code>true</code> if success, or <code>false</code>
* @since 2.7.8
*/
default boolean removeConfig(String key, String group) {
return true;
}
}

View File

@ -0,0 +1,171 @@
/*
* 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.dubbo.common.config.configcenter;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration;
import org.apache.dubbo.common.utils.PathUtils;
import org.apache.dubbo.common.utils.StringUtils;
import java.util.Collection;
import java.util.SortedSet;
import java.util.TreeSet;
import static java.util.Collections.emptySortedSet;
import static java.util.Collections.unmodifiableSortedSet;
import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
import static org.apache.dubbo.common.utils.PathUtils.buildPath;
/**
* An abstract implementation of {@link DynamicConfiguration} is like "tree-structure" path :
* <ul>
* <li>{@link FileSystemDynamicConfiguration "file"}</li>
* <li>{@link org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration "zookeeper"}</li>
* <li>{@link org.apache.dubbo.configcenter.consul.ConsulDynamicConfiguration "consul"}</li>
* </ul>
*
* @see DynamicConfiguration
* @see AbstractDynamicConfiguration
* @since 2.7.8
*/
public abstract class TreePathDynamicConfiguration extends AbstractDynamicConfiguration {
/**
* The parameter name of URL for the config base path
*/
public static final String CONFIG_BASE_PATH_PARAM_NAME = PARAM_NAME_PREFIX + "base-path";
/**
* The default value of parameter of URL for the config base path
*/
public static final String DEFAULT_CONFIG_BASE_PATH = "/config";
private final String rootPath;
public TreePathDynamicConfiguration(URL url) {
super(url);
this.rootPath = getRootPath(url);
}
public TreePathDynamicConfiguration(String rootPath,
String threadPoolPrefixName,
int threadPoolSize,
long keepAliveTime,
String group,
long timeout) {
super(threadPoolPrefixName, threadPoolSize, keepAliveTime, group, timeout);
this.rootPath = rootPath;
}
@Override
protected final String doGetConfig(String key, String group) throws Exception {
String pathKey = buildPathKey(group, key);
return doGetConfig(pathKey);
}
@Override
public final boolean publishConfig(String key, String group, String content) {
String pathKey = buildPathKey(group, key);
return execute(() -> doPublishConfig(pathKey, content), getDefaultTimeout());
}
@Override
protected final boolean doRemoveConfig(String key, String group) throws Exception {
String pathKey = buildPathKey(group, key);
return doRemoveConfig(pathKey);
}
@Override
public final void addListener(String key, String group, ConfigurationListener listener) {
String pathKey = buildPathKey(group, key);
doAddListener(pathKey, listener);
}
@Override
public final void removeListener(String key, String group, ConfigurationListener listener) {
String pathKey = buildPathKey(group, key);
doRemoveListener(pathKey, listener);
}
@Override
public final SortedSet<String> getConfigKeys(String group) throws UnsupportedOperationException {
String groupPath = buildGroupPath(group);
Collection<String> configKeys = doGetConfigKeys(groupPath);
return isEmpty(configKeys) ? emptySortedSet() : unmodifiableSortedSet(new TreeSet<>(configKeys));
}
protected abstract boolean doPublishConfig(String pathKey, String content) throws Exception;
protected abstract String doGetConfig(String pathKey) throws Exception;
protected abstract boolean doRemoveConfig(String pathKey) throws Exception;
protected abstract Collection<String> doGetConfigKeys(String groupPath);
protected abstract void doAddListener(String pathKey, ConfigurationListener listener);
protected abstract void doRemoveListener(String pathKey, ConfigurationListener listener);
protected String buildGroupPath(String group) {
return buildPath(rootPath, group);
}
protected String buildPathKey(String group, String key) {
return buildPath(buildGroupPath(group), key);
}
/**
* Get the root path from the specified {@link URL connection URl}
*
* @param url the specified {@link URL connection URl}
* @return non-null
*/
protected String getRootPath(URL url) {
String rootPath = PATH_SEPARATOR + getConfigNamespace(url) + getConfigBasePath(url);
rootPath = PathUtils.normalize(rootPath);
if (rootPath.endsWith(PATH_SEPARATOR)) {
rootPath = rootPath.substring(0, rootPath.length() - 1);
}
return rootPath;
}
/**
* Get the namespace from the specified {@link URL connection URl}
*
* @param url the specified {@link URL connection URl}
* @return non-null
*/
protected String getConfigNamespace(URL url) {
return url.getParameter(CONFIG_NAMESPACE_KEY, DEFAULT_GROUP);
}
/**
* Get the config base path from the specified {@link URL connection URl}
*
* @param url the specified {@link URL connection URl}
* @return non-null
*/
protected String getConfigBasePath(URL url) {
String configBasePath = url.getParameter(CONFIG_BASE_PATH_PARAM_NAME, DEFAULT_CONFIG_BASE_PATH);
if (StringUtils.isNotEmpty(configBasePath) && !configBasePath.startsWith(PATH_SEPARATOR)) {
configBasePath = PATH_SEPARATOR + configBasePath;
}
return configBasePath;
}
}

View File

@ -17,13 +17,14 @@
package org.apache.dubbo.common.config.configcenter.file;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration;
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.common.config.configcenter.TreePathDynamicConfiguration;
import org.apache.dubbo.common.function.ThrowableConsumer;
import org.apache.dubbo.common.function.ThrowableFunction;
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.utils.NamedThreadFactory;
import org.apache.dubbo.common.utils.StringUtils;
@ -39,6 +40,7 @@ import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
@ -48,7 +50,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.SynchronousQueue;
@ -67,14 +68,13 @@ import static java.util.Collections.unmodifiableMap;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.dubbo.common.utils.StringUtils.isBlank;
/**
* File-System based {@link DynamicConfiguration} implementation
*
* @since 2.7.5
*/
public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration {
public class FileSystemDynamicConfiguration extends TreePathDynamicConfiguration {
public static final String CONFIG_CENTER_DIR_PARAM_NAME = PARAM_NAME_PREFIX + "dir";
@ -147,6 +147,7 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
MODIFIERS = initWatchEventModifiers();
DELAY = initDelay(MODIFIERS);
WATCH_EVENTS_LOOP_THREAD_POOL = newWatchEventsLoopThreadPool();
registerDubboShutdownHook();
}
/**
@ -193,7 +194,7 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
String threadPoolPrefixName,
int threadPoolSize,
long keepAliveTime) {
super(threadPoolPrefixName, threadPoolSize, keepAliveTime);
super(rootDirectory.getAbsolutePath(), threadPoolPrefixName, threadPoolSize, keepAliveTime, DEFAULT_GROUP, -1L);
this.rootDirectory = rootDirectory;
this.encoding = encoding;
this.processingDirectories = initProcessingDirectories();
@ -209,47 +210,13 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
return isBasedPoolingWatchService() ? new LinkedHashSet<>() : emptySet();
}
@Override
public void addListener(String key, String group, ConfigurationListener listener) {
doInListener(key, group, (configFilePath, listeners) -> {
if (listeners.isEmpty()) { // If no element, it indicates watchService was registered before
ThrowableConsumer.execute(configFilePath, configFile -> {
FileUtils.forceMkdirParent(configFile);
// A rootDirectory to be watched
File configDirectory = configFile.getParentFile();
if (configDirectory != null) {
// Register the configDirectory
configDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS, MODIFIERS);
}
});
}
// Add into cache
listeners.add(listener);
});
}
@Override
public void removeListener(String key, String group, ConfigurationListener listener) {
doInListener(key, group, (file, listeners) -> {
// Remove into cache
listeners.remove(listener);
});
}
public File groupDirectory(String group) {
String actualGroup = isBlank(group) ? DEFAULT_GROUP : group;
return new File(rootDirectory, actualGroup);
}
public File configFile(String key, String group) {
return new File(groupDirectory(group), key);
return new File(buildPathKey(group, key));
}
private void doInListener(String key, String group, BiConsumer<File, List<ConfigurationListener>> consumer) {
private void doInListener(String configFilePath, BiConsumer<File, List<ConfigurationListener>> consumer) {
watchService.ifPresent(watchService -> {
File configFile = configFile(key, group);
File configFile = new File(configFilePath);
executeMutually(configFile.getParentFile(), () -> {
// process the WatchEvents if not start
if (!isProcessingWatchEvents()) {
@ -265,6 +232,24 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
});
}
/**
* Register the Dubbo ShutdownHook
*
* @since 2.7.8
*/
private static void registerDubboShutdownHook() {
ShutdownHookCallbacks.INSTANCE.addCallback(() -> {
watchService.ifPresent(w -> {
try {
w.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
});
getWatchEventsLoopThreadPool().shutdown();
});
}
private static boolean isProcessingWatchEvents() {
return getWatchEventsLoopThreadPool().getActiveCount() > 0;
}
@ -359,47 +344,78 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
}
@Override
public boolean publishConfig(String key, String group, String content) {
return delay(key, group, configFile -> {
protected boolean doPublishConfig(String pathKey, String content) throws Exception {
return delay(pathKey, configFile -> {
FileUtils.write(configFile, content, getEncoding());
return true;
});
}
@Override
public SortedSet<String> getConfigKeys(String group) {
File[] files = groupDirectory(group).listFiles(File::isFile);
protected String doGetConfig(String pathKey) throws Exception {
File configFile = new File(pathKey);
return getConfig(configFile);
}
@Override
protected boolean doRemoveConfig(String pathKey) throws Exception {
delay(pathKey, configFile -> {
String content = getConfig(configFile);
FileUtils.deleteQuietly(configFile);
return content;
});
return true;
}
@Override
protected Collection<String> doGetConfigKeys(String groupPath) {
File[] files = new File(groupPath).listFiles(File::isFile);
if (files == null) {
return new TreeSet<>();
} else {
return Stream.of(files)
.map(File::getName)
.collect(TreeSet::new, Set::add, Set::addAll);
.collect(Collectors.toList());
}
}
public String removeConfig(String key, String group) {
return delay(key, group, configFile -> {
@Override
protected void doAddListener(String pathKey, ConfigurationListener listener) {
doInListener(pathKey, (configFilePath, listeners) -> {
if (listeners.isEmpty()) { // If no element, it indicates watchService was registered before
ThrowableConsumer.execute(configFilePath, configFile -> {
FileUtils.forceMkdirParent(configFile);
// A rootDirectory to be watched
File configDirectory = configFile.getParentFile();
if (configDirectory != null) {
// Register the configDirectory
configDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS, MODIFIERS);
}
});
}
// Add into cache
listeners.add(listener);
});
}
String content = getConfig(configFile);
FileUtils.deleteQuietly(configFile);
return content;
@Override
protected void doRemoveListener(String pathKey, ConfigurationListener listener) {
doInListener(pathKey, (file, listeners) -> {
// Remove into cache
listeners.remove(listener);
});
}
/**
* Delay action for {@link #configFile(String, String) config file}
*
* @param key the key to represent a configuration
* @param group the group where the key belongs to
* @param function the customized {@link Function function} with {@link File}
* @param <V> the computed value
* @param configFilePath the key to represent a configuration
* @param function the customized {@link Function function} with {@link File}
* @param <V> the computed value
* @return
*/
protected <V> V delay(String key, String group, ThrowableFunction<File, V> function) {
File configFile = configFile(key, group);
protected <V> V delay(String configFilePath, ThrowableFunction<File, V> function) {
File configFile = new File(configFilePath);
// Must be based on PoolingWatchService and has listeners under config file
if (isBasedPoolingWatchService()) {
File configDirectory = configFile.getParentFile();
@ -410,8 +426,8 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
// wait for delay in seconds
long timeout = SECONDS.toMillis(delay);
if (logger.isDebugEnabled()) {
logger.debug(format("The config[key : %s, group : %s] is about to delay in %d ms.",
key, group, timeout));
logger.debug(format("The config[path : %s] is about to delay in %d ms.",
configFilePath, timeout));
}
configDirectory.wait(timeout);
}
@ -439,9 +455,9 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
}
/**
* Is processing on {@link #groupDirectory(String) config rootDirectory}
* Is processing on {@link #buildGroupPath(String) config rootDirectory}
*
* @param configDirectory {@link #groupDirectory(String) config rootDirectory}
* @param configDirectory {@link #buildGroupPath(String) config rootDirectory}
* @return if processing , return <code>true</code>, or <code>false</code>
*/
private boolean isProcessing(File configDirectory) {
@ -459,12 +475,6 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
.collect(Collectors.toSet());
}
@Override
protected String doGetConfig(String key, String group) throws Exception {
File configFile = configFile(key, group);
return getConfig(configFile);
}
protected String getConfig(File configFile) {
return ThrowableFunction.execute(configFile,
file -> canRead(configFile) ? readFileToString(configFile, getEncoding()) : null);

View File

@ -20,6 +20,7 @@ package org.apache.dubbo.common.constants;
import org.apache.dubbo.common.URL;
import java.net.NetworkInterface;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
@ -44,6 +45,11 @@ public interface CommonConstants {
String ANY_VALUE = "*";
/**
* @since 2.7.8
*/
char COMMA_SEPARATOR_CHAR = ',';
String COMMA_SEPARATOR = ",";
String DOT_SEPARATOR = ".";
@ -187,6 +193,14 @@ public interface CommonConstants {
String REMOTE_METADATA_STORAGE_TYPE = "remote";
/**
* The composite metadata storage type includes {@link #DEFAULT_METADATA_STORAGE_TYPE "local"} and
* {@link #REMOTE_METADATA_STORAGE_TYPE "remote"}.
*
* @since 2.7.8
*/
String COMPOSITE_METADATA_STORAGE_TYPE = "composite";
/**
* Consumer side 's proxy class
*/
@ -315,4 +329,19 @@ public interface CommonConstants {
String SSL_ENABLED_KEY = "ssl-enabled";
/**
* The parameter key for the class path of the ServiceNameMapping {@link Properties} file
*
* @since 2.7.8
*/
String SERVICE_NAME_MAPPING_PROPERTIES_FILE_KEY = "service-name-mapping.properties-path";
/**
* The default class path of the ServiceNameMapping {@link Properties} file
*
* @since 2.7.8
*/
String DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH = "META-INF/dubbo/service-name-mapping.properties";
}

View File

@ -76,6 +76,8 @@ public interface RegistryConstants {
/**
* The parameter key of the subscribed service names for Service-Oriented Registry
* <p>
* If there is a multiple-values, the "comma" is the separator.
*
* @since 2.7.5
*/

View File

@ -88,4 +88,21 @@ public interface Converter<S, T> extends Prioritized {
.findFirst()
.orElse(null);
}
/**
* Convert the value of source to target-type value if possible
*
* @param source the value of source
* @param targetType the target type
* @param <T> the target type
* @return <code>null</code> if can't be converted
* @since 2.7.8
*/
static <T> T convertIfPossible(Object source, Class<T> targetType) {
Converter converter = getConverter(source.getClass(), targetType);
if (converter != null) {
return (T) converter.convert(source);
}
return null;
}
}

View File

@ -16,11 +16,13 @@
*/
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.lang.Prioritized;
import java.util.Collection;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
/**
@ -61,4 +63,30 @@ public interface MultiValueConverter<S> extends Prioritized {
return findActualTypeArgument(getClass(), MultiValueConverter.class, 0);
}
/**
* Find the {@link MultiValueConverter} instance from {@link ExtensionLoader} with the specified source and target type
*
* @param sourceType the source type
* @param targetType the target type
* @return <code>null</code> if not found
* @see ExtensionLoader#getSupportedExtensionInstances()
* @since 2.7.8
*/
static MultiValueConverter<?> find(Class<?> sourceType, Class<?> targetType) {
return getExtensionLoader(MultiValueConverter.class)
.getSupportedExtensionInstances()
.stream()
.filter(converter -> converter.accept(sourceType, targetType))
.findFirst()
.orElse(null);
}
static <T> T convertIfPossible(Object source, Class<?> multiValueType, Class<?> elementType) {
Class<?> sourceType = source.getClass();
MultiValueConverter converter = find(sourceType, multiValueType);
if (converter != null) {
return (T) converter.convert(source, multiValueType, elementType);
}
return null;
}
}

View File

@ -63,7 +63,12 @@ public interface PathUtils {
if (index > -1) {
normalizedPath = normalizedPath.substring(0, index);
}
return replace(normalizedPath, "//", "/");
while (normalizedPath.contains("//")) {
normalizedPath = replace(normalizedPath, "//", "/");
}
return normalizedPath;
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.dubbo.common.utils;
import java.lang.reflect.Field;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.lang.reflect.Modifier.isFinal;
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
import static org.apache.dubbo.common.utils.FieldUtils.getFieldValue;
/**
* The constant field value {@link Predicate} for the specified {@link Class}
*
* @see Predicate
* @since 2.7.8
*/
public class StringConstantFieldValuePredicate implements Predicate<String> {
private final Set<String> constantFieldValues;
public StringConstantFieldValuePredicate(Class<?> targetClass) {
this.constantFieldValues = getConstantFieldValues(targetClass);
}
public static Predicate<String> of(Class<?> targetClass) {
return new StringConstantFieldValuePredicate(targetClass);
}
private Set<String> getConstantFieldValues(Class<?> targetClass) {
return Stream.of(targetClass.getFields())
.filter(f -> isStatic(f.getModifiers())) // static
.filter(f -> isPublic(f.getModifiers())) // public
.filter(f -> isFinal(f.getModifiers())) // final
.map(this::getConstantValue)
.filter(v -> v instanceof String) // filters String type
.map(String.class::cast) // Casts String type
.collect(Collectors.toSet());
}
@Override
public boolean test(String s) {
return constantFieldValues.contains(s);
}
private Object getConstantValue(Field field) {
return getFieldValue(null, field);
}
}

View File

@ -28,13 +28,17 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.String.valueOf;
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableSet;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.DOT_REGEX;
@ -699,6 +703,45 @@ public final class StringUtils {
return splitToList0(str, ch);
}
/**
* Split the specified value to be a {@link Set}
*
* @param value the content to be split
* @param separatorChar a char to separate
* @return non-null read-only {@link Set}
* @since 2.7.8
*/
public static Set<String> splitToSet(String value, char separatorChar) {
return splitToSet(value, separatorChar, false);
}
/**
* Split the specified value to be a {@link Set}
*
* @param value the content to be split
* @param separatorChar a char to separate
* @param trimElements require to trim the elements or not
* @return non-null read-only {@link Set}
* @since 2.7.8
*/
public static Set<String> splitToSet(String value, char separatorChar, boolean trimElements) {
List<String> values = splitToList(value, separatorChar);
int size = values.size();
if (size < 1) { // empty condition
return emptySet();
}
if (!trimElements) { // Do not require to trim the elements
return new LinkedHashSet(values);
}
return unmodifiableSet(values
.stream()
.map(String::trim)
.collect(LinkedHashSet::new, Set::add, Set::addAll));
}
/**
* join string.
*
@ -797,7 +840,7 @@ public final class StringUtils {
}
public static String getQueryStringValue(String qs, String key) {
Map<String, String> map = StringUtils.parseQueryString(qs);
Map<String, String> map = parseQueryString(qs);
return map.get(key);
}
@ -1051,4 +1094,16 @@ public final class StringUtils {
return (byte) ((hi << 4) + lo);
}
/**
* Create the common-delimited {@link String} by one or more {@link String} members
*
* @param one one {@link String}
* @param others others {@link String}
* @return <code>null</code> if <code>one</code> or <code>others</code> is <code>null</code>
* @since 2.7.8
*/
public static String toCommaDelimitedString(String one, String... others) {
String another = arrayToDelimitedString(others, COMMA_SEPARATOR);
return isEmpty(another) ? one : one + COMMA_SEPARATOR + another;
}
}

View File

@ -16,6 +16,8 @@
*/
package org.apache.dubbo.config.annotation;
import org.apache.dubbo.common.constants.RegistryConstants;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -279,4 +281,11 @@ public @interface DubboReference {
* @since 2.7.3
*/
String id() default "";
/**
* @return The service names that the Dubbo interface subscribed
* @see RegistryConstants#SUBSCRIBED_SERVICE_NAMES_KEY
* @since 2.7.8
*/
String[] services() default {};
}

View File

@ -67,10 +67,10 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
public static final String NAME = "config";
private final Map<String, Map<String, AbstractConfig>> configsCache = newMap();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
final Map<String, Map<String, AbstractConfig>> configsCache = newMap();
public ConfigManager() {
}
@ -371,6 +371,15 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
});
}
/**
* @throws IllegalStateException
* @since 2.7.8
*/
@Override
public void destroy() throws IllegalStateException {
clear();
}
/**
* Add the dubbo {@link AbstractConfig config}
*

View File

@ -56,7 +56,7 @@ public interface EventListener<E extends Event> extends java.util.EventListener,
* The comparison rule , refer to {@link #compareTo}.
*/
default int getPriority() {
return MIN_PRIORITY;
return NORMAL_PRIORITY;
}
/**

File diff suppressed because it is too large Load Diff

View File

@ -28,15 +28,17 @@ import java.util.concurrent.TimeUnit;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.DEFAULT_THREAD_POOL_KEEP_ALIVE_TIME;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.DEFAULT_THREAD_POOL_PREFIX;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.DEFAULT_THREAD_POOL_SIZE;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.GROUP_PARAM_NAME;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.PARAM_NAME_PREFIX;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.THREAD_POOL_KEEP_ALIVE_TIME_PARAM_NAME;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.THREAD_POOL_PREFIX_PARAM_NAME;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.THREAD_POOL_SIZE_PARAM_NAME;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.TIMEOUT_PARAM_NAME;
import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.DEFAULT_GROUP;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link AbstractDynamicConfiguration} Test
@ -49,7 +51,7 @@ public class AbstractDynamicConfigurationTest {
@BeforeEach
public void init() {
configuration = new AbstractDynamicConfiguration() {
configuration = new AbstractDynamicConfiguration(null) {
@Override
protected String doGetConfig(String key, String group) throws Exception {
return null;
@ -59,6 +61,11 @@ public class AbstractDynamicConfigurationTest {
protected void doClose() throws Exception {
}
@Override
protected boolean doRemoveConfig(String key, String group) throws Exception {
return false;
}
};
}
@ -71,6 +78,10 @@ public class AbstractDynamicConfigurationTest {
assertEquals("dubbo.config-center.thread-pool.keep-alive-time", THREAD_POOL_KEEP_ALIVE_TIME_PARAM_NAME);
assertEquals(1, DEFAULT_THREAD_POOL_SIZE);
assertEquals(60 * 1000, DEFAULT_THREAD_POOL_KEEP_ALIVE_TIME);
// @since 2.7.8
assertEquals("dubbo.config-center.group", GROUP_PARAM_NAME);
assertEquals("dubbo.config-center.timeout", TIMEOUT_PARAM_NAME);
}
@Test
@ -91,6 +102,11 @@ public class AbstractDynamicConfigurationTest {
protected void doClose() throws Exception {
}
@Override
protected boolean doRemoveConfig(String key, String group) throws Exception {
return false;
}
};
ThreadPoolExecutor threadPoolExecutor = configuration.getWorkersThreadPool();
@ -149,4 +165,42 @@ public class AbstractDynamicConfigurationTest {
public void testClose() throws Exception {
configuration.close();
}
/**
* Test {@link AbstractDynamicConfiguration#getGroup()} and
* {@link AbstractDynamicConfiguration#getDefaultGroup()} methods
*
* @since 2.7.8
*/
@Test
public void testGetGroupAndGetDefaultGroup() {
assertEquals(configuration.getGroup(), configuration.getDefaultGroup());
assertEquals(DEFAULT_GROUP, configuration.getDefaultGroup());
}
/**
* Test {@link AbstractDynamicConfiguration#getTimeout()} and
* {@link AbstractDynamicConfiguration#getDefaultTimeout()} methods
*
* @since 2.7.8
*/
@Test
public void testGetTimeoutAndGetDefaultTimeout() {
assertEquals(configuration.getTimeout(), configuration.getDefaultTimeout());
assertEquals(-1L, configuration.getDefaultTimeout());
}
/**
* Test {@link AbstractDynamicConfiguration#removeConfig(String, String)} and
* {@link AbstractDynamicConfiguration#doRemoveConfig(String, String)} methods
*
* @since 2.7.8
*/
@Test
public void testRemoveConfigAndDoRemoveConfig() throws Exception {
String key = null;
String group = null;
assertEquals(configuration.removeConfig(key, group), configuration.doRemoveConfig(key, group));
assertFalse(configuration.removeConfig(key, group));
}
}

View File

@ -17,6 +17,8 @@
package org.apache.dubbo.common.config.configcenter.file;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.AfterEach;
@ -24,15 +26,17 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.TreeSet;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicBoolean;
import static java.util.Arrays.asList;
import static org.apache.commons.io.FileUtils.deleteQuietly;
import static org.apache.dubbo.common.URL.valueOf;
import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.DEFAULT_GROUP;
import static org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration.CONFIG_CENTER_DIR_PARAM_NAME;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -41,6 +45,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/
public class FileSystemDynamicConfigurationTest {
private final Logger logger = LoggerFactory.getLogger(getClass());
private FileSystemDynamicConfiguration configuration;
private static final String KEY = "abc-def-ghi";
@ -53,11 +59,11 @@ public class FileSystemDynamicConfigurationTest {
rootDirectory.mkdirs();
URL url = valueOf("dubbo://127.0.0.1:20880").addParameter(CONFIG_CENTER_DIR_PARAM_NAME, rootDirectory.getAbsolutePath());
configuration = new FileSystemDynamicConfiguration(url);
deleteQuietly(configuration.getRootDirectory());
}
@AfterEach
public void destroy() throws Exception {
deleteQuietly(configuration.getRootDirectory());
configuration.close();
}
@ -73,9 +79,6 @@ public class FileSystemDynamicConfigurationTest {
assertEquals(ThreadPoolExecutor.class, configuration.getWorkersThreadPool().getClass());
assertEquals(1, (configuration.getWorkersThreadPool()).getCorePoolSize());
assertEquals(1, (configuration.getWorkersThreadPool()).getMaximumPoolSize());
assertNotNull(configuration.getWatchEventsLoopThreadPool());
assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getCorePoolSize());
assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getMaximumPoolSize());
if (configuration.isBasedPoolingWatchService()) {
assertEquals(2, configuration.getDelay());
@ -103,7 +106,7 @@ public class FileSystemDynamicConfigurationTest {
processedEvent.set(true);
assertEquals(KEY, event.getKey());
System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
logger.info(String.format("[%s] " + event + "\n", Thread.currentThread().getName()));
});
@ -127,7 +130,7 @@ public class FileSystemDynamicConfigurationTest {
configuration.addListener("test", "test", event -> {
processedEvent.set(true);
assertEquals("test", event.getKey());
System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
logger.info(String.format("[%s] " + event + "\n", Thread.currentThread().getName()));
});
processedEvent.set(false);
configuration.publishConfig("test", "test", "TEST");
@ -141,10 +144,36 @@ public class FileSystemDynamicConfigurationTest {
processedEvent.set(false);
File keyFile = configuration.configFile(KEY, DEFAULT_GROUP);
configuration.getRootDirectory();
File keyFile = new File(KEY, DEFAULT_GROUP);
FileUtils.deleteQuietly(keyFile);
while (!processedEvent.get()) {
Thread.sleep(1 * 1000L);
}
}
@Test
public void testRemoveConfig() throws Exception {
assertTrue(configuration.publishConfig(KEY, DEFAULT_GROUP, "A"));
assertEquals("A", FileUtils.readFileToString(configuration.configFile(KEY, DEFAULT_GROUP), configuration.getEncoding()));
assertTrue(configuration.removeConfig(KEY, DEFAULT_GROUP));
assertFalse(configuration.configFile(KEY, DEFAULT_GROUP).exists());
}
@Test
public void testGetConfigKeys() throws Exception {
assertTrue(configuration.publishConfig("A", DEFAULT_GROUP, "A"));
assertTrue(configuration.publishConfig("B", DEFAULT_GROUP, "B"));
assertTrue(configuration.publishConfig("C", DEFAULT_GROUP, "C"));
assertEquals(new TreeSet(asList("A", "B", "C")), configuration.getConfigKeys(DEFAULT_GROUP));
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.dubbo.common.constants;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR_CHAR;
import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH;
import static org.apache.dubbo.common.constants.CommonConstants.SERVICE_NAME_MAPPING_PROPERTIES_FILE_KEY;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link CommonConstants} Test-Cases
*
* @since 2.7.8
*/
public class CommonConstantsTest {
@Test
public void test() {
assertEquals(',', COMMA_SEPARATOR_CHAR);
assertEquals("composite", COMPOSITE_METADATA_STORAGE_TYPE);
assertEquals("service-name-mapping.properties-path", SERVICE_NAME_MAPPING_PROPERTIES_FILE_KEY);
assertEquals("META-INF/dubbo/service-name-mapping.properties", DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH);
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.dubbo.common.convert;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.common.convert.Converter.convertIfPossible;
import static org.apache.dubbo.common.convert.Converter.getConverter;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
/**
* {@link Converter} Test-Cases
*
* @since 2.7.8
*/
public class ConverterTest {
@Test
public void testGetConverter() {
getExtensionLoader(Converter.class)
.getSupportedExtensionInstances()
.forEach(converter -> {
assertSame(converter, getConverter(converter.getSourceType(), converter.getTargetType()));
});
}
@Test
public void testConvertIfPossible() {
assertEquals(Integer.valueOf(2), convertIfPossible("2", Integer.class));
assertEquals(Boolean.FALSE, convertIfPossible("false", Boolean.class));
assertEquals(Double.valueOf(1), convertIfPossible("1", Double.class));
}
}

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToBooleanConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToCharArrayConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToCharacterConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToDoubleConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToFloatConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToIntegerConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToLongConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToOptionalConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToShortConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert;
import org.apache.dubbo.common.convert.Converter;
import org.apache.dubbo.common.convert.StringToStringConverter;
package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -0,0 +1,72 @@
/*
* 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.dubbo.common.convert.multiple;
import org.junit.jupiter.api.Test;
import java.util.Collection;
import java.util.Deque;
import java.util.List;
import java.util.NavigableSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TransferQueue;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link MultiValueConverter} Test
*
* @since 2.7.8
*/
public class MultiValueConverterTest {
@Test
public void testFind() {
MultiValueConverter converter = MultiValueConverter.find(String.class, String[].class);
assertEquals(StringToArrayConverter.class, converter.getClass());
converter = MultiValueConverter.find(String.class, BlockingDeque.class);
assertEquals(StringToBlockingDequeConverter.class, converter.getClass());
converter = MultiValueConverter.find(String.class, BlockingQueue.class);
assertEquals(StringToBlockingQueueConverter.class, converter.getClass());
converter = MultiValueConverter.find(String.class, Collection.class);
assertEquals(StringToCollectionConverter.class, converter.getClass());
converter = MultiValueConverter.find(String.class, Deque.class);
assertEquals(StringToDequeConverter.class, converter.getClass());
converter = MultiValueConverter.find(String.class, List.class);
assertEquals(StringToListConverter.class, converter.getClass());
converter = MultiValueConverter.find(String.class, NavigableSet.class);
assertEquals(StringToNavigableSetConverter.class, converter.getClass());
converter = MultiValueConverter.find(String.class, Queue.class);
assertEquals(StringToQueueConverter.class, converter.getClass());
converter = MultiValueConverter.find(String.class, Set.class);
assertEquals(StringToSetConverter.class, converter.getClass());
converter = MultiValueConverter.find(String.class, TransferQueue.class);
assertEquals(StringToTransferQueueConverter.class, converter.getClass());
}
}

View File

@ -14,9 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
import org.apache.dubbo.common.convert.multiple.StringToArrayConverter;
package org.apache.dubbo.common.convert.multiple;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
import org.apache.dubbo.common.convert.multiple.StringToBlockingDequeConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
import org.apache.dubbo.common.convert.multiple.StringToBlockingQueueConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
import org.apache.dubbo.common.convert.multiple.StringToCollectionConverter;
package org.apache.dubbo.common.convert.multiple;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
import org.apache.dubbo.common.convert.multiple.StringToDequeConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
import org.apache.dubbo.common.convert.multiple.StringToListConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
import org.apache.dubbo.common.convert.multiple.StringToListConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
@ -47,7 +45,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link StringToListConverter} Test
* {@link StringToNavigableSetConverter} Test
*
* @since 2.7.6
*/

View File

@ -14,9 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.convert.multiple.StringToQueueConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;

View File

@ -14,9 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.convert.multiple.StringToSetConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
import org.apache.dubbo.common.convert.multiple.StringToListConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
@ -47,7 +45,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link StringToListConverter} Test
* {@link StringToSortedSetConverter} Test
*
* @since 2.7.6
*/

View File

@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.convert.multiple;
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
import org.apache.dubbo.common.convert.multiple.StringToListConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
@ -48,7 +46,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link StringToListConverter} Test
* {@link StringToTransferQueueConverter} Test
*
* @since 2.7.6
*/

View File

@ -16,7 +16,6 @@
*/
package org.apache.dubbo.common.utils;
import com.alibaba.fastjson.JSONObject;
import org.apache.dubbo.common.model.Person;
import org.apache.dubbo.common.model.SerializablePerson;
import org.apache.dubbo.common.model.User;
@ -26,6 +25,7 @@ import org.apache.dubbo.common.model.person.PersonInfo;
import org.apache.dubbo.common.model.person.PersonStatus;
import org.apache.dubbo.common.model.person.Phone;
import com.alibaba.fastjson.JSONObject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

View File

@ -0,0 +1,47 @@
/*
* 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.dubbo.common.utils;
import org.junit.jupiter.api.Test;
import java.util.function.Predicate;
import static org.apache.dubbo.common.utils.StringConstantFieldValuePredicate.of;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link StringConstantFieldValuePredicate} Test
*
* @since 2.7.8
*/
public class StringConstantFieldValuePredicateTest {
public static final String S1 = "1";
public static final Object O1 = "2";
public static final Object O2 = 3;
@Test
public void test() {
Predicate<String> predicate = of(getClass());
assertTrue(predicate.test("1"));
assertTrue(predicate.test("2"));
assertFalse(predicate.test("3"));
}
}

View File

@ -18,19 +18,33 @@ package org.apache.dubbo.common.utils;
import org.junit.jupiter.api.Test;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.util.Arrays.asList;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
import static org.apache.dubbo.common.utils.StringUtils.splitToList;
import static org.apache.dubbo.common.utils.StringUtils.splitToSet;
import static org.apache.dubbo.common.utils.StringUtils.toCommaDelimitedString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class StringUtilsTest {
@Test
@ -234,16 +248,32 @@ public class StringUtilsTest {
public void testSplitToList() throws Exception {
String str = "d,1,2,4";
assertEquals(4, StringUtils.splitToList(str, ',').size());
assertEquals(Arrays.asList(str.split(",")), StringUtils.splitToList(str, ','));
assertEquals(4, splitToList(str, ',').size());
assertEquals(asList(str.split(",")), splitToList(str, ','));
assertEquals(1, StringUtils.splitToList(str, 'a').size());
assertEquals(Arrays.asList(str.split("a")), StringUtils.splitToList(str, 'a'));
assertEquals(1, splitToList(str, 'a').size());
assertEquals(asList(str.split("a")), splitToList(str, 'a'));
assertEquals(0, StringUtils.splitToList("", 'a').size());
assertEquals(0, StringUtils.splitToList(null, 'a').size());
assertEquals(0, splitToList("", 'a').size());
assertEquals(0, splitToList(null, 'a').size());
}
/**
* Test {@link StringUtils#splitToSet(String, char, boolean)}
*
* @since 2.7.8
*/
@Test
public void testSplitToSet() {
String value = "1# 2#3 #4#3";
Set<String> values = splitToSet(value, '#', false);
assertEquals(ofSet("1", " 2", "3 ", "4", "3"), values);
values = splitToSet(value, '#', true);
assertEquals(ofSet("1", "2", "3", "4"), values);
}
@Test
public void testTranslate() throws Exception {
String s = "16314";
@ -363,4 +393,29 @@ public class StringUtilsTest {
assertEquals(0, illegalMap.size());
}
/**
* Test {@link StringUtils#toCommaDelimitedString(String, String...)}
* @since 2.7.8
*/
@Test
public void testToCommaDelimitedString() {
String value = toCommaDelimitedString(null);
assertNull(value);
value = toCommaDelimitedString(null, null);
assertNull(value);
value = toCommaDelimitedString("");
assertEquals("", value);
value = toCommaDelimitedString("one");
assertEquals("one", value);
value = toCommaDelimitedString("one", "two");
assertEquals("one,two", value);
value = toCommaDelimitedString("one", "two", "three");
assertEquals("one,two,three", value);
}
}

View File

@ -49,7 +49,12 @@ public class ConfigManagerTest {
@BeforeEach
public void init() {
configManager.clear();
configManager.destroy();
}
@Test
public void testDestroy() {
assertTrue(configManager.configsCache.isEmpty());
}
@Test

View File

@ -41,7 +41,7 @@ public class EchoEventListener2 extends Vector<EventListener<Event>> implements
@Override
public int getPriority() {
return 0;
return -1;
}
public int getEventOccurs() {

View File

@ -35,14 +35,14 @@ public class ConfigTest {
@AfterEach
public void tearDown() {
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@BeforeEach
public void setup() {
// In IDE env, make sure adding the following argument to VM options
System.setProperty("java.net.preferIPv4Stack", "true");
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@Test

View File

@ -38,12 +38,12 @@ public class ReferenceConfigTest {
@BeforeEach
public void setUp() {
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@AfterEach
public void tearDown() {
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@Test

View File

@ -135,6 +135,12 @@
<artifactId>dubbo-registry-eureka</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -156,6 +162,12 @@
<artifactId>dubbo-metadata-report-zookeeper</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
@ -170,6 +182,19 @@
<artifactId>dubbo-metadata-report-nacos</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metadata-report-consul</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
@ -191,6 +216,12 @@
<artifactId>dubbo-configcenter-nacos</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.config;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.bytecode.Wrapper;
import org.apache.dubbo.common.constants.RegistryConstants;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@ -31,10 +32,10 @@ import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.event.ReferenceConfigDestroyedEvent;
import org.apache.dubbo.config.event.ReferenceConfigInitializedEvent;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.event.Event;
import org.apache.dubbo.event.EventDispatcher;
import org.apache.dubbo.metadata.WritableMetadataService;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.ProxyFactory;
@ -57,25 +58,25 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR_CHAR;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PROXY_CLASS_REF;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.SEMICOLON_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.SUBSCRIBED_SERVICE_NAMES_KEY;
import static org.apache.dubbo.common.utils.NetUtils.isInvalidLocalHost;
import static org.apache.dubbo.common.utils.StringUtils.splitToSet;
import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
import static org.apache.dubbo.registry.Constants.CONSUMER_PROTOCOL;
import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
@ -140,6 +141,13 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
private DubboBootstrap bootstrap;
/**
* The service names that the Dubbo interface subscribed.
*
* @since 2.7.8
*/
private String services;
public ReferenceConfig() {
super();
this.repository = ApplicationModel.getServiceRepository();
@ -150,6 +158,40 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
this.repository = ApplicationModel.getServiceRepository();
}
/**
* Get a string presenting the service names that the Dubbo interface subscribed.
* If it is a multiple-values, the content will be a comma-delimited String.
*
* @return non-null
* @see RegistryConstants#SUBSCRIBED_SERVICE_NAMES_KEY
* @since 2.7.8
*/
@Parameter(key = SUBSCRIBED_SERVICE_NAMES_KEY)
public String getServices() {
return services;
}
/**
* It's an alias method for {@link #getServices()}, but the more convenient.
*
* @return the String {@link List} presenting the Dubbo interface subscribed
* @since 2.7.8
*/
@Parameter(excluded = true)
public Set<String> getSubscribedServices() {
return splitToSet(getServices(), COMMA_SEPARATOR_CHAR);
}
/**
* Set the service names that the Dubbo interface subscribed.
*
* @param services If it is a multiple-values, the content will be a comma-delimited String.
* @since 2.7.8
*/
public void setServices(String services) {
this.services = services;
}
public synchronized T get() {
if (destroyed) {
throw new IllegalStateException("The invoker of ReferenceConfig(" + url + ") has already destroyed!");
@ -221,10 +263,6 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
// appendParameters(map, consumer, Constants.DEFAULT_KEY);
AbstractConfig.appendParameters(map, consumer);
AbstractConfig.appendParameters(map, this);
MetadataReportConfig metadataReportConfig = getMetadataReportConfig();
if (metadataReportConfig != null && metadataReportConfig.isValid()) {
map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE);
}
Map<String, AsyncMethodInfo> attributes = null;
if (CollectionUtils.isNotEmpty(getMethods())) {
attributes = new HashMap<>();
@ -355,16 +393,6 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
if (logger.isInfoEnabled()) {
logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
}
/**
* @since 2.7.0
* ServiceData Store
*/
String metadata = map.get(METADATA_KEY);
WritableMetadataService metadataService = WritableMetadataService.getExtension(metadata == null ? DEFAULT_METADATA_STORAGE_TYPE : metadata);
if (metadataService != null) {
URL consumerURL = new URL(CONSUMER_PROTOCOL, map.remove(REGISTER_IP_KEY), 0, map.get(INTERFACE_KEY), map);
metadataService.publishServiceDefinition(consumerURL);
}
// create service proxy
return (T) PROXY_FACTORY.getProxy(invoker, ProtocolUtils.isGeneric(generic));
}
@ -469,7 +497,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
}
private void postProcessConfig() {
List<ConfigPostProcessor> configPostProcessors =ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class)
List<ConfigPostProcessor> configPostProcessors = ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class)
.getActivateExtension(URL.valueOf("configPostProcessor://"), (String[]) null);
configPostProcessors.forEach(component -> component.postProcessReferConfig(this));
}

View File

@ -37,7 +37,6 @@ import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.event.Event;
import org.apache.dubbo.event.EventDispatcher;
import org.apache.dubbo.metadata.WritableMetadataService;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
@ -68,16 +67,13 @@ import java.util.concurrent.TimeUnit;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_IP_TO_BIND;
import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY;
@ -187,7 +183,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
if (bootstrap == null) {
bootstrap = DubboBootstrap.getInstance();
bootstrap.init();
bootstrap.initialize();
}
checkAndUpdateSubConfigs();
@ -344,10 +340,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
AbstractConfig.appendParameters(map, provider);
AbstractConfig.appendParameters(map, protocolConfig);
AbstractConfig.appendParameters(map, this);
MetadataReportConfig metadataReportConfig = getMetadataReportConfig();
if (metadataReportConfig != null && metadataReportConfig.isValid()) {
map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE);
}
if (CollectionUtils.isNotEmpty(getMethods())) {
for (MethodConfig method : getMethods()) {
AbstractConfig.appendParameters(map, method, method.getName());
@ -502,14 +494,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
exporters.add(exporter);
}
/**
* @since 2.7.0
* ServiceData Store
*/
WritableMetadataService metadataService = WritableMetadataService.getExtension(url.getParameter(METADATA_KEY, DEFAULT_METADATA_STORAGE_TYPE));
if (metadataService != null) {
metadataService.publishServiceDefinition(url);
}
}
}
this.urls.add(url);

View File

@ -52,7 +52,6 @@ import org.apache.dubbo.config.bootstrap.builders.ReferenceBuilder;
import org.apache.dubbo.config.bootstrap.builders.RegistryBuilder;
import org.apache.dubbo.config.bootstrap.builders.ServiceBuilder;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.config.utils.ReferenceConfigCache;
import org.apache.dubbo.event.EventDispatcher;
@ -66,6 +65,7 @@ import org.apache.dubbo.registry.client.DefaultServiceInstance;
import org.apache.dubbo.registry.client.ServiceDiscovery;
import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
import org.apache.dubbo.registry.client.ServiceInstance;
import org.apache.dubbo.registry.client.ServiceInstanceCustomizer;
import org.apache.dubbo.registry.support.AbstractRegistryFactory;
import org.apache.dubbo.rpc.model.ApplicationModel;
@ -93,17 +93,17 @@ import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.g
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.apache.dubbo.common.function.ThrowableAction.execute;
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
import static org.apache.dubbo.metadata.WritableMetadataService.getExtension;
import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType;
import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
/**
* See {@link ApplicationModel} and {@link ExtensionLoader} for why this class is designed to be singleton.
*
* <p>
* The bootstrap class of Dubbo
*
* <p>
* Get singleton instance by calling static method {@link #getInstance()}.
* Designed as singleton because some classes inside Dubbo, such as ExtensionLoader, are designed only for one instance per process.
*
@ -141,7 +141,7 @@ public class DubboBootstrap extends GenericEventListener {
private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();
private final ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
private final ExecutorRepository executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
private final ConfigManager configManager;
@ -165,7 +165,7 @@ public class DubboBootstrap extends GenericEventListener {
private volatile MetadataService metadataService;
private volatile MetadataServiceExporter metadataServiceExporter;
private volatile Set<MetadataServiceExporter> metadataServiceExporters;
private List<ServiceConfigBase<?>> exportedServices = new ArrayList<>();
@ -500,7 +500,7 @@ public class DubboBootstrap extends GenericEventListener {
/**
* Initialize
*/
private void initialize() {
public void initialize() {
if (!initialized.compareAndSet(false, true)) {
return;
}
@ -509,14 +509,17 @@ public class DubboBootstrap extends GenericEventListener {
startConfigCenter();
useRegistryAsConfigCenterIfNecessary();
loadRemoteConfigs();
checkGlobalConfigs();
// @since 2.7.8
startMetadataCenter();
initMetadataService();
initMetadataServiceExports();
initEventListener();
if (logger.isInfoEnabled()) {
@ -583,6 +586,9 @@ public class DubboBootstrap extends GenericEventListener {
}
private void startConfigCenter() {
useRegistryAsConfigCenterIfNecessary();
Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
// check Config Center
@ -610,7 +616,10 @@ public class DubboBootstrap extends GenericEventListener {
configManager.refreshAll();
}
private void startMetadataReport() {
private void startMetadataCenter() {
useRegistryAsMetadataCenterIfNecessary();
ApplicationConfig applicationConfig = getApplication();
String metadataType = applicationConfig.getMetadataType();
@ -646,33 +655,87 @@ public class DubboBootstrap extends GenericEventListener {
return;
}
configManager.getDefaultRegistries().stream()
.filter(registryConfig -> registryConfig.getUseAsConfigCenter() == null || registryConfig.getUseAsConfigCenter())
.forEach(registryConfig -> {
String protocol = registryConfig.getProtocol();
String id = "config-center-" + protocol + "-" + registryConfig.getPort();
ConfigCenterConfig cc = new ConfigCenterConfig();
cc.setId(id);
if (cc.getParameters() == null) {
cc.setParameters(new HashMap<>());
}
if (registryConfig.getParameters() != null) {
cc.getParameters().putAll(registryConfig.getParameters());
}
cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
cc.setProtocol(registryConfig.getProtocol());
cc.setPort(registryConfig.getPort());
cc.setAddress(getRegistryCompatibleAddress(registryConfig.getAddress()));
cc.setNamespace(registryConfig.getGroup());
cc.setUsername(registryConfig.getUsername());
cc.setPassword(registryConfig.getPassword());
if (registryConfig.getTimeout() != null) {
cc.setTimeout(registryConfig.getTimeout().longValue());
}
cc.setHighestPriority(false);
configManager.addConfigCenter(cc);
});
startConfigCenter();
configManager
.getDefaultRegistries()
.stream()
.filter(this::isUsedRegistryAsConfigCenter)
.map(this::registryAsConfigCenter)
.forEach(configManager::addConfigCenter);
}
private boolean isUsedRegistryAsConfigCenter(RegistryConfig registryConfig) {
// TODO: confirm ? registryConfig.getUseAsConfigCenter() == null || registryConfig.getUseAsConfigCenter()
return Boolean.TRUE.equals(registryConfig.getUseAsConfigCenter());
}
private ConfigCenterConfig registryAsConfigCenter(RegistryConfig registryConfig) {
String protocol = registryConfig.getProtocol();
Integer port = registryConfig.getPort();
String id = "config-center-" + protocol + "-" + port;
ConfigCenterConfig cc = new ConfigCenterConfig();
cc.setId(id);
if (cc.getParameters() == null) {
cc.setParameters(new HashMap<>());
}
if (registryConfig.getParameters() != null) {
cc.getParameters().putAll(registryConfig.getParameters()); // copy the parameters
}
cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
cc.setProtocol(protocol);
cc.setPort(port);
cc.setGroup(registryConfig.getGroup());
cc.setAddress(getRegistryCompatibleAddress(registryConfig.getAddress()));
cc.setNamespace(registryConfig.getGroup());
cc.setUsername(registryConfig.getUsername());
cc.setPassword(registryConfig.getPassword());
if (registryConfig.getTimeout() != null) {
cc.setTimeout(registryConfig.getTimeout().longValue());
}
cc.setHighestPriority(false);
return cc;
}
private void useRegistryAsMetadataCenterIfNecessary() {
Collection<MetadataReportConfig> metadataConfigs = configManager.getMetadataConfigs();
if (CollectionUtils.isNotEmpty(metadataConfigs)) {
return;
}
configManager
.getDefaultRegistries()
.stream()
.filter(this::isUsedRegistryAsMetadataCenter)
.map(this::registryAsMetadataCenter)
.forEach(configManager::addMetadataReport);
}
private boolean isUsedRegistryAsMetadataCenter(RegistryConfig registryConfig) {
// TODO: confirm ? registryConfig.getUseAsMetadataCenter() == null || registryConfig.getUseAsMetadataCenter()
return Boolean.TRUE.equals(registryConfig.getUseAsMetadataCenter());
}
private MetadataReportConfig registryAsMetadataCenter(RegistryConfig registryConfig) {
String protocol = registryConfig.getProtocol();
Integer port = registryConfig.getPort();
String id = "metadata-center-" + protocol + "-" + port;
MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
metadataReportConfig.setId(id);
if (metadataReportConfig.getParameters() == null) {
metadataReportConfig.setParameters(new HashMap<>());
}
if (registryConfig.getParameters() != null) {
metadataReportConfig.getParameters().putAll(registryConfig.getParameters()); // copy the parameters
}
metadataReportConfig.getParameters().put(CLIENT_KEY, registryConfig.getClient());
metadataReportConfig.setGroup(registryConfig.getGroup());
metadataReportConfig.setAddress(getRegistryCompatibleAddress(registryConfig.getAddress()));
metadataReportConfig.setUsername(registryConfig.getUsername());
metadataReportConfig.setPassword(registryConfig.getPassword());
metadataReportConfig.setTimeout(registryConfig.getTimeout());
return metadataReportConfig;
}
private String getRegistryCompatibleAddress(String registryAddress) {
@ -719,12 +782,17 @@ public class DubboBootstrap extends GenericEventListener {
/**
* Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension
* Initialize {@link #metadataService WritableMetadataService} from {@link WritableMetadataService}'s extension
*/
private void initMetadataService() {
startMetadataReport();
this.metadataService = getExtension(getMetadataType());
this.metadataServiceExporter = new ConfigurableMetadataServiceExporter(metadataService);
this.metadataService = WritableMetadataService.getExtension(getMetadataType());
}
/**
* Initialize {@link #metadataServiceExporters MetadataServiceExporter}
*/
private void initMetadataServiceExports() {
this.metadataServiceExporters = getExtensionLoader(MetadataServiceExporter.class).getSupportedExtensionInstances();
}
/**
@ -926,13 +994,21 @@ public class DubboBootstrap extends GenericEventListener {
* export {@link MetadataService}
*/
private void exportMetadataService() {
metadataServiceExporter.export();
metadataServiceExporters
.stream()
.filter(this::supports)
.forEach(MetadataServiceExporter::export);
}
private void unexportMetadataService() {
if (metadataServiceExporter != null && metadataServiceExporter.isExported()) {
metadataServiceExporter.unexport();
}
metadataServiceExporters
.stream()
.filter(this::supports)
.forEach(MetadataServiceExporter::unexport);
}
private boolean supports(MetadataServiceExporter exporter) {
return exporter.supports(getMetadataType());
}
private void exportServices() {
@ -1025,9 +1101,37 @@ public class DubboBootstrap extends GenericEventListener {
ServiceInstance serviceInstance = createServiceInstance(serviceName, host, port);
preRegisterServiceInstance(serviceInstance);
getServiceDiscoveries().forEach(serviceDiscovery -> serviceDiscovery.register(serviceInstance));
}
/**
* Pre-register {@link ServiceInstance the service instance}
*
* @param serviceInstance {@link ServiceInstance the service instance}
* @since 2.7.8
*/
private void preRegisterServiceInstance(ServiceInstance serviceInstance) {
customizeServiceInstance(serviceInstance);
}
/**
* Customize {@link ServiceInstance the service instance}
*
* @param serviceInstance {@link ServiceInstance the service instance}
* @since 2.7.8
*/
private void customizeServiceInstance(ServiceInstance serviceInstance) {
ExtensionLoader<ServiceInstanceCustomizer> loader =
getExtensionLoader(ServiceInstanceCustomizer.class);
// FIXME, sort customizer before apply
loader.getSupportedExtensionInstances().forEach(customizer -> {
// customizes
customizer.customize(serviceInstance);
});
}
private URL selectMetadataServiceExportedURL() {
URL selectedURL = null;
@ -1118,7 +1222,7 @@ public class DubboBootstrap extends GenericEventListener {
}
private void clearConfigs() {
configManager.clear();
configManager.destroy();
if (logger.isDebugEnabled()) {
logger.debug(NAME + "'s configs have been clear.");
}

View File

@ -24,6 +24,8 @@ import org.apache.dubbo.config.ReferenceConfigBase;
import java.util.ArrayList;
import java.util.List;
import static org.apache.dubbo.common.utils.StringUtils.toCommaDelimitedString;
/**
* This is a builder for build {@link ReferenceConfigBase}.
*
@ -65,6 +67,13 @@ public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfi
*/
private String protocol;
/**
* The string presenting the service names that the Dubbo interface subscribed
*
* @since 2.7.8
*/
private String services;
public static ReferenceBuilder newBuilder() {
return new ReferenceBuilder();
}
@ -119,6 +128,17 @@ public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfi
return getThis();
}
/**
* @param service one service name
* @param otherServices other service names
* @return {@link ReferenceBuilder}
* @since 2.7.8
*/
public ReferenceBuilder<T> services(String service, String... otherServices) {
this.services = toCommaDelimitedString(service, otherServices);
return getThis();
}
public ReferenceConfig<T> build() {
ReferenceConfig<T> reference = new ReferenceConfig<>();
super.build(reference);
@ -132,6 +152,8 @@ public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfi
reference.setMethods(methods);
reference.setConsumer(consumer);
reference.setProtocol(protocol);
// @since 2.7.8
reference.setServices(services);
return reference;
}

View File

@ -285,6 +285,16 @@ public class RegistryBuilder extends AbstractBuilder<RegistryConfig, RegistryBui
return getThis();
}
/**
* @param name the parameter name
* @param value the parameter value
* @return {@link RegistryBuilder}
* @since 2.7.8
*/
public RegistryBuilder parameter(String name, String value) {
return appendParameter(name, value);
}
public RegistryBuilder appendParameters(Map<String, String> appendParameters) {
this.parameters = appendParameters(parameters, appendParameters);
return getThis();

View File

@ -0,0 +1,74 @@
/*
* 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.dubbo.config.event.listener;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.AbstractInterfaceConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.event.ReferenceConfigInitializedEvent;
import org.apache.dubbo.config.event.ServiceConfigExportedEvent;
import org.apache.dubbo.event.EventListener;
import org.apache.dubbo.event.GenericEventListener;
import org.apache.dubbo.metadata.WritableMetadataService;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.metadata.WritableMetadataService.getExtension;
/**
* An {@link EventListener} {@link WritableMetadataService#publishServiceDefinition(URL) publishs the service definition}
* when {@link ServiceConfigExportedEvent the event of the exported Dubbo service} and
* {@link ReferenceConfigInitializedEvent the event of the referenced Dubbo service} is raised.
*
* @see GenericEventListener
* @see ServiceConfigExportedEvent
* @see ReferenceConfigInitializedEvent
* @since 2.7.8
*/
public class PublishingServiceDefinitionListener extends GenericEventListener {
public void onEvent(ReferenceConfigInitializedEvent event) {
handleEvent(event.getReferenceConfig());
}
public void onEvent(ServiceConfigExportedEvent event) {
handleEvent(event.getServiceConfig());
}
private void handleEvent(AbstractInterfaceConfig config) {
String metadataType = getMetadataType(config);
for (URL exportedURL : config.getExportedUrls()) {
WritableMetadataService metadataService = getExtension(metadataType);
if (metadataService != null) {
metadataService.publishServiceDefinition(exportedURL);
}
}
}
private String getMetadataType(AbstractInterfaceConfig config) {
ApplicationConfig applicationConfig = config.getApplication();
String metadataType = applicationConfig.getMetadataType();
if (REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) {
MetadataReportConfig metadataReportConfig = config.getMetadataReportConfig();
if (metadataReportConfig == null || !metadataReportConfig.isValid()) {
metadataType = DEFAULT_METADATA_STORAGE_TYPE;
}
}
return metadataType;
}
}

View File

@ -24,8 +24,6 @@ import org.apache.dubbo.metadata.ServiceNameMapping;
import java.util.List;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.metadata.ServiceNameMapping.getDefaultExtension;
/**
@ -45,11 +43,7 @@ public class ServiceNameMappingListener implements EventListener<ServiceConfigEx
ServiceConfig serviceConfig = event.getServiceConfig();
List<URL> exportedURLs = serviceConfig.getExportedUrls();
exportedURLs.forEach(url -> {
String serviceInterface = url.getServiceInterface();
String group = url.getParameter(GROUP_KEY);
String version = url.getParameter(VERSION_KEY);
String protocol = url.getProtocol();
serviceNameMapping.map(serviceInterface, group, version, protocol);
serviceNameMapping.map(url);
});
}
}

View File

@ -0,0 +1,150 @@
/*
* 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.dubbo.config.metadata;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.metadata.MetadataServiceExporter;
import org.apache.dubbo.metadata.MetadataServiceType;
import org.apache.dubbo.metadata.WritableMetadataService;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static java.util.EnumSet.of;
import static org.apache.dubbo.metadata.MetadataServiceType.getOrDefault;
/**
* The abstract implementation of {@link MetadataServiceExporter} to provider the commons features for sub-types
*
* @see MetadataServiceExporter
* @see MetadataService
* @since 2.7.8
*/
public abstract class AbstractMetadataServiceExporter implements MetadataServiceExporter {
protected final Logger logger = LoggerFactory.getLogger(getClass());
protected final WritableMetadataService metadataService;
private final int priority;
private final Set<MetadataServiceType> supportedMetadataServiceTypes;
private volatile boolean exported = false;
public AbstractMetadataServiceExporter(String metadataType,
int priority,
MetadataServiceType supportMetadataServiceType,
MetadataServiceType... otherSupportMetadataServiceTypes) {
this(metadataType, priority, of(supportMetadataServiceType, otherSupportMetadataServiceTypes));
}
public AbstractMetadataServiceExporter(String metadataType,
int priority,
Set<MetadataServiceType> supportedMetadataServiceTypes) {
this.metadataService = WritableMetadataService.getExtension(metadataType);
this.priority = priority;
this.supportedMetadataServiceTypes = supportedMetadataServiceTypes;
}
@Override
public final MetadataServiceExporter export() {
if (!isExported()) {
try {
doExport();
exported = true;
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.error("Exporting the MetadataService fails", e);
}
exported = false;
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("The MetadataService has been exported : " + getExportedURLs());
}
}
return this;
}
@Override
public final MetadataServiceExporter unexport() {
if (isExported()) {
try {
doUnexport();
exported = false;
} catch (Exception e) {
if (logger.isErrorEnabled()) {
logger.error("UnExporting the MetadataService fails", e);
}
}
}
return this;
}
@Override
public List<URL> getExportedURLs() {
return metadataService
.getExportedURLs()
.stream()
.map(URL::valueOf)
.collect(Collectors.toList());
}
@Override
public boolean isExported() {
return exported;
}
@Override
public final boolean supports(String metadataType) {
MetadataServiceType metadataServiceType = getOrDefault(metadataType);
return supportedMetadataServiceTypes.contains(metadataServiceType);
}
@Override
public int getPriority() {
return priority;
}
/**
* Exports the {@link MetadataService}
*
* @throws Exception If some exception occurs
*/
protected abstract void doExport() throws Exception;
/**
* Unexports the {@link MetadataService}
*
* @throws Exception If some exception occurs
*/
protected abstract void doUnexport() throws Exception;
/**
* Get the underlying of {@link MetadataService}
*
* @return non-null
*/
public WritableMetadataService getMetadataService() {
return metadataService;
}
}

View File

@ -17,8 +17,6 @@
package org.apache.dubbo.config.metadata;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
@ -26,12 +24,15 @@ import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.metadata.MetadataServiceExporter;
import org.apache.dubbo.metadata.MetadataServiceType;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.emptyList;
import static java.util.EnumSet.allOf;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
/**
@ -49,56 +50,41 @@ import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
* @see ConfigManager
* @since 2.7.5
*/
public class ConfigurableMetadataServiceExporter implements MetadataServiceExporter {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final MetadataService metadataService;
public class ConfigurableMetadataServiceExporter extends AbstractMetadataServiceExporter {
private volatile ServiceConfig<MetadataService> serviceConfig;
public ConfigurableMetadataServiceExporter(MetadataService metadataService) {
this.metadataService = metadataService;
public ConfigurableMetadataServiceExporter() {
super(DEFAULT_METADATA_STORAGE_TYPE, MAX_PRIORITY, allOf(MetadataServiceType.class));
}
@Override
public ConfigurableMetadataServiceExporter export() {
protected void doExport() throws Exception {
if (!isExported()) {
ServiceConfig<MetadataService> serviceConfig = new ServiceConfig<>();
serviceConfig.setApplication(getApplicationConfig());
serviceConfig.setRegistries(getRegistries());
serviceConfig.setProtocol(generateMetadataProtocol());
serviceConfig.setInterface(MetadataService.class);
serviceConfig.setRef(metadataService);
serviceConfig.setGroup(getApplicationConfig().getName());
serviceConfig.setVersion(metadataService.version());
ServiceConfig<MetadataService> serviceConfig = new ServiceConfig<>();
serviceConfig.setApplication(getApplicationConfig());
serviceConfig.setRegistries(getRegistries());
serviceConfig.setProtocol(generateMetadataProtocol());
serviceConfig.setInterface(MetadataService.class);
serviceConfig.setRef(metadataService);
serviceConfig.setGroup(getApplicationConfig().getName());
serviceConfig.setVersion(metadataService.version());
// export
serviceConfig.export();
// export
serviceConfig.export();
if (logger.isInfoEnabled()) {
logger.info("The MetadataService exports urls : " + serviceConfig.getExportedUrls());
}
this.serviceConfig = serviceConfig;
} else {
if (logger.isWarnEnabled()) {
logger.warn("The MetadataService has been exported : " + serviceConfig.getExportedUrls());
}
if (logger.isInfoEnabled()) {
logger.info("The MetadataService exports urls : " + serviceConfig.getExportedUrls());
}
return this;
this.serviceConfig = serviceConfig;
}
@Override
public ConfigurableMetadataServiceExporter unexport() {
if (isExported()) {
protected void doUnexport() throws Exception {
if (serviceConfig != null) {
serviceConfig.unexport();
}
return this;
}
@Override
@ -110,6 +96,11 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
return serviceConfig != null && serviceConfig.isExported();
}
@Override
public int getPriority() {
return MAX_PRIORITY;
}
private ApplicationConfig getApplicationConfig() {
return ApplicationModel.getConfigManager().getApplication().get();
}

View File

@ -0,0 +1,79 @@
/*
* 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.dubbo.config.metadata;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.metadata.MetadataServiceExporter;
import org.apache.dubbo.metadata.MetadataServiceType;
import org.apache.dubbo.metadata.URLRevisionResolver;
import org.apache.dubbo.metadata.WritableMetadataService;
import org.apache.dubbo.metadata.report.MetadataReport;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
import java.util.SortedSet;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
/**
* The implementation of {@link MetadataServiceExporter} for
* {@link CommonConstants#REMOTE_METADATA_STORAGE_TYPE "remote" metadata storage type}
*
* @see MetadataServiceExporter
* @since 2.7.8
*/
public class RemoteMetadataServiceExporter extends AbstractMetadataServiceExporter {
private final URLRevisionResolver urlRevisionResolver;
public RemoteMetadataServiceExporter() {
super(REMOTE_METADATA_STORAGE_TYPE, MIN_PRIORITY, MetadataServiceType.REMOTE, MetadataServiceType.COMPOSITE);
this.urlRevisionResolver = URLRevisionResolver.INSTANCE;
}
@Override
protected void doExport() throws Exception {
WritableMetadataService metadataServiceDelegate = WritableMetadataService.getDefaultExtension();
if (publishServiceMetadata(metadataServiceDelegate)) {
publicConsumerMetadata(metadataServiceDelegate);
}
}
private boolean publishServiceMetadata(WritableMetadataService metadataServiceDelegate) {
String serviceName = metadataServiceDelegate.serviceName();
SortedSet<String> exportedURLs = metadataServiceDelegate.getExportedURLs();
String revision = urlRevisionResolver.resolve(exportedURLs);
return getMetadataReport().saveExportedURLs(serviceName, revision, exportedURLs);
}
private boolean publicConsumerMetadata(WritableMetadataService metadataServiceDelegate) {
String serviceName = metadataServiceDelegate.serviceName();
SortedSet<String> subscribedURLs = metadataServiceDelegate.getSubscribedURLs();
String revision = urlRevisionResolver.resolve(subscribedURLs);
getMetadataReport().saveSubscribedData(new SubscriberMetadataIdentifier(serviceName, revision), subscribedURLs);
return true;
}
private MetadataReport getMetadataReport() {
return MetadataReportInstance.getMetadataReport(true);
}
@Override
protected void doUnexport() throws Exception {
// DOES NOTHING
}
}

View File

@ -223,10 +223,12 @@ public class ConfigValidationUtils {
ApplicationConfig application = interfaceConfig.getApplication();
AbstractConfig.appendParameters(map, monitor);
AbstractConfig.appendParameters(map, application);
String address = monitor.getAddress();
String address = null;
String sysaddress = System.getProperty("dubbo.monitor.address");
if (sysaddress != null && sysaddress.length() > 0) {
address = sysaddress;
} else if (monitor != null) {
address = monitor.getAddress();
}
if (ConfigUtils.isNotEmpty(address)) {
if (!map.containsKey(PROTOCOL_KEY)) {
@ -237,7 +239,8 @@ public class ConfigValidationUtils {
}
}
return UrlUtils.parseURL(address, map);
} else if ((REGISTRY_PROTOCOL.equals(monitor.getProtocol()) || SERVICE_REGISTRY_PROTOCOL.equals(monitor.getProtocol()))
} else if (monitor != null &&
(REGISTRY_PROTOCOL.equals(monitor.getProtocol()) || SERVICE_REGISTRY_PROTOCOL.equals(monitor.getProtocol()))
&& registryURL != null) {
return URLBuilder.from(registryURL)
.setProtocol(DUBBO_PROTOCOL)

View File

@ -1,2 +1,4 @@
service-mapping=org.apache.dubbo.config.event.listener.ServiceNameMappingListener
config-logging=org.apache.dubbo.config.event.listener.LoggingEventListener
config-logging=org.apache.dubbo.config.event.listener.LoggingEventListener
# since 2.7.8
publishing-service-definition=org.apache.dubbo.config.event.listener.PublishingServiceDefinitionListener

View File

@ -0,0 +1,3 @@
# since 2.7.8
local = org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter
remote = org.apache.dubbo.config.metadata.RemoteMetadataServiceExporter

View File

@ -21,6 +21,7 @@ import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.api.DemoService;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@ -33,12 +34,12 @@ public class ReferenceConfigTest {
@BeforeEach
public void setUp() {
// ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@AfterEach
public void tearDown() {
// ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@Test

View File

@ -0,0 +1,52 @@
/*
* 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.dubbo.config.bootstrap;
import org.apache.dubbo.config.bootstrap.rest.UserService;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
/**
* Dubbo Provider Bootstrap
*
* @since 2.7.5
*/
public class ConsulDubboServiceConsumerBootstrap {
public static void main(String[] args) throws Exception {
DubboBootstrap bootstrap = DubboBootstrap.getInstance()
.application("consul-dubbo-consumer", app -> app.metadata(DEFAULT_METADATA_STORAGE_TYPE))
.registry("zookeeper", builder -> builder.address("consul://127.0.0.1:8500?registry-type=service&subscribed-services=consul-dubbo-provider")
.useAsConfigCenter(true)
.useAsMetadataCenter(true))
.reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo"))
.reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest"))
.start();
EchoService echoService = bootstrap.getCache().get(EchoService.class);
UserService userService = bootstrap.getCache().get(UserService.class);
for (int i = 0; i < 5; i++) {
Thread.sleep(2000L);
System.out.println(echoService.echo("Hello,World"));
System.out.println(userService.getUser(i * 1L));
}
bootstrap.stop();
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.dubbo.config.bootstrap;
import org.apache.dubbo.config.bootstrap.rest.UserService;
import org.apache.dubbo.config.bootstrap.rest.UserServiceImpl;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
/**
* TODO
*/
public class ConsulDubboServiceProviderBootstrap {
public static void main(String[] args) {
DubboBootstrap.getInstance()
.application("consul-dubbo-provider", app -> app.metadata(DEFAULT_METADATA_STORAGE_TYPE))
.registry(builder -> builder.address("consul://127.0.0.1:8500?registry-type=service")
.useAsConfigCenter(true)
.useAsMetadataCenter(true))
.protocol("dubbo", builder -> builder.port(-1).name("dubbo"))
.protocol("rest", builder -> builder.port(8081).name("rest"))
.service("echo", builder -> builder.interfaceClass(EchoService.class).ref(new EchoServiceImpl()).protocolIds("dubbo"))
.service("user", builder -> builder.interfaceClass(UserService.class).ref(new UserServiceImpl()).protocolIds("rest"))
.start()
.await();
}
}

View File

@ -17,9 +17,10 @@
package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.bootstrap.rest.UserService;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
/**
* Dubbo Provider Bootstrap
*
@ -30,21 +31,25 @@ public class NacosDubboServiceConsumerBootstrap {
public static void main(String[] args) throws Exception {
ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-nacos-consumer-demo");
// applicationConfig.setMetadataType("remote");
applicationConfig.setMetadataType(REMOTE_METADATA_STORAGE_TYPE);
DubboBootstrap bootstrap = DubboBootstrap.getInstance()
.application(applicationConfig)
// Zookeeper
// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service&subscribed.services=dubbo-nacos-provider-demo"))
// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-nacos-provider-demo"))
.registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-nacos-provider-demo"))
.metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
// Nacos in service registry type
.registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service")
.useAsConfigCenter(true)
.useAsMetadataCenter(true))
// Nacos in traditional registry type
// .registry("nacos-traditional", builder -> builder.address("nacos://127.0.0.1:8848"))
.reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo"))
.reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest"))
.start();
EchoService echoService = bootstrap.getCache().get(EchoService.class);
UserService userService = bootstrap.getCache().get(UserService.class);
for (int i = 0; i < 500; i++) {
for (int i = 0; i < 5; i++) {
Thread.sleep(2000L);
System.out.println(echoService.echo("Hello,World"));
System.out.println(userService.getUser(i * 1L));
}
}

View File

@ -17,10 +17,13 @@
package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.bootstrap.rest.UserService;
import org.apache.dubbo.config.bootstrap.rest.UserServiceImpl;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE;
/**
* Dubbo Provider Bootstrap
*
@ -30,15 +33,16 @@ public class NacosDubboServiceProviderBootstrap {
public static void main(String[] args) {
ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-nacos-provider-demo");
// applicationConfig.setMetadataType("remote");
applicationConfig.setMetadataType(REMOTE_METADATA_STORAGE_TYPE);
DubboBootstrap.getInstance()
.application(applicationConfig)
// Zookeeper in service registry type
.registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service").useAsConfigCenter(true))
// Nacos
// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service"))
// .registry(RegistryBuilder.newBuilder().address("etcd3://127.0.0.1:2379?registry.type=service").build())
.metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
// Nacos in service registry type
.registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848")
.parameter(REGISTRY_TYPE_KEY, SERVICE_REGISTRY_TYPE)
.useAsConfigCenter(true)
.useAsMetadataCenter(true))
// Nacos in traditional registry type
// .registry("nacos-traditional", builder -> builder.address("nacos://127.0.0.1:8848"))
.protocol("dubbo", builder -> builder.port(20885).name("dubbo"))
.protocol("rest", builder -> builder.port(9090).name("rest"))
.service(builder -> builder.id("echo").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).protocolIds("dubbo"))

View File

@ -18,6 +18,10 @@ package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.bootstrap.rest.UserService;
import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE;
/**
* Dubbo Provider Bootstrap
*
@ -28,9 +32,12 @@ public class ZookeeperDubboServiceConsumerBootstrap {
public static void main(String[] args) throws Exception {
DubboBootstrap bootstrap = DubboBootstrap.getInstance()
.application("zookeeper-dubbo-consumer")
.registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=zookeeper-dubbo-provider"))
.reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo"))
.application("zookeeper-dubbo-consumer", app -> app.metadata(COMPOSITE_METADATA_STORAGE_TYPE))
.registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181")
.parameter(REGISTRY_TYPE_KEY, SERVICE_REGISTRY_TYPE)
.useAsConfigCenter(true)
.useAsMetadataCenter(true))
.reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo").services("zookeeper-dubbo-provider"))
.reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest"))
.start();

View File

@ -19,6 +19,10 @@ package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.bootstrap.rest.UserService;
import org.apache.dubbo.config.bootstrap.rest.UserServiceImpl;
import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE;
/**
* TODO
*/
@ -26,8 +30,11 @@ public class ZookeeperDubboServiceProviderBootstrap {
public static void main(String[] args) {
DubboBootstrap.getInstance()
.application("zookeeper-dubbo-provider")
.registry(builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service"))
.application("zookeeper-dubbo-provider", app -> app.metadata(COMPOSITE_METADATA_STORAGE_TYPE))
.registry(builder -> builder.address("zookeeper://127.0.0.1:2181")
.parameter(REGISTRY_TYPE_KEY, SERVICE_REGISTRY_TYPE)
.useAsConfigCenter(true)
.useAsMetadataCenter(true))
.protocol("dubbo", builder -> builder.port(-1).name("dubbo"))
.protocol("rest", builder -> builder.port(8081).name("rest"))
.service("echo", builder -> builder.interfaceClass(EchoService.class).ref(new EchoServiceImpl()).protocolIds("dubbo"))

View File

@ -26,6 +26,8 @@ import org.junit.jupiter.api.Test;
import java.util.Collections;
import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
class ReferenceBuilderTest {
@Test
@ -95,8 +97,15 @@ class ReferenceBuilderTest {
MethodConfig method = new MethodConfig();
ReferenceBuilder<DemoService> builder = new ReferenceBuilder<>();
builder.id("id").interfaceClass(DemoService.class).protocol("protocol").client("client").url("url")
.consumer(consumer).addMethod(method);
builder.id("id")
.interfaceClass(DemoService.class)
.protocol("protocol")
.client("client")
.url("url")
.consumer(consumer)
.addMethod(method)
// introduced since 2.7.8
.services("test-service", "test-service2");
ReferenceConfig config = builder.build();
ReferenceConfig config2 = builder.build();
@ -107,6 +116,8 @@ class ReferenceBuilderTest {
Assertions.assertEquals("client", config.getClient());
Assertions.assertEquals("url", config.getUrl());
Assertions.assertEquals(consumer, config.getConsumer());
Assertions.assertEquals("test-service,test-service2", config.getServices());
Assertions.assertEquals(ofSet("test-service", "test-service2"), config.getSubscribedServices());
Assertions.assertTrue(config.getMethods().contains(method));
Assertions.assertEquals(1, config.getMethods().size());
Assertions.assertNotSame(config, config2);

View File

@ -220,7 +220,7 @@ class RegistryBuilderTest {
.transporter("transporter").server("server").client("client").cluster("cluster").group("group")
.version("version").timeout(1000).session(2000).file("file").wait(Integer.valueOf(10)).isCheck(true)
.isDynamic(false).register(true).subscribe(false).isDefault(true).simplified(false).extraKeys("A")
.appendParameter("default.num", "one").id("id").prefix("prefix");
.parameter("default.num", "one").id("id").prefix("prefix");
RegistryConfig config = builder.build();
RegistryConfig config2 = builder.build();

View File

@ -0,0 +1,94 @@
/*
* 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.dubbo.config.event.listener;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.bootstrap.EchoService;
import org.apache.dubbo.config.bootstrap.EchoServiceImpl;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.config.event.ServiceConfigExportedEvent;
import org.apache.dubbo.metadata.WritableMetadataService;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.rpc.model.ApplicationModel;
import com.google.gson.Gson;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
import static org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder.buildFullDefinition;
import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY;
import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* {@link PublishingServiceDefinitionListener} Test-Cases
*
* @since 2.7.8
*/
public class PublishingServiceDefinitionListenerTest {
private WritableMetadataService writableMetadataService;
@BeforeEach
public void init() {
String metadataType = DEFAULT_METADATA_STORAGE_TYPE;
ConfigManager configManager = ApplicationModel.getConfigManager();
ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-demo-provider");
applicationConfig.setMetadataType(metadataType);
configManager.setApplication(applicationConfig);
this.writableMetadataService = WritableMetadataService.getExtension(metadataType);
}
@AfterEach
public void reset() {
ApplicationModel.reset();
}
/**
* Test {@link ServiceConfigExportedEvent} arising
*/
@Test
public void testOnServiceConfigExportedEvent() {
ServiceConfig<EchoService> serviceConfig = new ServiceConfig<>();
serviceConfig.setInterface(EchoService.class);
serviceConfig.setRef(new EchoServiceImpl());
serviceConfig.setRegistry(new RegistryConfig("N/A"));
serviceConfig.export();
String serviceDefinition = writableMetadataService.getServiceDefinition(EchoService.class.getName());
List<URL> exportedUrls = serviceConfig.getExportedUrls();
FullServiceDefinition fullServiceDefinition = buildFullDefinition(
serviceConfig.getInterfaceClass(),
exportedUrls.get(0)
.removeParameters(PID_KEY, TIMESTAMP_KEY, BIND_IP_KEY, BIND_PORT_KEY, TIMESTAMP_KEY)
.getParameters()
);
assertEquals(serviceDefinition, new Gson().toJson(fullServiceDefinition));
}
}

View File

@ -0,0 +1,106 @@
/*
* 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.dubbo.config.metadata;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.metadata.MetadataServiceExporter;
import org.apache.dubbo.metadata.WritableMetadataService;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.service.EchoService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static java.util.Arrays.asList;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
import static org.apache.dubbo.metadata.MetadataServiceExporter.getExtension;
import static org.apache.dubbo.metadata.report.support.Constants.SYNC_REPORT_KEY;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link RemoteMetadataServiceExporter} Test-Cases
*
* @since 2.7.8
*/
public class RemoteMetadataServiceExporterTest {
private static final URL METADATA_REPORT_URL = URL.valueOf("file://")
.addParameter(APPLICATION_KEY, "test")
.addParameter(SYNC_REPORT_KEY, "true");
private static final Class<EchoService> INTERFACE_CLASS = EchoService.class;
private static final String INTERFACE_NAME = INTERFACE_CLASS.getName();
private static final String APP_NAME = "test-service";
private static final URL BASE_URL = URL
.valueOf("dubbo://127.0.0.1:20880")
.setPath(INTERFACE_NAME)
.addParameter(APPLICATION_KEY, APP_NAME)
.addParameter(SIDE_KEY, "provider");
private final MetadataServiceExporter exporter = getExtension(REMOTE_METADATA_STORAGE_TYPE);
private WritableMetadataService writableMetadataService;
@BeforeEach
public void init() {
ApplicationModel.getConfigManager().setApplication(new ApplicationConfig(APP_NAME));
MetadataReportInstance.init(METADATA_REPORT_URL);
writableMetadataService = WritableMetadataService.getDefaultExtension();
writableMetadataService.exportURL(BASE_URL);
}
@AfterEach
public void reset() {
ApplicationModel.reset();
}
@Test
public void testType() {
assertEquals(RemoteMetadataServiceExporter.class, exporter.getClass());
}
@Test
public void testSupports() {
assertTrue(exporter.supports(REMOTE_METADATA_STORAGE_TYPE));
assertTrue(exporter.supports(COMPOSITE_METADATA_STORAGE_TYPE));
assertFalse(exporter.supports(DEFAULT_METADATA_STORAGE_TYPE));
}
@Test
public void testExportAndUnexport() {
assertFalse(exporter.isExported());
assertEquals(exporter, exporter.export());
assertTrue(exporter.isExported());
assertEquals(asList(BASE_URL), exporter.getExportedURLs());
assertEquals(exporter, exporter.unexport());
assertFalse(exporter.isExported());
}
}

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.config.url;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
@ -42,13 +43,13 @@ public class ExporterSideConfigUrlTest extends UrlTestBase {
@BeforeEach
public void setUp() {
ApplicationModel.reset();
initServConf();
// ApplicationModel.getConfigManager().clear();
}
@AfterEach()
public void teardown() {
// ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@Test

View File

@ -0,0 +1,42 @@
/*
* 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.dubbo.metadata;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link MetadataServiceExporter} Test-Cases
*
* @since 2.7.8
*/
public class MetadataServiceExporterTest {
@Test
public void test() {
MetadataServiceExporter exporter = MetadataServiceExporter.getExtension(null);
assertEquals(exporter, MetadataServiceExporter.getDefaultExtension());
assertTrue(exporter.supports(DEFAULT_METADATA_STORAGE_TYPE));
assertTrue(exporter.supports(REMOTE_METADATA_STORAGE_TYPE));
assertTrue(exporter.supports(COMPOSITE_METADATA_STORAGE_TYPE));
}
}

View File

@ -142,6 +142,27 @@
<scope>test</scope>
</dependency>
<!-- Zookeeper dependencies for testing -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-zookeeper</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-metadata-report-zookeeper</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Nacos dependencies for testing -->
<dependency>
<groupId>org.apache.dubbo</groupId>

View File

@ -17,11 +17,11 @@
package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import com.alibaba.spring.beans.factory.annotation.AbstractAnnotationBeanPostProcessor;
import org.springframework.beans.BeansException;
@ -31,12 +31,9 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.AnnotationAttributes;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
@ -46,7 +43,6 @@ import java.util.concurrent.ConcurrentMap;
import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
import static com.alibaba.spring.util.AnnotationUtils.getAttributes;
import static java.lang.reflect.Proxy.newProxyInstance;
import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create;
import static org.springframework.util.StringUtils.hasText;
@ -60,7 +56,7 @@ import static org.springframework.util.StringUtils.hasText;
* @since 2.5.7
*/
public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBeanPostProcessor implements
ApplicationContextAware, ApplicationListener<ServiceBeanExportedEvent> {
ApplicationContextAware {
/**
* The bean name of {@link ReferenceAnnotationBeanPostProcessor}
@ -81,9 +77,6 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
private final ConcurrentMap<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedMethodReferenceBeanCache =
new ConcurrentHashMap<>(CACHE_SIZE);
private final ConcurrentMap<String, ReferencedBeanInvocationHandler> referencedBeanInvocationHandlersCache =
new ConcurrentHashMap<>();
private ApplicationContext applicationContext;
/**
@ -142,11 +135,13 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);
prepareReferenceBean(referencedBeanName, referenceBean, localServiceBean);
registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);
cacheInjectedReferenceBean(referenceBean, injectedElement);
return getOrCreateProxy(referencedBeanName, referenceBean, localServiceBean, injectedType);
return referenceBean.get();
}
/**
@ -261,23 +256,19 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
}
/**
* Get or Create a proxy of {@link ReferenceBean} for the specified the type of Dubbo service interface
* Prepare {@link ReferenceBean}
*
* @param referencedBeanName The name of bean that annotated Dubbo's {@link Service @Service} in the Spring {@link ApplicationContext}
* @param referenceBean the instance of {@link ReferenceBean}
* @param localServiceBean Is Local Service bean or not
* @param serviceInterfaceType the type of Dubbo service interface
* @return non-null
* @since 2.7.4
* @param referencedBeanName The name of bean that annotated Dubbo's {@link DubboService @DubboService}
* in the Spring {@link ApplicationContext}
* @param referenceBean the instance of {@link ReferenceBean}
* @param localServiceBean Is Local Service bean or not
* @since 2.7.8
*/
private Object getOrCreateProxy(String referencedBeanName, ReferenceBean referenceBean, boolean localServiceBean,
Class<?> serviceInterfaceType) {
if (localServiceBean) { // If the local @Service Bean exists, build a proxy of Service
return newProxyInstance(getClassLoader(), new Class[]{serviceInterfaceType},
newReferencedBeanInvocationHandler(referencedBeanName));
} else {
private void prepareReferenceBean(String referencedBeanName, ReferenceBean referenceBean, boolean localServiceBean) {
// Issue : https://github.com/apache/dubbo/issues/6224
if (localServiceBean) { // If the local @Service Bean exists
referenceBean.setInjvm(Boolean.TRUE);
exportServiceBeanIfNecessary(referencedBeanName); // If the referenced ServiceBean exits, export it immediately
return referenceBean.get();
}
}
@ -295,58 +286,6 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
return applicationContext.getBean(referencedBeanName, ServiceBean.class);
}
private InvocationHandler newReferencedBeanInvocationHandler(String referencedBeanName) {
return referencedBeanInvocationHandlersCache.computeIfAbsent(referencedBeanName,
ReferencedBeanInvocationHandler::new);
}
/**
* The {@link InvocationHandler} class for the referenced Bean
*/
@Override
public void onApplicationEvent(ServiceBeanExportedEvent event) {
initReferencedBeanInvocationHandler(event.getServiceBean());
}
private void initReferencedBeanInvocationHandler(ServiceBean serviceBean) {
String serviceBeanName = serviceBean.getBeanName();
referencedBeanInvocationHandlersCache.computeIfPresent(serviceBeanName, (name, handler) -> {
handler.init();
return null;
});
}
private class ReferencedBeanInvocationHandler implements InvocationHandler {
private final String referencedBeanName;
private Object bean;
private ReferencedBeanInvocationHandler(String referencedBeanName) {
this.referencedBeanName = referencedBeanName;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
if (bean == null) {
init();
}
result = method.invoke(bean, args);
} catch (InvocationTargetException e) {
// re-throws the actual Exception.
throw e.getTargetException();
}
return result;
}
private void init() {
ServiceBean serviceBean = applicationContext.getBean(referencedBeanName, ServiceBean.class);
this.bean = serviceBean.getRef();
}
}
@Override
protected String buildInjectedObjectCacheKey(AnnotationAttributes attributes, Object bean, String beanName,
Class<?> injectedType, InjectionMetadata.InjectedElement injectedElement) {
@ -402,7 +341,6 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
public void destroy() throws Exception {
super.destroy();
this.referenceBeanCache.clear();
this.referencedBeanInvocationHandlersCache.clear();
this.injectedFieldReferenceBeanCache.clear();
this.injectedMethodReferenceBeanCache.clear();
}

View File

@ -25,7 +25,6 @@ import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import static org.apache.dubbo.config.spring.util.DubboBeanUtils.registerCommonBeans;
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
import static org.springframework.util.StringUtils.trimArrayElements;
@ -58,8 +57,13 @@ public class AnnotationBeanDefinitionParser extends AbstractSingleBeanDefinition
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// @since 2.7.6 Register the common beans
registerCommonBeans(parserContext.getRegistry());
/**
* @since 2.7.6 Register the common beans
* @since 2.7.8 comment this code line, and migrated to
* @see DubboNamespaceHandler#parse(Element, ParserContext)
* @see https://github.com/apache/dubbo/issues/6174
*/
// registerCommonBeans(parserContext.getRegistry());
}
@Override

View File

@ -29,14 +29,13 @@ import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigAliasPostProcessor;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
@ -55,7 +54,6 @@ import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import static com.alibaba.spring.util.BeanRegistrar.registerInfrastructureBean;
import static org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX;
/**
@ -80,7 +78,7 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
}
@SuppressWarnings("unchecked")
private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
private static RootBeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(beanClass);
beanDefinition.setLazyInit(false);
@ -130,7 +128,7 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
parseProperties(element.getChildNodes(), classDefinition, parserContext);
beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
}
} else if (ProviderConfig.class.equals(beanClass)) {
} else if (ProviderConfig.class.equals(beanClass)) {
parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
} else if (ConsumerConfig.class.equals(beanClass)) {
parseNested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDefinition);
@ -350,11 +348,18 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
if (methods == null) {
methods = new ManagedList();
}
BeanDefinition methodBeanDefinition = parse(element,
RootBeanDefinition methodBeanDefinition = parse(element,
parserContext, MethodConfig.class, false);
String name = id + "." + methodName;
String beanName = id + "." + methodName;
// If the PropertyValue named "id" can't be found,
// bean name will be taken as the "id" PropertyValue for MethodConfig
if (!hasPropertyValue(methodBeanDefinition, "id")) {
addPropertyValue(methodBeanDefinition, "id", beanName);
}
BeanDefinitionHolder methodBeanDefinitionHolder = new BeanDefinitionHolder(
methodBeanDefinition, name);
methodBeanDefinition, beanName);
methods.add(methodBeanDefinitionHolder);
}
}
@ -363,6 +368,17 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
}
}
private static boolean hasPropertyValue(AbstractBeanDefinition beanDefinition, String propertyName) {
return beanDefinition.getPropertyValues().contains(propertyName);
}
private static void addPropertyValue(AbstractBeanDefinition beanDefinition, String propertyName, String propertyValue) {
if (StringUtils.isBlank(propertyName) || StringUtils.isBlank(propertyValue)) {
return;
}
beanDefinition.getPropertyValues().addPropertyValue(propertyName, propertyValue);
}
@SuppressWarnings("unchecked")
private static void parseArguments(String id, NodeList nodeList, RootBeanDefinition beanDefinition,
ParserContext parserContext) {
@ -395,22 +411,9 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// Register DubboConfigAliasPostProcessor
registerDubboConfigAliasPostProcessor(parserContext.getRegistry());
return parse(element, parserContext, beanClass, required);
}
/**
* Register {@link DubboConfigAliasPostProcessor}
*
* @param registry {@link BeanDefinitionRegistry}
* @since 2.7.5 [Feature] https://github.com/apache/dubbo/issues/5093
*/
private void registerDubboConfigAliasPostProcessor(BeanDefinitionRegistry registry) {
registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME, DubboConfigAliasPostProcessor.class);
}
private static String resolveAttribute(Element element, String attributeName, ParserContext parserContext) {
String attributeValue = element.getAttribute(attributeName);
Environment environment = parserContext.getReaderContext().getEnvironment();

View File

@ -6,7 +6,8 @@
targetNamespace="http://dubbo.apache.org/schema/dubbo">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/beans"
schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:annotation>
@ -702,7 +703,8 @@
</xsd:attribute>
<xsd:attribute name="cluster" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[ The config center cluster, it's real meaning may very on different Config Center products. ]]></xsd:documentation>
<xsd:documentation>
<![CDATA[ The config center cluster, it's real meaning may very on different Config Center products. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="namespace" type="xsd:string" use="optional">
@ -945,7 +947,8 @@
</xsd:attribute>
<xsd:attribute name="threadpool" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[ Consumer threadpool: cached, fixed, limited, eager]]></xsd:documentation>
<xsd:documentation>
<![CDATA[ Consumer threadpool: cached, fixed, limited, eager]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="corethreads" type="xsd:string">
@ -1011,6 +1014,14 @@
<xsd:documentation><![CDATA[ The service protocol. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="services" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
<![CDATA[ The service names that the Dubbo interface subscribed.
If it is a multiple-values, the content will be a comma-delimited String. ]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:anyAttribute namespace="##other" processContents="lax"/>
</xsd:extension>
</xsd:complexContent>

View File

@ -22,11 +22,14 @@ import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.api.DemoService;
import org.apache.dubbo.config.spring.api.HelloService;
import org.apache.dubbo.config.utils.ReferenceConfigCache;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -67,6 +70,16 @@ import static org.junit.Assert.assertTrue;
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class ReferenceAnnotationBeanPostProcessorTest {
@Before
public void setUp() {
ApplicationModel.reset();
}
@After
public void tearDown() {
ApplicationModel.reset();
}
private static final String AOP_SUFFIX = "(based on AOP)";
@Aspect

View File

@ -17,15 +17,20 @@
package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ -33,6 +38,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
import static org.springframework.util.ReflectionUtils.findField;
@ -40,6 +46,7 @@ import static org.springframework.util.ReflectionUtils.findField;
* {@link ReferenceBeanBuilder} Test
*
* @see ReferenceBeanBuilder
* @see DubboReference
* @see Reference
* @since 2.6.4
*/
@ -47,7 +54,7 @@ import static org.springframework.util.ReflectionUtils.findField;
@ContextConfiguration(classes = ReferenceBeanBuilderTest.class)
public class ReferenceBeanBuilderTest {
@Reference(
@DubboReference(
interfaceClass = CharSequence.class,
interfaceName = "java.lang.CharSequence",
version = "1.0.0", group = "TEST_GROUP", url = "dubbo://localhost:12345",
@ -62,17 +69,27 @@ public class ReferenceBeanBuilderTest {
timeout = 3, cache = "cache", filter = {"echo", "generic", "accesslog"},
listener = {"deprecated"}, parameters = {"n1=v1 ", "n2 = v2 ", " n3 = v3 "},
application = "application",
module = "module", consumer = "consumer", monitor = "monitor", registry = {"registry"}
module = "module", consumer = "consumer", monitor = "monitor", registry = {"registry"},
// @since 2.7.3
id = "reference",
// @since 2.7.8
services = {"service1", "service2", "service3", "service2", "service1"}
)
private static final Object TEST_FIELD = new Object();
@Autowired
private ApplicationContext context;
@Before
public void init() {
ApplicationModel.reset();
}
@Test
public void testBuild() throws Exception {
Reference reference = findAnnotation(findField(getClass(), "TEST_FIELD"), Reference.class);
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder.create(reference, context.getClassLoader(), context);
DubboReference reference = findAnnotation(findField(getClass(), "TEST_FIELD"), DubboReference.class);
AnnotationAttributes attributes = AnnotationUtils.getAnnotationAttributes(reference, false, false);
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder.create(attributes, context);
beanBuilder.interfaceClass(CharSequence.class);
ReferenceBean referenceBean = beanBuilder.build();
Assert.assertEquals(CharSequence.class, referenceBean.getInterfaceClass());
@ -81,7 +98,7 @@ public class ReferenceBeanBuilderTest {
Assert.assertEquals("dubbo://localhost:12345", referenceBean.getUrl());
Assert.assertEquals("client", referenceBean.getClient());
Assert.assertEquals(true, referenceBean.isGeneric());
Assert.assertNull(referenceBean.isInjvm());
Assert.assertTrue(referenceBean.isInjvm());
Assert.assertEquals(false, referenceBean.isCheck());
Assert.assertFalse(referenceBean.isInit());
Assert.assertEquals(true, referenceBean.getLazy());
@ -108,6 +125,8 @@ public class ReferenceBeanBuilderTest {
Assert.assertEquals("cache", referenceBean.getCache());
Assert.assertEquals("echo,generic,accesslog", referenceBean.getFilter());
Assert.assertEquals("deprecated", referenceBean.getListener());
Assert.assertEquals("reference", referenceBean.getId());
Assert.assertEquals(ofSet("service1", "service2", "service3"), referenceBean.getSubscribedServices());
// parameters
Map<String, String> parameters = new HashMap<String, String>();

View File

@ -18,8 +18,11 @@ package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.api.HelloService;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -49,6 +52,16 @@ import java.util.Map;
})
public class ServiceAnnotationBeanPostProcessorTest {
@Before
public void setUp() {
ApplicationModel.reset();
}
@After
public void tearDown() {
ApplicationModel.reset();
}
@Autowired
private ConfigurableListableBeanFactory beanFactory;

View File

@ -18,8 +18,11 @@ package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.api.HelloService;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -49,6 +52,16 @@ import java.util.Map;
})
public class ServiceClassPostProcessorTest {
@Before
public void setUp() {
ApplicationModel.reset();
}
@After
public void tearDown() {
ApplicationModel.reset();
}
@Autowired
private ConfigurableListableBeanFactory beanFactory;

View File

@ -0,0 +1,42 @@
/*
* 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.dubbo.config.spring.beans.factory.config;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ImportResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MultipleServicesWithMethodConfigsTest.class)
@ImportResource(locations = "classpath:/META-INF/spring/multiple-services-with-methods.xml")
public class MultipleServicesWithMethodConfigsTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void test() {
// Map<String, MethodConfig> methodConfigs = applicationContext.getBeansOfType(MethodConfig.class);
// assertEquals(2, methodConfigs.size());
}
}

View File

@ -41,12 +41,12 @@ public class DubboComponentScanRegistrarTest {
@BeforeEach
public void setUp() {
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@AfterEach
public void tearDown() {
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@Test

View File

@ -52,13 +52,13 @@ public class EnableDubboTest {
@BeforeEach
public void setUp() {
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
context = new AnnotationConfigApplicationContext();
}
@AfterEach
public void tearDown() {
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
context.close();
}

View File

@ -38,7 +38,10 @@ public class TestConsumerConfiguration {
private static final String remoteURL = "dubbo://127.0.0.1:12345?version=2.5.7";
@Reference(version = "2.5.7", url = remoteURL, application = "dubbo-demo-application")
@Reference(version = "2.5.7",
url = remoteURL,
application = "dubbo-demo-application",
filter = "mymock")
private DemoService demoService;
@Autowired

View File

@ -20,7 +20,10 @@ package org.apache.dubbo.config.spring.context.properties;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.runner.RunWith;
@ -34,6 +37,16 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ContextConfiguration(classes = DefaultDubboConfigBinder.class)
public class DefaultDubboConfigBinderTest {
@Before
public void setUp() {
ApplicationModel.reset();
}
@After
public void tearDown() {
ApplicationModel.reset();
}
@Autowired
private DubboConfigBinder dubboConfigBinder;

View File

@ -0,0 +1,50 @@
/*
* 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.dubbo.config.spring.issues;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* The test-case for https://github.com/apache/dubbo/issues/6252
*
* @since 2.7.8
*/
@Configuration
@EnableDubboConfig
@PropertySource("classpath:/META-INF/issue-6252-test.properties")
public class Issue6252Test {
@Bean
public static ReferenceBean referenceBean() {
return new ReferenceBean();
}
@Test
public void test() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Issue6252Test.class);
context.getBean(ReferenceBean.class);
context.close();
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.dubbo.config.spring.samples;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.spring.api.DemoService;
import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.PropertySource;
/**
* Zookeeper Dubbo Spring Provider Bootstrap
*
* @since 2.7.8
*/
@EnableDubboConfig
@PropertySource("classpath:/META-INF/service-introspection/zookeeper-dubbb-consumer.properties")
public class ZookeeperDubboSpringConsumerBootstrap {
@DubboReference(services = "${dubbo.provider.name},${dubbo.provider.name1},${dubbo.provider.name2}")
private DemoService demoService;
public static void main(String[] args) throws Exception {
Class<?> beanType = ZookeeperDubboSpringConsumerBootstrap.class;
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(beanType);
ZookeeperDubboSpringConsumerBootstrap bootstrap = context.getBean(ZookeeperDubboSpringConsumerBootstrap.class);
for (int i = 0; i < 100; i++) {
System.out.println(bootstrap.demoService.sayName("Hello"));
Thread.sleep(1000L);
}
System.in.read();
context.close();
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.dubbo.config.spring.samples;
import org.apache.dubbo.config.spring.api.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Zookeeper Dubbo Spring Provider XML Bootstrap
*
* @since 2.7.8
*/
public class ZookeeperDubboSpringConsumerXmlBootstrap {
public static void main(String[] args) throws Exception {
String location = "classpath:/META-INF/service-introspection/zookeeper-dubbo-consumer.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(location);
DemoService demoService = context.getBean("demoService", DemoService.class);
for (int i = 0; i < 100; i++) {
System.out.println(demoService.sayName("Hello"));
}
context.close();
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.dubbo.config.spring.samples;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.spring.api.Box;
import org.apache.dubbo.config.spring.api.DemoService;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.PropertySource;
import static java.lang.String.format;
/**
* Zookeeper Dubbo Spring Provider Bootstrap
*
* @since 2.7.8
*/
@EnableDubbo
@PropertySource("classpath:/META-INF/service-introspection/zookeeper-dubbb-provider.properties")
public class ZookeeperDubboSpringProviderBootstrap {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ZookeeperDubboSpringProviderBootstrap.class);
System.in.read();
context.close();
}
}
@DubboService
class DefaultDemoService implements DemoService {
@Override
public String sayName(String name) {
RpcContext rpcContext = RpcContext.getContext();
return format("[%s:%s] Say - %s", rpcContext.getLocalHost(), rpcContext.getLocalPort(), name);
}
@Override
public Box getBox() {
return null;
}
}

View File

@ -49,12 +49,12 @@ import static org.hamcrest.MatcherAssert.assertThat;
public class DubboNamespaceHandlerTest {
@BeforeEach
public void setUp() {
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@AfterEach
public void tearDown() {
ApplicationModel.getConfigManager().clear();
ApplicationModel.reset();
}
@Configuration

View File

@ -18,7 +18,10 @@ package org.apache.dubbo.config.spring.schema;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -34,6 +37,16 @@ import static org.junit.Assert.assertNotNull;
@ImportResource(locations = "classpath:/META-INF/spring/dubbo-generic-consumer.xml")
public class GenericServiceTest {
@Before
public void setUp() {
ApplicationModel.reset();
}
@After
public void tearDown() {
ApplicationModel.reset();
}
@Autowired
@Qualifier("demoServiceRef")
private ReferenceBean referenceBean;

View File

@ -0,0 +1,11 @@
dubbo.application.name=demo-zk
dubbo.application.qos-enable=false
dubbo.protocol.name=dubbo
dubbo.protocol.port=-1
dubbo.scan.basePackages=com.example.demo
dubbo.consumer.check=false
dubbo.registries.z214.address=zookeeper://192.168.99.214:2181
dubbo.registries.z214.timeout=60000
dubbo.registries.z214.subscribe=false
dubbo.registries.z205.address=zookeeper://192.168.99.205:2181
dubbo.registries.z205.timeout=60000

Some files were not shown because too many files have changed in this diff Show More