More robust instantiation in SpringClientFactory

SpringClientFactory returns null if the class is not aware of IClientConfig.

This change catches the exception when trying the constructor with IClientConfig so classes that aren't aware of IClientConfig can be created.

Fixes gh-1608
This commit is contained in:
Arnaud Brunet
2017-01-13 08:15:31 +11:00
committed by Spencer Gibb
parent 3b41b5e15f
commit b27ba0434a
2 changed files with 69 additions and 20 deletions

View File

@@ -16,6 +16,8 @@
package org.springframework.cloud.netflix.ribbon;
import java.lang.reflect.Constructor;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.context.named.NamedContextFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -80,33 +82,30 @@ public class SpringClientFactory extends NamedContextFactory<RibbonClientSpecifi
static <C> C instantiateWithConfig(AnnotationConfigApplicationContext context,
Class<C> clazz, IClientConfig config) {
C result = null;
if (IClientConfigAware.class.isAssignableFrom(clazz)) {
IClientConfigAware obj = (IClientConfigAware) BeanUtils.instantiate(clazz);
obj.initWithNiwsConfig(config);
@SuppressWarnings("unchecked")
C value = (C) obj;
result = value;
try {
Constructor<C> constructor = clazz.getConstructor(IClientConfig.class);
result = constructor.newInstance(config);
} catch (Throwable e) {
// Ignored
}
else {
try {
if (clazz.getConstructor(IClientConfig.class) != null) {
result = clazz.getConstructor(IClientConfig.class)
.newInstance(config);
}
else {
result = BeanUtils.instantiate(clazz);
}
if (result == null) {
result = BeanUtils.instantiate(clazz);
if (result instanceof IClientConfigAware) {
((IClientConfigAware) result).initWithNiwsConfig(config);
}
catch (Throwable ex) {
// NOPMD
if (context != null) {
context.getAutowireCapableBeanFactory().autowireBean(result);
}
}
if (context != null) {
context.getAutowireCapableBeanFactory().autowireBean(result);
}
return result;
}
@Override
public <C> C getInstance(String name, Class<C> type) {
C instance = super.getInstance(name, type);
if (instance != null) {

View File

@@ -23,9 +23,13 @@ import org.springframework.cloud.netflix.archaius.ArchaiusAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.netflix.client.DefaultLoadBalancerRetryHandler;
import com.netflix.client.IClientConfigAware;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.netflix.niws.client.http.RestClient;
import com.sun.jersey.client.apache4.ApacheHttpClient4;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.springframework.boot.test.util.EnvironmentTestUtils.addEnvironment;
@@ -35,6 +39,31 @@ import static org.springframework.boot.test.util.EnvironmentTestUtils.addEnviron
*/
public class SpringClientFactoryTests {
public static class ClientConfigInjectedByConstructor {
private IClientConfig clientConfig;
public ClientConfigInjectedByConstructor(IClientConfig clientConfig) {
this.clientConfig = clientConfig;
}
}
public static class ClientConfigInjectedByInitMethod implements IClientConfigAware {
private IClientConfig clientConfig;
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
this.clientConfig = clientConfig;
}
}
public static class NoClientConfigAware {
public NoClientConfigAware() {
// no client config
}
}
@Test
public void testConfigureRetry() {
@@ -65,4 +94,25 @@ public class SpringClientFactoryTests {
.getHttpClient().getParams().getParameter(ClientPNames.COOKIE_POLICY));
factory.destroy();
}
@Test
public void testInstantiateWithConfigInjectByConstructor() {
IClientConfig clientConfig = new DefaultClientConfigImpl();
ClientConfigInjectedByConstructor instance = SpringClientFactory.instantiateWithConfig(ClientConfigInjectedByConstructor.class, clientConfig);
assertThat(instance.clientConfig).isSameAs(clientConfig);
}
@Test
public void testInstantiateWithConfigInjectedByInitMethod() {
IClientConfig clientConfig = new DefaultClientConfigImpl();
ClientConfigInjectedByInitMethod instance = SpringClientFactory.instantiateWithConfig(ClientConfigInjectedByInitMethod.class, clientConfig);
assertThat(instance.clientConfig).isSameAs(clientConfig);
}
@Test
public void testInstantiateWithoutConfig() {
IClientConfig clientConfig = new DefaultClientConfigImpl();
NoClientConfigAware instance = SpringClientFactory.instantiateWithConfig(NoClientConfigAware.class, clientConfig);
assertThat(instance).isNotNull();
}
}