[3.0] fix destroy IllegalStateException and doOverrideIfNecessary NPE (#8768)

* fix destroy IllegalState and doOverrideIfNecessary potential NPE

* add ut and fix NPE

* add UT

* fix ut
This commit is contained in:
zrlw 2021-09-21 00:23:46 +08:00 committed by GitHub
parent f29188797c
commit 22dc29472c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 3 deletions

View File

@ -32,6 +32,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@ -275,6 +276,11 @@ public class ApplicationModel extends ScopeModel {
return getCurrentConfig().getName();
}
public String tryGetApplicationName() {
Optional<ApplicationConfig> appCfgOptional = getApplicationConfigManager().getApplication();
return appCfgOptional.isPresent() ? appCfgOptional.get().getName() : null;
}
void addModule(ModuleModel moduleModel, boolean isInternal) {
synchronized (moduleLock) {
if (!this.moduleModels.contains(moduleModel)) {

View File

@ -733,6 +733,57 @@ public class ReferenceConfigTest {
}
@Test
public void test2ReferenceRetry() {
ApplicationConfig application = new ApplicationConfig();
application.setName("test-reference-retry2");
application.setEnableFileCache(false);
ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(application);
RegistryConfig registry = new RegistryConfig();
registry.setAddress(zkUrl1);
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName("mockprotocol");
ReferenceConfig<DemoService> rc = new ReferenceConfig<>();
rc.setRegistry(registry);
rc.setInterface(DemoService.class.getName());
boolean success = false;
DemoService demoService = null;
try {
demoService = rc.get();
success = true;
} catch (Exception e) {
// ignore
}
Assertions.assertFalse(success);
Assertions.assertNull(demoService);
ServiceConfig<DemoService> sc = new ServiceConfig<>();
sc.setInterface(DemoService.class.getName());
sc.setRef(new DemoServiceImpl());
sc.setRegistry(registry);
sc.setProtocol(protocol);
try {
System.setProperty("java.net.preferIPv4Stack", "true");
sc.export();
demoService = rc.get();
success = true;
} catch (Exception e) {
// ignore
} finally {
rc.destroy();
sc.unexport();
System.clearProperty("java.net.preferIPv4Stack");
}
Assertions.assertTrue(success);
Assertions.assertNotNull(demoService);
}
@Test
public void testMetaData() {
ReferenceConfig config = new ReferenceConfig();

View File

@ -604,9 +604,14 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
for (ApplicationModel applicationModel : frameworkModel.getApplicationModels()) {
if (applicationModel.getModelEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
for (ModuleModel moduleModel : applicationModel.getPubModuleModels()) {
String applicationName = applicationModel.tryGetApplicationName();
if (applicationName == null) {
// already removed
continue;
}
if (moduleModel.getServiceRepository().getExportedServices().size() > 0) {
moduleModel.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension()
.removeListener(applicationModel.getApplicationName() + CONFIGURATORS_SUFFIX,
.removeListener(applicationName + CONFIGURATORS_SUFFIX,
getProviderConfigurationListener(moduleModel));
}
}
@ -732,13 +737,14 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
return;
}
//The current, may have been merged many times
URL currentUrl = exporter.getInvoker().getUrl();
Invoker<?> exporterInvoker = exporter.getInvoker();
URL currentUrl = exporterInvoker == null ? null : exporterInvoker.getUrl();
//Merged with this configuration
URL newUrl = getConfiguredInvokerUrl(configurators, originUrl);
newUrl = getConfiguredInvokerUrl(getProviderConfigurationListener(originUrl).getConfigurators(), newUrl);
newUrl = getConfiguredInvokerUrl(serviceConfigurationListeners.get(originUrl.getServiceKey())
.getConfigurators(), newUrl);
if (!currentUrl.equals(newUrl)) {
if (!newUrl.equals(currentUrl)) {
if (newUrl.getParameter(Constants.NEED_REEXPORT, true)) {
RegistryProtocol.this.reExport(originInvoker, newUrl);
}