You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2022/02/09 15:36:14 UTC

[logging-log4j2] branch release-2.x updated (17a77f5 -> 57cfe28)

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

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


    from 17a77f5  LOG4J2-3317: Fix RoutingAppender backcompat and improve lookup security
     new 77b6106  Sort members.
     new d532bed  Format tweaks.
     new 9a29030  [LOG4J2-3391] Add optional additional fields to NoSQLAppender.
     new 57cfe28  Possible NullPointerException in MongoDb4DocumentObject, MongoDbDocumentObject, DefaultNoSqlObject.

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../core/appender/nosql/DefaultNoSqlObject.java    |  22 +-
 .../core/appender/nosql/NoSqlDatabaseManager.java  | 229 ++++++++++-----------
 .../log4j/core/appender/nosql/NoSqlObject.java     |   1 +
 .../appender/nosql/NoSqlDatabaseManagerTest.java   |   5 +
 .../log4j/mongodb3/MongoDbDocumentObject.java      |   7 +-
 .../mongodb3/MongoDb3AdditionalFieldsTest.java     |  28 +--
 .../log4j/mongodb4/MongoDb4DocumentObject.java     |  10 +-
 .../mongodb4/MongoDb4AdditionalFieldsTest.java     |  26 +--
 src/changes/changes.xml                            |   3 +
 9 files changed, 167 insertions(+), 164 deletions(-)

[logging-log4j2] 02/04: Format tweaks.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d532bedb88f540fbe7d60de33409345abd9e36a8
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Wed Feb 9 08:49:50 2022 -0500

    Format tweaks.
---
 .../logging/log4j/core/appender/nosql/NoSqlDatabaseManagerTest.java  | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManagerTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManagerTest.java
