Является 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;
}
}