Steven,

Your question is quite intriguing.

One solution would be to use some sort of counting. Thus, each time you set a key in the MDC you would increment the count of that key in the MDC by one. Each time you would "remove" the key you would decrement the count by one but not really remove (i.e. call MDC.remove). You would really remove only if the count reached zero (assuming the count started at 0). I think this provides for quite a solid solution.

Let me give you an example:

-- File XMDC.java ------------------------------------------
import org.apache.log4j.MDC;

public class XMDC {

  static Object get(String key) {
    return  MDC.get(key);
  }

  static void put(String key, Object o) {
    Object value = MDC.get(key);

    if(value == null) {
      ContextCounter cc = new ContextCounter(value);
      cc.incCount();
      MDC.put(key, cc);
    } else if(o instanceof ContextCounter) {
      ContextCounter cc = (ContextCounter) value;
      cc.incCount();
      cc.setContext(o);
    } else {
      MDC.put(key, o);
    }
  }

  static void remove(String key) {
    Object o = MDC.get(key);

    if(o == null) {
      ; // nothing to do because there is nothing there
    } else if(o instanceof ContextCounter) {
      ContextCounter cc = (ContextCounter) o;
      cc.decCount();
      if(cc.isCountZero()) {
        MDC.remove(key);
      }
    } else {
      MDC.remove(key);
    }
  }
}

-- File  ContextCounter.java ---------------------------------
public class ContextCounter {
  int count = 0;
  Object context;

public ContextCounter(Object c) { context = c; }

  public void setContext(Object c) { context = c; }
  public Object getContext() { return context; }

  public boolean isCountZero() { return (count == 0); }
  public void incCount() { count++; }
  public void decCount() { count--; }
}

In your code you would use XMDC which would automatically track the reference count of the keys and values you entered into the MDC. Assuming each XMDC.put operation is matched by the corresponding XMDC.remove operation, you are guaranteed that "inner" put operations update the value of the key while inner remove operation are inoffensive, only the outer or topmost XMDC.remove will remove the key and its value from the MDC.

Think about it and let us know if it fits your purposes.

At 08:13 AM 4/3/2003 -0600, Ebersole, Steven wrote:
There is certain information which is thread contextual which I would like
to include into log4j's MDC to be available for logging.  One of these, for
example, is the currently executing user.  My architecture is such that all
requests come through a layer of stateless session EJBs.  Now these EJBs can
make calls into other session EJBs in order to fulfill their use-case:

public class SessionBeanA
...
{
    ...
    public void executeUseCase()
    {
        ... // Do some work
        SessionBeanB sessionBeanB = ...; // Lookup SessionBeanB
        sessionBeanB.executeSomeRelatedUseCase();
        ... // Do some more work
    }
}

public class SessionBeanB
...
{
    ...
    public void executeRelatedUseCase()
    {
        ... // Do something
    }
}

The typical usage of MDC seems to be:
1) put vars into MDC
2) do your work
3) clean up MDC

But if I apply this usage to the scenario above, when
SessionBeanB.executeRelatedUseCase() cleans up the MDC, the information
would no longer be contained in the MDC for LoggingEvents generated within
the "Do some more work" section of SessionBeanA.executeUseCase().

I run weblogic 6.1, which unfortunately does not have support for "call
interceptors" to know when a user context has been bound to a thread.
Otherwise, I could simply setup MDC when a "session" is begun and clean up
the MDC when the session ends.  The only way around this I have been able to
think of is to just always call MDC.put( "USER",
mySessionContext.getCallerPrincipal().getName() ) at the beginning of each
and every session bean method.  But I would not ever be able to clean up the
MDC because of this nesting described above.

Is this OK? Or this there a better way to do this?



Steve Ebersole
IT Integration Engineer
Vignette Corporation
Office: 512.741.4195
Mobile: 512.297.5438

Visit http://www.vignette.com

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

--
Ceki



--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to