index 369e577..a778f8f 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManagerTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManagerTest.java
@@ -54,17 +54,22 @@ import org.mockito.junit.MockitoJUnitRunner;
 
 @RunWith(MockitoJUnitRunner.class)
 public class NoSqlDatabaseManagerTest {
+    
     @Mock
     private NoSqlConnection<Map<String, Object>, DefaultNoSqlObject> connection;
+    
     @Mock
     private NoSqlProvider<NoSqlConnection<Map<String, Object>, DefaultNoSqlObject>> provider;
+    
     @Mock
     private Message message;
+    
     @Captor
     private ArgumentCaptor<NoSqlObject<Map<String, Object>>> captor;
 
     @Rule
     public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
+    
     @Rule
     public final ExpectedException expectedException = ExpectedException.none();
 

[logging-log4j2] 04/04: Possible NullPointerException in MongoDb4DocumentObject, MongoDbDocumentObject, DefaultNoSqlObject.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 57cfe28541d418fa482b2ed75c32ea152fb03655
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Wed Feb 9 10:36:08 2022 -0500

    Possible NullPointerException in MongoDb4DocumentObject,
    MongoDbDocumentObject, DefaultNoSqlObject.
---
 .../log4j/core/appender/nosql/DefaultNoSqlObject.java | 19 +++++++++++--------
 .../logging/log4j/mongodb3/MongoDbDocumentObject.java |  6 +++---
 .../log4j/mongodb4/MongoDb4DocumentObject.java        |  6 +++---
 src/changes/changes.xml                               |  3 +++
 4 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/DefaultNoSqlObject.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/DefaultNoSqlObject.java
index debe9e5..8020f3a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/DefaultNoSqlObject.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/DefaultNoSqlObject.java
@@ -45,22 +45,25 @@ public class DefaultNoSqlObject implements NoSqlObject<Map<String, Object>> {
 
     @Override
     public void set(final String field, final NoSqlObject<Map<String, Object>> value) {
-        this.map.put(field, value.unwrap());
+        this.map.put(field, value != null ? value.unwrap() : null);
     }
 
     @Override
     public void set(final String field, final Object[] values) {
-        this.map.put(field, Arrays.asList(values));
+        this.map.put(field, values != null ? Arrays.asList(values) : null);
     }
 
     @Override
     public void set(final String field, final NoSqlObject<Map<String, Object>>[] values) {
-        final List<Map<String, Object>> list = new ArrayList<>(values.length);
-        for (final NoSqlObject<Map<String, Object>> value : values) {
-            list.add(value.unwrap());
-        }
-        this.map.put(field, list);
-    }
+        if (values == null) {
+            this.map.put(field, null);
+        } else {
+            final List<Map<String, Object>> list = new ArrayList<>(values.length);
+            for (final NoSqlObject<Map<String, Object>> value : values) {
+                list.add(value.unwrap());
+            }
+            this.map.put(field, list);
+        }}
 
     @Override
     public Map<String, Object> unwrap() {
diff --git a/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDbDocumentObject.java b/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDbDocumentObject.java
index 020c676..f9a1d58 100644
--- a/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDbDocumentObject.java
+++ b/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDbDocumentObject.java
@@ -37,12 +37,12 @@ public final class MongoDbDocumentObject implements NoSqlObject<Document> {
 
     @Override
     public void set(final String field, final NoSqlObject<Document> value) {
-        this.document.append(field, value.unwrap());
+        this.document.append(field, value != null ? value.unwrap() : null);
     }
 
     @Override
     public void set(final String field, final NoSqlObject<Document>[] values) {
-        this.document.append(field, Arrays.asList(values));
+        this.document.append(field, values != null ? Arrays.asList(values) : null);
     }
 
     @Override
@@ -52,7 +52,7 @@ public final class MongoDbDocumentObject implements NoSqlObject<Document> {
 
     @Override
     public void set(final String field, final Object[] values) {
-        this.document.append(field, Arrays.asList(values));
+        this.document.append(field, values != null ? Arrays.asList(values) : null);
     }
 
     @Override
diff --git a/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java
index 63c3fae..4d81bb5 100644
--- a/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java
+++ b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java
@@ -37,12 +37,12 @@ public final class MongoDb4DocumentObject implements NoSqlObject<Document> {
 
     @Override
     public void set(final String field, final NoSqlObject<Document> value) {
-        this.document.append(field, value.unwrap());
+        this.document.append(field, value != null ? value.unwrap() : null);
     }
 
     @Override
     public void set(final String field, final NoSqlObject<Document>[] values) {
-        this.document.append(field, Arrays.asList(values));
+        this.document.append(field, values != null ? Arrays.asList(values) : null);
     }
 
     @Override
@@ -52,7 +52,7 @@ public final class MongoDb4DocumentObject implements NoSqlObject<Document> {
 
     @Override
     public void set(final String field, final Object[] values) {
-        this.document.append(field, Arrays.asList(values));
+        this.document.append(field, values != null ? Arrays.asList(values) : null);
     }
 
     @Override
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 8300101..3cd72ec 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -211,6 +211,9 @@
       <action issue="LOG4J2-3392" dev="ggregory" type="fix" due-to="Gary Gregory, Omer U">
         AppenderLoggingException logging any exception to a MongoDB Appender.
       </action>
+      <action issue="LOG4J2-3392" dev="ggregory" type="fix" due-to="Gary Gregory">
+        Possible NullPointerException in MongoDb4DocumentObject, MongoDbDocumentObject, DefaultNoSqlObject.
+      </action>
       <!-- ADD -->
       <action issue="LOG4J2-2486" dev="rgoers" type="add">
         Require log4j2.Script.enableLanguages to be specified to enable scripting for specific languages.

[logging-log4j2] 03/04: [LOG4J2-3391] Add optional additional fields to NoSQLAppender.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9a290307c1fb136dee0cd2ab9ec90b6b5f312ebb
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Wed Feb 9 09:51:07 2022 -0500

    [LOG4J2-3391] Add optional additional fields to NoSQLAppender.
    
    Use a document instead of an array.
---
 .../core/appender/nosql/DefaultNoSqlObject.java    |  3 +++
 .../core/appender/nosql/NoSqlDatabaseManager.java  | 13 ++++------
 .../log4j/core/appender/nosql/NoSqlObject.java     |  1 +
 .../log4j/mongodb3/MongoDbDocumentObject.java      |  1 +
 .../mongodb3/MongoDb3AdditionalFieldsTest.java     | 28 +++++++++-------------
 .../log4j/mongodb4/MongoDb4DocumentObject.java     |  4 ++--
 .../mongodb4/MongoDb4AdditionalFieldsTest.java     | 26 +++++++++-----------
 7 files changed, 34 insertions(+), 42 deletions(-)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/DefaultNoSqlObject.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/DefaultNoSqlObject.java
index 7600e1a..debe9e5 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/DefaultNoSqlObject.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/DefaultNoSqlObject.java
@@ -31,6 +31,9 @@ public class DefaultNoSqlObject implements NoSqlObject<Map<String, Object>> {
 
     private final Map<String, Object> map;
 
+    /**
+     * Constructs a new instance.
+     */
     public DefaultNoSqlObject() {
         this.map = new HashMap<>();
     }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManager.java
index 1dad261..df29f6a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManager.java
@@ -27,6 +27,7 @@ import org.apache.logging.log4j.core.appender.AppenderLoggingException;
 import org.apache.logging.log4j.core.appender.ManagerFactory;
 import org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager;
 import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.lookup.StrSubstitutor;
 import org.apache.logging.log4j.core.util.Closer;
 import org.apache.logging.log4j.core.util.KeyValuePair;
 import org.apache.logging.log4j.message.MapMessage;
@@ -142,13 +143,6 @@ public final class NoSqlDatabaseManager<W> extends AbstractDatabaseManager {
         }
     }
 
-    private NoSqlObject<W> convertAdditionalField(KeyValuePair field) {
-        final NoSqlObject<W> object = connection.createObject();
-        object.set("key", field.getKey());
-        object.set("value", getStrSubstitutor().replace(field.getValue()));
-        return object;
-    }
-
     private NoSqlObject<W>[] convertStackTrace(final StackTraceElement[] stackTrace) {
         final NoSqlObject<W>[] stackTraceEntities = this.connection.createList(stackTrace.length);
         for (int i = 0; i < stackTrace.length; i++) {
@@ -168,7 +162,10 @@ public final class NoSqlDatabaseManager<W> extends AbstractDatabaseManager {
 
     private void setAdditionalFields(final NoSqlObject<W> entity) {
         if (additionalFields != null) {
-            entity.set("additionalFields", Stream.of(additionalFields).map(this::convertAdditionalField).toArray());
+            final NoSqlObject<W> object = connection.createObject();
+            final StrSubstitutor strSubstitutor = getStrSubstitutor();
+            Stream.of(additionalFields).forEach(f -> object.set(f.getKey(), strSubstitutor != null ? strSubstitutor.replace(f.getValue()) : f.getValue()));
+            entity.set("additionalFields", object);
         }
     }
 
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlObject.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlObject.java
index 41bc7f9..6b047d7 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlObject.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlObject.java
@@ -22,6 +22,7 @@ package org.apache.logging.log4j.core.appender.nosql;
  * @param <W> Specifies what type of underlying object (such as a MongoDB BasicDBObject) this NoSqlObject wraps.
  */
 public interface NoSqlObject<W> {
+
     /**
      * Sets the value of a property on this object to a String or primitive.
      *
diff --git a/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDbDocumentObject.java b/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDbDocumentObject.java
index c12e998..020c676 100644
--- a/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDbDocumentObject.java
+++ b/log4j-mongodb3/src/main/java/org/apache/logging/log4j/mongodb3/MongoDbDocumentObject.java
@@ -25,6 +25,7 @@ import org.bson.Document;
  * The MongoDB implementation of {@link NoSqlObject} typed to a BSON {@link Document}.
  */
 public final class MongoDbDocumentObject implements NoSqlObject<Document> {
+
     private final Document document;
 
     /**
diff --git a/log4j-mongodb3/src/test/java/org/apache/logging/log4j/mongodb3/MongoDb3AdditionalFieldsTest.java b/log4j-mongodb3/src/test/java/org/apache/logging/log4j/mongodb3/MongoDb3AdditionalFieldsTest.java
index 9e8225d..a4c5399 100644
--- a/log4j-mongodb3/src/test/java/org/apache/logging/log4j/mongodb3/MongoDb3AdditionalFieldsTest.java
+++ b/log4j-mongodb3/src/test/java/org/apache/logging/log4j/mongodb3/MongoDb3AdditionalFieldsTest.java
@@ -16,8 +16,6 @@
  */
 package org.apache.logging.log4j.mongodb3;
 
-import java.util.List;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.categories.Appenders;
@@ -69,18 +67,14 @@ public class MongoDb3AdditionalFieldsTest {
             Assert.assertEquals(first.toJson(), "Hello log 1", first.getString("message"));
             Assert.assertEquals(first.toJson(), "INFO", first.getString("level"));
             //
-            List<Document> list;
+            Document list;
             final String envPath = System.getenv("PATH");
             //
-            list = first.getList("additionalFields", Document.class);
-            Assert.assertEquals(first.toJson(), "A", list.get(0).get("key"));
-            Assert.assertEquals(first.toJson(), "1", list.get(0).get("value"));
-            Assert.assertEquals(first.toJson(), "B", list.get(1).get("key"));
-            Assert.assertEquals(first.toJson(), "2", list.get(1).get("value"));
-            Assert.assertEquals(first.toJson(), "env1", list.get(2).get("key"));
-            Assert.assertEquals(first.toJson(), envPath, list.get(2).get("value"));
-            Assert.assertEquals(first.toJson(), "env2", list.get(3).get("key"));
-            Assert.assertEquals(first.toJson(), envPath, list.get(3).get("value"));
+            list = first.get("additionalFields", Document.class);
+            Assert.assertEquals(first.toJson(), "1", list.getString("A"));
+            Assert.assertEquals(first.toJson(), "2", list.getString("B"));
+            Assert.assertEquals(first.toJson(), envPath, list.getString("env1"));
+            Assert.assertEquals(first.toJson(), envPath, list.getString("env2"));
             //
             found.skip(1);
             final Document second = found.first();
@@ -90,11 +84,11 @@ public class MongoDb3AdditionalFieldsTest {
             final Document thrown = second.get("thrown", Document.class);
             Assert.assertEquals(thrown.toJson(), "Hello ex 2", thrown.getString("message"));
             //
-            list = second.getList("additionalFields", Document.class);
-            Assert.assertEquals(first.toJson(), "A", list.get(0).get("key"));
-            Assert.assertEquals(first.toJson(), "1", list.get(0).get("value"));
-            Assert.assertEquals(first.toJson(), "B", list.get(1).get("key"));
-            Assert.assertEquals(first.toJson(), "2", list.get(1).get("value"));
+            list = second.get("additionalFields", Document.class);
+            Assert.assertEquals(first.toJson(), "1", list.getString("A"));
+            Assert.assertEquals(first.toJson(), "2", list.getString("B"));
+            Assert.assertEquals(first.toJson(), envPath, list.getString("env1"));
+            Assert.assertEquals(first.toJson(), envPath, list.getString("env2"));
         }
     }
 }
diff --git a/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java
index 5978743..63c3fae 100644
--- a/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java
+++ b/log4j-mongodb4/src/main/java/org/apache/logging/log4j/mongodb4/MongoDb4DocumentObject.java
@@ -22,10 +22,10 @@ import org.apache.logging.log4j.core.appender.nosql.NoSqlObject;
 import org.bson.Document;
 
 /**
- * The MongoDB implementation of {@link NoSqlObject} typed to a BSON
- * {@link Document}.
+ * The MongoDB implementation of {@link NoSqlObject} typed to a BSON {@link Document}.
  */
 public final class MongoDb4DocumentObject implements NoSqlObject<Document> {
+
     private final Document document;
 
     /**
diff --git a/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4AdditionalFieldsTest.java b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4AdditionalFieldsTest.java
index 715162f..19e9c16 100644
--- a/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4AdditionalFieldsTest.java
+++ b/log4j-mongodb4/src/test/java/org/apache/logging/log4j/mongodb4/MongoDb4AdditionalFieldsTest.java
@@ -70,18 +70,14 @@ public class MongoDb4AdditionalFieldsTest {
             Assert.assertEquals(first.toJson(), "Hello log 1", first.getString("message"));
             Assert.assertEquals(first.toJson(), "INFO", first.getString("level"));
             //
-            List<Document> list;
+            Document list;
             final String envPath = System.getenv("PATH");
             //
-            list = first.getList("additionalFields", Document.class);
-            Assert.assertEquals(first.toJson(), "A", list.get(0).get("key"));
-            Assert.assertEquals(first.toJson(), "1", list.get(0).get("value"));
-            Assert.assertEquals(first.toJson(), "B", list.get(1).get("key"));
-            Assert.assertEquals(first.toJson(), "2", list.get(1).get("value"));
-            Assert.assertEquals(first.toJson(), "env1", list.get(2).get("key"));
-            Assert.assertEquals(first.toJson(), envPath, list.get(2).get("value"));
-            Assert.assertEquals(first.toJson(), "env2", list.get(3).get("key"));
-            Assert.assertEquals(first.toJson(), envPath, list.get(3).get("value"));
+            list = first.get("additionalFields", Document.class);
+            Assert.assertEquals(first.toJson(), "1", list.getString("A"));
+            Assert.assertEquals(first.toJson(), "2", list.getString("B"));
+            Assert.assertEquals(first.toJson(), envPath, list.getString("env1"));
+            Assert.assertEquals(first.toJson(), envPath, list.getString("env2"));
             //
             found.skip(1);
             final Document second = found.first();
@@ -91,11 +87,11 @@ public class MongoDb4AdditionalFieldsTest {
             final Document thrown = second.get("thrown", Document.class);
             Assert.assertEquals(thrown.toJson(), "Hello ex 2", thrown.getString("message"));
             //
-            list = second.getList("additionalFields", Document.class);
-            Assert.assertEquals(first.toJson(), "A", list.get(0).get("key"));
-            Assert.assertEquals(first.toJson(), "1", list.get(0).get("value"));
-            Assert.assertEquals(first.toJson(), "B", list.get(1).get("key"));
-            Assert.assertEquals(first.toJson(), "2", list.get(1).get("value"));
+            list = second.get("additionalFields", Document.class);
+            Assert.assertEquals(first.toJson(), "1", list.getString("A"));
+            Assert.assertEquals(first.toJson(), "2", list.getString("B"));
+            Assert.assertEquals(first.toJson(), envPath, list.getString("env1"));
+            Assert.assertEquals(first.toJson(), envPath, list.getString("env2"));
         }
     }
 }

[logging-log4j2] 01/04: Sort members.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 77b61063648551949d09cf8127330db1ee2af51e
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Wed Feb 9 08:47:24 2022 -0500

    Sort members.
---
 .../core/appender/nosql/NoSqlDatabaseManager.java  | 230 ++++++++++-----------
 1 file changed, 115 insertions(+), 115 deletions(-)

diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManager.java
index abd0da2..1dad261 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/nosql/NoSqlDatabaseManager.java
@@ -38,8 +38,63 @@ import org.apache.logging.log4j.util.ReadOnlyStringMap;
  * @param <W> A type parameter for reassuring the compiler that all operations are using the same {@link NoSqlObject}.
  */
 public final class NoSqlDatabaseManager<W> extends AbstractDatabaseManager {
+    /**
+     * Encapsulates data that {@link NoSQLDatabaseManagerFactory} uses to create managers.
+     */
+    private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
+        private final NoSqlProvider<?> provider;
+        private final KeyValuePair[] additionalFields;
+
+        protected FactoryData(final Configuration configuration, final int bufferSize, final NoSqlProvider<?> provider, final KeyValuePair[] additionalFields) {
+            super(configuration, bufferSize, null); // no layout
+            this.provider = Objects.requireNonNull(provider, "provider");
+            this.additionalFields = additionalFields; // null OK
+        }
+    }
+
+    /**
+     * Creates managers.
+     */
+    private static final class NoSQLDatabaseManagerFactory implements ManagerFactory<NoSqlDatabaseManager<?>, FactoryData> {
+        @Override
+        @SuppressWarnings("unchecked")
+        public NoSqlDatabaseManager<?> createManager(final String name, final FactoryData data) {
+            Objects.requireNonNull(data, "data");
+            return new NoSqlDatabaseManager(name, data.getBufferSize(), data.provider, data.additionalFields, data.getConfiguration());
+        }
+    }
+
     private static final NoSQLDatabaseManagerFactory FACTORY = new NoSQLDatabaseManagerFactory();
 
+    /**
+     * Creates a NoSQL manager for use within the {@link NoSqlAppender}, or returns a suitable one if it already exists.
+     *
+     * @param name The name of the manager, which should include connection details and hashed passwords where possible.
+     * @param bufferSize The size of the log event buffer.
+     * @param provider A provider instance which will be used to obtain connections to the chosen NoSQL database.
+     * @return a new or existing NoSQL manager as applicable.
+     * @deprecated Use {@link #getNoSqlDatabaseManager(String, int, NoSqlProvider, KeyValuePair[], Configuration)}.
+     */
+    @Deprecated
+    public static NoSqlDatabaseManager<?> getNoSqlDatabaseManager(final String name, final int bufferSize, final NoSqlProvider<?> provider) {
+        return AbstractDatabaseManager.getManager(name, new FactoryData(null, bufferSize, provider, null), FACTORY);
+    }
+
+    /**
+     * Creates a NoSQL manager for use within the {@link NoSqlAppender}, or returns a suitable one if it already exists.
+     *
+     * @param name The name of the manager, which should include connection details and hashed passwords where possible.
+     * @param bufferSize The size of the log event buffer.
+     * @param provider A provider instance which will be used to obtain connections to the chosen NoSQL database.
+     * @param additionalFields Additional fields.
+     * @param configuration TODO
+     * @return a new or existing NoSQL manager as applicable.
+     */
+    public static NoSqlDatabaseManager<?> getNoSqlDatabaseManager(final String name, final int bufferSize, final NoSqlProvider<?> provider,
+        final KeyValuePair[] additionalFields, final Configuration configuration) {
+        return AbstractDatabaseManager.getManager(name, new FactoryData(configuration, bufferSize, provider, additionalFields), FACTORY);
+    }
+
     private final NoSqlProvider<NoSqlConnection<W, ? extends NoSqlObject<W>>> provider;
 
     private NoSqlConnection<W, ? extends NoSqlObject<W>> connection;
@@ -53,15 +108,29 @@ public final class NoSqlDatabaseManager<W> extends AbstractDatabaseManager {
         this.additionalFields = additionalFields;
     }
 
-    @Override
-    protected void startupInternal() {
-        // nothing to see here
+    private NoSqlObject<W> buildMarkerEntity(final Marker marker) {
+        final NoSqlObject<W> entity = this.connection.createObject();
+        entity.set("name", marker.getName());
+
+        final Marker[] parents = marker.getParents();
+        if (parents != null) {
+            @SuppressWarnings("unchecked")
+            final NoSqlObject<W>[] parentEntities = new NoSqlObject[parents.length];
+            for (int i = 0; i < parents.length; i++) {
+                parentEntities[i] = buildMarkerEntity(parents[i]);
+            }
+            entity.set("parents", parentEntities);
+        }
+        return entity;
     }
 
     @Override
-    protected boolean shutdownInternal() {
-        // NoSQL doesn't use transactions, so all we need to do here is simply close the client
-        return Closer.closeSilently(this.connection);
+    protected boolean commitAndClose() {
+        // all NoSQL drivers auto-commit (since NoSQL doesn't generally use the concept of transactions).
+        // also, all our NoSQL drivers use internal connection pooling and provide clients, not connections.
+        // thus, we should not be closing the client until shutdown as NoSQL is very different from SQL.
+        // see LOG4J2-591 and LOG4J2-676
+        return true;
     }
 
     @Override
@@ -73,20 +142,28 @@ public final class NoSqlDatabaseManager<W> extends AbstractDatabaseManager {
         }
     }
 
-    @Override
-    protected void writeInternal(final LogEvent event, final Serializable serializable) {
-        if (!this.isRunning() || this.connection == null || this.connection.isClosed()) {
-            throw new AppenderLoggingException("Cannot write logging event; NoSQL manager not connected to the database.");
-        }
+    private NoSqlObject<W> convertAdditionalField(KeyValuePair field) {
+        final NoSqlObject<W> object = connection.createObject();
+        object.set("key", field.getKey());
+        object.set("value", getStrSubstitutor().replace(field.getValue()));
+        return object;
+    }
 
-        final NoSqlObject<W> entity = this.connection.createObject();
-        if (serializable instanceof MapMessage) {
-            setFields((MapMessage<?, ?>) serializable, entity);
-        } else {
-            setFields(event, entity);
+    private NoSqlObject<W>[] convertStackTrace(final StackTraceElement[] stackTrace) {
+        final NoSqlObject<W>[] stackTraceEntities = this.connection.createList(stackTrace.length);
+        for (int i = 0; i < stackTrace.length; i++) {
+            stackTraceEntities[i] = this.convertStackTraceElement(stackTrace[i]);
         }
-        setAdditionalFields(entity);
-        this.connection.insertObject(entity);
+        return stackTraceEntities;
+    }
+
+    private NoSqlObject<W> convertStackTraceElement(final StackTraceElement element) {
+        final NoSqlObject<W> elementEntity = this.connection.createObject();
+        elementEntity.set("className", element.getClassName());
+        elementEntity.set("methodName", element.getMethodName());
+        elementEntity.set("fileName", element.getFileName());
+        elementEntity.set("lineNumber", element.getLineNumber());
+        return elementEntity;
     }
 
     private void setAdditionalFields(final NoSqlObject<W> entity) {
@@ -95,18 +172,6 @@ public final class NoSqlDatabaseManager<W> extends AbstractDatabaseManager {
         }
     }
 
-    private NoSqlObject<W> convertAdditionalField(KeyValuePair field) {
-        final NoSqlObject<W> object = connection.createObject();
-        object.set("key", field.getKey());
-        object.set("value", getStrSubstitutor().replace(field.getValue()));
-        return object;
-    }
-
-    private void setFields(final MapMessage<?, ?> mapMessage, final NoSqlObject<W> noSqlObject) {
-        // Map without calling org.apache.logging.log4j.message.MapMessage#getData() which makes a copy of the map.
-        mapMessage.forEach((key, value) -> noSqlObject.set(key, value));
-    }
-
     private void setFields(final LogEvent event, final NoSqlObject<W> entity) {
         entity.set("level", event.getLevel());
         entity.set("loggerName", event.getLoggerName());
@@ -172,100 +237,35 @@ public final class NoSqlDatabaseManager<W> extends AbstractDatabaseManager {
         }
     }
 
-    private NoSqlObject<W> buildMarkerEntity(final Marker marker) {
-        final NoSqlObject<W> entity = this.connection.createObject();
-        entity.set("name", marker.getName());
-
-        final Marker[] parents = marker.getParents();
-        if (parents != null) {
-            @SuppressWarnings("unchecked")
-            final NoSqlObject<W>[] parentEntities = new NoSqlObject[parents.length];
-            for (int i = 0; i < parents.length; i++) {
-                parentEntities[i] = buildMarkerEntity(parents[i]);
-            }
-            entity.set("parents", parentEntities);
-        }
-        return entity;
+    private void setFields(final MapMessage<?, ?> mapMessage, final NoSqlObject<W> noSqlObject) {
+        // Map without calling org.apache.logging.log4j.message.MapMessage#getData() which makes a copy of the map.
+        mapMessage.forEach((key, value) -> noSqlObject.set(key, value));
     }
 
     @Override
-    protected boolean commitAndClose() {
-        // all NoSQL drivers auto-commit (since NoSQL doesn't generally use the concept of transactions).
-        // also, all our NoSQL drivers use internal connection pooling and provide clients, not connections.
-        // thus, we should not be closing the client until shutdown as NoSQL is very different from SQL.
-        // see LOG4J2-591 and LOG4J2-676
-        return true;
-    }
-
-    private NoSqlObject<W>[] convertStackTrace(final StackTraceElement[] stackTrace) {
-        final NoSqlObject<W>[] stackTraceEntities = this.connection.createList(stackTrace.length);
-        for (int i = 0; i < stackTrace.length; i++) {
-            stackTraceEntities[i] = this.convertStackTraceElement(stackTrace[i]);
-        }
-        return stackTraceEntities;
-    }
-
-    private NoSqlObject<W> convertStackTraceElement(final StackTraceElement element) {
-        final NoSqlObject<W> elementEntity = this.connection.createObject();
-        elementEntity.set("className", element.getClassName());
-        elementEntity.set("methodName", element.getMethodName());
-        elementEntity.set("fileName", element.getFileName());
-        elementEntity.set("lineNumber", element.getLineNumber());
-        return elementEntity;
-    }
-
-    /**
-     * Creates a NoSQL manager for use within the {@link NoSqlAppender}, or returns a suitable one if it already exists.
-     *
-     * @param name The name of the manager, which should include connection details and hashed passwords where possible.
-     * @param bufferSize The size of the log event buffer.
-     * @param provider A provider instance which will be used to obtain connections to the chosen NoSQL database.
-     * @return a new or existing NoSQL manager as applicable.
-     * @deprecated Use {@link #getNoSqlDatabaseManager(String, int, NoSqlProvider, KeyValuePair[], Configuration)}.
-     */
-    @Deprecated
-    public static NoSqlDatabaseManager<?> getNoSqlDatabaseManager(final String name, final int bufferSize, final NoSqlProvider<?> provider) {
-        return AbstractDatabaseManager.getManager(name, new FactoryData(null, bufferSize, provider, null), FACTORY);
+    protected boolean shutdownInternal() {
+        // NoSQL doesn't use transactions, so all we need to do here is simply close the client
+        return Closer.closeSilently(this.connection);
     }
 
-    /**
-     * Creates a NoSQL manager for use within the {@link NoSqlAppender}, or returns a suitable one if it already exists.
-     *
-     * @param name The name of the manager, which should include connection details and hashed passwords where possible.
-     * @param bufferSize The size of the log event buffer.
-     * @param provider A provider instance which will be used to obtain connections to the chosen NoSQL database.
-     * @param additionalFields Additional fields.
-     * @param configuration TODO
-     * @return a new or existing NoSQL manager as applicable.
-     */
-    public static NoSqlDatabaseManager<?> getNoSqlDatabaseManager(final String name, final int bufferSize, final NoSqlProvider<?> provider,
-        final KeyValuePair[] additionalFields, final Configuration configuration) {
-        return AbstractDatabaseManager.getManager(name, new FactoryData(configuration, bufferSize, provider, additionalFields), FACTORY);
+    @Override
+    protected void startupInternal() {
+        // nothing to see here
     }
 
-    /**
-     * Encapsulates data that {@link NoSQLDatabaseManagerFactory} uses to create managers.
-     */
-    private static final class FactoryData extends AbstractDatabaseManager.AbstractFactoryData {
-        private final NoSqlProvider<?> provider;
-        private final KeyValuePair[] additionalFields;
-
-        protected FactoryData(final Configuration configuration, final int bufferSize, final NoSqlProvider<?> provider, final KeyValuePair[] additionalFields) {
-            super(configuration, bufferSize, null); // no layout
-            this.provider = Objects.requireNonNull(provider, "provider");
-            this.additionalFields = additionalFields; // null OK
+    @Override
+    protected void writeInternal(final LogEvent event, final Serializable serializable) {
+        if (!this.isRunning() || this.connection == null || this.connection.isClosed()) {
+            throw new AppenderLoggingException("Cannot write logging event; NoSQL manager not connected to the database.");
         }
-    }
 
-    /**
-     * Creates managers.
-     */
-    private static final class NoSQLDatabaseManagerFactory implements ManagerFactory<NoSqlDatabaseManager<?>, FactoryData> {
-        @Override
-        @SuppressWarnings("unchecked")
-        public NoSqlDatabaseManager<?> createManager(final String name, final FactoryData data) {
-            Objects.requireNonNull(data, "data");
-            return new NoSqlDatabaseManager(name, data.getBufferSize(), data.provider, data.additionalFields, data.getConfiguration());
+        final NoSqlObject<W> entity = this.connection.createObject();
+        if (serializable instanceof MapMessage) {
+            setFields((MapMessage<?, ?>) serializable, entity);
+        } else {
+            setFields(event, entity);
         }
+        setAdditionalFields(entity);
+        this.connection.insertObject(entity);
     }
 }