Details
-
New Feature
-
Status: Resolved
-
Major
-
Resolution: Later
-
None
-
None
-
None
-
None
Description
Add Add ThreadContext.setContext(Map<String, String>).
Note that we have ThreadContext.setStack(Collection<String>) to set the whole stack but nothing to set the whole map.
My immediate goal is to be able to build a JUnit Rule to save and restore the thread context around each unit test method and/or a given class.
I have (not committed yet):
/** * Restores the ThreadContext to it's initial map and stack values after a JUnit test. */ public class ThreadContextRule extends ExternalResource { private final boolean restoreMap; private final boolean restoreStack; private ThreadContextHolder threadContextHolder; /** * Constructs an instance initialized to restore the stack and map. */ public ThreadContextRule() { this(true, true); } /** * Constructs an instance initialized to restore the given structures. * * @param restoreMap * Whether to restore the thread context map. * @param restoreStack * Whether to restore the thread context stack. */ public ThreadContextRule(final boolean restoreMap, final boolean restoreStack) { super(); this.restoreMap = restoreMap; this.restoreStack = restoreStack; } @Override protected void after() { if (threadContextHolder != null) { threadContextHolder.restore(); } } @Override protected void before() throws Throwable { threadContextHolder = new ThreadContextHolder(restoreMap, restoreStack); if (restoreMap) { ThreadContext.clearMap(); } if (restoreStack) { ThreadContext.clearStack(); } } }
and (in src/test):
/** * Holds an immutable copy of the ThreadContext stack and map. * * TODO Use LOG4J2-1517 Add ThreadContext.setContext(Map<String, String>) * * or * * TODO Might be replaced by something from LOG4J2-1447. * * or do nothing. * * @since 2.7 */ public class ThreadContextHolder { private final Map<String, String> immutableContext; private final ContextStack immutableStack; private final boolean restoreContext; private final boolean restoreStack; /** * Constructs a new holder initialized with an immutable copy of the ThreadContext stack and map. * @param restoreContext * @param restoreStack */ public ThreadContextHolder(final boolean restoreContext, final boolean restoreStack) { this.restoreContext = restoreContext; this.restoreStack = restoreStack; this.immutableContext = restoreContext ? ThreadContext.getImmutableContext() : null; this.immutableStack = restoreStack ? ThreadContext.getImmutableStack() : null; } /** * Restores the ThreadContext stack and map based on the values saved in the constructor. */ public void restore() { if (restoreStack) { ThreadContext.setStack(immutableStack); } if (restoreContext) { ThreadContext.setContext(immutableContext); } } }
and in ThreadContext:
/** * Sets this thread's context. * * @param map The map to use. * @since 2.7 */ public static void setContext(final Map<String, String> map) { if (map.isEmpty() || !useMap) { return; } contextMap.clear(); contextMap.putAll(map); }
For convenience:
/** * Restores the ThreadContext to it's initial map values after a JUnit test. */ public class ThreadContextMapRule extends ThreadContextRule { /** * Constructs an initialized instance. */ public ThreadContextMapRule() { super(true, false); } } /** * Restores the ThreadContext to it's initial stack values after a JUnit test. */ public class ThreadContextStackRule extends ThreadContextRule { /** * Constructs an initialized instance. */ public ThreadContextStackRule() { super(false, true); } }
Attachments
Issue Links
- is related to
-
LOG4J2-1349 Garbage-free ThreadContext map
- Closed
-
LOG4J2-1447 Garbage-free data structure for LogEvent's context map data
- Closed
- relates to
-
LOG4J2-1516 Add ThreadContextMap.putAll(Map<String, String>)
- Resolved
-
LOG4J2-1519 Add ThreadContext.putAll(Map<String, String>)
- Closed