JndiObjectFactoryBean converts a "defaultObject" value to the expected type if necessary
Issue: SPR-11039
This commit is contained in:
parent
dcc6ef262d
commit
0aedd81ccc
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -25,8 +25,14 @@ import org.aopalliance.intercept.MethodInterceptor;
|
|||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.SimpleTypeConverter;
|
||||
import org.springframework.beans.TypeConverter;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
|
@ -61,9 +67,10 @@ import org.springframework.util.ClassUtils;
|
|||
* @see #setCache
|
||||
* @see JndiObjectTargetSource
|
||||
*/
|
||||
public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryBean<Object>, BeanClassLoaderAware {
|
||||
public class JndiObjectFactoryBean extends JndiObjectLocator
|
||||
implements FactoryBean<Object>, BeanFactoryAware, BeanClassLoaderAware {
|
||||
|
||||
private Class[] proxyInterfaces;
|
||||
private Class<?>[] proxyInterfaces;
|
||||
|
||||
private boolean lookupOnStartup = true;
|
||||
|
||||
|
@ -73,6 +80,8 @@ public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryB
|
|||
|
||||
private Object defaultObject;
|
||||
|
||||
private ConfigurableBeanFactory beanFactory;
|
||||
|
||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
private Object jndiObject;
|
||||
|
@ -87,8 +96,8 @@ public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryB
|
|||
* @see #setLookupOnStartup
|
||||
* @see #setCache
|
||||
*/
|
||||
public void setProxyInterface(Class proxyInterface) {
|
||||
this.proxyInterfaces = new Class[] {proxyInterface};
|
||||
public void setProxyInterface(Class<?> proxyInterface) {
|
||||
this.proxyInterfaces = new Class<?>[] {proxyInterface};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,7 +109,7 @@ public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryB
|
|||
* @see #setLookupOnStartup
|
||||
* @see #setCache
|
||||
*/
|
||||
public void setProxyInterfaces(Class[] proxyInterfaces) {
|
||||
public void setProxyInterfaces(Class<?>... proxyInterfaces) {
|
||||
this.proxyInterfaces = proxyInterfaces;
|
||||
}
|
||||
|
||||
|
@ -149,12 +158,25 @@ public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryB
|
|||
* It is typically used for literal values in scenarios where the JNDI environment
|
||||
* might define specific config settings but those are not required to be present.
|
||||
* <p>Note: This is only supported for lookup on startup.
|
||||
* If specified together with {@link #setExpectedType}, the specified value
|
||||
* needs to be either of that type or convertible to it.
|
||||
* @see #setLookupOnStartup
|
||||
* @see ConfigurableBeanFactory#getTypeConverter()
|
||||
* @see SimpleTypeConverter
|
||||
*/
|
||||
public void setDefaultObject(Object defaultObject) {
|
||||
this.defaultObject = defaultObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (beanFactory instanceof ConfigurableBeanFactory) {
|
||||
// Just optional - for getting a specifically configured TypeConverter if needed.
|
||||
// We'll simply fall back to a SimpleTypeConverter if no specific one available.
|
||||
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
|
@ -180,9 +202,16 @@ public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryB
|
|||
else {
|
||||
if (this.defaultObject != null && getExpectedType() != null &&
|
||||
!getExpectedType().isInstance(this.defaultObject)) {
|
||||
throw new IllegalArgumentException("Default object [" + this.defaultObject +
|
||||
"] of type [" + this.defaultObject.getClass().getName() +
|
||||
"] is not of expected type [" + getExpectedType().getName() + "]");
|
||||
TypeConverter converter = (this.beanFactory != null ?
|
||||
this.beanFactory.getTypeConverter() : new SimpleTypeConverter());
|
||||
try {
|
||||
this.defaultObject = converter.convertIfNecessary(this.defaultObject, getExpectedType());
|
||||
}
|
||||
catch (TypeMismatchException ex) {
|
||||
throw new IllegalArgumentException("Default object [" + this.defaultObject + "] of type [" +
|
||||
this.defaultObject.getClass().getName() + "] is not of expected type [" +
|
||||
getExpectedType().getName() + "] and cannot be converted either", ex);
|
||||
}
|
||||
}
|
||||
// Locate specified JNDI object.
|
||||
this.jndiObject = lookupWithFallback();
|
||||
|
@ -267,7 +296,7 @@ public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryB
|
|||
* @return the merged interface as Class
|
||||
* @see java.lang.reflect.Proxy#getProxyClass
|
||||
*/
|
||||
protected Class createCompositeInterface(Class[] interfaces) {
|
||||
protected Class<?> createCompositeInterface(Class<?>[] interfaces) {
|
||||
return ClassUtils.createCompositeInterface(interfaces, this.beanClassLoader);
|
||||
}
|
||||
|
||||
|
@ -294,13 +323,13 @@ public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryB
|
|||
proxyFactory.setInterfaces(jof.proxyInterfaces);
|
||||
}
|
||||
else {
|
||||
Class targetClass = targetSource.getTargetClass();
|
||||
Class<?> targetClass = targetSource.getTargetClass();
|
||||
if (targetClass == null) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot deactivate 'lookupOnStartup' without specifying a 'proxyInterface' or 'expectedType'");
|
||||
}
|
||||
Class[] ifcs = ClassUtils.getAllInterfacesForClass(targetClass, jof.beanClassLoader);
|
||||
for (Class ifc : ifcs) {
|
||||
Class<?>[] ifcs = ClassUtils.getAllInterfacesForClass(targetClass, jof.beanClassLoader);
|
||||
for (Class<?> ifc : ifcs) {
|
||||
if (Modifier.isPublic(ifc.getModifiers())) {
|
||||
proxyFactory.addInterface(ifc);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import javax.naming.Context;
|
|||
import javax.naming.NamingException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.tests.mock.jndi.ExpectedLookupTemplate;
|
||||
import org.springframework.tests.sample.beans.DerivedTestBean;
|
||||
import org.springframework.tests.sample.beans.ITestBean;
|
||||
|
@ -142,8 +144,7 @@ public class JndiObjectFactoryBeanTests {
|
|||
@Test
|
||||
public void testLookupWithExpectedTypeAndNoMatch() throws Exception {
|
||||
JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
|
||||
Object o = new Object();
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", o));
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", new Object()));
|
||||
jof.setJndiName("foo");
|
||||
jof.setExpectedType(String.class);
|
||||
try {
|
||||
|
@ -151,15 +152,14 @@ public class JndiObjectFactoryBeanTests {
|
|||
fail("Should have thrown NamingException");
|
||||
}
|
||||
catch (NamingException ex) {
|
||||
assertTrue(ex.getMessage().indexOf("java.lang.String") != -1);
|
||||
assertTrue(ex.getMessage().contains("java.lang.String"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupWithDefaultObject() throws Exception {
|
||||
JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
|
||||
String s = "";
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", s));
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", ""));
|
||||
jof.setJndiName("myFoo");
|
||||
jof.setExpectedType(String.class);
|
||||
jof.setDefaultObject("myString");
|
||||
|
@ -170,8 +170,7 @@ public class JndiObjectFactoryBeanTests {
|
|||
@Test
|
||||
public void testLookupWithDefaultObjectAndExpectedType() throws Exception {
|
||||
JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
|
||||
String s = "";
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", s));
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", ""));
|
||||
jof.setJndiName("myFoo");
|
||||
jof.setExpectedType(String.class);
|
||||
jof.setDefaultObject("myString");
|
||||
|
@ -179,14 +178,36 @@ public class JndiObjectFactoryBeanTests {
|
|||
assertEquals("myString", jof.getObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupWithDefaultObjectAndExpectedTypeConversion() throws Exception {
|
||||
JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", ""));
|
||||
jof.setJndiName("myFoo");
|
||||
jof.setExpectedType(Integer.class);
|
||||
jof.setDefaultObject("5");
|
||||
jof.afterPropertiesSet();
|
||||
assertEquals(new Integer(5), jof.getObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupWithDefaultObjectAndExpectedTypeConversionViaBeanFactory() throws Exception {
|
||||
JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", ""));
|
||||
jof.setJndiName("myFoo");
|
||||
jof.setExpectedType(Integer.class);
|
||||
jof.setDefaultObject("5");
|
||||
jof.setBeanFactory(new DefaultListableBeanFactory());
|
||||
jof.afterPropertiesSet();
|
||||
assertEquals(new Integer(5), jof.getObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLookupWithDefaultObjectAndExpectedTypeNoMatch() throws Exception {
|
||||
JndiObjectFactoryBean jof = new JndiObjectFactoryBean();
|
||||
String s = "";
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", s));
|
||||
jof.setJndiTemplate(new ExpectedLookupTemplate("foo", ""));
|
||||
jof.setJndiName("myFoo");
|
||||
jof.setExpectedType(String.class);
|
||||
jof.setDefaultObject(Boolean.TRUE);
|
||||
jof.setExpectedType(Boolean.class);
|
||||
jof.setDefaultObject("5");
|
||||
try {
|
||||
jof.afterPropertiesSet();
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
|
|
Loading…
Reference in New Issue