INT-3977: Improve LoggingHandler for JavaConfig

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

* Add `Level` ctor
* Add `setLogExpression(Expression)` and `setLogExpressionString(String)`
* Deprecate existing `setExpression(String)` in favor of those new
* Some refactor for redundant code around `evaluationContext`
* Fix tests according a new `LoggingHandler` logic
* Add JavaConfig sample to the Reference Manual
This commit is contained in:
Artem Bilan
2016-04-05 12:19:27 -04:00
parent dee5c91bd8
commit c0b19e61b5
4 changed files with 108 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -28,6 +28,8 @@ import org.springframework.util.StringUtils;
* Parser for the 'logging-channel-adapter' element.
*
* @author Mark Fisher
* @author Artem Bilan
*
* @since 1.0.1
*/
public class LoggingChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
@@ -47,7 +49,7 @@ public class LoggingChannelAdapterParser extends AbstractOutboundChannelAdapterP
builder.addPropertyValue("shouldLogFullMessage", logFullMessage);
}
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "logger-name");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expression");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expression", "logExpressionString");
return builder.getBeanDefinition();
}

View File

@@ -38,6 +38,7 @@ import org.springframework.util.StringUtils;
*
* @author Mark Fisher
* @author Gary Russell
* @author Artem Bilan
* @since 1.0.1
*/
public class LoggingHandler extends AbstractMessageHandler {
@@ -68,9 +69,10 @@ public class LoggingHandler extends AbstractMessageHandler {
* The valid levels are: FATAL, ERROR, WARN, INFO, DEBUG, or TRACE
* </p>
* @param level The level.
* @see LoggingHandler(Level)
*/
public LoggingHandler(String level) {
Assert.notNull(level, "'level' cannot be null");
Assert.hasText(level, "'level' cannot be empty");
try {
this.level = Level.valueOf(level.toUpperCase());
}
@@ -79,14 +81,50 @@ public class LoggingHandler extends AbstractMessageHandler {
+ "'. The (case-insensitive) supported values are: "
+ StringUtils.arrayToCommaDelimitedString(Level.values()));
}
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext();
this.expression = EXPRESSION_PARSER.parseExpression("payload");
}
/**
* Create a {@link LoggingHandler} with the given log {@link Level}.
* @param level the {@link Level} to use.
* @since 4.3
*/
public LoggingHandler(Level level) {
Assert.notNull(level, "'level' cannot be null");
this.level = level;
}
/**
* Set a SpEL expression string to use.
* @param expressionString the SpEL expression string to use.
* @deprecated in favor of {@link #setLogExpressionString(String)}
*/
@Deprecated
public void setExpression(String expressionString) {
Assert.isTrue(!(this.shouldLogFullMessageSet), "Cannot set both 'expression' AND 'shouldLogFullMessage' properties");
setLogExpressionString(expressionString);
}
/**
* Set a SpEL expression string to use.
* @param expressionString the SpEL expression string to use.
* @since 4.3
* @see #setLogExpression(Expression)
*/
public void setLogExpressionString(String expressionString) {
Assert.hasText(expressionString, "'expressionString' must not be empty");
setLogExpression(EXPRESSION_PARSER.parseExpression(expressionString));
}
/**
* Set an {@link Expression} to evaluate a log entry at runtime against the request {@link Message}.
* @param expression the {@link Expression} to use.
* @since 4.3
* @see #setLogExpressionString(String)
*/
public void setLogExpression(Expression expression) {
Assert.isTrue(!(this.shouldLogFullMessageSet),
"Cannot set both 'expression' AND 'shouldLogFullMessage' properties");
this.expressionSet = true;
this.expression = EXPRESSION_PARSER.parseExpression(expressionString);
this.expression = expression;
}
/**
@@ -97,8 +135,7 @@ public class LoggingHandler extends AbstractMessageHandler {
}
/**
* Set the logging {@link Level}.
*
* Set the logging {@link Level} to change the behavior at runtime.
* @param level the level.
*/
public void setLevel(Level level) {
@@ -114,14 +151,14 @@ public class LoggingHandler extends AbstractMessageHandler {
/**
* Specify whether to log the full Message. Otherwise, only the payload will be logged. This value is
* <code>false</code> by default.
*
* @param shouldLogFullMessage true if the complete message should be logged.
*/
public void setShouldLogFullMessage(boolean shouldLogFullMessage) {
Assert.isTrue(!(this.expressionSet), "Cannot set both 'expression' AND 'shouldLogFullMessage' properties");
this.shouldLogFullMessageSet = true;
this.expression = (shouldLogFullMessage) ? EXPRESSION_PARSER.parseExpression("#root") : EXPRESSION_PARSER
.parseExpression("payload");
this.expression = (shouldLogFullMessage)
? EXPRESSION_PARSER.parseExpression("#root")
: EXPRESSION_PARSER.parseExpression("payload");
}
@Override
@@ -132,7 +169,10 @@ public class LoggingHandler extends AbstractMessageHandler {
@Override
protected void onInit() throws Exception {
super.onInit();
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(this.getBeanFactory());
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
if (this.expression == null) {
this.expression = EXPRESSION_PARSER.parseExpression("payload");
}
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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.
@@ -18,6 +18,7 @@ package org.springframework.integration.handler;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -29,6 +30,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
@@ -61,7 +63,7 @@ public class LoggingHandlerTests {
@Test
public void assertMutuallyExclusive() {
LoggingHandler loggingHandler = new LoggingHandler("INFO");
loggingHandler.setExpression("'foo'");
loggingHandler.setLogExpressionString("'foo'");
try {
loggingHandler.setShouldLogFullMessage(true);
fail("Expected IllegalArgumentException");
@@ -73,7 +75,7 @@ public class LoggingHandlerTests {
loggingHandler = new LoggingHandler("INFO");
loggingHandler.setShouldLogFullMessage(true);
try {
loggingHandler.setExpression("'foo'");
loggingHandler.setLogExpressionString("'foo'");
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
@@ -84,6 +86,9 @@ public class LoggingHandlerTests {
@Test
public void testDontEvaluateIfNotEnabled() {
LoggingHandler loggingHandler = new LoggingHandler("INFO");
loggingHandler.setBeanFactory(mock(BeanFactory.class));
loggingHandler.afterPropertiesSet();
DirectFieldAccessor accessor = new DirectFieldAccessor(loggingHandler);
Log log = (Log) accessor.getPropertyValue("messageLogger");
log = spy(log);
@@ -102,7 +107,10 @@ public class LoggingHandlerTests {
@Test
public void testChangeLevel() {
LoggingHandler loggingHandler = new LoggingHandler("INFO");
LoggingHandler loggingHandler = new LoggingHandler(Level.INFO);
loggingHandler.setBeanFactory(mock(BeanFactory.class));
loggingHandler.afterPropertiesSet();
DirectFieldAccessor accessor = new DirectFieldAccessor(loggingHandler);
Log log = (Log) accessor.getPropertyValue("messageLogger");
log = spy(log);

View File

@@ -40,3 +40,44 @@ This attribute cannot be specified if `expression` is specified.
<5> Specifies the _name_ of the logger (known as `category` in `log4j`) used for log messages created by this adapter.
This enables setting the log name (in the logging subsystem) for individual adapters.
By default, all adapters will log under the name `org.springframework.integration.handler.LoggingHandler`.
==== Configuring with Java Configuration
The following Spring Boot application provides an example of configuring the `LoggingHandler` using Java configuration:
[source, java]
----
@SpringBootApplication
public class LoggingJavaApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new SpringApplicationBuilder(LoggingJavaApplication.class)
.web(false)
.run(args);
MyGateway gateway = context.getBean(MyGateway.class);
gateway.sendToLogger("foo");
}
@Bean
public MessageChannel logInputChannel() {
return new DirectChannel();
}
@Bean
@ServiceActivator(inputChannel = "logChannel")
public LoggingHandler logging() {
LoggingHandler adapter = new LoggingHandler(LoggingHandler.Level.DEBUG);
adapter.setLoggerName("TEST_LOGGER");
adapter.setLogExpressionString("headers.id + ': ' + payload");
return adapter;
}
@MessagingGateway(defaultRequestChannel = "logChannel")
public interface MyGateway {
void sendToLogger(String data);
}
}
----