Currently I am use following code to lookup EJB3 sateless session beans for normal POJO class. (We are in JEE5 so we can not inject Stateless Session Beans in normal POJO class I have to use look up)
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;
}
So is Context object is ThredSafe? should I create Context object for each call [as shown in this code snippet] or I can reuse the Context for all threads?
Answers with regard to threadsafety are usually already mentioned in javadoc, whenever relevant. And indeed, the InitialContext
javadoc mentions the following:
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.
The last sentence confirms it: it's not threadsafe and per-thread synchronization is necessary. In your particular code example, however, no synchronization is necessary as it's been created in method local scope anyway (i.e. it's definitely not shared among threads). If the InitialContext
was in your particular code example been an instance variable, then you'd have to add the synchronized
keyword to the getEJB()
method.
But if I put this method inside a singleton class then can I use Context as a class variable?like in this below code method is inside a singleton ServiceLocator
class.
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;
}
}