This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/release-2.x by this push:
     new 5167561  LOG4J2-1606 LOG4J2-2624 Add flag to disable automatic log4j 
shutdown in log4j-web. (#463)
5167561 is described below

commit 516756119ff74cb5b4bcbea425bf6b26ec630f63
Author: perry2of5 <[email protected]>
AuthorDate: Wed Feb 3 11:25:09 2021 -0800

    LOG4J2-1606 LOG4J2-2624 Add flag to disable automatic log4j shutdown in 
log4j-web. (#463)
    
    Added flag to control auto-shutdown of Log4j when
    Log4jServletContainerInitializer is used for a servlet 3+ deployment.
    
    Added "Log4jShutdownOnContextDestroyedListener", a
    ServletContextListener, to shutdown log4j cleanly when
    contextDestroyed is called. Assuming this ServletContextListener is
    the very first listener registered in the web application's web.xml,
    then log4j will be shut down after all other components are shut down.
    Log4jShutdownOnContextDestroyedListener should only be used when
    auto-shutdown is disabled in Log4jServletContainerInitializer.
---
 log4j-web/pom.xml                                  |   8 +-
 .../web/Log4jServletContainerInitializer.java      |   5 +-
 .../log4j/web/Log4jServletContextListener.java     |   8 ++
 .../Log4jShutdownOnContextDestroyedListener.java   |  80 ++++++++++++
 .../apache/logging/log4j/web/Log4jWebSupport.java  |   7 +
 .../web/Log4jServletContainerInitializerTest.java  |  60 ++++++---
 .../log4j/web/Log4jServletContextListenerTest.java |  54 ++++++--
 .../logging/log4j/web/Log4jServletFilterTest.java  |  23 ++--
 ...g4jShutdownOnContextDestroyedListenerTest.java} |  68 +++++-----
 .../log4j/web/Log4jWebInitializerImplTest.java     | 143 ++++++++++-----------
 .../org/apache/logging/log4j/web/PropertyTest.java |  10 +-
 .../logging/log4j/web/ServletAppenderTest.java     |  12 +-
 .../apache/logging/log4j/web/WebLookupTest.java    |  42 +++---
 src/changes/changes.xml                            |  39 +++++-
 14 files changed, 382 insertions(+), 177 deletions(-)

diff --git a/log4j-web/pom.xml b/log4j-web/pom.xml
index 14700ae..4946830 100644
--- a/log4j-web/pom.xml
+++ b/log4j-web/pom.xml
@@ -61,14 +61,18 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.junit.vintage</groupId>
-      <artifactId>junit-vintage-engine</artifactId>
+       <groupId>org.hamcrest</groupId>
+       <artifactId>hamcrest-all</artifactId>
     </dependency>
     <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter-engine</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-junit-jupiter</artifactId>
+       </dependency>
+    <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-test</artifactId>
       <scope>test</scope>
diff --git 
a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContainerInitializer.java
 
b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContainerInitializer.java
index 19ac246..eda3853 100644
--- 
a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContainerInitializer.java
+++ 
b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContainerInitializer.java
@@ -57,7 +57,10 @@ public class Log4jServletContainerInitializer implements 
ServletContainerInitial
             initializer.start();
             initializer.setLoggerContext(); // the application is just now 
starting to start up
 
-            servletContext.addListener(new Log4jServletContextListener());
+            if (!"true".equalsIgnoreCase(servletContext.getInitParameter(
+                    Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED))) {
+                servletContext.addListener(new Log4jServletContextListener());
+            }
 
             filter.setAsyncSupported(true); // supporting async when the user 
isn't using async has no downsides
             
filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, 
"/*");
diff --git 
a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.java
 
