Является javax.naming.InitialContext ThreadSafe

В настоящее время я использую следующий код для поиска бездельной сессии EJB3 beans для обычного класса POJO. (Мы в JEE5, поэтому мы не можем вводить сессию без состояния beans в обычном классе POJO, я должен использовать поиск)

import javax.naming.Context;  
import javax.naming.InitialContext;  
import javax.naming.NamingException;  

import org.apache.log4j.Logger;  

public Object getEJB(String jndiName) {  

                logger.debug("WEBSPHERE EJB Lookup : " + jndiName);  
                String modifiedJndiName = "";  
                Hashtable<Object, Object> properties = new Hashtable<Object, Object>();  
                properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");  
                properties.put(Context.PROVIDER_URL, "iiop://localhost:2809");  
                try {  
                    Context context = new InitialContext(properties);  
                    logger.debug("WEBSPHERE EJB Lookup Modified JNDI Name: " + modifiedJndiName);  
                    return context.lookup("ejblocal:"+modifiedJndiName);  
                }catch (NamingException ne) {  
                    logger.debug("Naming Exception occurred :"+jndiName +">>>"+ne.getMessage());  
                    logger.error(ne.getMessage(), ne);  
                }  

                return null;  
            }  

Итак, объект Context - это ThredSafe? должен ли я создавать объект Контекста для каждого вызова [как показано в этом фрагменте кода] или я могу повторно использовать Контекст для всех потоков?

Ответ 1

Ответы в отношении безопасности потоков обычно упоминаются в javadoc, когда это необходимо. И действительно, InitialContext javadoc упоминает следующее:

Экземпляр InitialContext не синхронизируется с одновременным доступом несколькими потоками. Несколько потоков, которые обрабатывают другой экземпляр InitialContext, не должны синхронизироваться. Темы, которые должны иметь доступ к одному экземпляру InitialContext одновременно, должны синхронизировать между собой и обеспечивать необходимую блокировку.

Последнее предложение подтверждает это: это не потокобезопасная и ничейная синхронизация. Однако в вашем конкретном примере кода никакая синхронизация не требуется, поскольку она была создана в локальной области метода в любом случае (т.е. Она определенно не разделяется между потоками). Если InitialContext в вашем конкретном примере кода был переменной экземпляра, вам нужно добавить ключевое слово synchronized к методу getEJB().

Ответ 2

Но если я поместил этот метод в одноэлементный класс, могу ли я использовать Context как переменную класса, как в этом методе ниже кода, находится внутри одноэлементного класса ServiceLocator.

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class ServiceLocator {
    static volatile ServiceLocator serviceLocator = null;

    Map supportedAppServerMap = null;

    @Override
    public Object getEJB(String jndiName) {

        logger.debug("WEBSPHERE EJB Lookup : " + jndiName);
        String modifiedJndiName = "";
        Hashtable<Object, Object> properties = new Hashtable<Object, Object>();
        properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
        properties.put(Context.PROVIDER_URL, AMPPropertyUtil.getProperty("PROVIDER_URL"));
        try {
            Context context = new InitialContext(properties);
            if (null != jndiName && jndiName.indexOf(".") != -1)
                modifiedJndiName = jndiName.substring(jndiName.lastIndexOf(".") + 1);
            else
                modifiedJndiName = jndiName;
            logger.debug("WEBSPHERE EJB Lookup Modified JNDI Name: " + modifiedJndiName);
            return context.lookup("ejblocal:" + modifiedJndiName);
        } catch (NamingException ne) {
            logger.debug("Naming Exception occurred :" + jndiName + ">>>" + ne.getMessage());
            logger.error(ne.getMessage(), ne);
        }

        return null;
    }

    @Override
    public DataSource getDataSource() {
        Context context = null;
        final String dsName = AMPPropertyUtil.getProperty("dsName");
        Hashtable<Object, Object> properties = new Hashtable<Object, Object>();
        properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
        properties.put(Context.PROVIDER_URL, AMPPropertyUtil.getProperty("PROVIDER_URL"));
        try {

            context = new InitialContext();
            return (DataSource) context.lookup("java:comp/env/" + dsName);

        } catch (NamingException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    @Override
    public Object getResources(final String jndiName) {
        Context context = null;
        Hashtable<Object, Object> properties = new Hashtable<Object, Object>();
        properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
        properties.put(Context.PROVIDER_URL, AMPPropertyUtil.getProperty("PROVIDER_URL"));
        try {
            context = new InitialContext();
            return context.lookup(jndiName);

        } catch (NamingException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    public static ServiceLocator getInstance() {
        if (serviceLocator == null) {
            synchronized (ServiceLocator.class) {
                if (null == serviceLocator)
                    serviceLocator = new ServiceLocator();
            }
        }
        return serviceLocator;
    }

}