INT-3139: Add #jsonPath SpEL Function Support
* #jsonPath function is registered automatically if the library is on the classpath * Add otional dependency on `com.jayway.jsonpath:json-path` artifact * Add `JsonPathUtils` class as a wrapper around `JsonPath` * Add `#jsonPath` tests for: `<transformer>`, `<filter>`, `<splitter>`, `<router>` JIRA: https://jira.springsource.org/browse/INT-3139 INT-3139: Further improvements * Remove `SpelFunctionRegistrar` * Introduce `SpelFunctionFactoryBean` INT-3139: Polishing
This commit is contained in:
committed by
Gary Russell
parent
4d3bc36ff0
commit
63cbf736a2
@@ -185,6 +185,7 @@ project('spring-integration-core') {
|
||||
compile "com.eaio.uuid:uuid:$eaioUUIDVersion"
|
||||
compile("org.codehaus.jackson:jackson-mapper-asl:$jacksonVersion", optional)
|
||||
compile("com.fasterxml.jackson.core:jackson-databind:$jackson2Version", optional)
|
||||
compile('com.jayway.jsonpath:json-path:0.8.1', optional)
|
||||
testCompile "org.aspectj:aspectjweaver:$aspectjVersion"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class OutboundGatewayTests {
|
||||
}).when(context).getBean(anyString());
|
||||
when(context.containsBean(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME)).thenReturn(true);
|
||||
IntegrationEvaluationContextFactoryBean integrationEvaluationContextFactoryBean = new IntegrationEvaluationContextFactoryBean();
|
||||
integrationEvaluationContextFactoryBean.setBeanFactory(context);
|
||||
integrationEvaluationContextFactoryBean.setApplicationContext(context);
|
||||
integrationEvaluationContextFactoryBean.afterPropertiesSet();
|
||||
StandardEvaluationContext evalContext = integrationEvaluationContextFactoryBean.getObject();
|
||||
when(context.getBean(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME, StandardEvaluationContext.class))
|
||||
|
||||
@@ -25,11 +25,11 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
@@ -66,7 +66,7 @@ import org.springframework.util.Assert;
|
||||
* @since 3.0
|
||||
*/
|
||||
public class IntegrationEvaluationContextFactoryBean implements FactoryBean<StandardEvaluationContext>,
|
||||
BeanFactoryAware, InitializingBean {
|
||||
ApplicationContextAware, InitializingBean {
|
||||
|
||||
private volatile List<PropertyAccessor> propertyAccessors = new ArrayList<PropertyAccessor>();
|
||||
|
||||
@@ -74,14 +74,13 @@ public class IntegrationEvaluationContextFactoryBean implements FactoryBean<Stan
|
||||
|
||||
private TypeConverter typeConverter = new StandardTypeConverter();
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private BeanResolver beanResolver;
|
||||
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public void setPropertyAccessors(PropertyAccessor... accessors) {
|
||||
@@ -101,35 +100,26 @@ public class IntegrationEvaluationContextFactoryBean implements FactoryBean<Stan
|
||||
this.functions = functions;
|
||||
}
|
||||
|
||||
public void addFunction(String name, Method method) {
|
||||
this.functions.put(name, method);
|
||||
}
|
||||
|
||||
public void addFunctions(Map<String, Method> functions) {
|
||||
this.functions.putAll(functions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (this.propertyAccessors.isEmpty()) {
|
||||
this.loadDefaultPropertyAccessors(this.propertyAccessors);
|
||||
}
|
||||
if (this.beanFactory != null) {
|
||||
this.beanResolver = new BeanFactoryResolver(this.beanFactory);
|
||||
ConversionService conversionService = IntegrationContextUtils.getConversionService(this.beanFactory);
|
||||
if (this.applicationContext != null) {
|
||||
this.beanResolver = new BeanFactoryResolver(this.applicationContext);
|
||||
ConversionService conversionService = IntegrationContextUtils.getConversionService(this.applicationContext);
|
||||
if (conversionService != null) {
|
||||
this.typeConverter = new StandardTypeConverter(conversionService);
|
||||
}
|
||||
try {
|
||||
SpelFunctionRegistrar functionRegistrar = this.beanFactory.getBean(SpelFunctionRegistrar.class);
|
||||
if (functionRegistrar != null) {
|
||||
this.addFunctions(functionRegistrar.getFunctions());
|
||||
|
||||
Map<String, SpelFunctionFactoryBean> functionFactoryBeanMap =
|
||||
BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, SpelFunctionFactoryBean.class);
|
||||
for (SpelFunctionFactoryBean spelFunctionFactoryBean : functionFactoryBeanMap.values()) {
|
||||
if (!this.functions.containsKey(spelFunctionFactoryBean.getFunctionName())) {
|
||||
this.functions.put(spelFunctionFactoryBean.getFunctionName(), spelFunctionFactoryBean.getObject());
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
//Ignore it.
|
||||
//There is no <spel-function> components within application context.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
/**
|
||||
* A {@link FactoryBean} implementation to encapsulate the population of a static {@link Method}
|
||||
* from the provided {@linkplain #functionClass} and {@linkplain #functionMethodSignature} as
|
||||
* a valid {@link org.springframework.expression.spel.support.StandardEvaluationContext} function.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*
|
||||
* @see org.springframework.expression.spel.support.StandardEvaluationContext#registerFunction
|
||||
* @see BeanUtils#resolveSignature
|
||||
*/
|
||||
public class SpelFunctionFactoryBean implements FactoryBean<Method>, InitializingBean, BeanNameAware {
|
||||
|
||||
private final Class<?> functionClass;
|
||||
|
||||
private final String functionMethodSignature;
|
||||
|
||||
private String functionName;
|
||||
|
||||
private Method method;
|
||||
|
||||
public SpelFunctionFactoryBean(Class<?> functionClass, String functionMethodSignature) {
|
||||
this.functionClass = functionClass;
|
||||
this.functionMethodSignature = functionMethodSignature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
this.functionName = name;
|
||||
}
|
||||
|
||||
public String getFunctionName() {
|
||||
return functionName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.method = BeanUtils.resolveSignature(this.functionMethodSignature, this.functionClass);
|
||||
|
||||
if (this.method == null) {
|
||||
throw new BeanDefinitionStoreException(String.format("No declared method '%s' in class '%s'",
|
||||
this.functionMethodSignature, this.functionClass));
|
||||
}
|
||||
if (!Modifier.isStatic(this.method.getModifiers())) {
|
||||
throw new BeanDefinitionStoreException("SpEL-function method has to be 'static'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Method getObject() throws Exception {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Method.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Utility class that keeps track of a Map of SpEL functions in order to register
|
||||
* them with the "integrationEvaluationContext" upon initialization.
|
||||
* </p>
|
||||
* <p>
|
||||
* The {@link org.springframework.integration.config.xml.SpelFunctionParser}
|
||||
* doesn't register a bean for each <spel-function> within application context.
|
||||
* There is no automatic way to get 'functions' from a parent context
|
||||
* and this class provide a hook to get 'functions' from the parent context.
|
||||
* </p>
|
||||
*
|
||||
* @author Artem Bilan
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
class SpelFunctionRegistrar implements ApplicationContextAware, InitializingBean {
|
||||
|
||||
private final Map<String, Method> functions;
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
SpelFunctionRegistrar(Map<String, Method> functions) {
|
||||
this.functions = functions;
|
||||
}
|
||||
|
||||
Map<String, Method> getFunctions() {
|
||||
return functions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
ApplicationContext parent = this.applicationContext.getParent();
|
||||
if (parent != null) {
|
||||
try {
|
||||
SpelFunctionRegistrar parentFunctionRegistrar = parent.getBean(SpelFunctionRegistrar.class);
|
||||
Map<String, Method> parentFunctions = parentFunctionRegistrar.getFunctions();
|
||||
for (String key : parentFunctions.keySet()) {
|
||||
if(!this.functions.containsKey(key)) {
|
||||
this.functions.put(key, parentFunctions.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException e) {
|
||||
//Ignore it.
|
||||
//There is no <spel-function> components within parent application context.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,8 @@ package org.springframework.integration.config.xml;
|
||||
|
||||
import static org.springframework.integration.context.IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
@@ -37,6 +39,7 @@ import org.springframework.integration.config.IntegrationEvaluationContextFactor
|
||||
import org.springframework.integration.config.xml.ChannelInitializer.AutoCreateCandidatesCollector;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.expression.IntegrationEvaluationContextAwareBeanPostProcessor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -49,6 +52,8 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class AbstractIntegrationNamespaceHandler implements NamespaceHandler {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private static final String VERSION = "3.0";
|
||||
|
||||
public static final String CHANNEL_INITIALIZER_BEAN_NAME = "channelInitializer";
|
||||
@@ -67,6 +72,7 @@ public abstract class AbstractIntegrationNamespaceHandler implements NamespaceHa
|
||||
this.verifySchemaVersion(element, parserContext);
|
||||
this.registerImplicitChannelCreator(parserContext);
|
||||
this.registerIntegrationEvaluationContext(parserContext);
|
||||
this.registerBuiltInBeans(parserContext);
|
||||
this.registerDefaultConfiguringBeanFactoryPostProcessorIfNecessary(parserContext);
|
||||
return this.delegate.parse(element, parserContext);
|
||||
}
|
||||
@@ -141,6 +147,37 @@ public abstract class AbstractIntegrationNamespaceHandler implements NamespaceHa
|
||||
}
|
||||
}
|
||||
|
||||
private void registerBuiltInBeans(ParserContext parserContext) {
|
||||
String jsonPathBeanName = "jsonPath";
|
||||
boolean alreadyRegistered = false;
|
||||
if (parserContext.getRegistry() instanceof ListableBeanFactory) {
|
||||
alreadyRegistered = ((ListableBeanFactory) parserContext.getRegistry()).containsBean(jsonPathBeanName);
|
||||
}
|
||||
else {
|
||||
alreadyRegistered = parserContext.getRegistry().isBeanNameInUse(jsonPathBeanName);
|
||||
}
|
||||
if (!alreadyRegistered) {
|
||||
Class<?> jsonPathClass = null;
|
||||
try {
|
||||
jsonPathClass = ClassUtils.forName("com.jayway.jsonpath.JsonPath", parserContext.getReaderContext().getBeanClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
logger.debug("SpEL function '#jsonPath' isn't registered: there is no jayway json-path.jar on the classpath.");
|
||||
}
|
||||
|
||||
if (jsonPathClass != null) {
|
||||
IntegrationNamespaceUtils.registerSpelFunctionBean(parserContext.getRegistry(), jsonPathBeanName,
|
||||
IntegrationNamespaceUtils.BASE_PACKAGE + ".json.JsonPathUtils", "evaluate");
|
||||
}
|
||||
}
|
||||
|
||||
this.doRegisterBuiltInBeans(parserContext);
|
||||
}
|
||||
|
||||
protected void doRegisterBuiltInBeans(ParserContext parserContext) {
|
||||
|
||||
}
|
||||
|
||||
private void registerDefaultConfiguringBeanFactoryPostProcessorIfNecessary(ParserContext parserContext) {
|
||||
boolean alreadyRegistered = false;
|
||||
if (parserContext.getRegistry() instanceof ListableBeanFactory) {
|
||||
@@ -171,10 +208,10 @@ public abstract class AbstractIntegrationNamespaceHandler implements NamespaceHa
|
||||
}
|
||||
|
||||
private void verifySchemaVersion(Element element, ParserContext parserContext) {
|
||||
if (!(matchesVersion(element) && matchesVersion(element.getOwnerDocument().getDocumentElement()))) {
|
||||
if (!(matchesVersion(element) && matchesVersion(element.getOwnerDocument().getDocumentElement()))) {
|
||||
parserContext.getReaderContext().error(
|
||||
"You cannot use prior versions of Spring Integration schemas with Spring Integration " + VERSION +
|
||||
". Please upgrade your schema declarations or use versionless aliases (e.g. spring-integration.xsd).", element);
|
||||
"You cannot use prior versions of Spring Integration schemas with Spring Integration " + VERSION +
|
||||
". Please upgrade your schema declarations or use versionless aliases (e.g. spring-integration.xsd).", element);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,17 @@ import static org.springframework.beans.factory.xml.AbstractBeanDefinitionParser
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.config.TypedStringValue;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
|
||||
@@ -30,6 +35,7 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.expression.common.LiteralExpression;
|
||||
import org.springframework.integration.config.ExpressionFactoryBean;
|
||||
import org.springframework.integration.config.SpelFunctionFactoryBean;
|
||||
import org.springframework.integration.endpoint.AbstractPollingEndpoint;
|
||||
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
|
||||
import org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource;
|
||||
@@ -37,9 +43,6 @@ import org.springframework.transaction.interceptor.TransactionInterceptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Shared utility methods for integration namespace parsers.
|
||||
@@ -456,4 +459,14 @@ public abstract class IntegrationNamespaceUtils {
|
||||
}
|
||||
return expressionDef;
|
||||
}
|
||||
|
||||
|
||||
public static void registerSpelFunctionBean(BeanDefinitionRegistry registry, String functionId, String className,
|
||||
String methodSignature) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SpelFunctionFactoryBean.class)
|
||||
.addConstructorArgValue(className)
|
||||
.addConstructorArgValue(methodSignature);
|
||||
registry.registerBeanDefinition(functionId, builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,78 +16,29 @@
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.integration.config.SpelFunctionFactoryBean;
|
||||
|
||||
/**
|
||||
* Parser for the <spel-function> element.
|
||||
* Doesn't register a bean within application context, collects 'functions'
|
||||
* within {@link org.springframework.integration.config.SpelFunctionRegistrar} bean.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
public class SpelFunctionParser implements BeanDefinitionParser {
|
||||
|
||||
private final Map<String, Method> functions = new LinkedHashMap<String, Method>();
|
||||
|
||||
private volatile boolean initialized;
|
||||
public class SpelFunctionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
|
||||
this.initializeSpelFunctionRegistrarIfNecessary(parserContext);
|
||||
|
||||
String id = element.getAttribute("id");
|
||||
String className = element.getAttribute("class");
|
||||
String signature = element.getAttribute("method");
|
||||
|
||||
Class<?> clazz = null;
|
||||
try {
|
||||
clazz = ClassUtils.forName(className, parserContext.getReaderContext().getBeanClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
parserContext.getReaderContext().error(e.getMessage(), element);
|
||||
}
|
||||
|
||||
Method method = BeanUtils.resolveSignature(signature, clazz);
|
||||
|
||||
if (method == null) {
|
||||
parserContext.getReaderContext().error(String.format("No declared method '%s' in class '%s'",
|
||||
signature, className), element);
|
||||
return null;
|
||||
}
|
||||
if (!Modifier.isStatic(method.getModifiers())) {
|
||||
parserContext.getReaderContext().error("SpEL-function method has to be 'static'", element);
|
||||
}
|
||||
|
||||
this.functions.put(id, method);
|
||||
|
||||
return null;
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return SpelFunctionFactoryBean.class;
|
||||
}
|
||||
|
||||
private synchronized void initializeSpelFunctionRegistrarIfNecessary(ParserContext parserContext) {
|
||||
if (!this.initialized) {
|
||||
BeanDefinitionBuilder registrarBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(IntegrationNamespaceUtils.BASE_PACKAGE + ".config.SpelFunctionRegistrar")
|
||||
.setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
.addConstructorArgValue(this.functions);
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(registrarBuilder.getBeanDefinition(),
|
||||
parserContext.getRegistry());
|
||||
this.initialized = true;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void doParse(Element element, BeanDefinitionBuilder builder) {
|
||||
builder.addConstructorArgValue(element.getAttribute("class"))
|
||||
.addConstructorArgValue(element.getAttribute("method"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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 java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
import com.jayway.jsonpath.Filter;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
|
||||
/**
|
||||
* Utility class to {@link #evaluate} a jsonPath on the provided object.
|
||||
* Delegates evaluation to <a href="http://code.google.com/p/json-path">JsonPath</a>.
|
||||
* Note {@link #evaluate} is used as {@code #jsonPath()} SpEL function.
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class JsonPathUtils {
|
||||
|
||||
public static <T> T evaluate(Object json, String jsonPath, Filter<?>... filters) throws Exception {
|
||||
if (json instanceof String) {
|
||||
return JsonPath.read((String) json, jsonPath, filters);
|
||||
}
|
||||
else if (json instanceof File) {
|
||||
return JsonPath.read((File) json, jsonPath, filters);
|
||||
}
|
||||
else if (json instanceof URL) {
|
||||
return JsonPath.read((URL) json, jsonPath, filters);
|
||||
}
|
||||
else if (json instanceof InputStream) {
|
||||
return JsonPath.read((InputStream) json, jsonPath, filters);
|
||||
}
|
||||
else {
|
||||
return JsonPath.read(json, jsonPath, filters);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private JsonPathUtils() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public class PublisherExpressionTests {
|
||||
public void setup() throws Exception {
|
||||
context.registerSingleton("testChannel", QueueChannel.class);
|
||||
IntegrationEvaluationContextFactoryBean factory = new IntegrationEvaluationContextFactoryBean();
|
||||
factory.setBeanFactory(context);
|
||||
factory.setApplicationContext(context);
|
||||
factory.afterPropertiesSet();
|
||||
EvaluationContext ec = factory.getObject();
|
||||
context.getBeanFactory().registerSingleton(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME, ec);
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<bean id="bar" class="java.lang.String">
|
||||
<bean id="barString" class="java.lang.String">
|
||||
<constructor-arg value="bar"/>
|
||||
</bean>
|
||||
|
||||
<int:transformer input-channel="input" output-channel="output" expression="@foo + @bar"/>
|
||||
<int:transformer input-channel="input" output-channel="output" expression="@foo + @barString"/>
|
||||
|
||||
<int:channel id="output">
|
||||
<int:queue/>
|
||||
@@ -21,4 +21,6 @@
|
||||
|
||||
<int:spel-function id="barChild" class="org.springframework.integration.expression.ParentContextTests$Bar" method="bar"/>
|
||||
|
||||
<int:spel-function id="jsonPath" class="org.springframework.integration.expression.ParentContextTests$Bar" method="bar"/>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -19,22 +19,26 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.config.IntegrationEvaluationContextFactoryBean;
|
||||
import org.springframework.integration.json.JsonPathUtils;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
|
||||
@@ -56,34 +60,34 @@ public class ParentContextTests {
|
||||
* and parent contexts work.
|
||||
*/
|
||||
@Test
|
||||
public void testSpelBeanReferencesInChildAndParent() throws ClassNotFoundException {
|
||||
//To check if 'org.springframework.integration.config.SpelFunctionRegistrar#afterPropertiesSet()'
|
||||
//doesn't throw any Exception
|
||||
AbstractApplicationContext superParent = new GenericApplicationContext();
|
||||
superParent.refresh();
|
||||
public void testSpelBeanReferencesInChildAndParent() throws Exception {
|
||||
AbstractApplicationContext parent = new ClassPathXmlApplicationContext("ParentContext-context.xml", this.getClass());
|
||||
|
||||
AbstractApplicationContext parent = new ClassPathXmlApplicationContext(new String[]{"ParentContext-context.xml"},
|
||||
this.getClass(), superParent);
|
||||
|
||||
Class<?> spelFunctionRegistrarClass = Class.forName("org.springframework.integration.config.SpelFunctionRegistrar");
|
||||
Object parentSpelFunctionRegistrar = parent.getBean(spelFunctionRegistrarClass);
|
||||
assertEquals(2, TestUtils.getPropertyValue(parentSpelFunctionRegistrar, "functions", Map.class).size());
|
||||
Object parentEvaluationContextFactoryBean = parent.getBean(IntegrationEvaluationContextFactoryBean.class);
|
||||
Map parentFunctions = TestUtils.getPropertyValue(parentEvaluationContextFactoryBean, "functions", Map.class);
|
||||
assertEquals(3, parentFunctions.size());
|
||||
Object jsonPath = parentFunctions.get("jsonPath");
|
||||
assertNotNull(jsonPath);
|
||||
assertThat((Method) jsonPath, Matchers.isOneOf(JsonPathUtils.class.getMethods()));
|
||||
|
||||
assertEquals(2, evalContexts.size());
|
||||
ClassPathXmlApplicationContext child = new ClassPathXmlApplicationContext(parent);
|
||||
child.setConfigLocation("org/springframework/integration/expression/ChildContext-context.xml");
|
||||
child.refresh();
|
||||
|
||||
Object childSpelFunctionRegistrar = child.getBean(spelFunctionRegistrarClass);
|
||||
Map functions = TestUtils.getPropertyValue(childSpelFunctionRegistrar, "functions", Map.class);
|
||||
assertEquals(3, functions.size());
|
||||
assertTrue(functions.containsKey("barParent"));
|
||||
Object childEvaluationContextFactoryBean = child.getBean(IntegrationEvaluationContextFactoryBean.class);
|
||||
Map childFunctions = TestUtils.getPropertyValue(childEvaluationContextFactoryBean, "functions", Map.class);
|
||||
assertEquals(4, childFunctions.size());
|
||||
assertTrue(childFunctions.containsKey("barParent"));
|
||||
jsonPath = childFunctions.get("jsonPath");
|
||||
assertNotNull(jsonPath);
|
||||
assertThat((Method) jsonPath, Matchers.not(Matchers.isOneOf(JsonPathUtils.class.getMethods())));
|
||||
|
||||
assertEquals(3, evalContexts.size());
|
||||
assertSame(evalContexts.get(0).getBeanResolver(), evalContexts.get(1).getBeanResolver());
|
||||
assertNotSame(evalContexts.get(1).getBeanResolver(), evalContexts.get(2).getBeanResolver());
|
||||
assertSame(parent.getBeanFactory(), TestUtils.getPropertyValue(evalContexts.get(0).getBeanResolver(), "beanFactory"));
|
||||
assertSame(child.getBeanFactory(), TestUtils.getPropertyValue(evalContexts.get(2).getBeanResolver(), "beanFactory"));
|
||||
assertSame(parent, TestUtils.getPropertyValue(evalContexts.get(0).getBeanResolver(), "beanFactory"));
|
||||
assertSame(child, TestUtils.getPropertyValue(evalContexts.get(2).getBeanResolver(), "beanFactory"));
|
||||
|
||||
// Test transformer expressions
|
||||
child.getBean("input", MessageChannel.class).send(new GenericMessage<String>("baz"));
|
||||
|
||||
@@ -29,8 +29,8 @@ import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -52,6 +52,7 @@ import org.springframework.integration.test.util.TestUtils;
|
||||
* @author Mark Fisher
|
||||
* @author Gunnar Hillert
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ExpressionEvaluatingMessageProcessorTests {
|
||||
@@ -121,11 +122,11 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
}
|
||||
Expression expression = expressionParser.parseExpression("#target.find(payload)");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
ConfigurableListableBeanFactory beanFactory = new GenericApplicationContext().getBeanFactory();
|
||||
processor.setBeanFactory(beanFactory);
|
||||
AbstractApplicationContext applicationContext = new GenericApplicationContext();
|
||||
processor.setBeanFactory(applicationContext);
|
||||
IntegrationEvaluationContextFactoryBean factoryBean = new IntegrationEvaluationContextFactoryBean();
|
||||
factoryBean.setBeanFactory(beanFactory);
|
||||
beanFactory.registerSingleton(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME,
|
||||
factoryBean.setApplicationContext(applicationContext);
|
||||
applicationContext.getBeanFactory().registerSingleton(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME,
|
||||
factoryBean.getObject());
|
||||
processor.afterPropertiesSet();
|
||||
EvaluationContext evaluationContext = TestUtils.getPropertyValue(processor, "evaluationContext", EvaluationContext.class);
|
||||
@@ -173,6 +174,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
context.registerBeanDefinition("testString", beanDefinition);
|
||||
context.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME,
|
||||
new RootBeanDefinition(IntegrationEvaluationContextFactoryBean.class));
|
||||
context.refresh();
|
||||
|
||||
Expression expression = expressionParser.parseExpression("payload.concat(@testString)");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
processor.setBeanFactory(context);
|
||||
@@ -190,6 +193,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
context.registerBeanDefinition(IntegrationContextUtils.INTEGRATION_EVALUATION_CONTEXT_BEAN_NAME,
|
||||
new RootBeanDefinition(IntegrationEvaluationContextFactoryBean.class));
|
||||
context.registerBeanDefinition("testString", beanDefinition);
|
||||
context.refresh();
|
||||
|
||||
Expression expression = expressionParser.parseExpression("@testString.concat(payload)");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
processor.setBeanFactory(context);
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:component-scan base-package="org.springframework.integration.json">
|
||||
<context:include-filter type="regex" expression="JsonPathTests"/>
|
||||
</context:component-scan>
|
||||
|
||||
<channel id="output">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<transformer input-channel="transformerInput" output-channel="output"
|
||||
expression="#jsonPath(payload, '$.store.book[0].author')"/>
|
||||
|
||||
|
||||
|
||||
<filter input-channel="filterInput1" output-channel="output" discard-channel="discardChannel"
|
||||
throw-exception-on-rejection="true"
|
||||
expression="!#jsonPath(payload, '$..bicycle').empty"/>
|
||||
|
||||
<channel id="discardChannel">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<filter input-channel="filterInput2" output-channel="output"
|
||||
expression="#jsonPath(payload, '$..book[2].isbn') matches '^\d-\d{3}-\d{5}-\d$'"/>
|
||||
|
||||
<filter input-channel="filterInput3" output-channel="output"
|
||||
expression="#jsonPath(payload, '$..book[?(@.price > ' + headers.price + ')]').size() > 1"/>
|
||||
|
||||
<filter input-channel="filterInput4" output-channel="output"
|
||||
expression="#jsonPath(payload, '$.store.book[?]', @jsonPathFilter).empty"/>
|
||||
|
||||
|
||||
|
||||
<splitter input-channel="splitterInput" output-channel="splitterOutput"
|
||||
expression="#jsonPath(payload, '$.store.book')"/>
|
||||
|
||||
<channel id="splitterOutput">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
|
||||
|
||||
<router input-channel="routerInput" expression="#jsonPath(payload, headers.jsonPath)">
|
||||
<mapping channel="routerOutput1" value="reference"/>
|
||||
<mapping channel="routerOutput2" value="fiction"/>
|
||||
</router>
|
||||
|
||||
<channel id="routerOutput1">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<channel id="routerOutput2">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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 static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import com.jayway.jsonpath.Criteria;
|
||||
import com.jayway.jsonpath.Filter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageRejectedException;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
* @since 3.0
|
||||
*/
|
||||
@ContextConfiguration(classes = JsonPathTests.JsonPathTestsContextConfiguration.class, loader = AnnotationConfigContextLoader.class)
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class JsonPathTests {
|
||||
|
||||
private static File JSON_FILE;
|
||||
|
||||
private static String JSON;
|
||||
|
||||
private static Message<String> testMessage;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws IOException {
|
||||
ClassPathResource jsonResource = new ClassPathResource("JsonPathTests.json", JsonPathTests.class);
|
||||
JSON_FILE = jsonResource.getFile();
|
||||
JSON = new Scanner(JSON_FILE).useDelimiter("\\Z").next();
|
||||
testMessage = new GenericMessage<String>(JSON);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private PollableChannel output;
|
||||
|
||||
@Autowired
|
||||
private volatile MessageChannel transformerInput;
|
||||
|
||||
@Autowired
|
||||
private volatile MessageChannel filterInput1;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel discardChannel;
|
||||
|
||||
@Autowired
|
||||
private volatile MessageChannel filterInput2;
|
||||
|
||||
@Autowired
|
||||
private volatile MessageChannel filterInput3;
|
||||
|
||||
@Autowired
|
||||
private volatile MessageChannel filterInput4;
|
||||
|
||||
@Autowired
|
||||
private volatile MessageChannel splitterInput;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel splitterOutput;
|
||||
|
||||
@Autowired
|
||||
private volatile MessageChannel routerInput;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel routerOutput1;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel routerOutput2;
|
||||
|
||||
|
||||
@Test
|
||||
public void testInt3139JsonPathTransformer() throws IOException {
|
||||
this.transformerInput.send(testMessage);
|
||||
Message<?> receive = this.output.receive(1000);
|
||||
assertNotNull(receive);
|
||||
assertEquals("Nigel Rees", receive.getPayload());
|
||||
|
||||
this.transformerInput.send(new GenericMessage<File>(JSON_FILE));
|
||||
receive = this.output.receive(1000);
|
||||
assertNotNull(receive);
|
||||
|
||||
assertEquals("Nigel Rees", receive.getPayload());
|
||||
try {
|
||||
this.transformerInput.send(new GenericMessage<Object>(new Object()));
|
||||
fail("IllegalArgumentException expected");
|
||||
}
|
||||
catch (Exception e) {
|
||||
//MessageTransformationException / MessageHandlingException / InvocationTargetException / IllegalArgumentException
|
||||
Throwable cause = e.getCause().getCause().getCause();
|
||||
assertTrue(cause instanceof IllegalArgumentException);
|
||||
assertEquals("Invalid container object", cause.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt3139JsonPathFilter() {
|
||||
this.filterInput1.send(testMessage);
|
||||
Message<?> receive = this.output.receive(1000);
|
||||
assertNotNull(receive);
|
||||
assertEquals(JSON, receive.getPayload());
|
||||
|
||||
this.filterInput2.send(testMessage);
|
||||
receive = this.output.receive(1000);
|
||||
assertNotNull(receive);
|
||||
|
||||
Message<String> message = MessageBuilder.withPayload(JSON)
|
||||
.setHeader("price", 10)
|
||||
.build();
|
||||
this.filterInput3.send(message);
|
||||
receive = this.output.receive(1000);
|
||||
assertNotNull(receive);
|
||||
|
||||
this.filterInput4.send(testMessage);
|
||||
receive = this.output.receive(1000);
|
||||
assertNotNull(receive);
|
||||
|
||||
try {
|
||||
this.filterInput1.send(new GenericMessage<String>("{foo:{}}"));
|
||||
fail("MessageRejectedException is expected.");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertThat(e, Matchers.instanceOf(MessageRejectedException.class));
|
||||
}
|
||||
receive = this.output.receive(0);
|
||||
assertNull(receive);
|
||||
|
||||
receive = this.discardChannel.receive(1000);
|
||||
assertNotNull(receive);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt3139JsonPathSplitter() {
|
||||
this.splitterInput.send(testMessage);
|
||||
for(int i = 0; i < 3; i++) {
|
||||
Message<?> receive = this.splitterOutput.receive(1000);
|
||||
assertNotNull(receive);
|
||||
assertTrue(receive.getPayload() instanceof Map);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt3139JsonPathRouter() {
|
||||
Message<String> message = MessageBuilder.withPayload(JSON)
|
||||
.setHeader("jsonPath", "$.store.book[0].category")
|
||||
.build();
|
||||
this.routerInput.send(message);
|
||||
Message<?> receive = this.routerOutput1.receive(1000);
|
||||
assertNotNull(receive);
|
||||
assertEquals(JSON, receive.getPayload());
|
||||
assertNull(this.routerOutput2.receive(10));
|
||||
|
||||
message = MessageBuilder.withPayload(JSON)
|
||||
.setHeader("jsonPath", "$.store.book[2].category")
|
||||
.build();
|
||||
this.routerInput.send(message);
|
||||
receive = this.routerOutput2.receive(1000);
|
||||
assertNotNull(receive);
|
||||
assertEquals(JSON, receive.getPayload());
|
||||
assertNull(this.routerOutput1.receive(10));
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@ImportResource("classpath:org/springframework/integration/json/JsonPathTests-context.xml")
|
||||
public static class JsonPathTestsContextConfiguration {
|
||||
|
||||
@Bean
|
||||
public Filter jsonPathFilter() {
|
||||
return Filter.filter(Criteria.where("isbn").exists(true).and("category").ne("fiction"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{ "store": {
|
||||
"book": [
|
||||
{
|
||||
"category": "reference",
|
||||
"author": "Nigel Rees",
|
||||
"title": "Sayings of the Century",
|
||||
"price": 8.95
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "Evelyn Waugh",
|
||||
"title": "Sword of Honour",
|
||||
"price": 12.99
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "Herman Melville",
|
||||
"title": "Moby Dick",
|
||||
"isbn": "0-553-21311-3",
|
||||
"price": 8.99
|
||||
},
|
||||
{
|
||||
"category": "fiction",
|
||||
"author": "J. R. R. Tolkien",
|
||||
"title": "The Lord of the Rings",
|
||||
"isbn": "0-395-19395-8",
|
||||
"price": 22.99
|
||||
}
|
||||
],
|
||||
"bicycle": {
|
||||
"color": "red",
|
||||
"price": 19.95
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user