INT-1104 added support for 'expression' on the logging-channel-adapter element

This commit is contained in:
Mark Fisher
2010-05-04 22:50:48 +00:00
parent 0b41c9a670
commit 84c6202102
5 changed files with 121 additions and 6 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* 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.
@@ -33,13 +33,20 @@ public class LoggingChannelAdapterParser extends AbstractOutboundChannelAdapterP
@Override
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
Object source = parserContext.extractSource(element);
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".handler.LoggingHandler");
builder.addConstructorArgValue(element.getAttribute("level"));
String expression = element.getAttribute("expression");
String logFullMessage = element.getAttribute("log-full-message");
if (StringUtils.hasText(logFullMessage)) {
if (StringUtils.hasText(expression)) {
parserContext.getReaderContext().error(
"The 'expression' and 'log-full-message' attributes are mutually exclusive.", source);
}
builder.addPropertyValue("shouldLogFullMessage", logFullMessage);
}
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expression");
return builder.getBeanDefinition();
}

View File

@@ -19,6 +19,11 @@ package org.springframework.integration.handler;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.integration.core.Message;
import org.springframework.util.StringUtils;
@@ -35,11 +40,14 @@ public class LoggingHandler extends AbstractMessageHandler {
private static enum Level { FATAL, ERROR, WARN, INFO, DEBUG, TRACE }
private static final SpelExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
private boolean shouldLogFullMessage;
private volatile Expression expression;
private final Level level;
private final EvaluationContext evaluationContext;
/**
* Create a LoggingHandler with the given log level (case-insensitive).
@@ -53,15 +61,24 @@ public class LoggingHandler extends AbstractMessageHandler {
throw new IllegalArgumentException("Invalid log level '" + level +
"'. The (case-insensitive) supported values are: " + StringUtils.arrayToCommaDelimitedString(Level.values()));
}
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
evaluationContext.addPropertyAccessor(new MapAccessor());
this.evaluationContext = evaluationContext;
this.expression = EXPRESSION_PARSER.parseExpression("payload");
}
public void setExpression(String expressionString) {
this.expression = EXPRESSION_PARSER.parseExpression(expressionString);
}
/**
* Specify whether to log the full Message. Otherwise, only the payload
* will be logged. This value is <code>false</code> by default.
*/
public void setShouldLogFullMessage(boolean shouldLogFullMessage) {
this.shouldLogFullMessage = shouldLogFullMessage;
this.expression = (shouldLogFullMessage) ? EXPRESSION_PARSER.parseExpression("#root")
: EXPRESSION_PARSER.parseExpression("payload");
}
@Override
@@ -71,7 +88,7 @@ public class LoggingHandler extends AbstractMessageHandler {
@Override
protected void handleMessageInternal(Message<?> message) throws Exception {
Object logMessage = (this.shouldLogFullMessage) ? message : message.getPayload();
Object logMessage = this.expression.getValue(this.evaluationContext, message);
if (logMessage instanceof Throwable) {
StringWriter stringWriter = new StringWriter();
((Throwable) logMessage).printStackTrace(new PrintWriter(stringWriter, true));

View File

@@ -638,11 +638,24 @@
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="expression">
<xsd:annotation>
<xsd:documentation><![CDATA[
Provide a SpEL expression to be evaluated against the Message as the root object. For example,
the default behavior is equivalent to an expression of "payload", or an expression may evaluate
against the payload itself ("payload.address.city") or headers ("headers.foo"). This attribute and
the 'log-full-message' attribute are mutually exclusive. See the documentation on the
'log-full-message' attribute for more information.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="log-full-message">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specify whether to log the full message. If false, only the payload will be logged.
This value will be false by default.
Specify whether to log the full message. This attribute and the 'expression' attribute are
mutually exclusive. Setting this to true is equivalent to setting an expression value of "#root"
since the Message is the root object against which the expression will be evaluated. If no
'expression' is provided, and this value is false (the default), only the payload will be logged.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<logging-channel-adapter id="input" expression="payload.name + ':' + payload.age"/>
</beans:beans>

View File

@@ -0,0 +1,66 @@
/*
* 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.handler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.message.MessageBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mark Fisher
* @since 2.0
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class LoggingHandlerTests {
@Autowired
MessageChannel input;
@Test
public void logWithExpression() {
TestBean bean = new TestBean("test", 55);
input.send(MessageBuilder.withPayload(bean).setHeader("foo", "bar").build());
}
public static class TestBean {
private final String name;
private int age;
public TestBean(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
}