You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2024/04/16 04:48:40 UTC

(logging-log4j2) branch 2.x updated: Refactor ResourceLogger

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

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


The following commit(s) were added to refs/heads/2.x by this push:
     new 27aa8d57cf Refactor ResourceLogger
27aa8d57cf is described below

commit 27aa8d57cf8739fba46632a2217254bd6117b2c3
Author: Ralph Goers <rg...@apache.org>
AuthorDate: Mon Apr 15 21:48:17 2024 -0700

    Refactor ResourceLogger
---
 ...ggerTest.java => ScopedResourceLoggerTest.java} |   6 +-
 ...sourceLogger.java => ScopedResourceLogger.java} | 100 ++++++--------------
 .../AbstractResourceLogger.java}                   | 104 ++++++++++-----------
 ...ggerTest.java => ScopedResourceLoggerTest.java} |  12 +--
 ...t.java => QueuedScopedContextProviderTest.java} |   2 +-
 .../modules/ROOT/pages/manual/resource-logger.adoc |  55 ++++++++++-
 6 files changed, 142 insertions(+), 137 deletions(-)

diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/ResourceLoggerTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/ScopedResourceLoggerTest.java
similarity index 96%
rename from log4j-api-test/src/test/java/org/apache/logging/log4j/ResourceLoggerTest.java
rename to log4j-api-test/src/test/java/org/apache/logging/log4j/ScopedResourceLoggerTest.java
index 4822a52e12..0d9a2c353a 100644
--- a/log4j-api-test/src/test/java/org/apache/logging/log4j/ResourceLoggerTest.java
+++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/ScopedResourceLoggerTest.java
@@ -34,7 +34,7 @@ import org.junit.jupiter.api.Test;
 /**
  * Class Description goes here.
  */
