You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2021/07/07 09:02:59 UTC

[logging-log4j2] branch release-2.x updated (fb747ab -> d470a61)

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

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


    from fb747ab  LOG4J2-3107 SmtpManager.createManagerName() ignores port (#528)
     new 3a86977  LOG4J2-3074 Add replacement parameter to ReadOnlyStringMapResolver.
     new 2e391b6  Consolidate ReadOnlyStringMapResolver tests.
     new 55fa62b  Consolidate MessageResolver tests.
     new d470a61  Add missing license preambles to log4j-layout-template-json sources.

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:
 .../json/resolver/CaseConverterResolver.java       |  16 +
 .../resolver/CaseConverterResolverFactory.java     |  16 +
 .../json/resolver/ReadOnlyStringMapResolver.java   |  87 +++-
 .../json/resolver/TemplateResolverFactories.java   |  16 +
 .../template/json/JsonTemplateLayoutTest.java      | 506 +--------------------
 .../log4j/layout/template/json/TestHelpers.java    |  16 +
 .../json/resolver/CaseConverterResolverTest.java   |  16 +
 .../json/resolver/MessageResolverTest.java         | 158 +++++++
 .../resolver/ReadOnlyStringMapResolverTest.java    | 453 ++++++++++++++++++
 .../template/json/util/InstantFormatterTest.java   |  16 +
 src/changes/changes.xml                            |   3 +
 .../asciidoc/manual/json-template-layout.adoc.vm   |  51 ++-
 12 files changed, 823 insertions(+), 531 deletions(-)
 create mode 100644 log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolverTest.java

[logging-log4j2] 01/04: LOG4J2-3074 Add replacement parameter to ReadOnlyStringMapResolver.

Posted by vy...@apache.org.
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

commit 3a86977ecf0e1ea27ec59c587284b8617875b65e
Author: Volkan Yazici <vo...@gmail.com>
AuthorDate: Wed Jul 7 10:47:12 2021 +0200

    LOG4J2-3074 Add replacement parameter to ReadOnlyStringMapResolver.
---
 .../json/resolver/ReadOnlyStringMapResolver.java   |  87 +++++++++++++----
 .../resolver/ReadOnlyStringMapResolverTest.java    | 107 +++++++++++++++++++++
 src/changes/changes.xml                            |   3 +
 .../asciidoc/manual/json-template-layout.adoc.vm   |  51 ++++++++--
 4 files changed, 222 insertions(+), 26 deletions(-)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolver.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolver.java
index 3735017..788fa5d 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolver.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolver.java
@@ -25,6 +25,7 @@ import org.apache.logging.log4j.util.TriConsumer;
 
 import java.util.Map;
 import java.util.function.Function;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
@@ -39,8 +40,9 @@ import java.util.regex.Pattern;
  * key           = "key" -> string
  * stringified   = "stringified" -> boolean
  *
- * multiAccess   = [ pattern ] , [ flatten ] , [ stringified ]
+ * multiAccess   = [ pattern ] , [ replacement ] , [ flatten ] , [ stringified ]
  * pattern       = "pattern" -> string
+ * replacement   = "replacement" -> string
  * flatten       = "flatten" -> ( boolean | flattenConfig )
  * flattenConfig = [ flattenPrefix ]
  * flattenPrefix = "prefix" -> string
@@ -54,13 +56,20 @@ import java.util.regex.Pattern;
  * Enabling <tt>stringified</tt> flag converts each value to its string
  * representation.
  * <p>
- * Regex provided in the `pattern` is used to match against the keys.
+ * Regex provided in the <tt>pattern</tt> is used to match against the keys.
+ * If provided, <tt>replacement</tt> will be used to replace the matched keys.
+ * These two are effectively equivalent to
+ * <tt>Pattern.compile(pattern).matcher(key).matches()</tt> and
+ * <tt>Pattern.compile(pattern).matcher(key).replaceAll(replacement)</tt> calls.
  *
  * <h3>Garbage Footprint</h3>
  *
  * <tt>stringified</tt> allocates a new <tt>String</tt> for values that are not
  * of type <tt>String</tt>.
  * <p>
+ * <tt>pattern</tt> and <tt>replacement</tt> incur pattern matcher allocation
+ * costs.
+ * <p>
  * Writing certain non-primitive values (e.g., <tt>BigDecimal</tt>,
  * <tt>Set</tt>, etc.) to JSON generates garbage, though most (e.g.,
  * <tt>int</tt>, <tt>long</tt>, <tt>String</tt>, <tt>List</tt>,
@@ -72,21 +81,21 @@ import java.util.regex.Pattern;
  * defined by the actual resolver, e.g., {@link MapResolver},
  * {@link ThreadContextDataResolver}.
  * <p>
- * Resolve the value of the field keyed with <tt>userRole</tt>:
+ * Resolve the value of the field keyed with <tt>user:role</tt>:
  *
  * <pre>
  * {
  *   "$resolver": "…",
- *   "key": "userRole"
+ *   "key": "user:role"
  * }
  * </pre>
  *
- * Resolve the string representation of the <tt>userRank</tt> field value:
+ * Resolve the string representation of the <tt>user:rank</tt> field value:
  *
  * <pre>
  * {
  *   "$resolver": "…",
- *   "key": "userRank",
+ *   "key": "user:rank",
  *   "stringified": true
  * }
  * </pre>
@@ -109,14 +118,35 @@ import java.util.regex.Pattern;
  * }
  * </pre>
  *
+ * Resolve all fields whose keys match with the <tt>user:(role|rank)</tt> regex
+ * into an object:
+ *
+ * <pre>
+ * {
+ *   "$resolver": "…",
+ *   "pattern": "user:(role|rank)"
+ * }
+ * </pre>
+ *
+ * Resolve all fields whose keys match with the <tt>user:(role|rank)</tt> regex
+ * into an object after removing the <tt>user:</tt> prefix in the key:
+ *
+ * <pre>
+ * {
+ *   "$resolver": "…",
+ *   "pattern": "user:(role|rank)",
+ *   "replacement": "$1"
+ * }
+ * </pre>
+ *
  * Merge all fields whose keys are matching with the
- * <tt>user(Role|Rank)</tt> regex into the parent:
+ * <tt>user:(role|rank)</tt> regex into the parent:
  *
  * <pre>
  * {
  *   "$resolver": "…",
  *   "flatten": true,
- *   "pattern": "user(Role|Rank)"
+ *   "pattern": "user:(role|rank)"
  * }
  * </pre>
  *
@@ -162,15 +192,24 @@ class ReadOnlyStringMapResolver implements EventResolver {
         } else {
             throw new IllegalArgumentException("invalid flatten option: " + config);
         }
-        final String key = config.getString("key");
         final String prefix = config.getString(new String[] {"flatten", "prefix"});
+        final String key = config.getString("key");
+        if (key != null && flatten) {
+            throw new IllegalArgumentException(
+                    "key and flatten options cannot be combined: " + config);
+        }
         final String pattern = config.getString("pattern");
+        if (pattern != null && key != null) {
+            throw new IllegalArgumentException(
+                    "pattern and key options cannot be combined: " + config);
+        }
+        final String replacement = config.getString("replacement");
+        if (pattern == null && replacement != null) {
+            throw new IllegalArgumentException(
+                    "replacement cannot be provided without a pattern: " + config);
+        }
         final boolean stringified = config.getBoolean("stringified", false);
         if (key != null) {
-            if (flatten) {
-                throw new IllegalArgumentException(
-                        "both key and flatten options cannot be supplied: " + config);
-            }
             return createKeyResolver(key, stringified, mapAccessor);
         } else {
             final RecyclerFactory recyclerFactory = context.getRecyclerFactory();
@@ -179,6 +218,7 @@ class ReadOnlyStringMapResolver implements EventResolver {
                     flatten,
                     prefix,
                     pattern,
+                    replacement,
                     stringified,
                     mapAccessor);
         }
@@ -216,6 +256,7 @@ class ReadOnlyStringMapResolver implements EventResolver {
             final boolean flatten,
             final String prefix,
             final String pattern,
+            final String replacement,
             final boolean stringified,
             final Function<LogEvent, ReadOnlyStringMap> mapAccessor) {
 
@@ -234,6 +275,7 @@ class ReadOnlyStringMapResolver implements EventResolver {
                         loopContext.prefixedKey = new StringBuilder(prefix);
                     }
                     loopContext.pattern = compiledPattern;
+                    loopContext.replacement = replacement;
                     loopContext.stringified = stringified;
                     return loopContext;
                 });
