return get(key, true);
}
public StatefulBeanContext get(final Object key, boolean markInUse) throws EJBException
{
StatefulBeanContext entry = null;
synchronized (cacheMap)
{
entry = cacheMap.get(key);
}
if(entry == null)
{
// TODO: optimize
synchronized (cacheMap)
{
entry = cacheMap.get(key);
if(entry == null)
{
Iterator<StatefulBeanContext> i = passivationQueue.iterator();
while(i.hasNext())
{
StatefulBeanContext ctx = i.next();
if(ctx.getId().equals(key))
{
boolean passivationCanceled = passivationQueue.remove(ctx);
if(passivationCanceled)
{
entry = ctx;
cacheMap.put(key, entry);
}
break;
}
}
}
}
}
if (entry == null)
{
// JBPAPP-7523: create a task for activation while holding the pm lock,
// then execute said task outside the lock
FutureTask<StatefulBeanContext> activation;
final boolean executeActivation;
synchronized(pm)
{
activation = activations.get(key);
if (activation == null)
{
activation = new FutureTask<StatefulBeanContext>(new Callable<StatefulBeanContext>()
{
@Override
public StatefulBeanContext call() throws Exception {
StatefulBeanContext entry;
// has someone already activated it?
synchronized (cacheMap)
{
entry = cacheMap.get(key);
}
if(entry == null)
{
entry = pm.activateSession(key);
if (entry == null)
{
throw new NoSuchEJBException("Could not find stateful bean: " + key);
}
--passivatedCount;
// We cache the entry even if we will throw an exception below
// as we may still need it for its children and XPC references
if (log.isTraceEnabled())
{
log.trace("Caching activated context " + entry.getId() + " of type " + entry.getClass());
}
synchronized (cacheMap)
{
cacheMap.put(key, entry);
// remove the activation, worst case a new task will be constructed and
// the check whether someone has already activated it will prevent actual activation.
activations.remove(key);
}
}
return entry;
}
});
activations.put(key, activation);
executeActivation = true;
}
else
executeActivation = false;
}
if (executeActivation)
activation.run();
try {
entry = activation.get();
}
catch (InterruptedException e)
{
throw new EJBException(e);
}
catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
throw (RuntimeException) e.getCause();
throw (EJBException) new EJBException().initCause(e.getCause());
}
}
// Now we know entry isn't null
if (markInUse)
{
if (entry.isRemoved())
{
throw new NoSuchEJBException("Could not find stateful bean: " + key +
" (bean was marked as removed");
}
entry.setInUse(true);
entry.lastUsed = System.currentTimeMillis();
}
return entry;
}