INT-3427: Add JsonNodeToStringConverter

JIRA: https://jira.spring.io/browse/INT-3427

INT-3427: Workaround for String -> File converter

INT-3427: PR comments
This commit is contained in:
Artem Bilan
2014-07-04 18:33:50 +03:00
committed by Gary Russell
parent f0ab3b03bd
commit 85866a2ea8
8 changed files with 201 additions and 54 deletions

View File

@@ -31,6 +31,7 @@ import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -63,13 +64,20 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
private static final Log logger = LogFactory.getLog(IntegrationRegistrar.class);
private final static IntegrationConverterInitializer INTEGRATION_CONVERTER_INITIALIZER =
new IntegrationConverterInitializer();
private static final Set<Integer> registriesProcessed = new HashSet<Integer>();
private ClassLoader classLoader;
private volatile boolean jackson2Present;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
this.jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
}
/**
@@ -99,13 +107,14 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
* This method will auto-register a ChannelInitializer which could also be overridden by the user
* by simply registering a ChannelInitializer {@code <bean>} with its {@code autoCreate} property
* set to false to suppress channel creation.
* It will also register a ChannelInitializer$AutoCreateCandidatesCollector which simply collects candidate channel names.
*
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link org.springframework.beans.factory.config.BeanDefinition}s.
* It will also register a ChannelInitializer$AutoCreateCandidatesCollector
* which simply collects candidate channel names.
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
*/
private void registerImplicitChannelCreator(BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(IntegrationContextUtils.CHANNEL_INITIALIZER_BEAN_NAME)) {
String channelsAutoCreateExpression = IntegrationProperties.getExpressionFor(IntegrationProperties.CHANNELS_AUTOCREATE);
String channelsAutoCreateExpression =
IntegrationProperties.getExpressionFor(IntegrationProperties.CHANNELS_AUTOCREATE);
BeanDefinitionBuilder channelDef = BeanDefinitionBuilder.genericBeanDefinition(ChannelInitializer.class)
.addPropertyValue("autoCreate", channelsAutoCreateExpression);
BeanDefinitionHolder channelCreatorHolder = new BeanDefinitionHolder(channelDef.getBeanDefinition(),
@@ -117,16 +126,16 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
BeanDefinitionBuilder channelRegistryBuilder = BeanDefinitionBuilder
.genericBeanDefinition(ChannelInitializer.AutoCreateCandidatesCollector.class);
channelRegistryBuilder.addConstructorArgValue(new ManagedSet<String>());
BeanDefinitionHolder channelRegistryHolder = new BeanDefinitionHolder(channelRegistryBuilder.getBeanDefinition(),
IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME);
BeanDefinitionHolder channelRegistryHolder =
new BeanDefinitionHolder(channelRegistryBuilder.getBeanDefinition(),
IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME);
BeanDefinitionReaderUtils.registerBeanDefinition(channelRegistryHolder, registry);
}
}
/**
* Register {@code integrationGlobalProperties} bean if necessary.
*
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link org.springframework.beans.factory.config.BeanDefinition}s.
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
*/
private void registerIntegrationProperties(BeanDefinitionRegistry registry) {
boolean alreadyRegistered = false;
@@ -135,13 +144,16 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
.containsBean(IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME);
}
else {
alreadyRegistered = registry.isBeanNameInUse(IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME);
alreadyRegistered =
registry.isBeanNameInUse(IntegrationContextUtils.INTEGRATION_GLOBAL_PROPERTIES_BEAN_NAME);
}
if (!alreadyRegistered) {
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(this.classLoader);
try {
Resource[] defaultResources = resourceResolver.getResources("classpath*:META-INF/spring.integration.default.properties");
Resource[] userResources = resourceResolver.getResources("classpath*:META-INF/spring.integration.properties");
Resource[] defaultResources =
resourceResolver.getResources("classpath*:META-INF/spring.integration.default.properties");
Resource[] userResources =
resourceResolver.getResources("classpath*:META-INF/spring.integration.properties");
List<Resource> resources = new LinkedList<Resource>(Arrays.asList(defaultResources));
resources.addAll(Arrays.asList(userResources));
@@ -162,8 +174,7 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
/**
* Register {@link IntegrationEvaluationContextFactoryBean} bean
* and {@link IntegrationEvaluationContextAwareBeanPostProcessor}, if necessary.
*
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link org.springframework.beans.factory.config.BeanDefinition}s.
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
*/
private void registerIntegrationEvaluationContext(BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME)) {
@@ -178,15 +189,15 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
BeanDefinitionReaderUtils.registerBeanDefinition(integrationEvaluationContextHolder,
registry);
RootBeanDefinition integrationEvalContextBPP = new RootBeanDefinition(IntegrationEvaluationContextAwareBeanPostProcessor.class);
RootBeanDefinition integrationEvalContextBPP =
new RootBeanDefinition(IntegrationEvaluationContextAwareBeanPostProcessor.class);
BeanDefinitionReaderUtils.registerWithGeneratedName(integrationEvalContextBPP, registry);
}
}
/**
* Register {@code jsonPath} and {@code xpath} SpEL-function beans, if necessary.
*
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link org.springframework.beans.factory.config.BeanDefinition}s.
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
*/
private void registerBuiltInBeans(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
@@ -205,7 +216,8 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
jsonPathClass = ClassUtils.forName("com.jayway.jsonpath.JsonPath", this.classLoader);
}
catch (ClassNotFoundException e) {
logger.debug("SpEL function '#jsonPath' isn't registered: there is no jayway json-path.jar on the classpath.");
logger.debug("SpEL function '#jsonPath' isn't registered: " +
"there is no jayway json-path.jar on the classpath.");
}
if (jsonPathClass != null) {
@@ -225,10 +237,12 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
if (!alreadyRegistered && !registriesProcessed.contains(registryId)) {
Class<?> xpathClass = null;
try {
xpathClass = ClassUtils.forName(IntegrationConfigUtils.BASE_PACKAGE + ".xml.xpath.XPathUtils", this.classLoader);
xpathClass = ClassUtils.forName(IntegrationConfigUtils.BASE_PACKAGE + ".xml.xpath.XPathUtils",
this.classLoader);
}
catch (ClassNotFoundException e) {
logger.debug("SpEL function '#xpath' isn't registered: there is no spring-integration-xml.jar on the classpath.");
logger.debug("SpEL function '#xpath' isn't registered: " +
"there is no spring-integration-xml.jar on the classpath.");
}
if (xpathClass != null) {
@@ -237,49 +251,73 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
}
}
alreadyRegistered = false;
if (registry instanceof ListableBeanFactory) {
alreadyRegistered = ((ListableBeanFactory) registry)
.containsBean(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME);
}
else {
alreadyRegistered = registry
.isBeanNameInUse(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME);
}
if (!alreadyRegistered && !registriesProcessed.contains(registryId) && this.jackson2Present) {
registry.registerBeanDefinition(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME,
BeanDefinitionBuilder.genericBeanDefinition(IntegrationConfigUtils.BASE_PACKAGE +
".json.ToStringFriendlyJsonNodeToStringConverter")
.getBeanDefinition());
INTEGRATION_CONVERTER_INITIALIZER.registerConverter(registry,
new RuntimeBeanReference(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME));
}
registriesProcessed.add(registryId);
}
/**
* Register {@code DefaultConfiguringBeanFactoryPostProcessor}, if necessary.
*
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link org.springframework.beans.factory.config.BeanDefinition}s.
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
*/
private void registerDefaultConfiguringBeanFactoryPostProcessor(BeanDefinitionRegistry registry) {
boolean alreadyRegistered = false;
if (registry instanceof ListableBeanFactory) {
alreadyRegistered = ((ListableBeanFactory) registry).containsBean(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
alreadyRegistered = ((ListableBeanFactory) registry)
.containsBean(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
}
else {
alreadyRegistered = registry.isBeanNameInUse(IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
}
if (!alreadyRegistered) {
BeanDefinitionBuilder postProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(DefaultConfiguringBeanFactoryPostProcessor.class);
BeanDefinitionBuilder postProcessorBuilder =
BeanDefinitionBuilder.genericBeanDefinition(DefaultConfiguringBeanFactoryPostProcessor.class);
BeanDefinitionHolder postProcessorHolder = new BeanDefinitionHolder(
postProcessorBuilder.getBeanDefinition(), IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
postProcessorBuilder.getBeanDefinition(),
IntegrationContextUtils.DEFAULT_CONFIGURING_POSTPROCESSOR_BEAN_NAME);
BeanDefinitionReaderUtils.registerBeanDefinition(postProcessorHolder, registry);
}
}
/**
* Register a {@link DefaultHeaderChannelRegistry} in the given {@link BeanDefinitionRegistry}, if necessary.
*
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link org.springframework.beans.factory.config.BeanDefinition}s.
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
*/
private void registerHeaderChannelRegistry(BeanDefinitionRegistry registry) {
boolean alreadyRegistered = false;
if (registry instanceof ListableBeanFactory) {
alreadyRegistered = ((ListableBeanFactory) registry).containsBean(IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME);
alreadyRegistered = ((ListableBeanFactory) registry)
.containsBean(IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME);
}
else {
alreadyRegistered = registry.isBeanNameInUse(IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME);
alreadyRegistered =
registry.isBeanNameInUse(IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME);
}
if (!alreadyRegistered) {
if (logger.isInfoEnabled()) {
logger.info("No bean named '" + IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME +
"' has been explicitly defined. Therefore, a default DefaultHeaderChannelRegistry will be created.");
"' has been explicitly defined. " +
"Therefore, a default DefaultHeaderChannelRegistry will be created.");
}
BeanDefinitionBuilder schedulerBuilder = BeanDefinitionBuilder.genericBeanDefinition(DefaultHeaderChannelRegistry.class);
BeanDefinitionBuilder schedulerBuilder =
BeanDefinitionBuilder.genericBeanDefinition(DefaultHeaderChannelRegistry.class);
BeanDefinitionHolder replyChannelRegistryComponent = new BeanDefinitionHolder(
schedulerBuilder.getBeanDefinition(),
IntegrationContextUtils.INTEGRATION_HEADER_CHANNEL_REGISTRY_BEAN_NAME);
@@ -289,51 +327,54 @@ public class IntegrationRegistrar implements ImportBeanDefinitionRegistrar, Bean
/**
* Register a {@link GlobalChannelInterceptorProcessor} in the given {@link BeanDefinitionRegistry}, if necessary.
*
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link org.springframework.beans.factory.config.BeanDefinition}s.
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
*/
private void registerGlobalChannelInterceptorProcessor(BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(IntegrationContextUtils.GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME)) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(GlobalChannelInterceptorProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(GlobalChannelInterceptorProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(IntegrationContextUtils.GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME, builder.getBeanDefinition());
registry.registerBeanDefinition(IntegrationContextUtils.GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME,
builder.getBeanDefinition());
}
}
/**
* Register {@link MessagingAnnotationPostProcessor} and {@link PublisherAnnotationBeanPostProcessor}, if necessary.
* Inject {@code defaultPublishedChannel} from provided {@link AnnotationMetadata}, if any.
*
* @param meta The {@link AnnotationMetadata} to get additional properties for {@link org.springframework.beans.factory.config.BeanDefinition}s.
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link org.springframework.beans.factory.config.BeanDefinition}s.
* @param meta The {@link AnnotationMetadata} to get additional properties for {@link BeanDefinition}s.
* @param registry The {@link BeanDefinitionRegistry} to register additional {@link BeanDefinition}s.
*/
private void registerMessagingAnnotationPostProcessors(AnnotationMetadata meta, BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(IntegrationContextUtils.MESSAGING_ANNOTATION_POSTPROCESSOR_NAME)) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MessagingAnnotationPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(MessagingAnnotationPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(IntegrationContextUtils.MESSAGING_ANNOTATION_POSTPROCESSOR_NAME, builder.getBeanDefinition());
registry.registerBeanDefinition(IntegrationContextUtils.MESSAGING_ANNOTATION_POSTPROCESSOR_NAME,
builder.getBeanDefinition());
}
new PublisherRegistrar().registerBeanDefinitions(meta, registry);
}
/**
* Register {@link IntegrationConfigurationBeanFactoryPostProcessor} to process the external Integration infrastructure.
* Register {@link IntegrationConfigurationBeanFactoryPostProcessor}
* to process the external Integration infrastructure.
*/
private void registerIntegrationConfigurationBeanFactoryPostProcessor(BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME)) {
BeanDefinitionBuilder postProcessorBuilder = BeanDefinitionBuilder
.genericBeanDefinition(IntegrationConfigurationBeanFactoryPostProcessor.class)
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME, postProcessorBuilder.getBeanDefinition());
registry.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_CONFIGURATION_POST_PROCESSOR_BEAN_NAME,
postProcessorBuilder.getBeanDefinition());
}
}
/**
* Register the default datatype channel MessageConverter.
*
* @param registry the registry.
*/
private void registerDefaultDatatypeChannelMessageConverter(BeanDefinitionRegistry registry) {

View File

@@ -52,7 +52,9 @@ public abstract class AbstractIntegrationNamespaceHandler implements NamespaceHa
@Override
public final BeanDefinition parse(Element element, ParserContext parserContext) {
this.verifySchemaVersion(element, parserContext);
new IntegrationRegistrar().registerBeanDefinitions(null, parserContext.getRegistry());
IntegrationRegistrar integrationRegistrar = new IntegrationRegistrar();
integrationRegistrar.setBeanClassLoader(parserContext.getReaderContext().getBeanClassLoader());
integrationRegistrar.registerBeanDefinitions(null, parserContext.getRegistry());
return this.delegate.parse(element, parserContext);
}

View File

@@ -74,6 +74,9 @@ public abstract class IntegrationContextUtils {
public static final String GLOBAL_CHANNEL_INTERCEPTOR_PROCESSOR_BEAN_NAME = "globalChannelInterceptorProcessor";
public static final String TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME =
"toStringFriendlyJsonNodeToStringConverter";
/**
* @param beanFactory BeanFactory for lookup, must not be null.
* @return The {@link MetadataStore} bean whose name is "metadataStore".

View File

@@ -0,0 +1,38 @@
/*
* Copyright 2014 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.json;
import org.springframework.core.convert.converter.Converter;
/**
* The {@link Converter} implementation for the conversion of
* {@link JsonPropertyAccessor.ToStringFriendlyJsonNode} to {@link String},
* when the {@link JsonPropertyAccessor.ToStringFriendlyJsonNode} can be a result of the
* expression for JSON in case of the {@link JsonPropertyAccessor} usage.
*
* @author Artem Bilan
* @since 4.1
*/
class ToStringFriendlyJsonNodeToStringConverter
implements Converter<JsonPropertyAccessor.ToStringFriendlyJsonNode, String> {
@Override
public String convert(JsonPropertyAccessor.ToStringFriendlyJsonNode source) {
return source.toString();
}
}

View File

@@ -34,4 +34,17 @@
<bean id="parentJsonPropertyAccessor" class="org.springframework.integration.json.JsonPropertyAccessor"/>
<bean id="barService" class="org.springframework.integration.expression.ParentContextTests$Bar" />
<int:chain input-channel="testJsonNodeToStringConverterInputChannel"
output-channel="testJsonNodeToStringConverterOutputChannel">
<int:object-to-json-transformer result-type="NODE"/>
<int:transformer expression="payload.firstName"/>
<int:service-activator ref="barService" method="testJsonNodeToStringConverter"/>
</int:chain>
<int:channel id="testJsonNodeToStringConverterOutputChannel">
<int:queue/>
</int:channel>
</beans>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 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.
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.expression;
import static org.hamcrest.Matchers.instanceOf;
@@ -30,6 +31,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hamcrest.Matchers;
import org.junit.Test;
@@ -42,10 +44,12 @@ import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.IntegrationEvaluationContextFactoryBean;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.json.JsonPathUtils;
import org.springframework.integration.json.TestPerson;
import org.springframework.integration.support.MutableMessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
/**
@@ -66,14 +70,19 @@ public class ParentContextTests {
* and the parent's ones are last in the propertyAccessors list of EvaluationContext.
* Verifies that SpEL functions are inherited from parent context and overridden with the same 'id'.
* Verifies that child and parent contexts can have different message builders.
* <p>
* Only single test method is allowed for 'ParentContext-context.xml',
* since it relies on static 'evalContexts' variable.
*/
@Test
@SuppressWarnings("unchecked")
public void testSpelBeanReferencesInChildAndParent() throws Exception {
AbstractApplicationContext parent = new ClassPathXmlApplicationContext("ParentContext-context.xml", this.getClass());
AbstractApplicationContext parent = new ClassPathXmlApplicationContext("ParentContext-context.xml",
this.getClass());
Object parentEvaluationContextFactoryBean = parent.getBean(IntegrationEvaluationContextFactoryBean.class);
Map<?, ?> parentFunctions = TestUtils.getPropertyValue(parentEvaluationContextFactoryBean, "functions", Map.class);
Map<?, ?> parentFunctions = TestUtils.getPropertyValue(parentEvaluationContextFactoryBean, "functions",
Map.class);
assertEquals(3, parentFunctions.size());
Object jsonPath = parentFunctions.get("jsonPath");
assertNotNull(jsonPath);
@@ -84,7 +93,8 @@ public class ParentContextTests {
child.refresh();
Object childEvaluationContextFactoryBean = child.getBean(IntegrationEvaluationContextFactoryBean.class);
Map<?, ?> childFunctions = TestUtils.getPropertyValue(childEvaluationContextFactoryBean, "functions", Map.class);
Map<?, ?> childFunctions = TestUtils.getPropertyValue(childEvaluationContextFactoryBean, "functions",
Map.class);
assertEquals(4, childFunctions.size());
assertTrue(childFunctions.containsKey("barParent"));
jsonPath = childFunctions.get("jsonPath");
@@ -101,7 +111,8 @@ public class ParentContextTests {
assertTrue(propertyAccessors.contains(parentPropertyAccessor));
assertTrue(propertyAccessors.indexOf(parentPropertyAccessorOverride) > propertyAccessors.indexOf(parentPropertyAccessor));
Map<String, Object> variables = (Map<String, Object>) TestUtils.getPropertyValue(evalContexts.get(0), "variables");
Map<String, Object> variables = (Map<String, Object>) TestUtils.getPropertyValue(evalContexts.get(0),
"variables");
assertEquals(3, variables.size());
assertTrue(variables.containsKey("bar"));
assertTrue(variables.containsKey("barParent"));
@@ -161,6 +172,37 @@ public class ParentContextTests {
assertEquals("org.springframework.integration.support.MutableMessage", out.getClass().getName());
assertEquals("FOO", out.getPayload());
assertTrue(parent
.containsBean(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME));
assertTrue(child
.containsBean(IntegrationContextUtils.TO_STRING_FRIENDLY_JSON_NODE_TO_STRING_CONVERTER_BEAN_NAME));
Object converterRegistrar = parent.getBean(IntegrationContextUtils.CONVERTER_REGISTRAR_BEAN_NAME);
assertNotNull(converterRegistrar);
Set<?> converters = TestUtils.getPropertyValue(converterRegistrar, "converters", Set.class);
boolean toStringFriendlyJsonNodeToStringConverterPresent = false;
for (Object converter : converters) {
if ("ToStringFriendlyJsonNodeToStringConverter".equals(converter.getClass().getSimpleName())) {
toStringFriendlyJsonNodeToStringConverterPresent = true;
break;
}
}
assertTrue(toStringFriendlyJsonNodeToStringConverterPresent);
MessageChannel input = parent.getBean("testJsonNodeToStringConverterInputChannel", MessageChannel.class);
PollableChannel output = parent.getBean("testJsonNodeToStringConverterOutputChannel", PollableChannel.class);
TestPerson person = new TestPerson();
person.setFirstName("John");
input.send(new GenericMessage<Object>(person));
Message<?> result = output.receive(1000);
assertNotNull(result);
assertEquals("JOHN", result.getPayload());
child.close();
parent.close();
}
@@ -180,5 +222,10 @@ public class ParentContextTests {
return o;
}
public String testJsonNodeToStringConverter(String payload) {
return payload.toUpperCase();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 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.
@@ -20,7 +20,7 @@ package org.springframework.integration.json;
* @author Mark Fisher
* @since 2.0
*/
class TestPerson {
public class TestPerson {
private volatile String firstName;
@@ -30,7 +30,7 @@ class TestPerson {
private volatile TestAddress address;
TestPerson() {
public TestPerson() {
}
public TestPerson(String firstName, String lastName, int age) {

View File

@@ -798,7 +798,10 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
private File generateLocalDirectory(Message<?> message, String remoteDirectory) {
EvaluationContext evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.getBeanFactory());
evaluationContext.setVariable("remoteDirectory", remoteDirectory);
File localDir = this.localDirectoryExpression.getValue(evaluationContext, message, File.class);
//TODO see org.springframework.integration.context.CustomConversionServiceFactoryBean
// File localDir = this.localDirectoryExpression.getValue(evaluationContext, message, File.class);
String localDirPath = this.localDirectoryExpression.getValue(evaluationContext, message, String.class);
File localDir = new File(localDirPath);
if (!localDir.exists()) {
Assert.isTrue(localDir.mkdirs(), "Failed to make local directory: " + localDir);
}