INT-2888 Fix MapToObjectTransformerParser CL Issue

In the parent-child environment configuration that relies on class names may produce
a `ClassNotFoundException`.

* remove usage of `ClassLoader` in the `MapToObjectTransformerParser` and allow to use the `ConversionService` from application context
* remove deprecation from `MapToObjectTransformer`
* refactor `MapToObjectTransformer` to use `IntegrationObjectSupport#getConversionService()`
* remove fallback to the `beanFactory#getConversionService()` in the `ExpressionUtils`

JIRA: https://jira.springsource.org/browse/INT-2888

INT-2928: Do Not Fallback to BF's ConversionService

* Polishing according PR's comments
* Important note about `conversionService` & `integrationConversionService` beans
* Link a JIRA about elimination of `BeanFactory`'s `ConversionService` usage
* Add a note to the 2.2-3.0 Migration Guide

JIRA: https://jira.springsource.org/browse/INT-2928

INT-2888 Doc Polishing
This commit is contained in:
Artem Bilan
2013-01-18 11:37:09 +02:00
committed by Gary Russell
parent e994c4dab3
commit 77fae8844a
7 changed files with 194 additions and 130 deletions

View File

@@ -9,27 +9,27 @@
<int:channel id="output">
<int:queue/>
</int:channel>
<int:map-to-object-transformer input-channel="input"
output-channel="output"
<int:map-to-object-transformer input-channel="input"
output-channel="output"
type="org.springframework.integration.config.xml.MapToObjectTransformerParserTests$Person"/>
<int:channel id="inputA"/>
<int:channel id="outputA">
<int:queue/>
</int:channel>
<int:map-to-object-transformer input-channel="inputA"
output-channel="outputA"
<int:map-to-object-transformer input-channel="inputA"
output-channel="outputA"
ref="person"/>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<bean id="conversionService" name="integrationConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="org.springframework.integration.config.xml.MapToObjectTransformerParserTests$StringToAddressConverter" />
</list>
</property>
</bean>
<bean id="person" class="org.springframework.integration.config.xml.MapToObjectTransformerParserTests$Person" scope="prototype"/>
</beans>

View File

@@ -20,43 +20,49 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.integration.Message;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.util.ClassUtils;
/**
* @author Oleg Zhurakousky
* @author Gunnar Hillert
*
* @author Artem Bilan
* @since 2.0
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public class MapToObjectTransformerTests {
@Test
public void testMapToObjectTransformation(){
Map map = new HashMap();
public void testMapToObjectTransformation() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("fname", "Justin");
map.put("lname", "Case");
Address address = new Address();
address.setStreet("1123 Main st");
map.put("address", address);
Message message = MessageBuilder.withPayload(map).build();
Message<?> message = MessageBuilder.withPayload(map).build();
MapToObjectTransformer transformer = new MapToObjectTransformer(Person.class);
transformer.setBeanFactory(this.getBeanFactory());
Message newMessage = transformer.transform(message);
Message<?> newMessage = transformer.transform(message);
Person person = (Person) newMessage.getPayload();
assertNotNull(person);
assertEquals("Justin", person.getFname());
@@ -67,20 +73,20 @@ public class MapToObjectTransformerTests {
}
@Test
public void testMapToObjectTransformationWithPrototype(){
Map map = new HashMap();
public void testMapToObjectTransformationWithPrototype() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("fname", "Justin");
map.put("lname", "Case");
Address address = new Address();
address.setStreet("1123 Main st");
map.put("address", address);
Message message = MessageBuilder.withPayload(map).build();
Message<?> message = MessageBuilder.withPayload(map).build();
StaticApplicationContext ac = new StaticApplicationContext();
ac.registerPrototype("person", Person.class);
MapToObjectTransformer transformer = new MapToObjectTransformer("person");
transformer.setBeanFactory(ac.getBeanFactory());
Message newMessage = transformer.transform(message);
Message<?> newMessage = transformer.transform(message);
Person person = (Person) newMessage.getPayload();
assertNotNull(person);
assertEquals("Justin", person.getFname());
@@ -91,20 +97,22 @@ public class MapToObjectTransformerTests {
}
@Test
public void testMapToObjectTransformationWithConversionService(){
Map map = new HashMap();
public void testMapToObjectTransformationWithConversionService() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("fname", "Justin");
map.put("lname", "Case");
map.put("address", "1123 Main st");
Message message = MessageBuilder.withPayload(map).build();
Message<?> message = MessageBuilder.withPayload(map).build();
MapToObjectTransformer transformer = new MapToObjectTransformer(Person.class);
ConfigurableBeanFactory beanFactory = this.getBeanFactory();
((GenericConversionService)beanFactory.getConversionService()).addConverter(new StringToAddressConverter());
BeanFactory beanFactory = this.getBeanFactory();
ConverterRegistry conversionService =
beanFactory.getBean(IntegrationContextUtils.INTEGRATION_CONVERSION_SERVICE_BEAN_NAME, ConverterRegistry.class);
conversionService.addConverter(new StringToAddressConverter());
transformer.setBeanFactory(beanFactory);
Message newMessage = transformer.transform(message);
Message<?> newMessage = transformer.transform(message);
Person person = (Person) newMessage.getPayload();
assertNotNull(person);
assertEquals("Justin", person.getFname());
@@ -113,45 +121,73 @@ public class MapToObjectTransformerTests {
assertEquals("1123 Main st", person.getAddress().getStreet());
}
private ConfigurableBeanFactory getBeanFactory(){
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
GenericConversionService conversionService = new DefaultConversionService();
beanFactory.setConversionService(conversionService);
return beanFactory;
private BeanFactory getBeanFactory() {
GenericApplicationContext ctx = TestUtils.createTestApplicationContext();
Constructor<?> constructorToUse = null;
try {
// Add the integrationConversionService (reflection needed because of package protection)
final Class<?> conversionServiceCreatorClass = ClassUtils.forName("org.springframework.integration.context.ConversionServiceCreator",
ClassUtils.getDefaultClassLoader());
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
public Constructor<?> run() throws Exception {
return conversionServiceCreatorClass.getDeclaredConstructor((Class[]) null);
}
});
}
catch (Exception e) {
throw new RuntimeException("Unexpected Privilege Exception: ", e);
}
ctx.addBeanFactoryPostProcessor((BeanFactoryPostProcessor) BeanUtils.instantiateClass(constructorToUse));
ctx.refresh();
return ctx;
}
public static class Person{
public static class Person {
private String fname;
private String lname;
private String ssn;
private Address address;
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public static class Address {
private String street;
public String getStreet() {
@@ -163,7 +199,8 @@ public class MapToObjectTransformerTests {
}
}
public class StringToAddressConverter implements Converter<String, Address>{
public class StringToAddressConverter implements Converter<String, Address> {
public Address convert(String source) {
Address address = new Address();
address.setStreet(source);