b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.java
index 4a65d92..af756e3 100644
--- 
a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.java
+++ 
b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jServletContextListener.java
@@ -50,6 +50,14 @@ public class Log4jServletContextListener implements 
ServletContextListener {
     public void contextInitialized(final ServletContextEvent event) {
         this.servletContext = event.getServletContext();
         LOGGER.debug("Log4jServletContextListener ensuring that Log4j starts 
up properly.");
+        
+        if ("true".equalsIgnoreCase(servletContext.getInitParameter(
+                Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED))) {
+               throw new IllegalStateException("Do not use " + 
getClass().getSimpleName() + " when "
+                               + 
Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED + " is true. Please use "
+                               + 
Log4jShutdownOnContextDestroyedListener.class.getSimpleName() + " instead of "
+                               + getClass().getSimpleName() + ".");
+        }
 
         this.initializer = 
WebLoggerContextUtils.getWebLifeCycle(this.servletContext);
         try {
diff --git 
a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListener.java
 
b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListener.java
new file mode 100644
index 0000000..9bbe9c1
--- /dev/null
+++ 
b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListener.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.logging.log4j.web;
+
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LifeCycle2;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.Strings;
+
+public class Log4jShutdownOnContextDestroyedListener implements 
ServletContextListener {
+
+    private static final int DEFAULT_STOP_TIMEOUT = 30;
+    private static final TimeUnit DEFAULT_STOP_TIMEOUT_TIMEUNIT = 
TimeUnit.SECONDS;
+
+    private static final String KEY_STOP_TIMEOUT = "log4j.stop.timeout";
+    private static final String KEY_STOP_TIMEOUT_TIMEUNIT = 
"log4j.stop.timeout.timeunit";
+
+    private static final Logger LOGGER = StatusLogger.getLogger();
+
+    private ServletContext servletContext;
+    private Log4jWebLifeCycle initializer;
+
+    @Override
+    public void contextInitialized(final ServletContextEvent event) {
+        
LOGGER.debug(Log4jShutdownOnContextDestroyedListener.class.getSimpleName() + 
+                       " ensuring that Log4j started up properly.");
+        servletContext = event.getServletContext();
+        if (null == 
servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)) {
+               throw new IllegalStateException(
+                               "Context did not contain required 
Log4jWebLifeCycle in the " 
+                               + Log4jWebSupport.SUPPORT_ATTRIBUTE + " 
attribute.");
+        }
+        this.initializer = 
WebLoggerContextUtils.getWebLifeCycle(servletContext);
+    }
+
+    @Override
+    public void contextDestroyed(final ServletContextEvent event) {
+        if (this.servletContext == null || this.initializer == null) {
+            LOGGER.warn("Context destroyed before it was initialized.");
+            return;
+        }
+        
LOGGER.debug(Log4jShutdownOnContextDestroyedListener.class.getSimpleName() +
+                       " ensuring that Log4j shuts down properly.");
+
+        this.initializer.clearLoggerContext(); // the application is finished
+        // shutting down now
+        if (initializer instanceof LifeCycle2) {
+            final String stopTimeoutStr = 
servletContext.getInitParameter(KEY_STOP_TIMEOUT);
+            final long stopTimeout = Strings.isEmpty(stopTimeoutStr) ? 
DEFAULT_STOP_TIMEOUT
+                    : Long.parseLong(stopTimeoutStr);
+            final String timeoutTimeUnitStr = 
servletContext.getInitParameter(KEY_STOP_TIMEOUT_TIMEUNIT);
+            final TimeUnit timeoutTimeUnit = 
Strings.isEmpty(timeoutTimeUnitStr) ? DEFAULT_STOP_TIMEOUT_TIMEUNIT
+                    : 
TimeUnit.valueOf(timeoutTimeUnitStr.toUpperCase(Locale.ROOT));
+            ((LifeCycle2) this.initializer).stop(stopTimeout, timeoutTimeUnit);
+        } else {
+            this.initializer.stop();
+        }
+    }
+}
diff --git 
a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jWebSupport.java 
b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jWebSupport.java
index c611a16..22ed45d 100644
--- a/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jWebSupport.java
+++ b/log4j-web/src/main/java/org/apache/logging/log4j/web/Log4jWebSupport.java
@@ -56,6 +56,13 @@ public interface Log4jWebSupport {
     String IS_LOG4J_AUTO_INITIALIZATION_DISABLED = 
"isLog4jAutoInitializationDisabled";
 
     /**
+     * The {@link javax.servlet.ServletContext} parameter name for the flag 
that disables Log4j's auto-shutdown
+     * in Servlet 3.0+ web applications. Set a context parameter with this 
name to "true" to disable
+     * auto-shutdown.
+     */
+    String IS_LOG4J_AUTO_SHUTDOWN_DISABLED = "isLog4jAutoShutdownDisabled";
+
+    /**
      * The attribute key for the {@link javax.servlet.ServletContext} 
attribute that the singleton support instance
      * is stored in.
      */
diff --git 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContainerInitializerTest.java
 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContainerInitializerTest.java
index 0cd3988..7b61f1c 100644
--- 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContainerInitializerTest.java
+++ 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContainerInitializerTest.java
@@ -24,22 +24,24 @@ import javax.servlet.FilterRegistration;
 import javax.servlet.ServletContext;
 
 import org.apache.logging.log4j.util.Strings;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.BDDMockito.any;
 import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.never;
 import static org.mockito.BDDMockito.then;
 import static org.mockito.BDDMockito.willThrow;
 import static org.mockito.Mockito.mock;
 
-@RunWith(MockitoJUnitRunner.class)
+@ExtendWith(MockitoExtension.class)
 public class Log4jServletContainerInitializerTest {
     @Mock
     private ServletContext servletContext;
@@ -52,7 +54,7 @@ public class Log4jServletContainerInitializerTest {
 
     private Log4jServletContainerInitializer containerInitializer;
 
-    @Before
+    @BeforeEach
     public void setUp() {
         this.containerInitializer = new Log4jServletContainerInitializer();
     }
@@ -83,6 +85,29 @@ public class Log4jServletContainerInitializerTest {
     }
 
     @Test
+    public void 
testOnStartupWithServletVersion3_xEffectiveVersion3_xShutdownDisabled() throws 
Exception {
+        final FilterRegistration.Dynamic registration = 
mock(FilterRegistration.Dynamic.class);
+        given(servletContext.getMajorVersion()).willReturn(3);
+        given(servletContext.getEffectiveMajorVersion()).willReturn(3);
+        
given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED)))
+                      .willReturn("true");
+        
given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_INITIALIZATION_DISABLED))).willReturn(
+                null);
+        given(servletContext.addFilter(eq("log4jServletFilter"), 
filterCaptor.capture())).willReturn(registration);
+        
given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
+
+        this.containerInitializer.onStartup(null, this.servletContext);
+
+        then(initializer).should().start();
+        then(initializer).should().setLoggerContext();
+        then(registration).should().setAsyncSupported(eq(true));
+        
then(registration).should().addMappingForUrlPatterns(eq(EnumSet.allOf(DispatcherType.class)),
 eq(false), eq("/*"));
+
+        // initParam IS_LOG4J_AUTO_SHUTDOWN_DISABLED is "true" so addListener 
shouldn't be called.
+        
then(servletContext).should(never()).addListener(any(Log4jServletContextListener.class));
+    }
+
+    @Test
     public void 
testOnStartupWithServletVersion3_xEffectiveVersion3_xDisabledTRUE() throws 
Exception {
         given(servletContext.getMajorVersion()).willReturn(3);
         given(servletContext.getEffectiveMajorVersion()).willReturn(3);
@@ -110,12 +135,13 @@ public class Log4jServletContainerInitializerTest {
         then(registration).should().setAsyncSupported(eq(true));
         
then(registration).should().addMappingForUrlPatterns(eq(EnumSet.allOf(DispatcherType.class)),
 eq(false), eq("/*"));
 
-        assertNotNull("The listener should not be null.", 
listenerCaptor.getValue());
-        assertSame("The listener is not correct.", 
Log4jServletContextListener.class,
-            listenerCaptor.getValue().getClass());
+        assertNotNull(listenerCaptor.getValue(), "The listener should not be 
null.");
+        assertSame(Log4jServletContextListener.class,
+            listenerCaptor.getValue().getClass(),
+            "The listener is not correct.");
 
-        assertNotNull("The filter should not be null.", 
filterCaptor.getValue());
-        assertSame("The filter is not correct.", Log4jServletFilter.class, 
filterCaptor.getValue());
+        assertNotNull(filterCaptor.getValue(), "The filter should not be 
null.");
+        assertSame(Log4jServletFilter.class, filterCaptor.getValue(), "The 
filter is not correct.");
     }
 
     @Test
@@ -128,8 +154,8 @@ public class Log4jServletContainerInitializerTest {
 
         this.containerInitializer.onStartup(null, this.servletContext);
 
-        assertNotNull("The filter should not be null.", 
filterCaptor.getValue());
-        assertSame("The filter is not correct.", Log4jServletFilter.class, 
filterCaptor.getValue());
+        assertNotNull(filterCaptor.getValue(), "The filter should not be 
null.");
+        assertSame(Log4jServletFilter.class, filterCaptor.getValue(), "The 
filter is not correct.");
     }
 
     @Test
@@ -148,11 +174,11 @@ public class Log4jServletContainerInitializerTest {
             this.containerInitializer.onStartup(null, this.servletContext);
             fail("Expected the exception thrown by the initializer; got no 
exception.");
         } catch (final IllegalStateException e) {
-            assertSame("The exception is not correct.", exception, e);
+            assertSame(exception, e, "The exception is not correct.");
         }
 
         then(initializer).should().start();
-        assertNotNull("The filter should not be null.", 
filterCaptor.getValue());
-        assertSame("The filter is not correct.", Log4jServletFilter.class, 
filterCaptor.getValue());
+        assertNotNull(filterCaptor.getValue(), "The filter should not be 
null.");
+        assertSame(Log4jServletFilter.class, filterCaptor.getValue(), "The 
filter is not correct.");
     }
 }
diff --git 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContextListenerTest.java
 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContextListenerTest.java
index 7be7b9c..35d662d 100644
--- 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContextListenerTest.java
+++ 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContextListenerTest.java
@@ -20,29 +20,33 @@ import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
 
 import org.apache.logging.log4j.util.Strings;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.BDDMockito.eq;
 import static org.mockito.BDDMockito.given;
 import static org.mockito.BDDMockito.then;
 import static org.mockito.BDDMockito.willThrow;
 
-@RunWith(MockitoJUnitRunner.class)
+@ExtendWith(MockitoExtension.class)
 public class Log4jServletContextListenerTest {
-    @Mock
-    private ServletContextEvent event;
-    @Mock
+       /* event and servletContext are marked lenient because they aren't used 
in the
+        * testDestroyWithNoInit but are only accessed during initialization
+        */
+       @Mock(lenient = true)
+       private ServletContextEvent event;
+       @Mock(lenient = true)
     private ServletContext servletContext;
     @Mock
     private Log4jWebLifeCycle initializer;
 
     private Log4jServletContextListener listener;
 
-    @Before
+    @BeforeEach
     public void setUp() {
         this.listener = new Log4jServletContextListener();
         given(event.getServletContext()).willReturn(servletContext);
@@ -70,8 +74,36 @@ public class Log4jServletContextListenerTest {
             this.listener.contextInitialized(this.event);
             fail("Expected a RuntimeException.");
         } catch (final RuntimeException e) {
-            assertEquals("The message is not correct.", "Failed to initialize 
Log4j properly.", e.getMessage());
+            assertEquals("Failed to initialize Log4j properly.", 
e.getMessage(), "The message is not correct.");
         }
     }
 
+    @Test
+    public void 
initializingLog4jServletContextListenerShouldFaileWhenAutoShutdownIsTrue() 
throws Exception {
+        
given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED)))
+                .willReturn("true");
+        ensureInitializingFailsWhenAuthShutdownIsEnabled();
+    }
+
+    @Test
+    public void 
initializingLog4jServletContextListenerShouldFaileWhenAutoShutdownIsTRUE() 
throws Exception {
+        
given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED)))
+                .willReturn("TRUE");
+        ensureInitializingFailsWhenAuthShutdownIsEnabled();
+    }
+    
+    private void ensureInitializingFailsWhenAuthShutdownIsEnabled() {
+        try {
+            this.listener.contextInitialized(this.event);
+            fail("Expected a RuntimeException.");
+        } catch (final RuntimeException e) {
+            String expectedMessage = 
+                    "Do not use " + 
Log4jServletContextListener.class.getSimpleName() + " when " 
+                    + Log4jWebSupport.IS_LOG4J_AUTO_SHUTDOWN_DISABLED + " is 
true. Please use " 
+                    + 
Log4jShutdownOnContextDestroyedListener.class.getSimpleName() + " instead of " 
+                    + Log4jServletContextListener.class.getSimpleName() + ".";
+
+            assertEquals(expectedMessage, e.getMessage(), "The message is not 
correct");
+        }
+    }
 }
diff --git 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletFilterTest.java
 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletFilterTest.java
index 1fb72a3..479ac26 100644
--- 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletFilterTest.java
+++ 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletFilterTest.java
@@ -22,23 +22,24 @@ import javax.servlet.ServletContext;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.BeforeEach;
 import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
 
+import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.same;
 import static org.mockito.BDDMockito.given;
 import static org.mockito.BDDMockito.then;
 import static org.mockito.Mockito.reset;
 
-@RunWith(MockitoJUnitRunner.class)
+@ExtendWith(MockitoExtension.class)
 public class Log4jServletFilterTest {
-    @Mock
+    @Mock(lenient = true) // because filterConfig is not used in testDestroy
     private FilterConfig filterConfig;
-    @Mock
+    @Mock(lenient = true) // because filterConfig is not used in testDestroy
     private ServletContext servletContext;
     @Mock
     private Log4jWebLifeCycle initializer;
@@ -51,7 +52,7 @@ public class Log4jServletFilterTest {
 
     private Log4jServletFilter filter;
 
-    @Before
+    @BeforeEach
     public void setUp() {
         given(filterConfig.getServletContext()).willReturn(servletContext);
         
given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
@@ -69,9 +70,11 @@ public class Log4jServletFilterTest {
         then(initializer).should().setLoggerContext();
     }
 
-    @Test(expected = IllegalStateException.class)
+    @Test
     public void testDestroy() {
-        this.filter.destroy();
+       assertThrows(IllegalStateException.class, () -> {
+               this.filter.destroy();
+       });
     }
 
     @Test
diff --git 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContextListenerTest.java
 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListenerTest.java
similarity index 53%
copy from 
log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContextListenerTest.java
copy to 
log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListenerTest.java
index 7be7b9c..5577381 100644
--- 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jServletContextListenerTest.java
+++ 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jShutdownOnContextDestroyedListenerTest.java
@@ -16,45 +16,46 @@
  */
 package org.apache.logging.log4j.web;
 
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.BDDMockito.then;
+import static org.mockito.Mockito.never;
+
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContextEvent;
 
-import org.apache.logging.log4j.util.Strings;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-
-import static org.junit.Assert.*;
-import static org.mockito.BDDMockito.given;
-import static org.mockito.BDDMockito.then;
-import static org.mockito.BDDMockito.willThrow;
+import org.mockito.junit.jupiter.MockitoExtension;
 
-@RunWith(MockitoJUnitRunner.class)
-public class Log4jServletContextListenerTest {
-    @Mock
+@ExtendWith(MockitoExtension.class)
+public class Log4jShutdownOnContextDestroyedListenerTest {
+    @Mock(lenient = true)
     private ServletContextEvent event;
-    @Mock
+    @Mock(lenient = true)
     private ServletContext servletContext;
     @Mock
     private Log4jWebLifeCycle initializer;
 
-    private Log4jServletContextListener listener;
+    private Log4jShutdownOnContextDestroyedListener listener;
 
-    @Before
-    public void setUp() {
-        this.listener = new Log4jServletContextListener();
+    public void setUp(boolean mockInitializer) {
+        this.listener = new Log4jShutdownOnContextDestroyedListener();
         given(event.getServletContext()).willReturn(servletContext);
-        
given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(initializer);
+        if (mockInitializer) {         
+               
given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE))
+                               .willReturn(initializer);
+        }
     }
-
+               
     @Test
     public void testInitAndDestroy() throws Exception {
+       setUp(true);
         this.listener.contextInitialized(this.event);
 
-        then(initializer).should().start();
-        then(initializer).should().setLoggerContext();
+        then(initializer).should(never()).start();
+        then(initializer).should(never()).setLoggerContext();
 
         this.listener.contextDestroyed(this.event);
 
@@ -63,15 +64,20 @@ public class Log4jServletContextListenerTest {
     }
 
     @Test
-    public void testInitFailure() throws Exception {
-        willThrow(new 
IllegalStateException(Strings.EMPTY)).given(initializer).start();
+    public void testDestroy() throws Exception {
+       setUp(true);
+        this.listener.contextDestroyed(this.event);
 
-        try {
-            this.listener.contextInitialized(this.event);
-            fail("Expected a RuntimeException.");
-        } catch (final RuntimeException e) {
-            assertEquals("The message is not correct.", "Failed to initialize 
Log4j properly.", e.getMessage());
-        }
+        then(initializer).should(never()).clearLoggerContext();
+        then(initializer).should(never()).stop();
+    }
+    
+    @Test
+    public void 
whenNoInitializerInContextTheContextInitializedShouldThrowAnException() {
+       setUp(false);
+       
+       assertThrows(IllegalStateException.class, () -> {
+               this.listener.contextInitialized(this.event);
+       });
     }
-
 }
diff --git 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jWebInitializerImplTest.java
 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jWebInitializerImplTest.java
index 86fde20..40e10df 100644
--- 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jWebInitializerImplTest.java
+++ 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/Log4jWebInitializerImplTest.java
@@ -24,79 +24,76 @@ import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.DefaultConfiguration;
 import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
 import org.apache.logging.log4j.core.impl.ContextAnchor;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.jupiter.MockitoExtension;
 
 import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.BDDMockito.given;
 import static org.mockito.BDDMockito.then;
 
-@RunWith(MockitoJUnitRunner.class)
+@ExtendWith(MockitoExtension.class)
 public class Log4jWebInitializerImplTest {
-    @Mock
-    private ServletContext servletContext;
+       /* Marking servletContext lenient because otherwise 
testCompositeLocationParameterWithEmptyUriListSetsDefaultConfiguration fails
+        * when null is passed in as the initial param because Mockito deciced 
null isn't a String rather than the absence of a string.
+        */
+       @Mock(lenient = true)
+       private ServletContext servletContext;
     @Captor
     private ArgumentCaptor<Log4jWebLifeCycle> initializerCaptor;
     @Captor
     private ArgumentCaptor<LoggerContext> loggerContextCaptor;
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
 
     private Log4jWebInitializerImpl initializerImpl;
 
-    @Before
+    @BeforeEach
     public void setUp() {
         
given(servletContext.getAttribute(Log4jWebSupport.SUPPORT_ATTRIBUTE)).willReturn(null);
 
         final Log4jWebLifeCycle initializer = 
WebLoggerContextUtils.getWebLifeCycle(this.servletContext);
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.SUPPORT_ATTRIBUTE),
 initializerCaptor.capture());
-        assertNotNull("The initializer should not be null.", initializer);
-        assertSame("The capture is not correct.", initializer, 
initializerCaptor.getValue());
-        assertTrue("The initializer is not correct.", initializer instanceof 
Log4jWebInitializerImpl);
+        assertNotNull(initializer, "The initializer should not be null.");
+        assertSame(initializer, initializerCaptor.getValue(), "The capture is 
not correct.");
+        assertTrue(initializer instanceof Log4jWebInitializerImpl, "The 
initializer is not correct.");
 
         this.initializerImpl = (Log4jWebInitializerImpl) initializer;
     }
 
     @Test
     public void testDeinitializeBeforeInitialize() {
-        expectedException.expect(IllegalStateException.class);
-        this.initializerImpl.stop();
+       assertThrows(IllegalStateException.class, () -> {
+               this.initializerImpl.stop();
+       });
     }
 
     @Test
     public void testSetLoggerContextBeforeInitialize() {
-        assertNull("The context should be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null.");
 
         this.initializerImpl.setLoggerContext();
 
-        assertNull("The context should still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
still be null.");
     }
 
     @Test
     public void testClearLoggerContextBeforeInitialize() {
-        assertNull("The context should be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null.");
 
         this.initializerImpl.clearLoggerContext();
 
-        assertNull("The context should still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
still be null.");
     }
 
     @Test
@@ -110,30 +107,30 @@ public class Log4jWebInitializerImplTest {
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
         final org.apache.logging.log4j.spi.LoggerContext loggerContext = 
loggerContextCaptor.getValue();
 
-        assertNull("The context should still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
still be null.");
 
         this.initializerImpl.setLoggerContext();
 
         final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
-        assertNotNull("The context should not be null.", context);
-        assertSame("The context is not correct.", loggerContext, context);
+        assertNotNull(context, "The context should not be null.");
+        assertSame(loggerContext, context, "The context is not correct.");
 
         this.initializerImpl.clearLoggerContext();
 
-        assertNull("The context should be null again.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null again.");
 
         this.initializerImpl.stop();
 
         
then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
 
-        assertNull("The context should again still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
again still be null.");
 
         this.initializerImpl.setLoggerContext();
 
-        assertNull("The context should finally still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
finally still be null.");
     }
 
     @Test
@@ -144,35 +141,35 @@ public class Log4jWebInitializerImplTest {
         
given(servletContext.getServletContextName()).willReturn("helloWorld02");
         given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
         
given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
-        assertNull("The context should be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null.");
 
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
         final org.apache.logging.log4j.spi.LoggerContext loggerContext = 
loggerContextCaptor.getValue();
 
-        assertNull("The context should still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
still be null.");
 
         this.initializerImpl.setLoggerContext();
 
         final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
-        assertNotNull("The context should not be null.", context);
-        assertSame("The context is not correct.", loggerContext, context);
+        assertNotNull(context, "The context should not be null.");
+        assertSame(loggerContext, context, "The context is not correct.");
 
         this.initializerImpl.clearLoggerContext();
 
-        assertNull("The context should be null again.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null again.");
 
         this.initializerImpl.stop();
 
         
then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
 
-        assertNull("The context should again still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
again still be null.");
 
         this.initializerImpl.setLoggerContext();
 
-        assertNull("The context should finally still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
finally still be null.");
     }
 
     @Test
@@ -183,12 +180,12 @@ public class Log4jWebInitializerImplTest {
         
given(servletContext.getServletContextName()).willReturn("helloWorld03");
         given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
         
given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
-        assertNull("The context should be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null.");
 
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
 
         this.initializerImpl.start();
         this.initializerImpl.start();
@@ -206,19 +203,20 @@ public class Log4jWebInitializerImplTest {
         
given(servletContext.getServletContextName()).willReturn("helloWorld04");
         given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
         
given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
-        assertNull("The context should be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null.");
 
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
 
         this.initializerImpl.stop();
 
         
then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
 
-        expectedException.expect(IllegalStateException.class);
-        this.initializerImpl.start();
+       assertThrows(IllegalStateException.class, () -> {
+               this.initializerImpl.start();
+       });
     }
 
     @Test
@@ -229,12 +227,12 @@ public class Log4jWebInitializerImplTest {
         
given(servletContext.getServletContextName()).willReturn("helloWorld05");
         given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
         
given(servletContext.getClassLoader()).willReturn(getClass().getClassLoader());
-        assertNull("The context should be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null.");
 
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
 
         this.initializerImpl.stop();
         this.initializerImpl.stop();
@@ -248,10 +246,11 @@ public class Log4jWebInitializerImplTest {
         
given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
         
given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("true");
         given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
-        assertNull("The context should be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null.");
 
-        expectedException.expect(IllegalStateException.class);
-        this.initializerImpl.start();
+       assertThrows(IllegalStateException.class, () -> {
+               this.initializerImpl.start();
+       });
     }
 
     @Test
@@ -260,30 +259,30 @@ public class Log4jWebInitializerImplTest {
         
given(servletContext.getInitParameter(eq(Log4jWebSupport.LOG4J_CONFIG_LOCATION))).willReturn(null);
         
given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn("true");
         given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
-        assertNull("The context should be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null.");
 
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNull("The context attribute should be null.", 
loggerContextCaptor.getValue());
+        assertNull(loggerContextCaptor.getValue(), "The context attribute 
should be null.");
 
-        assertNull("The context should still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
still be null.");
 
         this.initializerImpl.setLoggerContext();
 
-        assertNull("The context should still be null because no named 
selector.", ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
still be null because no named selector.");
 
         this.initializerImpl.clearLoggerContext();
 
-        assertNull("The context should be null again.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null again.");
 
         this.initializerImpl.stop();
 
-        assertNull("The context should again still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
again still be null.");
 
         this.initializerImpl.setLoggerContext();
 
-        assertNull("The context should finally still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
finally still be null.");
     }
 
     @Test
@@ -293,35 +292,35 @@ public class Log4jWebInitializerImplTest {
         
given(servletContext.getInitParameter(eq(Log4jWebSupport.IS_LOG4J_CONTEXT_SELECTOR_NAMED))).willReturn(null);
         
given(servletContext.getServletContextName()).willReturn("helloWorld07");
         given(servletContext.getResourcePaths("/WEB-INF/")).willReturn(null);
-        assertNull("The context should be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null.");
 
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
         final org.apache.logging.log4j.spi.LoggerContext loggerContext = 
loggerContextCaptor.getValue();
 
-        assertNull("The context should still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
still be null.");
 
         final Runnable runnable = () -> {
             final LoggerContext context = ContextAnchor.THREAD_CONTEXT.get();
-            assertNotNull("The context should not be null.", context);
-            assertSame("The context is not correct.", loggerContext, context);
+            assertNotNull(context, "The context should not be null.");
+            assertSame(loggerContext, context, "The context is not correct.");
         };
 
         this.initializerImpl.wrapExecution(runnable);
 
-        assertNull("The context should be null again.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should be 
null again.");
 
         this.initializerImpl.stop();
 
         
then(servletContext).should().removeAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE));
 
-        assertNull("The context should again still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
again still be null.");
 
         this.initializerImpl.setLoggerContext();
 
-        assertNull("The context should finally still be null.", 
ContextAnchor.THREAD_CONTEXT.get());
+        assertNull(ContextAnchor.THREAD_CONTEXT.get(), "The context should 
finally still be null.");
     }
 
     @Test
@@ -331,7 +330,7 @@ public class Log4jWebInitializerImplTest {
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
 
         assertThat(loggerContextCaptor.getValue().getConfigLocation(), 
is(nullValue()));
 
@@ -346,7 +345,7 @@ public class Log4jWebInitializerImplTest {
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
 
         assertThat(loggerContextCaptor.getValue().getConfigLocation(), 
is(URI.create("file:/a/b/c/WEB-INF/log4j2.xml")));
 
@@ -364,7 +363,7 @@ public class Log4jWebInitializerImplTest {
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
 
         assertThat(loggerContextCaptor.getValue().getConfigLocation(),
                 is(URI.create("file:/a/b/c/WEB-INF/log4j2-mycontext.xml")));
@@ -379,7 +378,7 @@ public class Log4jWebInitializerImplTest {
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
 
         assertThat(loggerContextCaptor.getValue().getConfiguration(), 
is(instanceOf(DefaultConfiguration.class)));
 
@@ -395,7 +394,7 @@ public class Log4jWebInitializerImplTest {
         this.initializerImpl.start();
 
         
then(servletContext).should().setAttribute(eq(Log4jWebSupport.CONTEXT_ATTRIBUTE),
 loggerContextCaptor.capture());
-        assertNotNull("The context attribute should not be null.", 
loggerContextCaptor.getValue());
+        assertNotNull(loggerContextCaptor.getValue(), "The context attribute 
should not be null.");
 
         assertThat(loggerContextCaptor.getValue().getConfiguration(), 
is(instanceOf(CompositeConfiguration.class)));
 
diff --git 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/PropertyTest.java 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/PropertyTest.java
index d17f495..40945c2 100644
--- a/log4j-web/src/test/java/org/apache/logging/log4j/web/PropertyTest.java
+++ b/log4j-web/src/test/java/org/apache/logging/log4j/web/PropertyTest.java
@@ -19,9 +19,9 @@ package org.apache.logging.log4j.web;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.core.impl.Log4jContextFactory;
 import org.apache.logging.log4j.util.Constants;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 
 /**
  *
@@ -31,12 +31,12 @@ public class PropertyTest {
     @Test
     public void testShutdownHookDisabled() {
         assertFalse(
-                "Shutdown hook should be disabled by default in web 
applications",
-                ((Log4jContextFactory) 
LogManager.getFactory()).isShutdownHookEnabled());
+                ((Log4jContextFactory) 
LogManager.getFactory()).isShutdownHookEnabled(),
+                "Shutdown hook should be disabled by default in web 
applications");
     }
 
     @Test
     public void testIsWebApp() {
-        assertTrue("When servlet classes are available IS_WEB_APP should 
default to true", Constants.IS_WEB_APP);
+        assertTrue(Constants.IS_WEB_APP, "When servlet classes are available 
IS_WEB_APP should default to true");
     }
 }
diff --git 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/ServletAppenderTest.java 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/ServletAppenderTest.java
index bb7147c..0317b02 100644
--- 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/ServletAppenderTest.java
+++ 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/ServletAppenderTest.java
@@ -24,10 +24,10 @@ import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.impl.ContextAnchor;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 import org.springframework.mock.web.MockServletContext;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 
 /**
  *
@@ -50,12 +50,12 @@ public class ServletAppenderTest {
             initializer.start();
             initializer.setLoggerContext();
             final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
-            assertNotNull("No LoggerContext", ctx);
-            assertNotNull("No ServletContext", 
WebLoggerContextUtils.getServletContext());
+            assertNotNull(ctx, "No LoggerContext");
+            assertNotNull(WebLoggerContextUtils.getServletContext(), "No 
ServletContext");
             final Configuration configuration = ctx.getConfiguration();
-            assertNotNull("No configuration", configuration);
+            assertNotNull(configuration, "No configuration");
             final Appender appender = configuration.getAppender("Servlet");
-            assertNotNull("No ServletAppender", appender);
+            assertNotNull(appender, "No ServletAppender");
             final Logger logger = LogManager.getLogger("Test");
             logger.info("This is a test");
             logger.error("This is a test 2", new 
IllegalStateException().fillInStackTrace());
diff --git 
a/log4j-web/src/test/java/org/apache/logging/log4j/web/WebLookupTest.java 
b/log4j-web/src/test/java/org/apache/logging/log4j/web/WebLookupTest.java
index 0a257ff..a75e97c 100644
--- a/log4j-web/src/test/java/org/apache/logging/log4j/web/WebLookupTest.java
+++ b/log4j-web/src/test/java/org/apache/logging/log4j/web/WebLookupTest.java
@@ -26,10 +26,10 @@ import org.apache.logging.log4j.core.appender.FileAppender;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.impl.ContextAnchor;
 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 import org.springframework.mock.web.MockServletContext;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.*;
 
 public class WebLookupTest {
 
@@ -47,27 +47,27 @@ public class WebLookupTest {
             initializer.start();
             initializer.setLoggerContext();
             final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
-            assertNotNull("No LoggerContext", ctx);
-            assertNotNull("No ServletContext", 
WebLoggerContextUtils.getServletContext());
+            assertNotNull(ctx, "No LoggerContext");
+            assertNotNull(WebLoggerContextUtils.getServletContext(), "No 
ServletContext");
             final Configuration config = ctx.getConfiguration();
-            assertNotNull("No Configuration", config);
+            assertNotNull(config, "No Configuration");
             final StrSubstitutor substitutor = config.getStrSubstitutor();
-            assertNotNull("No Interpolator", substitutor);
+            assertNotNull(substitutor, "No Interpolator");
             String value = substitutor.replace("${web:initParam.TestParam}");
-            assertNotNull("No value for TestParam", value);
-            assertEquals("Incorrect value for TestParam: " + value, 
"ParamValue", value);
+            assertNotNull(value, "No value for TestParam");
+            assertEquals("ParamValue", value, "Incorrect value for TestParam: 
" + value);
             value = substitutor.replace("${web:attr.TestAttr}");
-            assertNotNull("No value for TestAttr", value);
-            assertEquals("Incorrect value for TestAttr: " + value, 
"AttrValue", value);
+            assertNotNull(value, "No value for TestAttr");
+            assertEquals("AttrValue", value, "Incorrect value for TestAttr: " 
+ value);
             value = substitutor.replace("${web:Name1}");
-            assertNotNull("No value for Name1", value);
-            assertEquals("Incorrect value for Name1: " + value, "Ben", value);
+            assertNotNull(value, "No value for Name1");
+            assertEquals("Ben", value, "Incorrect value for Name1: " + value);
             value = substitutor.replace("${web:Name2}");
-            assertNotNull("No value for Name2", value);
-            assertEquals("Incorrect value for Name2: " + value, "Jerry", 
value);
+            assertNotNull(value, "No value for Name2");
+            assertEquals("Jerry", value, "Incorrect value for Name2: " + 
value);
             value = substitutor.replace("${web:contextPathName}");
-            assertNotNull("No value for context name", value);
-            assertEquals("Incorrect value for context name", "WebApp", value);
+            assertNotNull(value, "No value for context name");
+            assertEquals("WebApp", value, "Incorrect value for context name");
         } catch (final IllegalStateException e) {
             fail("Failed to initialize Log4j properly." + e.getMessage());
         }
@@ -89,10 +89,10 @@ public class WebLookupTest {
         initializer.start();
         initializer.setLoggerContext();
         final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
-        assertNotNull("No LoggerContext", ctx);
-        assertNotNull("No ServletContext", 
WebLoggerContextUtils.getServletContext());
+        assertNotNull(ctx, "No LoggerContext");
+        assertNotNull(WebLoggerContextUtils.getServletContext(), "No 
ServletContext");
         final Configuration config = ctx.getConfiguration();
-        assertNotNull("No Configuration", config);
+        assertNotNull(config, "No Configuration");
         final Map<String, Appender> appenders = config.getAppenders();
         for (final Map.Entry<String, Appender> entry : appenders.entrySet()) {
             if (entry.getKey().equals("file")) {
@@ -102,8 +102,8 @@ public class WebLookupTest {
         }
         final StrSubstitutor substitutor = config.getStrSubstitutor();
         String value = substitutor.replace("${web:contextPathName:-default}");
-        assertEquals("Incorrect value for context name", "default", value);
-        assertNotNull("No value for context name", value);
+        assertEquals("default", value, "Incorrect value for context name");
+        assertNotNull(value, "No value for context name");
         initializer.stop();
         ContextAnchor.THREAD_CONTEXT.remove();
     }
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 22e5b2a..83da37b 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,22 @@
     -->
     <release version="2.14.1" date="2021-MM-DD" description="GA Release 
2.14.1">
       <!-- FIXES -->
+      <action issue="LOG4J2-2624" dev="mattsicker" type="fix" due-to="Tim 
Perry">
+        Allow auto-shutdown of log4j in log4j-web to be turned off and provide 
a 
+        ServletContextListener "Log4jShutdownOnContextDestroyedListener" to 
stop log4j.
+        Register the listener at the top of web.xml to ensure the shutdown 
happens last.
+      </action>
+      <action issue="LOG4J2-1606" dev="mattsicker" type="fix" due-to="Tim 
Perry">
+        Allow auto-shutdown of log4j in log4j-web to be turned off and provide 
a 
+        ServletContextListener "Log4jShutdownOnContextDestroyedListener" to 
stop log4j. 
+        Register the listener at the top of web.xml to ensure the shutdown 
happens last.
+      </action>
+      <action issue="LOG4J2-2999" dev="vy" type="add">
+        Replace JsonTemplateLayout resolver configurations table in docs with 
sections.
+      </action>
+      <action issue="LOG4J2-2993" dev="vy" type="add">
+        Support stack trace truncation in JsonTemplateLayout.
+      </action>
       <action issue="LOG4J2-2998" dev="vy" type="fix">
         Fix truncation of excessive strings ending with a high surrogate in 
JsonWriter.
       </action>
@@ -64,7 +80,7 @@
       <action issue="LOG4J2-2976" dev="ckozak" type="fix">
         JdbcAppender composes an incorrect INSERT statement without a 
ColumnMapping element.
       </action>
-      <action issue="LOG4J2-2976" dev="ggregory" type="fix" due-to="Lee 
Breisacher, Gary Gregory">
+      <action issue="LOG4J2-3014" dev="ggregory" type="fix" due-to="Lee 
Breisacher, Gary Gregory">
         Log4j1ConfigurationConverter on Windows produces "&#xd;" at end of 
every line.
       </action>
       <!-- ADDS -->     
@@ -173,6 +189,27 @@
       </action>
       <action dev="ggregory" type="update">
         Update Woodstox 5.0.3 -> 6.2.3 to match Jackson 2.12.1.
+      </action>  
+      <action dev="ggregory" type="update">
+        Update org.apache.activemq:* 5.16.0 -> 5.16.1.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.mockito:mockito-* 3.7.0 -> 3.7.7.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.springframework:* 5.3.2 -> 5.3.3.
+      </action>
+      <action dev="ggregory" type="update">
+        Update mongodb4.version 4.1.1 -> 4.2.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.fusesource.jansi:jansi 1.18 -> 2.2.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update org.assertj:assertj-core 3.18.1 -> 3.19.0.
+      </action>
+      <action dev="ggregory" type="update">
+        Update net.javacrumbs.json-unit:json-unit 2.22.0 -> 2.23.0.
       </action>
     </release>
     <release version="2.14.0" date="2020-11-06" description="GA Release 
2.14.0">

Reply via email to