2012-02-19 65 views
4

现在我的同事们开始使用日志子系统,他们希望绑定单独的操作,这是从一些业务方法启动的。例如,如果来自bean A的方法调用bean B中的某个方法,然后调用bean C,那么知道bean B中的业务方法并且bean C会为bean A中的方法执行一些工作人员将会非常棒。特别是,知道B和C的方法完成了豆A的具体调用的一些工作单元。EJB3关联ID

所以,问题是如何将这些工作单元合并成一个总的东西?显然,使用方法参数进行绑定并不美丽!

而且我认为现在是时候提出另一个问题了,这个问题已经足够接近前一个问题了。如果我想从bean A传播一些上下文信息到另一个bean,那么从A中调用?像安全凭证和安全主体?我能做什么? 可能是我问的问题是某种不好的做法?

回答

3

看起来像是一个很好的用例,可用于LogbackLog4J。实际上,您将一些自定义值附加到线程,并且来自该线程的所有日志消息都可以将该值附加到消息中。

我认为最好的方式来实现这在EJB将是一个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"); 
     } 
    } 
} 

现在你所要做的就是增加:

%X{user} 

到你的日志模式(logback.xmllog4j.xml )。

+0

谢谢!我明天会看这个。 – gkuzmin 2012-02-19 21:52:16

+0

只要您使用本地EJB,就应该这样做。一旦开始使用远程EJB,所有基于ThreadLocal的方法都将失败。 – Bogdan 2012-02-23 20:20:41

+0

您可能是指'%X {cid}'而不是'%X {user}'。 – alesch 2017-11-10 14:14:22

0

请参见您可以使用通用上下文信息。它可能是这个样子:

@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); 
     ... 
    } 
} 

我相信它通常使用ThreadLocal变量通常每个事务映射到应用程序服务器线程事务所实施。因此,如果TransactionSynchronizationRegistry没有在您的AS中实现(例如在JBoss 4.2.3中)或者您需要较低级别的工具,则可以直接使用ThreadLocal变量。

顺便说一句,我猜MDC公用事业公司在封面下使用相同的东西。