@@ -262,7 +304,7 @@ class ReadOnlyStringMapResolver implements EventResolver {
 
             @Override
             public void resolve(final LogEvent value, final JsonWriter jsonWriter) {
-                throw new UnsupportedOperationException();
+                resolve(value, jsonWriter, false);
             }
 
             @Override
@@ -310,6 +352,8 @@ class ReadOnlyStringMapResolver implements EventResolver {
 
         private Pattern pattern;
 
+        private String replacement;
+
         private boolean stringified;
 
         private JsonWriter jsonWriter;
@@ -329,10 +373,15 @@ class ReadOnlyStringMapResolver implements EventResolver {
                 final String key,
                 final Object value,
                 final LoopContext loopContext) {
-            final boolean keyMatched =
-                    loopContext.pattern == null ||
-                            loopContext.pattern.matcher(key).matches();
+            final Matcher matcher = loopContext.pattern != null
+                    ? loopContext.pattern.matcher(key)
+                    : null;
+            final boolean keyMatched = matcher == null || matcher.matches();
             if (keyMatched) {
+                final String replacedKey =
+                        matcher != null && loopContext.replacement != null
+                                ? matcher.replaceAll(loopContext.replacement)
+                                : key;
                 final boolean succeedingEntry =
                         loopContext.succeedingEntry ||
                                 loopContext.initJsonWriterStringBuilderLength <
@@ -341,10 +390,10 @@ class ReadOnlyStringMapResolver implements EventResolver {
                     loopContext.jsonWriter.writeSeparator();
                 }
                 if (loopContext.prefix == null) {
-                    loopContext.jsonWriter.writeObjectKey(key);
+                    loopContext.jsonWriter.writeObjectKey(replacedKey);
                 } else {
                     loopContext.prefixedKey.setLength(loopContext.prefix.length());
-                    loopContext.prefixedKey.append(key);
+                    loopContext.prefixedKey.append(replacedKey);
                     loopContext.jsonWriter.writeObjectKey(loopContext.prefixedKey);
                 }
                 if (loopContext.stringified && !(value instanceof String)) {
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolverTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolverTest.java
new file mode 100644
index 0000000..baaedef
--- /dev/null
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolverTest.java
@@ -0,0 +1,107 @@
+package org.apache.logging.log4j.layout.template.json.resolver;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
+import org.apache.logging.log4j.util.SortedArrayStringMap;
+import org.apache.logging.log4j.util.StringMap;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.regex.PatternSyntaxException;
+
+import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ReadOnlyStringMapResolverTest {
+
+    @Test
+    void key_should_not_be_allowed_with_flatten() {
+        verifyConfigFailure(
+                writeJson(asMap(
+                        "$resolver", "mdc",
+                        "key", "foo",
+                        "flatten", true)),
+                IllegalArgumentException.class,
+                "key and flatten options cannot be combined");
+    }
+
+    @Test
+    void invalid_pattern_should_fail() {
+        verifyConfigFailure(
+                writeJson(asMap(
+                        "$resolver", "mdc",
+                        "pattern", "[1")),
+                PatternSyntaxException.class,
+                "Unclosed character");
+    }
+
+    @Test
+    void pattern_should_not_be_allowed_with_key() {
+        verifyConfigFailure(
+                writeJson(asMap(
+                        "$resolver", "mdc",
+                        "key", "foo",
+                        "pattern", "bar")),
+                IllegalArgumentException.class,
+                "pattern and key options cannot be combined");
+    }
+
+    @Test
+    void replacement_should_not_be_allowed_without_pattern() {
+        verifyConfigFailure(
+                writeJson(asMap(
+                        "$resolver", "mdc",
+                        "replacement", "$1")),
+                IllegalArgumentException.class,
+                "replacement cannot be provided without a pattern");
+    }
+
+    private void verifyConfigFailure(
+            final String eventTemplate,
+            final Class<? extends Throwable> failureClass,
+            final String failureMessage) {
+        Assertions
+                .assertThatThrownBy(() -> JsonTemplateLayout
+                        .newBuilder()
+                        .setConfiguration(CONFIGURATION)
+                        .setEventTemplate(eventTemplate)
+                        .build())
+                .isInstanceOf(failureClass)
+                .hasMessageContaining(failureMessage);
+    }
+
+    @Test
+    void pattern_replacement_should_work() {
+
+        // Create the event template.
+        final String eventTemplate = writeJson(asMap(
+                "$resolver", "mdc",
+                "pattern", "user:(role|rank)",
+                "replacement", "$1"));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Create the log event.
+        final StringMap contextData = new SortedArrayStringMap();
+        contextData.putValue("user:role", "engineer");
+        contextData.putValue("user:rank", "senior");
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setContextData(contextData)
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+            assertThat(accessor.getString("role")).isEqualTo("engineer");
+            assertThat(accessor.getString("rank")).isEqualTo("senior");
+        });
+
+    }
+
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 6b35a21..bbddae2 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
     -->
     <release version="2.15.0" date="2021-MM-DD" description="GA Release 2.15.0">
       <!-- ADDS -->
+      <action issue="LOG4J2-3074" dev="vy" type="add">
+        Add replacement parameter to ReadOnlyStringMapResolver.
+      </action>
       <action issue="LOG4J2-3051" dev="vy" type="add">
         Add CaseConverterResolver to JsonTemplateLayout.
       </action>
diff --git a/src/site/asciidoc/manual/json-template-layout.adoc.vm b/src/site/asciidoc/manual/json-template-layout.adoc.vm
index 97e9a05..768e222 100644
--- a/src/site/asciidoc/manual/json-template-layout.adoc.vm
+++ b/src/site/asciidoc/manual/json-template-layout.adoc.vm
@@ -1279,8 +1279,9 @@ singleAccess  = key , [ stringified ]
 key           = "key" -> string
 stringified   = "stringified" -> boolean
 
-multiAccess   = [ pattern ] , [ flatten ] , [ stringified ]
+multiAccess   = [ pattern ] , [ replacement ] , [ flatten ] , [ stringified ]
 pattern       = "pattern" -> string
+replacement   = "replacement" -> string
 flatten       = "flatten" -> ( boolean | flattenConfig )
 flattenConfig = [ flattenPrefix ]
 flattenPrefix = "prefix" -> string
@@ -1290,32 +1291,45 @@ flattenPrefix = "prefix" -> string
 multitude of fields. If `flatten` is provided, `multiAccess` merges the fields
 with the parent, otherwise creates a new JSON object containing the values.
 
+Enabling `stringified` flag converts each value to its string representation.
+
+Regex provided in the `pattern` is used to match against the keys. If provided,
+`replacement` will be used to replace the matched keys. These two are
+effectively equivalent to `Pattern.compile(pattern).matcher(key).matches()` and
+`Pattern.compile(pattern).matcher(key).replaceAll(replacement)` calls.
+
 [WARNING]
 ====
 Regarding garbage footprint, `stringified` flag translates to
 `String.valueOf(value)`, hence mind not-`String`-typed values.
+
+`pattern` and `replacement` incur pattern matcher allocation costs.
+
+Writing certain non-primitive values (e.g., `BigDecimal`, `Set`, etc.) to JSON
+generates garbage, though most (e.g., `int`, `long`, `String`, `List`,
+`boolean[]`, etc.) don't.
 ====
 
 `"${dollar}resolver"` is left out in the following examples, since it is to be
 defined by the actual resolver, e.g., `map`, `mdc`.
 
-Resolve the value of the field keyed with `userRole`:
+Resolve the value of the field keyed with `user:role`:
 
 [source,json]
 ----
 {
   "$resolver": "…",
-  "key": "userRole"
+  "key": "user:role"
 }
 ----
 
-Resolve the string representation of the `userRank` field value:
+Resolve the string representation of the `user:rank` field value:
 
 [source,json]
 ----
 {
   "$resolver": "…",
-  "key": "userRank",
+  "key": "user:rank",
   "stringified": true
 }
 ----
@@ -1339,7 +1353,30 @@ Resolve all fields into an object such that values are converted to string:
 }
 ----
 
-Merge all fields whose keys are matching with the `user(Role|Rank)` regex into
+Resolve all fields whose keys match with the `user:(role|rank)` regex into an
+object:
+
+[source,json]
+----
+{
+  "$resolver": "…",
+  "pattern": "user:(role|rank)"
+}
+----
+
+Resolve all fields whose keys match with the `user:(role|rank)` regex into an
+object after removing the `user:` prefix in the key:
+
+[source,json]
+----
+{
+  "$resolver": "…",
+  "pattern": "user:(role|rank)",
+  "replacement": "$1"
+}
+----
+
+Merge all fields whose keys are matching with the `user:(role|rank)` regex into
 the parent:
 
 [source,json]
@@ -1347,7 +1384,7 @@ the parent:
 {
   "$resolver": "…",
   "flatten": true,
-  "pattern": "user(Role|Rank)"
+  "pattern": "user:(role|rank)"
 }
 ----
 

[logging-log4j2] 04/04: Add missing license preambles to log4j-layout-template-json sources.

Posted by vy...@apache.org.
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

commit d470a61604d839c6558c92e9b601f8fdfa233209
Author: Volkan Yazici <vo...@gmail.com>
AuthorDate: Wed Jul 7 11:01:23 2021 +0200

    Add missing license preambles to log4j-layout-template-json sources.
---
 .../template/json/resolver/CaseConverterResolver.java    | 16 ++++++++++++++++
 .../json/resolver/CaseConverterResolverFactory.java      | 16 ++++++++++++++++
 .../json/resolver/TemplateResolverFactories.java         | 16 ++++++++++++++++
 .../logging/log4j/layout/template/json/TestHelpers.java  | 16 ++++++++++++++++
 .../json/resolver/CaseConverterResolverTest.java         | 16 ++++++++++++++++
 .../layout/template/json/util/InstantFormatterTest.java  | 16 ++++++++++++++++
 6 files changed, 96 insertions(+)

diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolver.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolver.java
index a8e09be..51372e8 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolver.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolver.java
@@ -1,3 +1,19 @@
+/*
+ * 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.layout.template.json.resolver;
 
 import org.apache.logging.log4j.core.LogEvent;
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverFactory.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverFactory.java
index 3d0395a..6d109ed 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverFactory.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverFactory.java
@@ -1,3 +1,19 @@
+/*
+ * 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.layout.template.json.resolver;
 
 import org.apache.logging.log4j.core.config.plugins.Plugin;
diff --git a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.java b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.java
index 83270ab..16ec4fc 100644
--- a/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.java
+++ b/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.java
@@ -1,3 +1,19 @@
+/*
+ * 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.layout.template.json.resolver;
 
 import org.apache.logging.log4j.Logger;
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/TestHelpers.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/TestHelpers.java
index 78404b6..04ac179 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/TestHelpers.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/TestHelpers.java
@@ -1,3 +1,19 @@
+/*
+ * 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.layout.template.json;
 
 import org.apache.logging.log4j.core.Layout;
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverTest.java
index a52659c..fd51eda 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/CaseConverterResolverTest.java
@@ -1,3 +1,19 @@
+/*
+ * 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.layout.template.json.resolver;
 
 import org.apache.logging.log4j.core.LogEvent;
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/InstantFormatterTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/InstantFormatterTest.java
index 762b3df..bc1fd42 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/InstantFormatterTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/util/InstantFormatterTest.java
@@ -1,3 +1,19 @@
+/*
+ * 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.layout.template.json.util;
 
 import org.apache.logging.log4j.core.time.MutableInstant;

[logging-log4j2] 03/04: Consolidate MessageResolver tests.

Posted by vy...@apache.org.
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

commit 55fa62b8ad337b7b9ae875b4b3e221c98199da03
Author: Volkan Yazici <vo...@gmail.com>
AuthorDate: Wed Jul 7 10:55:45 2021 +0200

    Consolidate MessageResolver tests.
---
 .../template/json/JsonTemplateLayoutTest.java      | 165 +--------------------
 .../json/resolver/MessageResolverTest.java         | 158 ++++++++++++++++++++
 2 files changed, 159 insertions(+), 164 deletions(-)

diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
index fa0d275..95210b8 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
@@ -49,8 +49,6 @@ import org.apache.logging.log4j.message.ReusableMessageFactory;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.message.StringMapMessage;
 import org.apache.logging.log4j.test.AvailablePortFinder;
-import org.apache.logging.log4j.util.SortedArrayStringMap;
-import org.apache.logging.log4j.util.StringMap;
 import org.apache.logging.log4j.util.Strings;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
@@ -72,7 +70,6 @@ import java.time.temporal.TemporalAccessor;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ArrayBlockingQueue;
@@ -82,10 +79,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
-import static org.apache.logging.log4j.layout.template.json.TestHelpers.CONFIGURATION;
-import static org.apache.logging.log4j.layout.template.json.TestHelpers.asMap;
-import static org.apache.logging.log4j.layout.template.json.TestHelpers.usingSerializedLogEventAccessor;
-import static org.apache.logging.log4j.layout.template.json.TestHelpers.writeJson;
+import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
 import static org.assertj.core.api.Assertions.assertThat;
 
 @SuppressWarnings("DoubleBraceInitialization")
@@ -293,91 +287,6 @@ class JsonTemplateLayoutTest {
     }
 
     @Test
-    void test_MapMessage_serialization() {
-
-        // Create the event template.
-        final String eventTemplate = writeJson(asMap(
-                "message", asMap("$resolver", "message")));
-
-        // Create the layout.
-        final JsonTemplateLayout layout = JsonTemplateLayout
-                .newBuilder()
-                .setConfiguration(CONFIGURATION)
-                .setEventTemplate(eventTemplate)
-                .build();
-
-        // Create the log event with a MapMessage.
-        final StringMapMessage mapMessage = new StringMapMessage()
-                .with("key1", "val1")
-                .with("key2", 0xDEADBEEF)
-                .with("key3", Collections.singletonMap("key3.1", "val3.1"));
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(mapMessage)
-                .setTimeMillis(System.currentTimeMillis())
-                .build();
-
-        // Check the serialized event.
-        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
-            assertThat(accessor.getString(new String[]{"message", "key1"})).isEqualTo("val1");
-            assertThat(accessor.getInteger(new String[]{"message", "key2"})).isEqualTo(0xDEADBEEF);
-            assertThat(accessor.getString(new String[]{"message", "key3", "key3.1"})).isEqualTo("val3.1");
-        });
-
-    }
-
-    @Test
-    void test_message_fallbackKey() {
-
-        // Create the event template.
-        final String eventTemplate = writeJson(asMap(
-                "message", asMap(
-                        "$resolver", "message",
-                        "fallbackKey", "formattedMessage")));
-
-        // Create the layout.
-        final JsonTemplateLayout layout = JsonTemplateLayout
-                .newBuilder()
-                .setConfiguration(CONFIGURATION)
-                .setEventTemplate(eventTemplate)
-                .build();
-
-        // Create a log event with a MapMessage.
-        final Message mapMessage = new StringMapMessage()
-                .with("key1", "val1");
-        final LogEvent mapMessageLogEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(mapMessage)
-                .setTimeMillis(System.currentTimeMillis())
-                .build();
-
-        // Check the serialized MapMessage.
-        usingSerializedLogEventAccessor(layout, mapMessageLogEvent, accessor ->
-                assertThat(accessor.getString(new String[]{"message", "key1"}))
-                        .isEqualTo("val1"));
-
-        // Create a log event with a SimpleMessage.
-        final Message simpleMessage = new SimpleMessage("simple");
-        final LogEvent simpleMessageLogEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(simpleMessage)
-                .setTimeMillis(System.currentTimeMillis())
-                .build();
-
-        // Check the serialized MapMessage.
-        usingSerializedLogEventAccessor(layout, simpleMessageLogEvent, accessor ->
-                assertThat(accessor.getString(new String[]{"message", "formattedMessage"}))
-                        .isEqualTo("simple"));
-
-    }
-
-    @Test
     void test_property_injection() {
 
         // Create the log event.
@@ -666,78 +575,6 @@ class JsonTemplateLayoutTest {
     }
 
     @Test
-    void test_StringMapMessage() {
-
-        // Create the log event.
-        final StringMapMessage message = new StringMapMessage();
-        message.put("message", "Hello, World!");
-        message.put("bottle", "Kickapoo Joy Juice");
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(message)
-                .build();
-
-        // Create the event template.
-        final String eventTemplate = writeJson(asMap(
-                "message", asMap("$resolver", "message")));
-
-        // Create the layout.
-        final JsonTemplateLayout layout = JsonTemplateLayout
-                .newBuilder()
-                .setConfiguration(CONFIGURATION)
-                .setStackTraceEnabled(true)
-                .setEventTemplate(eventTemplate)
-                .build();
-
-        // Check the serialized event.
-        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
-            assertThat(accessor.getString(new String[]{"message", "message"})).isEqualTo("Hello, World!");
-            assertThat(accessor.getString(new String[]{"message", "bottle"})).isEqualTo("Kickapoo Joy Juice");
-        });
-
-    }
-
-    @Test
-    void test_ObjectMessage() {
-
-        // Create the log event.
-        final int id = 0xDEADBEEF;
-        final String name = "name-" + id;
-        final Object attachment = new LinkedHashMap<String, Object>() {{
-            put("id", id);
-            put("name", name);
-        }};
-        final ObjectMessage message = new ObjectMessage(attachment);
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(message)
-                .build();
-
-        // Create the event template.
-        final String eventTemplate = writeJson(asMap(
-                "message", asMap("$resolver", "message")));
-
-        // Create the layout.
-        JsonTemplateLayout layout = JsonTemplateLayout
-                .newBuilder()
-                .setConfiguration(CONFIGURATION)
-                .setStackTraceEnabled(true)
-                .setEventTemplate(eventTemplate)
-                .build();
-
-        // Check the serialized event.
-        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
-            assertThat(accessor.getInteger(new String[]{"message", "id"})).isEqualTo(id);
-            assertThat(accessor.getString(new String[]{"message", "name"})).isEqualTo(name);
-        });
-
-    }
-
-    @Test
     void test_StackTraceElement_template() {
 
         // Create the stack trace element template.
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.java
index 5dccd47..595ee91 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/MessageResolverTest.java
@@ -16,19 +16,30 @@
  */
 package org.apache.logging.log4j.layout.template.json.resolver;
 
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.junit.LoggerContextSource;
 import org.apache.logging.log4j.junit.Named;
+import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
 import org.apache.logging.log4j.layout.template.json.util.JsonReader;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.ObjectMessage;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.message.StringMapMessage;
 import org.apache.logging.log4j.test.appender.ListAppender;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
 class MessageResolverTest {
 
     /**
@@ -74,4 +85,151 @@ class MessageResolverTest {
 
     }
 
+    @Test
+    void test_message_fallbackKey() {
+
+        // Create the event template.
+        final String eventTemplate = writeJson(asMap(
+                "message", asMap(
+                        "$resolver", "message",
+                        "fallbackKey", "formattedMessage")));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Create a log event with a MapMessage.
+        final Message mapMessage = new StringMapMessage()
+                .with("key1", "val1");
+        final LogEvent mapMessageLogEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(mapMessage)
+                .setTimeMillis(System.currentTimeMillis())
+                .build();
+
+        // Check the serialized MapMessage.
+        usingSerializedLogEventAccessor(layout, mapMessageLogEvent, accessor ->
+                assertThat(accessor.getString(new String[]{"message", "key1"}))
+                        .isEqualTo("val1"));
+
+        // Create a log event with a SimpleMessage.
+        final Message simpleMessage = new SimpleMessage("simple");
+        final LogEvent simpleMessageLogEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(simpleMessage)
+                .setTimeMillis(System.currentTimeMillis())
+                .build();
+
+        // Check the serialized MapMessage.
+        usingSerializedLogEventAccessor(layout, simpleMessageLogEvent, accessor ->
+                assertThat(accessor.getString(new String[]{"message", "formattedMessage"}))
+                        .isEqualTo("simple"));
+
+    }
+
+    @Test
+    void test_StringMapMessage() {
+
+        // Create the log event.
+        final StringMapMessage message = new StringMapMessage();
+        message.put("message", "Hello, World!");
+        message.put("bottle", "Kickapoo Joy Juice");
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(message)
+                .build();
+
+        // Create the event template.
+        final String eventTemplate = writeJson(asMap(
+                "message", asMap("$resolver", "message")));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setStackTraceEnabled(true)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+            assertThat(accessor.getString(new String[]{"message", "message"})).isEqualTo("Hello, World!");
+            assertThat(accessor.getString(new String[]{"message", "bottle"})).isEqualTo("Kickapoo Joy Juice");
+        });
+
+    }
+
+    @Test
+    void test_ObjectMessage() {
+
+        // Create the log event.
+        final int id = 0xDEADBEEF;
+        final String name = "name-" + id;
+        final Object attachment = new LinkedHashMap<String, Object>() {{
+            put("id", id);
+            put("name", name);
+        }};
+        final ObjectMessage message = new ObjectMessage(attachment);
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(message)
+                .build();
+
+        // Create the event template.
+        final String eventTemplate = writeJson(asMap(
+                "message", asMap("$resolver", "message")));
+
+        // Create the layout.
+        JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setStackTraceEnabled(true)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+            assertThat(accessor.getInteger(new String[]{"message", "id"})).isEqualTo(id);
+            assertThat(accessor.getString(new String[]{"message", "name"})).isEqualTo(name);
+        });
+
+    }
+
+    @Test
+    void test_MapMessage_serialization() {
+
+        // Create the event template.
+        final String eventTemplate = writeJson(asMap(
+                "message", asMap("$resolver", "message")));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Create the log event with a MapMessage.
+        final StringMapMessage mapMessage = new StringMapMessage()
+                .with("key1", "val1")
+                .with("key2", 0xDEADBEEF)
+                .with("key3", Collections.singletonMap("key3.1", "val3.1"));
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(mapMessage)
+                .setTimeMillis(System.currentTimeMillis())
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+            assertThat(accessor.getString(new String[]{"message", "key1"})).isEqualTo("val1");
+            assertThat(accessor.getInteger(new String[]{"message", "key2"})).isEqualTo(0xDEADBEEF);
+            assertThat(accessor.getString(new String[]{"message", "key3", "key3.1"})).isEqualTo("val3.1");
+        });
+
+    }
+
 }

[logging-log4j2] 02/04: Consolidate ReadOnlyStringMapResolver tests.

Posted by vy...@apache.org.
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

commit 2e391b6d35f904f900b77de0005a7e64330864ca
Author: Volkan Yazici <vo...@gmail.com>
AuthorDate: Wed Jul 7 10:52:28 2021 +0200

    Consolidate ReadOnlyStringMapResolver tests.
---
 .../template/json/JsonTemplateLayoutTest.java      | 341 --------------------
 .../resolver/ReadOnlyStringMapResolverTest.java    | 348 ++++++++++++++++++++-
 2 files changed, 347 insertions(+), 342 deletions(-)

diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
index a0c4321..fa0d275 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayoutTest.java
@@ -329,47 +329,6 @@ class JsonTemplateLayoutTest {
     }
 
     @Test
-    void test_MapMessage_keyed_access() {
-
-        // Create the event template.
-        final String key = "list";
-        final String eventTemplate = writeJson(asMap(
-                "typedValue", asMap(
-                        "$resolver", "map",
-                        "key", key),
-                "stringifiedValue", asMap(
-                        "$resolver", "map",
-                        "key", key,
-                        "stringified", true)));
-
-        // Create the layout.
-        final JsonTemplateLayout layout = JsonTemplateLayout
-                .newBuilder()
-                .setConfiguration(CONFIGURATION)
-                .setEventTemplate(eventTemplate)
-                .build();
-
-        // Create the log event with a MapMessage.
-        final List<Integer> value = Arrays.asList(1, 2);
-        final StringMapMessage mapMessage = new StringMapMessage()
-                .with(key, value);
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(mapMessage)
-                .setTimeMillis(System.currentTimeMillis())
-                .build();
-
-        // Check the serialized event.
-        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
-            assertThat(accessor.getObject("typedValue")).isEqualTo(value);
-            assertThat(accessor.getString("stringifiedValue")).isEqualTo(String.valueOf(value));
-        });
-
-    }
-
-    @Test
     void test_message_fallbackKey() {
 
         // Create the event template.
@@ -707,306 +666,6 @@ class JsonTemplateLayoutTest {
     }
 
     @Test
-    void test_mdc_key_access() {
-
-        // Create the log event.
-        final SimpleMessage message = new SimpleMessage("Hello, World!");
-        final StringMap contextData = new SortedArrayStringMap();
-        final String mdcDirectlyAccessedKey = "mdcKey1";
-        final String mdcDirectlyAccessedValue = "mdcValue1";
-        contextData.putValue(mdcDirectlyAccessedKey, mdcDirectlyAccessedValue);
-        final String mdcDirectlyAccessedNullPropertyKey = "mdcKey2";
-        contextData.putValue(mdcDirectlyAccessedNullPropertyKey, null);
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(message)
-                .setContextData(contextData)
-                .build();
-
-        // Check the serialized event.
-        testReadOnlyStringMapKeyAccess(
-                mdcDirectlyAccessedKey,
-                mdcDirectlyAccessedValue,
-                mdcDirectlyAccessedNullPropertyKey,
-                logEvent,
-                "mdc");
-
-    }
-
-    @Test
-    public void test_map_key_access() {
-
-        // Create the log event.
-        final String directlyAccessedKey = "mapKey1";
-        final String directlyAccessedValue = "mapValue1";
-        final String directlyAccessedNullPropertyKey = "mapKey2";
-        final Message message = new StringMapMessage()
-                .with(directlyAccessedKey, directlyAccessedValue);
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(message)
-                .build();
-
-        // Check the serialized event.
-        testReadOnlyStringMapKeyAccess(
-                directlyAccessedKey,
-                directlyAccessedValue,
-                directlyAccessedNullPropertyKey,
-                logEvent,
-                "map");
-
-    }
-
-    private static void testReadOnlyStringMapKeyAccess(
-            final String directlyAccessedKey,
-            final String directlyAccessedValue,
-            final String directlyAccessedNullPropertyKey,
-            final LogEvent logEvent,
-            final String resolverName) {
-
-        // Create the event template.
-        String eventTemplate = writeJson(asMap(
-                directlyAccessedKey, asMap(
-                        "$resolver", resolverName,
-                        "key", directlyAccessedKey),
-                directlyAccessedNullPropertyKey, asMap(
-                        "$resolver", resolverName,
-                        "key", directlyAccessedNullPropertyKey)));
-
-        // Create the layout.
-        final JsonTemplateLayout layout = JsonTemplateLayout
-                .newBuilder()
-                .setConfiguration(CONFIGURATION)
-                .setStackTraceEnabled(true)
-                .setEventTemplate(eventTemplate)
-                .build();
-
-        // Check the serialized event.
-        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
-            assertThat(accessor.getString(directlyAccessedKey)).isEqualTo(directlyAccessedValue);
-            assertThat(accessor.getString(directlyAccessedNullPropertyKey)).isNull();
-        });
-
-    }
-
-    @Test
-    void test_mdc_pattern() {
-
-        // Create the log event.
-        final SimpleMessage message = new SimpleMessage("Hello, World!");
-        final StringMap contextData = new SortedArrayStringMap();
-        final String mdcPatternMatchedKey = "mdcKey1";
-        final String mdcPatternMatchedValue = "mdcValue1";
-        contextData.putValue(mdcPatternMatchedKey, mdcPatternMatchedValue);
-        final String mdcPatternMismatchedKey = "mdcKey2";
-        final String mdcPatternMismatchedValue = "mdcValue2";
-        contextData.putValue(mdcPatternMismatchedKey, mdcPatternMismatchedValue);
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(message)
-                .setContextData(contextData)
-                .build();
-
-        // Check the serialized event.
-        testReadOnlyStringMapPattern(
-                mdcPatternMatchedKey,
-                mdcPatternMatchedValue,
-                mdcPatternMismatchedKey,
-                logEvent,
-                "mdc");
-
-    }
-
-    @Test
-    public void test_map_pattern() {
-
-        // Create the log event.
-        final String patternMatchedKey = "mapKey1";
-        final String patternMatchedValue = "mapValue1";
-        final String patternMismatchedKey = "mapKey2";
-        final String patternMismatchedValue = "mapValue2";
-        final Message message = new StringMapMessage()
-                .with(patternMatchedKey, patternMatchedValue)
-                .with(patternMismatchedKey, patternMismatchedValue);
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(message)
-                .build();
-
-        // Check the serialized event.
-        testReadOnlyStringMapPattern(
-                patternMatchedKey,
-                patternMatchedValue,
-                patternMismatchedKey,
-                logEvent,
-                "map");
-
-    }
-
-    private static void testReadOnlyStringMapPattern(
-            final String patternMatchedKey,
-            final String patternMatchedValue,
-            final String patternMismatchedKey,
-            final LogEvent logEvent,
-            final String resolverName) {
-
-        // Create the event template.
-        final String mapFieldName = "map";
-        final String eventTemplate = writeJson(asMap(
-                mapFieldName, asMap(
-                        "$resolver", resolverName,
-                        "pattern", patternMatchedKey)));
-
-        // Create the layout.
-        final JsonTemplateLayout layout = JsonTemplateLayout
-                .newBuilder()
-                .setConfiguration(CONFIGURATION)
-                .setStackTraceEnabled(true)
-                .setEventTemplate(eventTemplate)
-                .build();
-
-        // Check the serialized event.
-        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
-            assertThat(accessor.getString(new String[]{mapFieldName, patternMatchedKey})).isEqualTo(patternMatchedValue);
-            assertThat(accessor.exists(new String[]{mapFieldName, patternMismatchedKey})).isFalse();
-        });
-
-    }
-
-    @Test
-    void test_mdc_flatten() {
-
-        // Create the log event.
-        final SimpleMessage message = new SimpleMessage("Hello, World!");
-        final StringMap contextData = new SortedArrayStringMap();
-        final String mdcPatternMatchedKey = "mdcKey1";
-        final String mdcPatternMatchedValue = "mdcValue1";
-        contextData.putValue(mdcPatternMatchedKey, mdcPatternMatchedValue);
-        final String mdcPatternMismatchedKey = "mdcKey2";
-        final String mdcPatternMismatchedValue = "mdcValue2";
-        contextData.putValue(mdcPatternMismatchedKey, mdcPatternMismatchedValue);
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(message)
-                .setContextData(contextData)
-                .build();
-
-        // Check the serialized event.
-        testReadOnlyStringMapFlatten(
-                mdcPatternMatchedKey,
-                mdcPatternMatchedValue,
-                mdcPatternMismatchedKey,
-                logEvent,
-                "mdc");
-
-    }
-
-    @Test
-    public void test_map_flatten() {
-
-        // Create the log event.
-        final String patternMatchedKey = "mapKey1";
-        final String patternMatchedValue = "mapValue1";
-        final String patternMismatchedKey = "mapKey2";
-        final String patternMismatchedValue = "mapValue2";
-        final Message message = new StringMapMessage()
-                .with(patternMatchedKey, patternMatchedValue)
-                .with(patternMismatchedKey, patternMismatchedValue);
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(message)
-                .build();
-
-        // Check the serialized event.
-        testReadOnlyStringMapFlatten(
-                patternMatchedKey,
-                patternMatchedValue,
-                patternMismatchedKey,
-                logEvent,
-                "map");
-
-    }
-
-    private static void testReadOnlyStringMapFlatten(
-            final String patternMatchedKey,
-            final String patternMatchedValue,
-            final String patternMismatchedKey,
-            final LogEvent logEvent,
-            final String resolverName) {
-
-        // Create the event template.
-        final String prefix = "_map.";
-        final String eventTemplate = writeJson(asMap(
-                "ignoredFieldName", asMap(
-                        "$resolver", resolverName,
-                        "pattern", patternMatchedKey,
-                        "flatten", asMap("prefix", prefix))));
-
-        // Create the layout.
-        final JsonTemplateLayout layout = JsonTemplateLayout
-                .newBuilder()
-                .setConfiguration(CONFIGURATION)
-                .setStackTraceEnabled(true)
-                .setEventTemplate(eventTemplate)
-                .build();
-
-        // Check the serialized event.
-        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
-            assertThat(accessor.getString(prefix + patternMatchedKey)).isEqualTo(patternMatchedValue);
-            assertThat(accessor.exists(prefix + patternMismatchedKey)).isFalse();
-        });
-
-    }
-
-    @Test
-    void test_MapResolver() {
-
-        // Create the log event.
-        final StringMapMessage message = new StringMapMessage().with("key1", "val1");
-        final LogEvent logEvent = Log4jLogEvent
-                .newBuilder()
-                .setLoggerName(LOGGER_NAME)
-                .setLevel(Level.INFO)
-                .setMessage(message)
-                .build();
-
-        // Create the event template node with map values.
-        final String eventTemplate = writeJson(asMap(
-                "mapValue1", asMap(
-                        "$resolver", "map",
-                        "key", "key1"),
-                "mapValue2", asMap(
-                        "$resolver", "map",
-                        "key", "key?")));
-
-        // Create the layout.
-        final JsonTemplateLayout layout = JsonTemplateLayout
-                .newBuilder()
-                .setConfiguration(CONFIGURATION)
-                .setEventTemplate(eventTemplate)
-                .build();
-
-        // Check serialized event.
-        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
-            assertThat(accessor.getString("mapValue1")).isEqualTo("val1");
-            assertThat(accessor.getString("mapValue2")).isNull();
-        });
-
-    }
-
-    @Test
     void test_StringMapMessage() {
 
         // Create the log event.
diff --git a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolverTest.java b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolverTest.java
index baaedef..921e153 100644
--- a/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolverTest.java
+++ b/log4j-layout-template-json/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/ReadOnlyStringMapResolverTest.java
@@ -1,13 +1,34 @@
+/*
+ * 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.layout.template.json.resolver;
 
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.layout.template.json.JsonTemplateLayout;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.message.StringMapMessage;
 import org.apache.logging.log4j.util.SortedArrayStringMap;
 import org.apache.logging.log4j.util.StringMap;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.regex.PatternSyntaxException;
 
 import static org.apache.logging.log4j.layout.template.json.TestHelpers.*;
@@ -57,7 +78,7 @@ class ReadOnlyStringMapResolverTest {
                 "replacement cannot be provided without a pattern");
     }
 
-    private void verifyConfigFailure(
+    private static void verifyConfigFailure(
             final String eventTemplate,
             final Class<? extends Throwable> failureClass,
             final String failureMessage) {
@@ -104,4 +125,329 @@ class ReadOnlyStringMapResolverTest {
 
     }
 
+    @Test
+    void test_mdc_key_access() {
+
+        // Create the log event.
+        final SimpleMessage message = new SimpleMessage("Hello, World!");
+        final StringMap contextData = new SortedArrayStringMap();
+        final String mdcDirectlyAccessedKey = "mdcKey1";
+        final String mdcDirectlyAccessedValue = "mdcValue1";
+        contextData.putValue(mdcDirectlyAccessedKey, mdcDirectlyAccessedValue);
+        final String mdcDirectlyAccessedNullPropertyKey = "mdcKey2";
+        contextData.putValue(mdcDirectlyAccessedNullPropertyKey, null);
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(message)
+                .setContextData(contextData)
+                .build();
+
+        // Check the serialized event.
+        testReadOnlyStringMapKeyAccess(
+                mdcDirectlyAccessedKey,
+                mdcDirectlyAccessedValue,
+                mdcDirectlyAccessedNullPropertyKey,
+                logEvent,
+                "mdc");
+
+    }
+
+    @Test
+    public void test_map_key_access() {
+
+        // Create the log event.
+        final String directlyAccessedKey = "mapKey1";
+        final String directlyAccessedValue = "mapValue1";
+        final String directlyAccessedNullPropertyKey = "mapKey2";
+        final Message message = new StringMapMessage()
+                .with(directlyAccessedKey, directlyAccessedValue);
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(message)
+                .build();
+
+        // Check the serialized event.
+        testReadOnlyStringMapKeyAccess(
+                directlyAccessedKey,
+                directlyAccessedValue,
+                directlyAccessedNullPropertyKey,
+                logEvent,
+                "map");
+
+    }
+
+    private static void testReadOnlyStringMapKeyAccess(
+            final String directlyAccessedKey,
+            final String directlyAccessedValue,
+            final String directlyAccessedNullPropertyKey,
+            final LogEvent logEvent,
+            final String resolverName) {
+
+        // Create the event template.
+        String eventTemplate = writeJson(asMap(
+                directlyAccessedKey, asMap(
+                        "$resolver", resolverName,
+                        "key", directlyAccessedKey),
+                directlyAccessedNullPropertyKey, asMap(
+                        "$resolver", resolverName,
+                        "key", directlyAccessedNullPropertyKey)));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setStackTraceEnabled(true)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+            assertThat(accessor.getString(directlyAccessedKey)).isEqualTo(directlyAccessedValue);
+            assertThat(accessor.getString(directlyAccessedNullPropertyKey)).isNull();
+        });
+
+    }
+
+    @Test
+    void test_mdc_pattern() {
+
+        // Create the log event.
+        final SimpleMessage message = new SimpleMessage("Hello, World!");
+        final StringMap contextData = new SortedArrayStringMap();
+        final String mdcPatternMatchedKey = "mdcKey1";
+        final String mdcPatternMatchedValue = "mdcValue1";
+        contextData.putValue(mdcPatternMatchedKey, mdcPatternMatchedValue);
+        final String mdcPatternMismatchedKey = "mdcKey2";
+        final String mdcPatternMismatchedValue = "mdcValue2";
+        contextData.putValue(mdcPatternMismatchedKey, mdcPatternMismatchedValue);
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(message)
+                .setContextData(contextData)
+                .build();
+
+        // Check the serialized event.
+        testReadOnlyStringMapPattern(
+                mdcPatternMatchedKey,
+                mdcPatternMatchedValue,
+                mdcPatternMismatchedKey,
+                logEvent,
+                "mdc");
+
+    }
+
+    @Test
+    public void test_map_pattern() {
+
+        // Create the log event.
+        final String patternMatchedKey = "mapKey1";
+        final String patternMatchedValue = "mapValue1";
+        final String patternMismatchedKey = "mapKey2";
+        final String patternMismatchedValue = "mapValue2";
+        final Message message = new StringMapMessage()
+                .with(patternMatchedKey, patternMatchedValue)
+                .with(patternMismatchedKey, patternMismatchedValue);
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(message)
+                .build();
+
+        // Check the serialized event.
+        testReadOnlyStringMapPattern(
+                patternMatchedKey,
+                patternMatchedValue,
+                patternMismatchedKey,
+                logEvent,
+                "map");
+
+    }
+
+    private static void testReadOnlyStringMapPattern(
+            final String patternMatchedKey,
+            final String patternMatchedValue,
+            final String patternMismatchedKey,
+            final LogEvent logEvent,
+            final String resolverName) {
+
+        // Create the event template.
+        final String mapFieldName = "map";
+        final String eventTemplate = writeJson(asMap(
+                mapFieldName, asMap(
+                        "$resolver", resolverName,
+                        "pattern", patternMatchedKey)));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setStackTraceEnabled(true)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+            assertThat(accessor.getString(new String[]{mapFieldName, patternMatchedKey})).isEqualTo(patternMatchedValue);
+            assertThat(accessor.exists(new String[]{mapFieldName, patternMismatchedKey})).isFalse();
+        });
+
+    }
+
+    @Test
+    void test_mdc_flatten() {
+
+        // Create the log event.
+        final SimpleMessage message = new SimpleMessage("Hello, World!");
+        final StringMap contextData = new SortedArrayStringMap();
+        final String mdcPatternMatchedKey = "mdcKey1";
+        final String mdcPatternMatchedValue = "mdcValue1";
+        contextData.putValue(mdcPatternMatchedKey, mdcPatternMatchedValue);
+        final String mdcPatternMismatchedKey = "mdcKey2";
+        final String mdcPatternMismatchedValue = "mdcValue2";
+        contextData.putValue(mdcPatternMismatchedKey, mdcPatternMismatchedValue);
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(message)
+                .setContextData(contextData)
+                .build();
+
+        // Check the serialized event.
+        testReadOnlyStringMapFlatten(
+                mdcPatternMatchedKey,
+                mdcPatternMatchedValue,
+                mdcPatternMismatchedKey,
+                logEvent,
+                "mdc");
+
+    }
+
+    @Test
+    public void test_map_flatten() {
+
+        // Create the log event.
+        final String patternMatchedKey = "mapKey1";
+        final String patternMatchedValue = "mapValue1";
+        final String patternMismatchedKey = "mapKey2";
+        final String patternMismatchedValue = "mapValue2";
+        final Message message = new StringMapMessage()
+                .with(patternMatchedKey, patternMatchedValue)
+                .with(patternMismatchedKey, patternMismatchedValue);
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(message)
+                .build();
+
+        // Check the serialized event.
+        testReadOnlyStringMapFlatten(
+                patternMatchedKey,
+                patternMatchedValue,
+                patternMismatchedKey,
+                logEvent,
+                "map");
+
+    }
+
+    private static void testReadOnlyStringMapFlatten(
+            final String patternMatchedKey,
+            final String patternMatchedValue,
+            final String patternMismatchedKey,
+            final LogEvent logEvent,
+            final String resolverName) {
+
+        // Create the event template.
+        final String prefix = "_map.";
+        final String eventTemplate = writeJson(asMap(
+                "ignoredFieldName", asMap(
+                        "$resolver", resolverName,
+                        "pattern", patternMatchedKey,
+                        "flatten", asMap("prefix", prefix))));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setStackTraceEnabled(true)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+            assertThat(accessor.getString(prefix + patternMatchedKey)).isEqualTo(patternMatchedValue);
+            assertThat(accessor.exists(prefix + patternMismatchedKey)).isFalse();
+        });
+
+    }
+
+    @Test
+    void test_MapResolver() {
+
+        // Create the log event.
+        final StringMapMessage message = new StringMapMessage().with("key1", "val1");
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(message)
+                .build();
+
+        // Create the event template node with map values.
+        final String eventTemplate = writeJson(asMap(
+                "mapValue1", asMap(
+                        "$resolver", "map",
+                        "key", "key1"),
+                "mapValue2", asMap(
+                        "$resolver", "map",
+                        "key", "key?")));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Check serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+            assertThat(accessor.getString("mapValue1")).isEqualTo("val1");
+            assertThat(accessor.getString("mapValue2")).isNull();
+        });
+
+    }
+
+    @Test
+    void test_MapMessage_keyed_access() {
+
+        // Create the event template.
+        final String key = "list";
+        final String eventTemplate = writeJson(asMap(
+                "typedValue", asMap(
+                        "$resolver", "map",
+                        "key", key),
+                "stringifiedValue", asMap(
+                        "$resolver", "map",
+                        "key", key,
+                        "stringified", true)));
+
+        // Create the layout.
+        final JsonTemplateLayout layout = JsonTemplateLayout
+                .newBuilder()
+                .setConfiguration(CONFIGURATION)
+                .setEventTemplate(eventTemplate)
+                .build();
+
+        // Create the log event with a MapMessage.
+        final List<Integer> value = Arrays.asList(1, 2);
+        final StringMapMessage mapMessage = new StringMapMessage()
+                .with(key, value);
+        final LogEvent logEvent = Log4jLogEvent
+                .newBuilder()
+                .setMessage(mapMessage)
+                .setTimeMillis(System.currentTimeMillis())
+                .build();
+
+        // Check the serialized event.
+        usingSerializedLogEventAccessor(layout, logEvent, accessor -> {
+            assertThat(accessor.getObject("typedValue")).isEqualTo(value);
+            assertThat(accessor.getString("stringifiedValue")).isEqualTo(String.valueOf(value));
+        });
+
+    }
+
 }