diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml index d9c90fea0dd..e8affc89d03 100644 --- a/spring-boot-dependencies/pom.xml +++ b/spring-boot-dependencies/pom.xml @@ -445,6 +445,11 @@ jackson-dataformat-xml ${jackson.version} + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson.version} + com.fasterxml.jackson.datatype jackson-datatype-joda diff --git a/spring-boot-docs/src/main/asciidoc/howto.adoc b/spring-boot-docs/src/main/asciidoc/howto.adoc index 76455e057c8..62f34024019 100644 --- a/spring-boot-docs/src/main/asciidoc/howto.adoc +++ b/spring-boot-docs/src/main/asciidoc/howto.adoc @@ -1241,6 +1241,18 @@ samples for more detail and to see it in action. +[[howto-configure-log4j-for-logging-yaml-or-json-config]] +==== Use YAML or JSON to configure Log4j 2 +In addition to its default XML configuration format, Log4j 2 also supports YAML and JSON +configuration files. To configure Log4j 2 to use an alternative configuration file format +all you need to do is add an appropriate dependency to the classpath. To use YAML, add a +dependency on `com.fasterxml.jackson.dataformat:jackson-dataformat-yaml` and Log4j 2 will +look for configuration files names `log4j2.yaml` or `log4j2.yml`. To use JSON, add a +dependency on `com.fasterxml.jackson.core:jackson-databind` and Log4j 2 will look for +configuration files named `log4j2.json` or `log4j2.jsn` + + + [[howto-data-access]] == Data Access diff --git a/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java b/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java index 67119fbfae9..18780942da2 100644 --- a/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java +++ b/spring-boot/src/main/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystem.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 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. @@ -17,8 +17,10 @@ package org.springframework.boot.logging.log4j2; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.logging.log4j.Level; @@ -38,6 +40,7 @@ import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LoggingSystem; import org.springframework.boot.logging.Slf4JLoggingSystem; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; import org.springframework.util.ResourceUtils; /** @@ -95,7 +98,24 @@ public class Log4J2LoggingSystem extends Slf4JLoggingSystem { @Override protected String[] getStandardConfigLocations() { - return new String[] { "log4j2.json", "log4j2.jsn", "log4j2.xml" }; + return getCurrentlySupportedConfigLocations(); + } + + private String[] getCurrentlySupportedConfigLocations() { + List supportedConfigLocations = new ArrayList(); + if (isClassAvailable("com.fasterxml.jackson.dataformat.yaml.YAMLParser")) { + Collections.addAll(supportedConfigLocations, "log4j2.yaml", "log4j2.yml"); + } + if (isClassAvailable("com.fasterxml.jackson.databind.ObjectMapper")) { + Collections.addAll(supportedConfigLocations, "log4j2.json", "log4j2.jsn"); + } + supportedConfigLocations.add("log4j2.xml"); + return supportedConfigLocations.toArray(new String[supportedConfigLocations + .size()]); + } + + protected boolean isClassAvailable(String className) { + return ClassUtils.isPresent(className, getClassLoader()); } @Override diff --git a/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java b/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java index 788925ab737..d28b24a4e4c 100644 --- a/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/logging/log4j2/Log4J2LoggingSystemTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 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. @@ -17,6 +17,9 @@ package org.springframework.boot.logging.log4j2; import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -29,7 +32,11 @@ import org.springframework.boot.logging.LogLevel; import org.springframework.boot.test.OutputCapture; import org.springframework.util.StringUtils; +import com.fasterxml.jackson.databind.ObjectMapper; + +import static org.hamcrest.Matchers.arrayContaining; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -39,14 +46,14 @@ import static org.junit.Assert.assertTrue; * * @author Daniel Fullarton * @author Phillip Webb + * @author Andy Wilkinson */ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests { @Rule public OutputCapture output = new OutputCapture(); - private final Log4J2LoggingSystem loggingSystem = new Log4J2LoggingSystem(getClass() - .getClassLoader()); + private final TestLog4J2LoggingSystem loggingSystem = new TestLog4J2LoggingSystem(); private Logger logger; @@ -120,4 +127,55 @@ public class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests { assertTrue("Wrong output:\n" + output, output.contains("Hello world")); } + @Test + public void configLocationsWithNoExtraDependencies() { + assertThat(this.loggingSystem.getStandardConfigLocations(), + is(arrayContaining("log4j2.xml"))); + } + + @Test + public void configLocationsWithJacksonDatabind() { + this.loggingSystem.availableClasses(ObjectMapper.class.getName()); + assertThat(this.loggingSystem.getStandardConfigLocations(), + is(arrayContaining("log4j2.json", "log4j2.jsn", "log4j2.xml"))); + } + + @Test + public void configLocationsWithJacksonDataformatYaml() { + this.loggingSystem + .availableClasses("com.fasterxml.jackson.dataformat.yaml.YAMLParser"); + assertThat(this.loggingSystem.getStandardConfigLocations(), + is(arrayContaining("log4j2.yaml", "log4j2.yml", "log4j2.xml"))); + } + + @Test + public void configLocationsWithJacksonDatabindAndDataformatYaml() { + this.loggingSystem.availableClasses( + "com.fasterxml.jackson.dataformat.yaml.YAMLParser", + ObjectMapper.class.getName()); + assertThat( + this.loggingSystem.getStandardConfigLocations(), + is(arrayContaining("log4j2.yaml", "log4j2.yml", "log4j2.json", + "log4j2.jsn", "log4j2.xml"))); + } + + private static class TestLog4J2LoggingSystem extends Log4J2LoggingSystem { + + private List availableClasses = new ArrayList(); + + public TestLog4J2LoggingSystem() { + super(TestLog4J2LoggingSystem.class.getClassLoader()); + } + + @Override + protected boolean isClassAvailable(String className) { + return this.availableClasses.contains(className); + } + + private void availableClasses(String... classNames) { + Collections.addAll(this.availableClasses, classNames); + } + + } + }