简体   繁体   English

每次都使用新的 InitialContext JNDI 查找 EJB?

[英]JNDI lookup of EJB with new InitialContext each time?

We use EJB3 and JBOSS application Server in our Application.我们在我们的应用程序中使用EJB3JBOSS应用程序服务器。 I have a Bean lookup utility method where its a generic method written to lookup stateless EJB Beans by JNDI name:我有一个 Bean 查找实用程序方法,它是一个通用方法,用于通过 JNDI 名称查找无状态 EJB Bean:

public class BeanFactory {

    static  Logger logger = LogManager.getLogger(BeanFactory.class.getName());
    /**
     * 
     * @param jndiName
     * @return
     */
    public static <T> T lookup(String jndiName){

        logger.info("Inside bean BeanFactory lookup: " + jndiName);
        
        T handle = null;

        try {
            InitialContext ctx = new InitialContext();
            handle = (T) ctx.lookup(jndiName);
        } catch (Exception e) {
            logger.error(e, e.fillInStackTrace());
        }
        return handle;
    }

So there are classes which have dependencies on Beans and they use lookup method to invoke the methods of the Bean.所以有些类依赖于 Bean,它们使用查找方法来调用 Bean 的方法。 For Example例如

 private AuthenticationProfileDTO getAuthenticationProfile(String credId) throws OneM2MException {
            
            ResourceProceduresDao dao = BeanFactory.lookup(ResourceProceduresDao.JNDI_NAME);
            
            AuthenticationProfileRemote apRemote = BeanFactory.lookup(AuthenticationProfileRemote.JNDI_NAME);
            
            AuthenticationProfileDTO authenticationProfileDTO;
    
            if (isKpsaId(credId))
                authenticationProfileDTO = apRemote.getAuthenticationProfileDTOForSymmKeyID(credId);
            else
                authenticationProfileDTO = apRemote.getAuthenticationProfileDTOForCredentialID(credId);
            return authenticationProfileDTO;
        }

So now when we ran JProfiler on the code the lookup method is coming to be time consuming because every time lookup is called a new InitialContext is instantiated.因此,现在当我们在代码上运行JProfiler时, lookup方法变得非常耗时,因为每次调用lookup时都会实例化一个新的InitialContext

I was thinking of making the InitialContext static so that only once it's initialized in a static block, but I don't know what implications will it have in terms of getting Bean instances.我正在考虑制作 InitialContext static 以便仅在 static 块中初始化它,但我不知道它对获取 Bean 实例有什么影响。 Since this piece of code is managed by EJB Container, the run time impacts are unknown.由于这段代码由 EJB Container 管理,运行时影响是未知的。 After looking up some articles online not much clarity was there.在网上查了一些文章后,不太清楚。

Any help is appreciated.任何帮助表示赞赏。

Note that javadoc for InitialContext warns that:请注意, InitialContext的 javadoc 警告说:

An InitialContext instance is not synchronized against concurrent
access by multiple threads. Multiple threads each manipulating a
different InitialContext instance need not synchronize.
Threads that need to access a single InitialContext instance
concurrently should synchronize amongst themselves and provide the
necessary locking.

So, making the field static isn't necessarily a good idea as you'll need to synchronize each lookup(jndiName) call, and this may cause other issues as per comment by James R. Perkins因此,创建字段 static 不一定是一个好主意,因为您需要同步每个lookup(jndiName)调用,这可能会根据James R. Perkins James R. Perkins . James R. Perkins

However as you have shown that getAuthenticationProfile(String credId) calls lookup twice, there is no reason why you can't make a BeanFactory hold one InitialContext to reduce the number of instances by re-using InitialContext within same calling methods.但是,正如您已经表明getAuthenticationProfile(String credId)调用了两次lookup ,没有理由不能让BeanFactory持有一个InitialContext以通过在相同的调用方法中重新使用InitialContext来减少实例的数量。

public class BeanFactory {

    private final InitialContext ctx;
    private BeanFactory(InitialContext initialContext) {
        this.ctx = initialContext;
    }
    private static final Logger logger = LogManager.getLogger(BeanFactory.class.getName());
    /** JNDI lookup*/
    public <T> T lookup(String jndiName){
        // logger.info("Inside bean BeanFactory lookup: " + jndiName);
        try {
            return (T) ctx.lookup(jndiName);
        } catch (Exception e) {
            RuntimeException re = new RuntimeException("Could not find jndi: "+jndiName, e);
            logger.error(re);
            throw re;
        }
    }
    /** Setup a new BeanFactory */
    public static BeanFactory create() {
       try {
            return new BeanFactory(new InitialContext());
        } catch (Exception e) {
            throw new RuntimeException("Could not create a new context", e);
            logger.error(re);
            throw re;
        }
    }

This allows getAuthenticationProfile to use a single InitialContext for 2 lookups:这允许getAuthenticationProfile使用单个InitialContext进行 2 次查找:

BeanFactory ctx = BeanFactory.create();
ResourceProceduresDao            dao = ctx.lookup(ResourceProceduresDao.JNDI_NAME);
AuthenticationProfileRemote apRemote = ctx.lookup(AuthenticationProfileRemote.JNDI_NAME);

You might also consider whether saving BeanFactory as a thread local would help though I would be very concerned about doing this an application server because you may have little control over which and how many threads instantiate InitialContext and what from what context they run.您可能还会考虑将BeanFactory保存为本地线程是否会有所帮助,尽管我非常担心在应用程序服务器上执行此操作,因为您可能几乎无法控制哪些线程以及多少线程实例化InitialContext以及它们从什么上下文运行。 However it might be suitable within a standalone client program accessing your EJB server logic:但是,它可能适用于访问 EJB 服务器逻辑的独立客户端程序:

private static final ThreadLocal<BeanFactory> BEANS = ThreadLocal.withInitial(BeanFactory::create);
private static BeanFactory local() {
    return BEANS.get();
}
// Example lookups:
ResourceProceduresDao            dao = BeanFactory.local().lookup(ResourceProceduresDao.JNDI_NAME);
AuthenticationProfileRemote apRemote = BeanFactory.local().lookup(AuthenticationProfileRemote.JNDI_NAME);

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

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