简体   繁体   English

在无状态会话Bean之间传递对象

[英]Pass objects between stateless session beans

I have several stateless and singleton beans. 我有几个无状态和单例豆。

@Stateful
@Local(IMyService.class)
@LocalBean
public class MyService implements IMyService {

    private @EJB Singleton1 singleton1;
    private @EJB Singleton2 singleton2;

    public void doSomeStuff() {
        // construct shared object
        singleton1.doOtherStuff();
        singleton2.doOtherStuff();
    }
}

@Singleton
@LocalBean
public class Singleton1 extends MySingleton {
    @Override
    public void doOtherStuff() {
        // use shared object
    }
}

@Singleton
@LocalBean
public class Singleton2 extends MySingleton {
    @Override
    public void doOtherStuff() {
        // use shared object
    }
}

public abstract class MySingleton {
    public abstract void doOtherStuff();
}

Now I want to have an object shared between all those beans without having to pass it as a parameter. 现在,我希望在所有这些bean之间共享一个对象,而不必将其作为参数传递。

I could have used stateful session beans, but injeting stateful beans in stateless beans will not work. 我本可以使用有状态会话Bean,但是在无状态Bean中注入有状态Bean无效。

I'm not passing it as a parameter because I don't want to keep passing that parameter into methods while it's only needed in few situations. 我没有将其作为参数传递,因为我不想一直将其传递给方法,尽管仅在少数情况下才需要使用它。

Is there a mean to inject an object in the client session so that I can read it wherever I am ? 是否有在客户端会话中注入对象的方法,以便无论我身在何处都可以读取它?

You can use ContextHolder pattern along with ThreadLocal and Interceptor. 您可以将ContextHolder模式与ThreadLocal和Interceptor一起使用。

ThreadLocal — This class allows for variables to be stored at the thread scope. ThreadLocal —此类允许将变量存储在线程作用域中。 I have no intention of getting into the pros and cons of using ThreadLocal. 我无意进入使用ThreadLocal的利弊。 I will simply say it is very powerful and must be used very carefully. 我只是说它非常强大,必须非常小心地使用。

EJB Interceptor — Used to intercept calls to business methods and lifecycle events of bean instances. EJB拦截器 —用于拦截对bean实例的业务方法和生命周期事件的调用。

Now let we want to have an user object shared between all those beans without having to pass it as a parameter. 现在让我们希望在所有这些bean之间共享一个用户对象,而不必将其作为参数传递。

So our AuditContextHolder would be: 因此,我们的AuditContextHolder将是:

public class AuditContextHolder {
    private static final ThreadLocal<String> AUDIT_CONTEXT = new ThreadLocal<>();

    private AuditContextHolder() {
    }

    public static void put(String  auditUser) {
        AUDIT_CONTEXT.set(auditUser);
    }

    public static String get() {
        return AUDIT_CONTEXT.get();
    }

    public static void cleanup() {
        AUDIT_CONTEXT.remove();
    }
} 

And the Audit Interceptor would be this: 审计拦截器将是这样的:

public class AuditInterceptor {

    @Resource
    private SessionContext sessionContext;

    @AroundInvoke
    public Object inject(InvocationContext ctx) throws Exception {
        String userName = sessionContext.getCallerPrincipal().toString();
        try {
            AuditContextHolder.put(userName);
            return ctx.proceed();
        } finally {
            // very important
            AuditContextHolder.cleanup();
        }
    }
}

Now you can use @Interceptors(AuditInterceptor.class) in your stateless session bean which is first in call chain. 现在,您可以在调用链中第一个无状态会话Bean中使用@Interceptors(AuditInterceptor.class) And everywhere inside the call chain you can get the audit user by calling AuditContextHolder.get() 在调用链中的任何地方,您都可以通过调用AuditContextHolder.get()获得审核用户。

References: 参考文献:

  1. http://www.adam-bien.com/roller/abien/entry/how_to_pass_context_with http://www.adam-bien.com/roller/abien/entry/how_to_pass_context_with
  2. https://www.captechconsulting.com/blogs/a-persistence-pattern-using-threadlocal-and-ejb-interceptors https://www.captechconsulting.com/blogs/a-persistence-pattern-using-threadlocal-and-ejb-interceptors

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM