Skip to content

Commit

Permalink
Enhancement and Bugfix in 2.7.1 ( Part 1 ) (#3670)
Browse files Browse the repository at this point in the history
* Polish /#3429 : Fix The NPE issue

* Polish /#3615 : SpringStatusChecker execute errors on non-XML Spring configuration

* Polish /#3193 : Change the default behavior of @EnableDubboConfig.multiple()
  • Loading branch information
mercyblitz authored and beiwei30 committed Mar 15, 2019
1 parent cb11ce0 commit bce2f44
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 113 deletions.
Expand Up @@ -32,6 +32,7 @@

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
Expand Down Expand Up @@ -155,7 +156,18 @@ private ReferenceBeanInvocationHandler(ReferenceBean referenceBean) {

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(bean, args);
Object result = null;
try {
if (bean == null) { // If the bean is not initialized, invoke init()
// issue: https://github.com/apache/incubator-dubbo/issues/3429
init();
}
result = method.invoke(bean, args);
} catch (InvocationTargetException e) {
// re-throws the actual Exception.
throw e.getTargetException();
}
return result;
}

private void init() {
Expand Down
Expand Up @@ -44,10 +44,11 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B

boolean multiple = attributes.getBoolean("multiple");

if (multiple) {
// Single Config Bindings
registerBeans(registry, DubboConfigConfiguration.Single.class);

if (multiple) { // Since 2.6.6 https://github.com/apache/incubator-dubbo/issues/3193
registerBeans(registry, DubboConfigConfiguration.Multiple.class);
} else {
registerBeans(registry, DubboConfigConfiguration.Single.class);
}
}

Expand Down
Expand Up @@ -76,6 +76,6 @@
* @see EnableDubboConfig#multiple()
*/
@AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple")
boolean multipleConfig() default false;
boolean multipleConfig() default true;

}
Expand Up @@ -59,7 +59,7 @@
*
* @see EnableDubboConfigBinding
* @see DubboConfigConfiguration
* @see DubboConfigConfigurationSelector
* @see DubboConfigConfigurationRegistrar
* @since 2.5.8
*/
@Target({ElementType.TYPE})
Expand All @@ -75,6 +75,6 @@
* @return the default value is <code>false</code>
* @revised 2.5.9
*/
boolean multiple() default false;
boolean multiple() default true;

}
@@ -1,94 +1,101 @@
/*
* 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.status;

import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.status.Status;
import org.apache.dubbo.common.status.StatusChecker;
import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;

import org.springframework.context.ApplicationContext;
import org.springframework.context.Lifecycle;

import java.lang.reflect.Method;

/**
* SpringStatusChecker
*/
@Activate
public class SpringStatusChecker implements StatusChecker {

private static final Logger logger = LoggerFactory.getLogger(SpringStatusChecker.class);

@Override
public Status check() {
ApplicationContext context = null;
for (ApplicationContext c : SpringExtensionFactory.getContexts()) {
if (c != null) {
context = c;
break;
}
}

if (context == null) {
return new Status(Status.Level.UNKNOWN);
}

Status.Level level = Status.Level.OK;
if (context instanceof Lifecycle) {
if (((Lifecycle) context).isRunning()) {
level = Status.Level.OK;
} else {
level = Status.Level.ERROR;
}
} else {
level = Status.Level.UNKNOWN;
}
StringBuilder buf = new StringBuilder();
try {
Class<?> cls = context.getClass();
Method method = null;
while (cls != null && method == null) {
try {
method = cls.getDeclaredMethod("getConfigLocations", new Class<?>[0]);
} catch (NoSuchMethodException t) {
cls = cls.getSuperclass();
}
}
if (method != null) {
if (!method.isAccessible()) {
method.setAccessible(true);
}
String[] configs = (String[]) method.invoke(context, new Object[0]);
if (configs != null && configs.length > 0) {
for (String config : configs) {
if (buf.length() > 0) {
buf.append(",");
}
buf.append(config);
}
}
}
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
return new Status(level, buf.toString());
}

}
/*
* 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.status;

import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.status.Status;
import org.apache.dubbo.common.status.StatusChecker;
import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;

import org.springframework.context.ApplicationContext;
import org.springframework.context.Lifecycle;
import org.springframework.web.context.support.GenericWebApplicationContext;

import java.lang.reflect.Method;

/**
* SpringStatusChecker
*/
@Activate
public class SpringStatusChecker implements StatusChecker {

private static final Logger logger = LoggerFactory.getLogger(SpringStatusChecker.class);

@Override
public Status check() {
ApplicationContext context = null;
for (ApplicationContext c : SpringExtensionFactory.getContexts()) {
// [Issue] SpringStatusChecker execute errors on non-XML Spring configuration
// issue : https://github.com/apache/incubator-dubbo/issues/3615
if(c instanceof GenericWebApplicationContext) { // ignore GenericXmlApplicationContext
continue;
}

if (c != null) {
context = c;
break;
}
}

if (context == null) {
return new Status(Status.Level.UNKNOWN);
}

Status.Level level = Status.Level.OK;
if (context instanceof Lifecycle) {
if (((Lifecycle) context).isRunning()) {
level = Status.Level.OK;
} else {
level = Status.Level.ERROR;
}
} else {
level = Status.Level.UNKNOWN;
}
StringBuilder buf = new StringBuilder();
try {
Class<?> cls = context.getClass();
Method method = null;
while (cls != null && method == null) {
try {
method = cls.getDeclaredMethod("getConfigLocations", new Class<?>[0]);
} catch (NoSuchMethodException t) {
cls = cls.getSuperclass();
}
}
if (method != null) {
if (!method.isAccessible()) {
method.setAccessible(true);
}
String[] configs = (String[]) method.invoke(context, new Object[0]);
if (configs != null && configs.length > 0) {
for (String config : configs) {
if (buf.length() > 0) {
buf.append(",");
}
buf.append(config);
}
}
}
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
return new Status(level, buf.toString());
}

}
Expand Up @@ -96,7 +96,7 @@ public Map<String, String> convert(String[] source) {
Assert.assertEquals("dubbo://localhost:12345", referenceBean.getUrl());
Assert.assertEquals("client", referenceBean.getClient());
Assert.assertEquals(true, referenceBean.isGeneric());
Assert.assertEquals(true, referenceBean.isInjvm());
Assert.assertNull(referenceBean.isInjvm());
Assert.assertEquals(false, referenceBean.isCheck());
Assert.assertEquals(true, referenceBean.isInit());
Assert.assertEquals(true, referenceBean.getLazy());
Expand Down
Expand Up @@ -81,7 +81,7 @@ public void testBuild() throws Exception {
Assert.assertEquals("dubbo://localhost:12345", referenceBean.getUrl());
Assert.assertEquals("client", referenceBean.getClient());
Assert.assertEquals(true, referenceBean.isGeneric());
Assert.assertEquals(true, referenceBean.isInjvm());
Assert.assertNull(referenceBean.isInjvm());
Assert.assertEquals(false, referenceBean.isCheck());
Assert.assertEquals(null, referenceBean.isInit());
Assert.assertEquals(true, referenceBean.getLazy());
Expand Down
Expand Up @@ -26,7 +26,6 @@

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.PropertySource;

Expand Down Expand Up @@ -95,13 +94,13 @@ public void testMultiple() {

}

@EnableDubboConfig(multiple = true)
@EnableDubboConfig
@PropertySource("META-INF/config.properties")
private static class TestMultipleConfig {

}

@EnableDubboConfig
@EnableDubboConfig(multiple = false)
@PropertySource("META-INF/config.properties")
private static class TestConfig {

Expand Down
Expand Up @@ -45,11 +45,6 @@ public String sayName(String name) {

@Override
public Box getBox() {
return new Box() {
@Override
public String getName() {
return "MyBox";
}
};
throw new UnsupportedOperationException("For Purposes!");
}
}
Expand Up @@ -20,14 +20,15 @@
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;

import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.context.ApplicationContext;
import org.springframework.context.Lifecycle;
import org.springframework.web.context.support.GenericWebApplicationContext;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
Expand Down Expand Up @@ -90,4 +91,14 @@ public void testWithoutLifeCycleRunning() {
interface ApplicationLifeCycle extends Lifecycle, ApplicationContext {
String[] getConfigLocations();
}

@Test
public void testGenericWebApplicationContext() {
SpringExtensionFactory.clearContexts();
GenericWebApplicationContext context = new GenericWebApplicationContext();
SpringExtensionFactory.addApplicationContext(context);
SpringStatusChecker checker = new SpringStatusChecker();
Status status = checker.check();
Assert.assertEquals(Status.Level.UNKNOWN, status.getLevel());
}
}

0 comments on commit bce2f44

Please sign in to comment.