-public class ResourceLoggerTest {
+public class ScopedResourceLoggerTest {
     @BeforeAll
     public static void beforeAll() {
         System.setProperty("log4j2.loggerContextFactory", TestLoggerContextFactory.class.getName());
@@ -50,7 +50,7 @@ public class ResourceLoggerTest {
         Connection connection = new Connection("Test", "dummy");
         connection.useConnection();
         MapSupplier mapSupplier = new MapSupplier(connection);
-        Logger logger = ResourceLogger.newBuilder()
+        Logger logger = ScopedResourceLogger.newBuilder()
                 .withClass(this.getClass())
                 .withSupplier(mapSupplier)
                 .build();
@@ -73,7 +73,7 @@ public class ResourceLoggerTest {
         connection = new Connection("NewConnection", "fiber");
         connection.useConnection();
         mapSupplier = new MapSupplier(connection);
-        logger = ResourceLogger.newBuilder().withSupplier(mapSupplier).build();
+        logger = ScopedResourceLogger.newBuilder().withSupplier(mapSupplier).build();
         logger.debug("Connection: {}", "NewConnection");
         assertThat(events, hasSize(1));
         assertThat(events.get(0), containsString("Name=NewConnection"));
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/ResourceLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/ScopedResourceLogger.java
similarity index 51%
copy from log4j-api/src/main/java/org/apache/logging/log4j/ResourceLogger.java
copy to log4j-api/src/main/java/org/apache/logging/log4j/ScopedResourceLogger.java
index 7a30dab94d..e2974413dc 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/ResourceLogger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/ScopedResourceLogger.java
@@ -21,9 +21,8 @@ import java.util.Map;
 import java.util.function.Supplier;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.MessageFactory;
+import org.apache.logging.log4j.spi.AbstractResourceLogger;
 import org.apache.logging.log4j.spi.ExtendedLogger;
-import org.apache.logging.log4j.spi.ExtendedLoggerWrapper;
-import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.StackLocatorUtil;
 import org.apache.logging.log4j.util.Strings;
 
@@ -36,28 +35,39 @@ import org.apache.logging.log4j.util.Strings;
  * Unlike regular Loggers ResourceLoggers CANNOT be declared to be static. A ResourceLogger
  * must be declared as a class member that will be garbage collected along with the instance of the resource.
  */
-public final class ResourceLogger extends ExtendedLoggerWrapper {
+public final class ScopedResourceLogger extends AbstractResourceLogger {
     private static final long serialVersionUID = -5837924138744974513L;
-    private final Supplier<Map<String, ?>> supplier;
+    private final ScopedContext.Instance scopedInstance;
 
-    public static ResourceLoggerBuilder newBuilder() {
-        return new ResourceLoggerBuilder();
+    public static ScopedResourceLoggerBuilder newBuilder() {
+        return new ScopedResourceLoggerBuilder();
     }
 
     /*
      * Pass our MessageFactory with its Supplier to AbstractLogger. This will be used to create
      * the Messages prior to them being passed to the "real" Logger.
      */
-    private ResourceLogger(
+    private ScopedResourceLogger(
             final ExtendedLogger logger, final Supplier<Map<String, ?>> supplier, MessageFactory messageFactory) {
-        super(logger, logger.getName(), messageFactory);
-        this.supplier = supplier;
+        super(logger, supplier, messageFactory);
+        scopedInstance = null;
+    }
+
+    /*
+     * Pass our MessageFactory with its Map to AbstractLogger. This will be used to create
+     * the Messages prior to them being passed to the "real" Logger.
+     */
+    private ScopedResourceLogger(final ExtendedLogger logger, final Map<String, ?> map, MessageFactory messageFactory) {
+        super(logger, map, messageFactory);
+        scopedInstance = ScopedContext.where(map);
     }
 
     @Override
     public void logMessage(String fqcn, Level level, Marker marker, Message message, Throwable t) {
         if (supplier != null) {
             ScopedContext.runWhere(supplier.get(), () -> logger.logMessage(fqcn, level, marker, message, t));
+        } else if (scopedInstance != null) {
+            scopedInstance.run(() -> logger.logMessage(fqcn, level, marker, message, t));
         } else {
             logger.logMessage(fqcn, level, marker, message, t);
         }
@@ -66,70 +76,13 @@ public final class ResourceLogger extends ExtendedLoggerWrapper {
     /**
      * Constructs a ResourceLogger.
      */
-    public static final class ResourceLoggerBuilder {
-        private static final Logger LOGGER = StatusLogger.getLogger();
-        private ExtendedLogger logger;
-        private String name;
-        private Supplier<Map<String, ?>> supplier;
-        private MessageFactory messageFactory;
+    public static final class ScopedResourceLoggerBuilder extends ResourceLoggerBuilder<ScopedResourceLoggerBuilder> {
 
         /**
          * Create the builder.
          */
-        private ResourceLoggerBuilder() {}
-
-        /**
-         * Add the underlying Logger to use. If a Logger, logger name, or class is not required
-         * the name of the calling class wiill be used.
-         * @param logger The Logger to use.
-         * @return The ResourceLoggerBuilder.
-         */
-        public ResourceLoggerBuilder withLogger(ExtendedLogger logger) {
-            this.logger = logger;
-            return this;
-        }
-
-        /**
-         * Add the Logger name. If a Logger, logger name, or class is not required
-         * the name of the calling class wiill be used.
-         * @param name the name to assign to the Logger.
-         * @return The ResourceLoggerBuilder.
-         */
-        public ResourceLoggerBuilder withName(String name) {
-            this.name = name;
-            return this;
-        }
-
-        /**
-         * The resource Class. If a Logger, logger name, or class is not required
-         * the name of the calling class wiill be used.
-         * @param clazz the resource Class.
-         * @return the ResourceLoggerBuilder.
-         */
-        public ResourceLoggerBuilder withClass(Class<?> clazz) {
-            this.name = clazz.getCanonicalName() != null ? clazz.getCanonicalName() : clazz.getName();
-            return this;
-        }
-
-        /**
-         * The Map Supplier.
-         * @param supplier the method that provides the Map of resource data to include in logs.
-         * @return the ResourceLoggerBuilder.
-         */
-        public ResourceLoggerBuilder withSupplier(Supplier<Map<String, ?>> supplier) {
-            this.supplier = supplier;
-            return this;
-        }
-
-        /**
-         * Adds a MessageFactory.
-         * @param messageFactory the MessageFactory to use to build messages. If a MessageFactory
-         * is not specified the default MessageFactory will be used.
-         * @return the ResourceLoggerBuilder.
-         */
-        public ResourceLoggerBuilder withMessageFactory(MessageFactory messageFactory) {
-            this.messageFactory = messageFactory;
-            return this;
+        private ScopedResourceLoggerBuilder() {
+            super();
         }
 
         /**
@@ -144,8 +97,13 @@ public final class ResourceLogger extends ExtendedLoggerWrapper {
                 }
                 this.logger = (ExtendedLogger) LogManager.getLogger(name);
             }
-            Supplier<Map<String, ?>> mapSupplier = this.supplier != null ? this.supplier : Collections::emptyMap;
-            return new ResourceLogger(logger, mapSupplier, messageFactory);
+            if (supplyOnce) {
+                Map<String, ?> map = this.supplier != null ? supplier.get() : Collections.emptyMap();
+                return new ScopedResourceLogger(logger, map, messageFactory);
+            } else {
+                Supplier<Map<String, ?>> mapSupplier = this.supplier != null ? this.supplier : Collections::emptyMap;
+                return new ScopedResourceLogger(logger, mapSupplier, messageFactory);
+            }
         }
     }
 }
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/ResourceLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractResourceLogger.java
similarity index 56%
rename from log4j-api/src/main/java/org/apache/logging/log4j/ResourceLogger.java
rename to log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractResourceLogger.java
index 7a30dab94d..f1e0a2e0b8 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/ResourceLogger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractResourceLogger.java
@@ -14,69 +14,64 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.logging.log4j;
+package org.apache.logging.log4j.spi;
 
-import java.util.Collections;
 import java.util.Map;
 import java.util.function.Supplier;
-import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.message.MessageFactory;
-import org.apache.logging.log4j.spi.ExtendedLogger;
-import org.apache.logging.log4j.spi.ExtendedLoggerWrapper;
 import org.apache.logging.log4j.status.StatusLogger;
-import org.apache.logging.log4j.util.StackLocatorUtil;
-import org.apache.logging.log4j.util.Strings;
 
 /**
  * Logger for resources. The Supplier provides resource attributes that should be included in all log events generated
- * from the current resource. Note that since the Supplier is called for every LogEvent being generated
- * the values returned may change as necessary. Care should be taken to make the Supplier as efficient as
- * possible to avoid performance issues.
+ * from the current resource. The Supplier may be called when the Logger is created or for every log event.
+ * Therefore, care should be taken to make the Supplier as efficient as possible to avoid performance issues.
  *
  * Unlike regular Loggers ResourceLoggers CANNOT be declared to be static. A ResourceLogger
  * must be declared as a class member that will be garbage collected along with the instance of the resource.
  */
-public final class ResourceLogger extends ExtendedLoggerWrapper {
-    private static final long serialVersionUID = -5837924138744974513L;
-    private final Supplier<Map<String, ?>> supplier;
-
-    public static ResourceLoggerBuilder newBuilder() {
-        return new ResourceLoggerBuilder();
-    }
+public abstract class AbstractResourceLogger extends ExtendedLoggerWrapper {
+    private static final long serialVersionUID = -2657891242014543083L;
+    protected final Supplier<Map<String, ?>> supplier;
+    protected final Map<String, ?> contextMap;
 
     /*
      * Pass our MessageFactory with its Supplier to AbstractLogger. This will be used to create
      * the Messages prior to them being passed to the "real" Logger.
      */
-    private ResourceLogger(
+    protected AbstractResourceLogger(
             final ExtendedLogger logger, final Supplier<Map<String, ?>> supplier, MessageFactory messageFactory) {
         super(logger, logger.getName(), messageFactory);
         this.supplier = supplier;
+        this.contextMap = null;
     }
 
-    @Override
-    public void logMessage(String fqcn, Level level, Marker marker, Message message, Throwable t) {
-        if (supplier != null) {
-            ScopedContext.runWhere(supplier.get(), () -> logger.logMessage(fqcn, level, marker, message, t));
-        } else {
-            logger.logMessage(fqcn, level, marker, message, t);
-        }
+    /*
+     * Pass our MessageFactory with the Map created by the Supplier to AbstractLogger. This will be used to create
+     * the Messages prior to them being passed to the "real" Logger.
+     */
+    protected AbstractResourceLogger(
+            final ExtendedLogger logger, final Map<String, ?> map, MessageFactory messageFactory) {
+        super(logger, logger.getName(), messageFactory);
+        this.supplier = null;
+        this.contextMap = map;
     }
 
     /**
      * Constructs a ResourceLogger.
      */
-    public static final class ResourceLoggerBuilder {
-        private static final Logger LOGGER = StatusLogger.getLogger();
-        private ExtendedLogger logger;
-        private String name;
-        private Supplier<Map<String, ?>> supplier;
-        private MessageFactory messageFactory;
+    protected abstract static class ResourceLoggerBuilder<B extends ResourceLoggerBuilder<B>> {
+        protected static final Logger LOGGER = StatusLogger.getLogger();
+        protected ExtendedLogger logger;
+        protected String name;
+        protected Supplier<Map<String, ?>> supplier;
+        protected MessageFactory messageFactory;
+        protected boolean supplyOnce;
 
         /**
          * Create the builder.
          */
-        private ResourceLoggerBuilder() {}
+        protected ResourceLoggerBuilder() {}
 
         /**
          * Add the underlying Logger to use. If a Logger, logger name, or class is not required
@@ -84,9 +79,9 @@ public final class ResourceLogger extends ExtendedLoggerWrapper {
          * @param logger The Logger to use.
          * @return The ResourceLoggerBuilder.
          */
-        public ResourceLoggerBuilder withLogger(ExtendedLogger logger) {
+        public B withLogger(ExtendedLogger logger) {
             this.logger = logger;
-            return this;
+            return asBuilder();
         }
 
         /**
@@ -95,9 +90,9 @@ public final class ResourceLogger extends ExtendedLoggerWrapper {
          * @param name the name to assign to the Logger.
          * @return The ResourceLoggerBuilder.
          */
-        public ResourceLoggerBuilder withName(String name) {
+        public B withName(String name) {
             this.name = name;
-            return this;
+            return asBuilder();
         }
 
         /**
@@ -106,9 +101,9 @@ public final class ResourceLogger extends ExtendedLoggerWrapper {
          * @param clazz the resource Class.
          * @return the ResourceLoggerBuilder.
          */
-        public ResourceLoggerBuilder withClass(Class<?> clazz) {
+        public B withClass(Class<?> clazz) {
             this.name = clazz.getCanonicalName() != null ? clazz.getCanonicalName() : clazz.getName();
-            return this;
+            return asBuilder();
         }
 
         /**
@@ -116,9 +111,9 @@ public final class ResourceLogger extends ExtendedLoggerWrapper {
          * @param supplier the method that provides the Map of resource data to include in logs.
          * @return the ResourceLoggerBuilder.
          */
-        public ResourceLoggerBuilder withSupplier(Supplier<Map<String, ?>> supplier) {
+        public B withSupplier(Supplier<Map<String, ?>> supplier) {
             this.supplier = supplier;
-            return this;
+            return asBuilder();
         }
 
         /**
@@ -127,25 +122,30 @@ public final class ResourceLogger extends ExtendedLoggerWrapper {
          * is not specified the default MessageFactory will be used.
          * @return the ResourceLoggerBuilder.
          */
-        public ResourceLoggerBuilder withMessageFactory(MessageFactory messageFactory) {
+        public B withMessageFactory(MessageFactory messageFactory) {
             this.messageFactory = messageFactory;
-            return this;
+            return asBuilder();
+        }
+
+        /**
+         * Instruct the ResourceLogger to invoke the Supplier only once during Logger creation, if the
+         * implementation supports it.
+         * @return the ResourceLoggerBuilder.
+         */
+        public B supplyOnce() {
+            this.supplyOnce = true;
+            return asBuilder();
         }
 
         /**
          * Construct the ResourceLogger.
          * @return the ResourceLogger.
          */
-        public Logger build() {
-            if (this.logger == null) {
-                if (Strings.isEmpty(name)) {
-                    Class<?> clazz = StackLocatorUtil.getCallerClass(2);
-                    name = clazz.getCanonicalName() != null ? clazz.getCanonicalName() : clazz.getName();
-                }
-                this.logger = (ExtendedLogger) LogManager.getLogger(name);
-            }
-            Supplier<Map<String, ?>> mapSupplier = this.supplier != null ? this.supplier : Collections::emptyMap;
-            return new ResourceLogger(logger, mapSupplier, messageFactory);
+        public abstract Logger build();
+
+        @SuppressWarnings("unchecked")
+        public B asBuilder() {
+            return (B) this;
         }
     }
 }
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/ResourceLoggerTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/ScopedResourceLoggerTest.java
similarity index 93%
rename from log4j-core-test/src/test/java/org/apache/logging/log4j/ResourceLoggerTest.java
rename to log4j-core-test/src/test/java/org/apache/logging/log4j/ScopedResourceLoggerTest.java
index 738abeec7b..18e0bd8cfc 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/ResourceLoggerTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/ScopedResourceLoggerTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.logging.log4j.message;
+package org.apache.logging.log4j;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.aMapWithSize;
@@ -28,8 +28,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Supplier;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.ResourceLogger;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.LoggerContext;
 import org.apache.logging.log4j.core.test.appender.ListAppender;
@@ -42,11 +40,11 @@ import org.junit.jupiter.api.Test;
  * Tests the ParameterizedMapMessageFactory class.
  */
 @LoggerContextSource("log4j-map.xml")
-public class ResourceLoggerTest {
+public class ScopedResourceLoggerTest {
 
     private final ListAppender app;
 
-    public ResourceLoggerTest(@Named("List") final ListAppender list) {
+    public ScopedResourceLoggerTest(@Named("List") final ListAppender list) {
         app = list.clear();
     }
 
@@ -55,7 +53,7 @@ public class ResourceLoggerTest {
         Connection connection = new Connection("Test", "dummy");
         connection.useConnection();
         MapSupplier mapSupplier = new MapSupplier(connection);
-        Logger logger = ResourceLogger.newBuilder()
+        Logger logger = ScopedResourceLogger.newBuilder()
                 .withClass(this.getClass())
                 .withSupplier(mapSupplier)
                 .build();
@@ -86,7 +84,7 @@ public class ResourceLoggerTest {
         connection = new Connection("NewConnection", "fiber");
         connection.useConnection();
         mapSupplier = new MapSupplier(connection);
-        logger = ResourceLogger.newBuilder().withSupplier(mapSupplier).build();
+        logger = ScopedResourceLogger.newBuilder().withSupplier(mapSupplier).build();
         logger.debug("Connection: {}", "NewConnection");
         events = app.getEvents();
         assertThat(events, hasSize(1));
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/internal/DefaultScopedContextProviderTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/internal/QueuedScopedContextProviderTest.java
similarity index 95%
rename from log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/internal/DefaultScopedContextProviderTest.java
rename to log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/internal/QueuedScopedContextProviderTest.java
index a5957fc084..9d7e93502a 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/internal/DefaultScopedContextProviderTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/internal/QueuedScopedContextProviderTest.java
@@ -19,7 +19,7 @@ package org.apache.logging.log4j.core.impl.internal;
 import org.apache.logging.log4j.test.spi.ScopedContextProviderSuite;
 import org.junit.jupiter.api.Test;
 
-class DefaultScopedContextProviderTest extends ScopedContextProviderSuite {
+class QueuedScopedContextProviderTest extends ScopedContextProviderSuite {
 
     private static QueuedScopedContextProvider createProvider() {
         return new QueuedScopedContextProvider();
diff --git a/src/site/antora/modules/ROOT/pages/manual/resource-logger.adoc b/src/site/antora/modules/ROOT/pages/manual/resource-logger.adoc
index 674de056aa..3951cd09dc 100644
--- a/src/site/antora/modules/ROOT/pages/manual/resource-logger.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/resource-logger.adoc
@@ -16,10 +16,13 @@
 ////
 
 = Resource Logging
-The link:../log4j-api/apidocs/org/apache/logging/log4j/ResourceLogger.html[`ResourceLogger`]
+
+== ScopedResourceLogger
+
+The link:../log4j-api/apidocs/org/apache/logging/log4j/ScopedResourceLogger.html[`ScopedResourceLogger`]
 is available in Log4j API releases 2.24.0 and greater.
 
-A `ResourceLogger` is a special kind of Logger that:
+A `ScopedResourceLogger` is a special kind of Logger that:
 
  * is a regular class member variable that will be garbage collected along with the class instance.
  * can provide a Map of key/value pairs of data associate with the resource (the class instance)
@@ -85,4 +88,50 @@ and a loginId of testUser and a role of Admin, after a successful login would re
 {LoginId=testUser, Role=Admin, Count=1} Login succeeded
 ----
 
-Every logging call is wrapped in a ScopedContext and populated by the supplier configured on the ResourceLogger, which is called when generating every log event. This allows values, such as counters, to be updated and the log event will contain the actual value at the time the event was logged.
+Every logging call is wrapped in a ScopedContext and populated by the supplier configured on the ScopedResourceLogger, which is called when generating every log event. This allows values, such as counters, to be updated and the log event will contain the actual value at the time the event was logged.
+The ScopedResourceLogger can also be configured to only call the Supplier once when the Logger is
+created instead of on every logging call by specifying the `supplyOnce` method on the builder as
+shown here
+
+[source,java]
+----
+
+     private class User {
+
+        private final String loginId;
+        private final String role;
+        private final ResourceLogger logger;
+
+        public User(final String loginId, final String role) {
+            this.loginId = loginId;
+            this.role = role;
+            logger = ResourceLogger.newBuilder()
+                .withClass(this.getClass())
+                .withSupplier(new UserSupplier())
+                .supplyOnce()
+                .build();
+        }
+
+        public void login() throws Exception {
+            try {
+                authenticator.authenticate(loginId);
+                logger.info("Login succeeded");
+            } catch (Exception ex) {
+                logger.warn("Failed login");
+                throw ex;
+            }
+        }
+
+
+        private class UserSupplier implements Supplier<Map<String, String>> {
+
+            public Map<String, String> get() {
+                Map<String, String> map = new HashMap<>();
+                map.put("LoginId", loginId);
+                map.put("Role", role);
+                return map;
+            }
+        }
+    }
+
+----