INT-1178 added support for existing ConversionService as well as existing ConversioinService in the parent AC

This commit is contained in:
Oleg Zhurakousky
2010-07-20 14:33:27 +00:00
parent 5c2e5d33db
commit 970bde86dc
6 changed files with 243 additions and 11 deletions

View File

@@ -21,10 +21,11 @@ import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.support.ConversionServiceFactoryBean;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.util.ConverterRegistrar;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
@@ -34,16 +35,15 @@ import org.w3c.dom.Element;
* @since 2.0
*/
public class ConverterParser extends AbstractBeanDefinitionParser {
private final ManagedList<Object> converters = new ManagedList<Object>();
private final static String CONVERSION_SERVICE = "integrationConversionService";
private final ManagedSet<Object> converters = new ManagedSet<Object>();
private String CONVERTER_REGISTRAR = "converterRegistrar";
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#parseInternal(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
*/
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
if (!parserContext.getReaderContext().getRegistry().containsBeanDefinition(CONVERSION_SERVICE)){
this.defineConversionSesrvice(parserContext);
if (!parserContext.getRegistry().containsBeanDefinition(CONVERTER_REGISTRAR)){
this.defineConverterRegistrar(parserContext);
}
BeanComponentDefinition converterDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext);
if (converterDefinition == null){
@@ -58,10 +58,10 @@ public class ConverterParser extends AbstractBeanDefinitionParser {
/*
*
*/
private void defineConversionSesrvice(ParserContext parserContext){
BeanDefinitionBuilder conversionServiceBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConversionServiceFactoryBean.class);
conversionServiceBuilder.addPropertyValue("converters", converters);
BeanDefinitionHolder bdHolder = new BeanDefinitionHolder(conversionServiceBuilder.getBeanDefinition(), CONVERSION_SERVICE);
private void defineConverterRegistrar(ParserContext parserContext){
BeanDefinitionBuilder conversionServiceBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConverterRegistrar.class);
conversionServiceBuilder.addConstructorArgValue(converters);
BeanDefinitionHolder bdHolder = new BeanDefinitionHolder(conversionServiceBuilder.getBeanDefinition(), CONVERTER_REGISTRAR);
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, parserContext.getRegistry());
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2002-2010 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.
* 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.springframework.integration.util;
import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.support.ConversionServiceFactoryBean;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.GenericConversionService;
/**
* @author Oleg Zhurakousky
* @since 2.0
*/
public class ConverterRegistrar implements BeanFactoryPostProcessor {
private final Set<Converter<?, ?>> converters;
public ConverterRegistrar(Set<Converter<?, ?>> converters){
this.converters = converters;
}
/**
* This method will add converters to the SI's conversion service - {@link SI#CONVERSION_SERVICE}
* If SI's conversion service does not exist, then an instance of the {@link ConversionService} will
* be created and registered under the name {@link SI#CONVERSION_SERVICE}
*/
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (!beanFactory.containsBean(SI.CONVERSION_SERVICE)){
BeanDefinitionBuilder conversionServiceBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConversionServiceFactoryBean.class);
BeanDefinitionHolder csHolder = new BeanDefinitionHolder(conversionServiceBuilder.getBeanDefinition(), SI.CONVERSION_SERVICE);
BeanDefinitionReaderUtils.registerBeanDefinition(csHolder, (BeanDefinitionRegistry) beanFactory);
}
GenericConversionService conversionService = beanFactory.getBean(SI.CONVERSION_SERVICE, GenericConversionService.class);
ConversionServiceFactory.registerConverters(converters, conversionService);
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2002-2010 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.
* 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.springframework.integration.util;
/**
* @author Oleg Zhurakousky
* @since 2.0
*/
public interface SI {
public String CONVERSION_SERVICE = "integrationConversionService";
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
<int:converter ref="sampleConverter"/>
<bean id="sampleConverter" class="org.springframework.integration.config.xml.ConverterParserWithExistingConversionServiceTests$TestConverter"/>
<int:converter>
<bean class="org.springframework.integration.config.xml.ConverterParserWithExistingConversionServiceTests$TestConverter3"/>
</int:converter>
<bean id="integrationConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"/>
</beans>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
<bean id="integrationConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"/>
</beans>

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2002-2010 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.
* 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.springframework.integration.config.xml;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.integration.util.SI;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
/**
* @author Oleg Zhurakousky
*
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class ConverterParserWithExistingConversionServiceTests {
@Autowired
private ApplicationContext applicationContext;
@Autowired
@Qualifier(SI.CONVERSION_SERVICE)
private ConversionService conversionService;
@Test
public void testConversionServiceAvailability(){
Assert.isTrue(applicationContext.getBean(SI.CONVERSION_SERVICE).equals(conversionService));
Assert.isTrue(conversionService.canConvert(TestBean1.class, TestBean2.class));
Assert.isTrue(conversionService.canConvert(TestBean1.class, TestBean3.class));
}
@Test
public void testParentConversionServiceAvailability(){
ApplicationContext parentContext =
new ClassPathXmlApplicationContext("ConverterParserWithExistingConversionServiceTests-parent.xml", ConverterParserWithExistingConversionServiceTests.class);
GenericApplicationContext childContext = new GenericApplicationContext();
childContext.setParent(parentContext);
GenericConversionService conversionServiceParent = parentContext.getBean(SI.CONVERSION_SERVICE,GenericConversionService.class);
GenericConversionService conversionServiceChild = childContext.getBean(SI.CONVERSION_SERVICE,GenericConversionService.class);
Assert.isTrue(conversionServiceParent == conversionServiceChild); // validating that they are pointing to the same object
conversionServiceChild.addConverter(new TestConverter());
conversionServiceChild.addConverter(new TestConverter3());
Assert.isTrue(conversionServiceChild.canConvert(TestBean1.class, TestBean2.class));
Assert.isTrue(conversionServiceChild.canConvert(TestBean1.class, TestBean3.class));
}
private static class TestBean1 {
private String text;
public TestBean1(String text) {
this.text = text;
}
}
private static class TestBean2 {
private String text;
public TestBean2(String text) {
this.text = text;
}
// called by router for channel name
public String toString() {
return this.text.replace("-TEST", "_TARGET_CHANNEL");
}
}
private static class TestBean3 {
private String text;
public TestBean3(String text) {
this.text = text;
}
// called by router for channel name
public String toString() {
return this.text.replace("-TEST", "_TARGET_CHANNEL");
}
}
@SuppressWarnings("unused")
private static class TestConverter implements Converter<TestBean1, TestBean2> {
public TestBean2 convert(TestBean1 source) {
return new TestBean2(source.text.toUpperCase());
}
}
@SuppressWarnings("unused")
private static class TestConverter3 implements Converter<TestBean1, TestBean3> {
public TestBean3 convert(TestBean1 source) {
return new TestBean3(source.text.toUpperCase());
}
}
}