EJB3 correlation identifier

Now my colleagues are working on a registration subsystem, and they want to link the individual operations that were initiated using some business method. For example, if a method from bean A calls a method in bean B and then in bean C, it will be useful to know what business methods are in bean B and bean C, some employees for the method from bean A. It will be especially good to know that the methods from B and C did some unit of work for a particular call to bean A.

So, the question is how to relate these units of work to something in common? Obviously, it’s nice to use method arguments to bind!

And also I think that the time has come to ask another question, which is close enough to the previous one. What if I want to distribute some contextual information from bean A to other beans called from A? Something like a security credential and a security principal? What can I do? Maybe the questions I asked are some bad practice?

+4
source share
2 answers

Sounds like a good use , available in both Logback and Log4J . Essentially, you are attaching some kind of user-defined value to a stream, and all log messages sent from that stream can attach this value to the message.

I think the best way to implement this in EJB would 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 template ( logback.xml or log4j.xml ).

see also

+3
source

For general contextual information, you can use TransactionSynchronizationRegistry . It might 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 that it is usually implemented using ThreadLocal variables, since usually each transaction maps to a sigle thread on application servers. Therefore, if TransactionSynchronizationRegistry is not implemented in your AS (for example, in JBoss 4.2.3) or you need a lower-level tool, you can directly use ThreadLocal variables.

By the way. I believe that MDC utilities use the same thing under covers.

0
source

Source: https://habr.com/ru/post/1397326/


All Articles