Question

Now my colleagues work on logging subsystem and they want to bind separate operations, that was initiated from some business method. For example, if method from bean A calls to some method in bean B and then in bean C it will be great to know than business methods in bean B and bean C does some staff for method from bean A. Especially it will be great to know that methods from B and C done some unit of work for concrete call of bean A.

So, the question is how to tie this units of work into something total? Obviously, it is not beautiful to use method arguments for binding!

And also I think that it is time to ask another question, that is close enough to previous one. What if I want to propagate some context information from bean A to another beans, that are called from A? Something like security credentials and security principal? What can I do? May be questions that I asked is some kind of bad practice?

Was it helpful?

Solution

Looks like a good use case for , available in both Logback and Log4J. Essentially you are attaching some custom value to a thread and all logging messages comming from that thread can attach that value to the message.

I think the best way to implement this in EJB will be an interceptor:

public class MdcInterceptor {

    @AroundInvoke
    public Object addMdcValue(InvocationContext context) throws Exception {
        MDC.put("cid", RandomStringUtils.randomAlphanumeric(16));
        try {
            return context.proceed();
        } finaly {
            MDC.remove("cid");
        }
    }
}

Now all you have to do is add:

%X{user}

to your logging pattern (logback.xml or log4j.xml).

See also

OTHER TIPS

For general purpose context information you can use TransactionSynchronizationRegistry. It could look something like this:

@Stateless
public class MyBean {

    @Resource
    TransactionSynchronizationRegistry registry;

    @AroundInvoke
    public Object setEntryName(InvocationContext ic) throws Exception {
        registry.putResource(NAME, "MyBean");
        return ic.proceed();
    }
}

@Stateless
public class MyBean2 {

    @Resource
    TransactionSynchronizationRegistry registry;

    public void doJob() {
        String entryName = (String)registry.getResource(NAME);
        ...
    }
}

I believe it is usually implemented using ThreadLocal variables as normally each transaction maps to a sigle thread in application servers. So if TransactionSynchronizationRegistry is not implemented in your AS (like e.g. in JBoss 4.2.3) or you need lower level tool, you could use ThreadLocal variables directly.

BTW I guess that MDC utilities use the same thing under the covers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top