diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/log4j/AmqpAppender.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/log4j/AmqpAppender.java
index 9050c7d8..8fe2f7dc 100644
--- a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/log4j/AmqpAppender.java
+++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/log4j/AmqpAppender.java
@@ -1,17 +1,14 @@
/*
* Copyright (c) 2011 by the original author(s).
- *
- * 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.
+ *
+ * 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.amqp.rabbit.log4j;
@@ -52,7 +49,9 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
*
* A fully-configured AmqpAppender, with every option set to their defaults, would look like this:
*
- *
+ *
+ *
+ *
* log4j.appender.amqp=org.springframework.amqp.log4j.AmqpAppender
* #-------------------------------
* ## Connection settings
@@ -69,7 +68,8 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
* log4j.appender.amqp.exchangeName=logs
* log4j.appender.amqp.exchangeType=topic
* #-------------------------------
- * ## What Log4J-format pattern to use to create a routing key
+ * ## Log4J-format pattern to use to create a routing key.
+ * ## The application id is available as %X{applicationId}.
* #-------------------------------
* log4j.appender.amqp.routingKeyPattern=%c.%p
* #-------------------------------
@@ -92,395 +92,411 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
* #-------------------------------
* log4j.appender.amqp.layout=org.apache.log4j.PatternLayout
* log4j.appender.amqp.layout.ConversionPattern=%d %p %t [%c] - <%m>%n
- *
- *
+ *
+ *
+ *
* @author Jon Brisbin
*/
public class AmqpAppender extends AppenderSkeleton {
- protected static final String APPLICATION_ID = "applicationId";
- protected static final String CATEGORY_NAME = "categoryName";
- protected static final String CATEGORY_LEVEL = "level";
+ /**
+ * Key name for the application id (if there is one set via the appender config) in the message properties.
+ */
+ public static final String APPLICATION_ID = "applicationId";
- /**
- * Name of the exchange to publish log events to.
- */
- protected String exchangeName = "logs";
- /**
- * Type of the exchange to publish log events to.
- */
- protected String exchangeType = "topic";
- /**
- * Log4J pattern format to use to generate a routing key.
- */
- protected String routingKeyPattern = "%c.%p";
- /**
- * Log4J Layout to use to generate routing key.
- */
- protected Layout routingKeyLayout = new PatternLayout(routingKeyPattern);
- /**
- * Whether or not we've tried to declare this exchange yet.
- */
- protected AtomicBoolean exchangeDeclared = new AtomicBoolean(false);
- /**
- * How long to wait for a connection to time out.
- */
- protected int connectionTimeout = 0;
- /**
- * Configuration arbitrary application ID.
- */
- protected String applicationId = null;
- /**
- * Where LoggingEvents are queued to send.
- */
- protected LinkedBlockingQueue events = new LinkedBlockingQueue();
- /**
- * The pool of senders.
- */
- protected ExecutorService senderPool = null;
- /**
- * How many senders to use at once. Use more senders if you have lots of log output going through this appender.
- */
- protected int senderPoolSize = 2;
- /**
- * How many times to retry sending a message if the broker is unavailable or there is some other error.
- */
- protected int maxSenderRetries = 30;
- /**
- * Retries are delayed like: N ^ log(N), where N is the retry number.
- */
- protected Timer retryTimer = new Timer("log-event-retry-delay", true);
- /**
- * RabbitMQ ConnectionFactory.
- */
- protected CachingConnectionFactory connectionFactory;
- /**
- * RabbitMQ host to connect to.
- */
- protected String host = "localhost";
- /**
- * RabbitMQ virtual host to connect to.
- */
- protected String virtualHost = "/";
- /**
- * RabbitMQ port to connect to.
- */
- protected int port = 5672;
- /**
- * RabbitMQ user to connect as.
- */
- protected String username = "guest";
- /**
- * RabbitMQ password for this user.
- */
- protected String password = "guest";
- /**
- * Default content-type of log messages.
- */
- protected String contentType = "text/plain";
- /**
- * Default content-encoding of log messages.
- */
- protected String contentEncoding = null;
- /**
- * Whether or not to try and declare the configured exchange when this appender starts.
- */
- protected boolean declareExchange = false;
- /**
- * Used to synchronize access when creating the RabbitMQ ConnectionFactory.
- */
- protected final String mutex = "mutex";
+ /**
+ * Key name for the logger category name in the message properties
+ */
+ public static final String CATEGORY_NAME = "categoryName";
- public AmqpAppender() {
- }
+ /**
+ * Key name for the logger level name in the message properties
+ */
+ public static final String CATEGORY_LEVEL = "level";
- public String getHost() {
- return host;
- }
+ /**
+ * Name of the exchange to publish log events to.
+ */
+ private String exchangeName = "logs";
+ /**
+ * Type of the exchange to publish log events to.
+ */
+ private String exchangeType = "topic";
+ /**
+ * Log4J pattern format to use to generate a routing key.
+ */
+ private String routingKeyPattern = "%c.%p";
+ /**
+ * Log4J Layout to use to generate routing key.
+ */
+ private Layout routingKeyLayout = new PatternLayout(routingKeyPattern);
+ /**
+ * Whether or not we've tried to declare this exchange yet.
+ */
+ private AtomicBoolean exchangeDeclared = new AtomicBoolean(false);
+ /**
+ * How long to wait for a connection to time out.
+ */
+ private int connectionTimeout = 0;
+ /**
+ * Configuration arbitrary application ID.
+ */
+ private String applicationId = null;
+ /**
+ * Where LoggingEvents are queued to send.
+ */
+ private LinkedBlockingQueue events = new LinkedBlockingQueue();
+ /**
+ * The pool of senders.
+ */
+ private ExecutorService senderPool = null;
+ /**
+ * How many senders to use at once. Use more senders if you have lots of log output going through this appender.
+ */
+ private int senderPoolSize = 2;
+ /**
+ * How many times to retry sending a message if the broker is unavailable or there is some other error.
+ */
+ private int maxSenderRetries = 30;
+ /**
+ * Retries are delayed like: N ^ log(N), where N is the retry number.
+ */
+ private Timer retryTimer = new Timer("log-event-retry-delay", true);
+ /**
+ * RabbitMQ ConnectionFactory.
+ */
+ private CachingConnectionFactory connectionFactory;
+ /**
+ * RabbitMQ host to connect to.
+ */
+ private String host = "localhost";
+ /**
+ * RabbitMQ virtual host to connect to.
+ */
+ private String virtualHost = "/";
+ /**
+ * RabbitMQ port to connect to.
+ */
+ private int port = 5672;
+ /**
+ * RabbitMQ user to connect as.
+ */
+ private String username = "guest";
+ /**
+ * RabbitMQ password for this user.
+ */
+ private String password = "guest";
+ /**
+ * Default content-type of log messages.
+ */
+ private String contentType = "text/plain";
+ /**
+ * Default content-encoding of log messages.
+ */
+ private String contentEncoding = null;
+ /**
+ * Whether or not to try and declare the configured exchange when this appender starts.
+ */
+ private boolean declareExchange = false;
+ /**
+ * Used to synchronize access when creating the RabbitMQ ConnectionFactory.
+ */
+ private final String mutex = "mutex";
- public void setHost(String host) {
- this.host = host;
- }
+ public AmqpAppender() {
+ }
- public int getPort() {
- return port;
- }
+ public String getHost() {
+ return host;
+ }
- public void setPort(int port) {
- this.port = port;
- }
+ public void setHost(String host) {
+ this.host = host;
+ }
- public String getVirtualHost() {
- return virtualHost;
- }
+ public int getPort() {
+ return port;
+ }
- public void setVirtualHost(String virtualHost) {
- this.virtualHost = virtualHost;
- }
+ public void setPort(int port) {
+ this.port = port;
+ }
- public String getUsername() {
- return username;
- }
+ public String getVirtualHost() {
+ return virtualHost;
+ }
- public void setUsername(String username) {
- this.username = username;
- }
+ public void setVirtualHost(String virtualHost) {
+ this.virtualHost = virtualHost;
+ }
- public String getPassword() {
- return password;
- }
+ public String getUsername() {
+ return username;
+ }
- public void setPassword(String password) {
- this.password = password;
- }
+ public void setUsername(String username) {
+ this.username = username;
+ }
- public String getExchangeName() {
- return exchangeName;
- }
+ public String getPassword() {
+ return password;
+ }
- public void setExchangeName(String exchangeName) {
- this.exchangeName = exchangeName;
- }
+ public void setPassword(String password) {
+ this.password = password;
+ }
- public String getExchangeType() {
- return exchangeType;
- }
+ public String getExchangeName() {
+ return exchangeName;
+ }
- public void setExchangeType(String exchangeType) {
- this.exchangeType = exchangeType;
- }
+ public void setExchangeName(String exchangeName) {
+ this.exchangeName = exchangeName;
+ }
- public String getRoutingKeyPattern() {
- return routingKeyPattern;
- }
+ public String getExchangeType() {
+ return exchangeType;
+ }
- public void setRoutingKeyPattern(String routingKeyPattern) {
- this.routingKeyPattern = routingKeyPattern;
- this.routingKeyLayout = new PatternLayout(routingKeyPattern);
- }
+ public void setExchangeType(String exchangeType) {
+ this.exchangeType = exchangeType;
+ }
- public boolean isDeclareExchange() {
- return declareExchange;
- }
+ public String getRoutingKeyPattern() {
+ return routingKeyPattern;
+ }
- public void setDeclareExchange(boolean declareExchange) {
- this.declareExchange = declareExchange;
- }
+ public void setRoutingKeyPattern(String routingKeyPattern) {
+ this.routingKeyPattern = routingKeyPattern;
+ this.routingKeyLayout = new PatternLayout(routingKeyPattern);
+ }
- public int getConnectionTimeout() {
- return connectionTimeout;
- }
+ public boolean isDeclareExchange() {
+ return declareExchange;
+ }
- public String getContentType() {
- return contentType;
- }
+ public void setDeclareExchange(boolean declareExchange) {
+ this.declareExchange = declareExchange;
+ }
- public void setContentType(String contentType) {
- this.contentType = contentType;
- }
+ public int getConnectionTimeout() {
+ return connectionTimeout;
+ }
- public String getContentEncoding() {
- return contentEncoding;
- }
+ public String getContentType() {
+ return contentType;
+ }
- public void setContentEncoding(String contentEncoding) {
- this.contentEncoding = contentEncoding;
- }
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
- public String getApplicationId() {
- return applicationId;
- }
+ public String getContentEncoding() {
+ return contentEncoding;
+ }
- public void setApplicationId(String applicationId) {
- this.applicationId = applicationId;
- }
+ public void setContentEncoding(String contentEncoding) {
+ this.contentEncoding = contentEncoding;
+ }
- public int getSenderPoolSize() {
- return senderPoolSize;
- }
+ public String getApplicationId() {
+ return applicationId;
+ }
- public void setSenderPoolSize(int senderPoolSize) {
- this.senderPoolSize = senderPoolSize;
- }
+ public void setApplicationId(String applicationId) {
+ this.applicationId = applicationId;
+ }
- public int getMaxSenderRetries() {
- return maxSenderRetries;
- }
+ public int getSenderPoolSize() {
+ return senderPoolSize;
+ }
- public void setMaxSenderRetries(int maxSenderRetries) {
- this.maxSenderRetries = maxSenderRetries;
- }
+ public void setSenderPoolSize(int senderPoolSize) {
+ this.senderPoolSize = senderPoolSize;
+ }
- /**
- * Submit the required number of senders into the pool.
- */
- protected void startSenders() {
- senderPool = Executors.newCachedThreadPool();
- for (int i = 0; i < senderPoolSize; i++) {
- senderPool.submit(new EventSender());
- }
- }
+ public int getMaxSenderRetries() {
+ return maxSenderRetries;
+ }
- /**
- * Maybe declare the exchange.
- */
- protected void maybeDeclareExchange() {
- RabbitAdmin admin = new RabbitAdmin(connectionFactory);
- if (declareExchange) {
- Exchange x;
- if ("topic".equals(exchangeType)) {
- x = new TopicExchange(exchangeName, true, false);
- } else if ("direct".equals(exchangeType)) {
- x = new DirectExchange(exchangeName, true, false);
- } else if ("fanout".equals(exchangeType)) {
- x = new FanoutExchange(exchangeName, true, false);
- } else if ("headers".equals(exchangeType)) {
- x = new HeadersExchange(exchangeType, true, false);
- } else {
- x = new TopicExchange(exchangeName);
- }
- //admin.deleteExchange(exchangeName);
- admin.declareExchange(x);
- }
- }
+ public void setMaxSenderRetries(int maxSenderRetries) {
+ this.maxSenderRetries = maxSenderRetries;
+ }
- @Override
- public void append(LoggingEvent event) {
- if (null == senderPool) {
- synchronized (mutex) {
- connectionFactory = new CachingConnectionFactory();
- connectionFactory.setHost(host);
- connectionFactory.setPort(port);
- connectionFactory.setUsername(username);
- connectionFactory.setPassword(password);
- connectionFactory.setVirtualHost(virtualHost);
- maybeDeclareExchange();
- exchangeDeclared.set(true);
+ /**
+ * Submit the required number of senders into the pool.
+ */
+ protected void startSenders() {
+ senderPool = Executors.newCachedThreadPool();
+ for (int i = 0; i < senderPoolSize; i++) {
+ senderPool.submit(new EventSender());
+ }
+ }
- startSenders();
- }
- }
- events.add(new Event(event, event.getProperties()));
- }
+ /**
+ * Maybe declare the exchange.
+ */
+ protected void maybeDeclareExchange() {
+ RabbitAdmin admin = new RabbitAdmin(connectionFactory);
+ if (declareExchange) {
+ Exchange x;
+ if ("topic".equals(exchangeType)) {
+ x = new TopicExchange(exchangeName, true, false);
+ } else if ("direct".equals(exchangeType)) {
+ x = new DirectExchange(exchangeName, true, false);
+ } else if ("fanout".equals(exchangeType)) {
+ x = new FanoutExchange(exchangeName, true, false);
+ } else if ("headers".equals(exchangeType)) {
+ x = new HeadersExchange(exchangeType, true, false);
+ } else {
+ x = new TopicExchange(exchangeName);
+ }
+ // admin.deleteExchange(exchangeName);
+ admin.declareExchange(x);
+ }
+ }
- public void close() {
- if (null != senderPool) {
- senderPool.shutdownNow();
- senderPool = null;
- }
- }
+ @Override
+ public void append(LoggingEvent event) {
+ if (null == senderPool) {
+ synchronized (mutex) {
+ connectionFactory = new CachingConnectionFactory();
+ connectionFactory.setHost(host);
+ connectionFactory.setPort(port);
+ connectionFactory.setUsername(username);
+ connectionFactory.setPassword(password);
+ connectionFactory.setVirtualHost(virtualHost);
+ maybeDeclareExchange();
+ exchangeDeclared.set(true);
- public boolean requiresLayout() {
- return true;
- }
+ startSenders();
+ }
+ }
+ events.add(new Event(event, event.getProperties()));
+ }
- /**
- * Helper class to actually send LoggingEvents asynchronously.
- */
- protected class EventSender implements Runnable {
- public void run() {
- try {
- RabbitTemplate rabbitTmpl = new RabbitTemplate(connectionFactory);
- while (true) {
- final Event event = events.take();
- LoggingEvent logEvent = event.getEvent();
+ public void close() {
+ if (null != senderPool) {
+ senderPool.shutdownNow();
+ senderPool = null;
+ }
+ }
- String name = logEvent.getLogger().getName();
- Level level = logEvent.getLevel();
+ public boolean requiresLayout() {
+ return true;
+ }
- MessageProperties amqpProps = new MessageProperties();
- amqpProps.setContentType(contentType);
- if (null != contentEncoding) {
- amqpProps.setContentEncoding(contentEncoding);
- }
- amqpProps.setHeader(CATEGORY_NAME, name);
- amqpProps.setHeader(CATEGORY_LEVEL, level.toString());
+ /**
+ * Helper class to actually send LoggingEvents asynchronously.
+ */
+ protected class EventSender implements Runnable {
+ public void run() {
+ try {
+ RabbitTemplate rabbitTmpl = new RabbitTemplate(connectionFactory);
+ while (true) {
+ final Event event = events.take();
+ LoggingEvent logEvent = event.getEvent();
- // Set applicationId, if we're using one
- if (null != applicationId) {
- amqpProps.setAppId(applicationId);
- MDC.put(APPLICATION_ID, applicationId);
- }
+ String name = logEvent.getLogger().getName();
+ Level level = logEvent.getLevel();
- // Set timestamp
- Calendar tstamp = Calendar.getInstance();
- tstamp.setTimeInMillis(logEvent.getTimeStamp());
- amqpProps.setTimestamp(tstamp.getTime());
+ MessageProperties amqpProps = new MessageProperties();
+ amqpProps.setContentType(contentType);
+ if (null != contentEncoding) {
+ amqpProps.setContentEncoding(contentEncoding);
+ }
+ amqpProps.setHeader(CATEGORY_NAME, name);
+ amqpProps.setHeader(CATEGORY_LEVEL, level.toString());
- // Copy properties in from MDC
- Map props = event.getProperties();
- for (Object key : event.getProperties().entrySet()) {
- amqpProps.setHeader(key.toString(), props.get(key));
- }
- LocationInfo locInfo = logEvent.getLocationInformation();
- if (!"?".equals(locInfo.getClassName())) {
- amqpProps.setHeader("location", String.format("%s.%s()[%s]", locInfo.getClassName(), locInfo.getMethodName(), locInfo.getLineNumber()));
- }
+ // Set applicationId, if we're using one
+ if (null != applicationId) {
+ amqpProps.setAppId(applicationId);
+ MDC.put(APPLICATION_ID, applicationId);
+ }
- StringBuffer msgBody = new StringBuffer(String.format("%s%n", logEvent.getRenderedMessage()));
- if (null != logEvent.getThrowableInformation()) {
- ThrowableInformation tinfo = logEvent.getThrowableInformation();
- for (String line : tinfo.getThrowableStrRep()) {
- msgBody.append(String.format("%s%n", line));
- }
- }
+ // Set timestamp
+ Calendar tstamp = Calendar.getInstance();
+ tstamp.setTimeInMillis(logEvent.getTimeStamp());
+ amqpProps.setTimestamp(tstamp.getTime());
- // Send a message
- String routingKey = routingKeyLayout.format(logEvent);
- try {
- rabbitTmpl.send(exchangeName, routingKey, new Message(msgBody.toString().getBytes(), amqpProps));
- } catch (AmqpException e) {
- int retries = event.incrementRetries();
- if (retries < maxSenderRetries) {
- // Schedule a retry based on the number of times I've tried to re-send this
- retryTimer.schedule(new TimerTask() {
- @Override
- public void run() {
- events.add(event);
- }
- }, (long) (Math.pow(retries, Math.log(retries)) * 1000));
- } else {
- errorHandler.error("Could not send log message " + logEvent.getRenderedMessage() + " after " + maxSenderRetries + " retries",
- e,
- ErrorCode.WRITE_FAILURE,
- logEvent);
- }
- } finally {
- if (null != applicationId) {
- MDC.remove(APPLICATION_ID);
- }
- }
- }
- } catch (Throwable t) {
- throw new RuntimeException(t.getMessage(), t);
- }
- }
- }
+ // Copy properties in from MDC
+ @SuppressWarnings("rawtypes")
+ Map props = event.getProperties();
+ for (Object key : event.getProperties().entrySet()) {
+ amqpProps.setHeader(key.toString(), props.get(key));
+ }
+ LocationInfo locInfo = logEvent.getLocationInformation();
+ if (!"?".equals(locInfo.getClassName())) {
+ amqpProps.setHeader(
+ "location",
+ String.format("%s.%s()[%s]", locInfo.getClassName(), locInfo.getMethodName(),
+ locInfo.getLineNumber()));
+ }
- /**
- * Small helper class to encapsulate a LoggingEvent, its MDC properties, and the number of retries.
- */
- protected class Event {
- final LoggingEvent event;
- final Map properties;
- AtomicInteger retries = new AtomicInteger(0);
+ StringBuffer msgBody = new StringBuffer(String.format("%s%n", logEvent.getRenderedMessage()));
+ if (null != logEvent.getThrowableInformation()) {
+ ThrowableInformation tinfo = logEvent.getThrowableInformation();
+ for (String line : tinfo.getThrowableStrRep()) {
+ msgBody.append(String.format("%s%n", line));
+ }
+ }
- public Event(LoggingEvent event, Map properties) {
- this.event = event;
- this.properties = properties;
- }
+ // Send a message
+ String routingKey = routingKeyLayout.format(logEvent);
+ try {
+ rabbitTmpl
+ .send(exchangeName, routingKey, new Message(msgBody.toString().getBytes(), amqpProps));
+ } catch (AmqpException e) {
+ int retries = event.incrementRetries();
+ if (retries < maxSenderRetries) {
+ // Schedule a retry based on the number of times I've tried to re-send this
+ retryTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ events.add(event);
+ }
+ }, (long) (Math.pow(retries, Math.log(retries)) * 1000));
+ } else {
+ errorHandler.error("Could not send log message " + logEvent.getRenderedMessage()
+ + " after " + maxSenderRetries + " retries", e, ErrorCode.WRITE_FAILURE, logEvent);
+ }
+ } finally {
+ if (null != applicationId) {
+ MDC.remove(APPLICATION_ID);
+ }
+ }
+ }
+ } catch (Throwable t) {
+ throw new RuntimeException(t.getMessage(), t);
+ }
+ }
+ }
- public LoggingEvent getEvent() {
- return event;
- }
+ /**
+ * Small helper class to encapsulate a LoggingEvent, its MDC properties, and the number of retries.
+ */
+ @SuppressWarnings("rawtypes")
+ protected class Event {
+ final LoggingEvent event;
+ final Map properties;
+ AtomicInteger retries = new AtomicInteger(0);
- public Map getProperties() {
- return properties;
- }
+ public Event(LoggingEvent event, Map properties) {
+ this.event = event;
+ this.properties = properties;
+ }
- public int incrementRetries() {
- return retries.incrementAndGet();
- }
- }
+ public LoggingEvent getEvent() {
+ return event;
+ }
+
+ public Map getProperties() {
+ return properties;
+ }
+
+ public int incrementRetries() {
+ return retries.incrementAndGet();
+ }
+ }
}
diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/log4j/AmqpAppenderIntegrationTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/log4j/AmqpAppenderIntegrationTests.java
new file mode 100644
index 00000000..abbc2ea4
--- /dev/null
+++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/log4j/AmqpAppenderIntegrationTests.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2011 by the original author(s).
+ *
+ * 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.amqp.rabbit.log4j;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.MDC;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
+import org.springframework.amqp.rabbit.test.BrokerRunning;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.util.Log4jConfigurer;
+
+/**
+ * @author Jon Brisbin
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "org.springframework.amqp.rabbit.log4j" }, loader = AnnotationConfigContextLoader.class)
+public class AmqpAppenderIntegrationTests {
+
+ @Rule
+ public BrokerRunning brokerIsRunning = BrokerRunning.isRunning();
+
+ @Autowired
+ private ApplicationContext applicationContext;
+
+ private Logger log;
+
+ private SimpleMessageListenerContainer listenerContainer;
+
+ @Before
+ public void setUp() throws Exception {
+ Log4jConfigurer.initLogging("classpath:log4j-amqp.properties");
+ log = Logger.getLogger(getClass());
+ listenerContainer = applicationContext.getBean(SimpleMessageListenerContainer.class);
+ }
+
+ @After
+ public void tearDown() {
+ listenerContainer.shutdown();
+ }
+
+ @Test
+ public void testAppender() throws InterruptedException {
+ TestListener testListener = (TestListener) applicationContext.getBean("testListener", 4);
+ listenerContainer.setMessageListener(testListener);
+ listenerContainer.start();
+
+ Logger log = Logger.getLogger(getClass());
+
+ log.debug("This is a DEBUG message");
+ log.info("This is an INFO message");
+ log.warn("This is a WARN message");
+ log.error("This is an ERROR message", new RuntimeException("Test exception"));
+
+ testListener.getLatch().await(5, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testAppenderWithProps() throws InterruptedException {
+ TestListener testListener = (TestListener) applicationContext.getBean("testListener", 4);
+ listenerContainer.setMessageListener(testListener);
+ listenerContainer.start();
+
+ MDC.put("someproperty", "property.value");
+ log.debug("This is a DEBUG message with properties");
+ log.info("This is an INFO message with properties");
+ log.warn("This is a WARN message with properties");
+ log.error("This is an ERROR message with properties", new RuntimeException("Test exception"));
+ MDC.remove("someproperty");
+
+ testListener.getLatch().await(5, TimeUnit.SECONDS);
+ }
+
+}
diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/log4j/AmqpAppenderTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/log4j/AmqpAppenderTests.java
deleted file mode 100644
index 5642c559..00000000
--- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/log4j/AmqpAppenderTests.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2011 by the original author(s).
- *
- * 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.amqp.rabbit.log4j;
-
-import java.util.concurrent.TimeUnit;
-
-import org.apache.log4j.Logger;
-import org.apache.log4j.MDC;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-/**
- * @author Jon Brisbin
- */
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(
- locations = {
- "org.springframework.amqp.rabbit.log4j"
- },
- loader = AnnotationConfigContextLoader.class
-)
-public class AmqpAppenderTests {
-
- @Autowired
- ApplicationContext applicationContext;
-
- Logger log;
- SimpleMessageListenerContainer listenerContainer;
-
- @Before
- public void setUp() {
- log = Logger.getLogger(getClass());
- listenerContainer = applicationContext.getBean(SimpleMessageListenerContainer.class);
- }
-
- @After
- public void tearDown() {
- listenerContainer.shutdown();
- }
-
- @Test
- public void testAppender() throws InterruptedException {
- TestListener testListener = (TestListener) applicationContext.getBean("testListener", 4);
- listenerContainer.setMessageListener(testListener);
- listenerContainer.start();
-
- Logger log = Logger.getLogger(getClass());
-
- log.debug("This is a DEBUG message");
- log.info("This is an INFO message");
- log.warn("This is a WARN message");
- log.error("This is an ERROR message", new RuntimeException("Test exception"));
-
- testListener.getLatch().await(5, TimeUnit.SECONDS);
- }
-
- @Test
- public void testAppenderWithProps() throws InterruptedException {
- TestListener testListener = (TestListener) applicationContext.getBean("testListener", 4);
- listenerContainer.setMessageListener(testListener);
- listenerContainer.start();
-
- MDC.put("someproperty", "property.value");
- log.debug("This is a DEBUG message with properties");
- log.info("This is an INFO message with properties");
- log.warn("This is a WARN message with properties");
- log.error("This is an ERROR message with properties", new RuntimeException("Test exception"));
- MDC.remove("someproperty");
-
- testListener.getLatch().await(5, TimeUnit.SECONDS);
- }
-
-}
diff --git a/spring-rabbit/src/test/resources/log4j-amqp.properties b/spring-rabbit/src/test/resources/log4j-amqp.properties
new file mode 100644
index 00000000..4a5f7f0b
--- /dev/null
+++ b/spring-rabbit/src/test/resources/log4j-amqp.properties
@@ -0,0 +1,17 @@
+log4j.rootCategory=INFO, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p %t [%c] - <%m>%n
+
+log4j.appender.amqp=org.springframework.amqp.rabbit.log4j.AmqpAppender
+log4j.appender.amqp.applicationId=AmqpAppenderTest
+log4j.appender.amqp.routingKeyPattern=%X{applicationId}.%c.%p
+log4j.appender.amqp.layout=org.apache.log4j.PatternLayout
+log4j.appender.amqp.layout.ConversionPattern=%d %p %t [%c] - <%m>%n
+
+log4j.category.org.springframework.amqp.rabbit.log4j=DEBUG, amqp
+
+log4j.category.org.springframework.amqp.rabbit=DEBUG
+log4j.category.org.springframework.beans.factory=INFO
+
diff --git a/spring-rabbit/src/test/resources/log4j.properties b/spring-rabbit/src/test/resources/log4j.properties
index 4a5f7f0b..29b93fc0 100644
--- a/spring-rabbit/src/test/resources/log4j.properties
+++ b/spring-rabbit/src/test/resources/log4j.properties
@@ -4,14 +4,6 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p %t [%c] - <%m>%n
-log4j.appender.amqp=org.springframework.amqp.rabbit.log4j.AmqpAppender
-log4j.appender.amqp.applicationId=AmqpAppenderTest
-log4j.appender.amqp.routingKeyPattern=%X{applicationId}.%c.%p
-log4j.appender.amqp.layout=org.apache.log4j.PatternLayout
-log4j.appender.amqp.layout.ConversionPattern=%d %p %t [%c] - <%m>%n
-
-log4j.category.org.springframework.amqp.rabbit.log4j=DEBUG, amqp
-
-log4j.category.org.springframework.amqp.rabbit=DEBUG
+log4j.category.org.springframework.amqp.rabbit=INFO
log4j.category.org.springframework.beans.factory=INFO