use of com.sun.enterprise.transaction.api.JavaEETransaction in project Payara by payara.
the class EJBContainerTransactionManager method useClientTx.
/**
* Use caller transaction to execute a bean method
*/
protected void useClientTx(Transaction prevTx, EjbInvocation inv) {
Transaction clientTx;
int status = -1;
int prevStatus = -1;
try {
// Note: inv.clientTx will not be set at this point.
clientTx = transactionManager.getTransaction();
// clientTx cant be null
status = clientTx.getStatus();
if (prevTx != null) {
prevStatus = prevTx.getStatus();
}
} catch (Exception ex) {
try {
transactionManager.setRollbackOnly();
} catch (Exception e) {
// FIXME: Use LogStrings.properties
_logger.log(Level.FINEST, "", e);
}
throw new TransactionRolledbackLocalException("", ex);
}
// to invoke the EJB, so throw an exception back to client.
if (status == Status.STATUS_MARKED_ROLLBACK || status == Status.STATUS_ROLLEDBACK || status == Status.STATUS_ROLLING_BACK) {
throw new TransactionRolledbackLocalException("Client's transaction aborted");
}
container.validateEMForClientTx(inv, (JavaEETransaction) clientTx);
if (prevTx == null || prevStatus == Status.STATUS_NO_TRANSACTION) {
// First time the bean is running in this new client Tx
EJBContextImpl context = (EJBContextImpl) inv.context;
// Must change this for singleton
if (!container.isSingleton) {
context.setTransaction(clientTx);
}
try {
transactionManager.enlistComponentResources();
if (!container.isStatelessSession && !container.isMessageDriven && !container.isSingleton) {
// Register sync for methods other than finders/home methods
if (!inv.invocationInfo.isHomeFinder) {
ejbContainerUtilImpl.getContainerSync(clientTx).addBean(context);
}
container.afterBegin(context);
}
} catch (Exception ex) {
try {
transactionManager.setRollbackOnly();
} catch (Exception e) {
// FIXME: Use LogStrings.properties
_logger.log(Level.FINEST, "", e);
}
throw new TransactionRolledbackLocalException("", ex);
}
} else {
// Bean already has a transaction associated with it.
if (!prevTx.equals(clientTx)) {
// EntityBeans will get a different context for every Tx.
if (container.isSession) {
// Row 2 in Table E
throw new IllegalStateException("EJB is already associated with an incomplete transaction");
}
} else {
// with the transaction
try {
transactionManager.enlistComponentResources();
} catch (Exception ex) {
try {
transactionManager.setRollbackOnly();
} catch (Exception e) {
// FIXME: Use LogStrings.properties
_logger.log(Level.FINEST, "", e);
}
throw new TransactionRolledbackLocalException("", ex);
}
}
}
}
use of com.sun.enterprise.transaction.api.JavaEETransaction in project Payara by payara.
the class ActiveTxCache method addIncompleteTxEJB.
/**
* Called only from afterBegin.
* This EJB is invoked either with client's tx (in which case
* it would already be in table), or with new tx (in which case
* it would not be in table).
*/
private void addIncompleteTxEJB(EntityContextImpl context) {
JavaEETransaction current = (JavaEETransaction) context.getTransaction();
if (current == null) {
return;
}
if ((containerStateManager.isNullEJBObject(context)) && (containerStateManager.isNullEJBLocalObject(context))) {
return;
}
// Its ok to add this context without checking if its already there.
ActiveTxCache activeTxCache = (ActiveTxCache) ejbContainerUtilImpl.getActiveTxCache(current);
if (activeTxCache == null) {
activeTxCache = new ActiveTxCache(DEFAULT_TX_CACHE_BUCKETS);
ejbContainerUtilImpl.setActiveTxCache(current, activeTxCache);
}
activeTxCache.add(context);
Vector beans = ejbContainerUtilImpl.getBeans(current);
beans.add(context);
}
use of com.sun.enterprise.transaction.api.JavaEETransaction in project Payara by payara.
the class ActiveTxCache method getEJBWithIncompleteTx.
// getReadyEJB(inv)
// called from releaseContext, afterCompletion
/**
* Get an EJB instance for this EJBObject and current client Tx
* Called only from getContext.
* Return null if there no INCOMPLETE_TX bean for the pkey & tx.
*/
private EntityContextImpl getEJBWithIncompleteTx(EjbInvocation inv) {
// We need to make sure that two concurrent client
// invocations with same primary key and same client tx
// get the SAME EJB instance.
// So we need to maintain exactly one copy of an EJB's state
// per transaction.
JavaEETransaction current = null;
try {
current = (JavaEETransaction) transactionManager.getTransaction();
} catch (SystemException ex) {
throw new EJBException(ex);
}
EntityContextImpl ctx = null;
if (current != null) {
ActiveTxCache activeTxCache = (ActiveTxCache) ejbContainerUtilImpl.getActiveTxCache(current);
ctx = (activeTxCache == null) ? null : activeTxCache.get(this, getInvocationKey(inv));
inv.foundInTxCache = (ctx != null);
}
return ctx;
}
use of com.sun.enterprise.transaction.api.JavaEETransaction in project Payara by payara.
the class ConnectionPool method getResourceFromTransaction.
/**
* Try to get a resource from current transaction if it is shareable<br>
* @param tran Current Transaction
* @param alloc ResourceAllocator
* @param spec ResourceSpec
* @return result ResourceHandle
*/
private ResourceHandle getResourceFromTransaction(Transaction tran, ResourceAllocator alloc, ResourceSpec spec) {
ResourceHandle result = null;
try {
// shareable, so abort right here if that's not the case
if (tran != null && alloc.shareableWithinComponent()) {
// TODO should be handled by PoolTxHelper
JavaEETransaction j2eetran = (JavaEETransaction) tran;
// case 1. look for free and enlisted in same tx
Set set = j2eetran.getResources(poolInfo);
if (set != null) {
Iterator iter = set.iterator();
while (iter.hasNext()) {
ResourceHandle h = (ResourceHandle) iter.next();
if (h.hasConnectionErrorOccurred()) {
iter.remove();
continue;
}
ResourceState state = h.getResourceState();
/*
* One can share a resource only for the following conditions:
* 1. The caller resource is shareable (look at the outermost
* if marked comment-1
* 2. The resource enlisted inside the transaction is shareable
* 3. We are dealing with XA resources OR
* We are dealing with a non-XA resource that's not in use
* Note that sharing a non-xa resource that's in use involves
* associating physical connections.
* 4. The credentials of the resources match
*/
if (h.getResourceAllocator().shareableWithinComponent()) {
if (spec.isXA() || poolTxHelper.isNonXAResourceAndFree(j2eetran, h)) {
if (matchConnections) {
if (!alloc.matchConnection(h)) {
if (poolLifeCycleListener != null) {
poolLifeCycleListener.connectionNotMatched();
}
continue;
}
if (h.hasConnectionErrorOccurred()) {
if (failAllConnections) {
// if failAllConnections has happened, we flushed the
// pool, so we don't have to do iter.remove else we
// will get a ConncurrentModificationException
result = null;
break;
}
iter.remove();
continue;
}
if (poolLifeCycleListener != null) {
poolLifeCycleListener.connectionMatched();
}
}
if (state.isFree())
setResourceStateToBusy(h);
result = h;
break;
}
}
}
}
}
} catch (ClassCastException e) {
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "Pool: getResource : " + "transaction is not JavaEETransaction but a " + tran.getClass().getName(), e);
}
}
return result;
}
use of com.sun.enterprise.transaction.api.JavaEETransaction in project Payara by payara.
the class ConnectionPool method getResource.
/**
* returns resource from the pool.
*
* @return a free pooled resource object matching the ResourceSpec
* @throws PoolingException - if any error occurrs
* - or the pool has reached its max size and the
* max-connection-wait-time-in-millis has expired.
*/
public ResourceHandle getResource(ResourceSpec spec, ResourceAllocator alloc, Transaction txn) throws PoolingException, RetryableUnavailableException {
// Note: this method should not be synchronized or the
// startTime would be incorrect for threads waiting to enter
/*
* Here are all the comments for the method put together for
* easy reference.
* 1.
// - Try to get a free resource. Note: internalGetResource()
// will create a new resource if none is free and the max has
// not been reached.
// - If can't get one, get on the wait queue.
// - Repeat this until maxWaitTime expires.
// - If maxWaitTime == 0, repeat indefinitely.
2.
//the doFailAllConnectionsProcessing method would already
//have been invoked by now.
//We simply go ahead and create a new resource here
//from the allocator that we have and adjust the resources
//list accordingly so as to not exceed the maxPoolSize ever
//(i.e if steadyPoolSize == maxPoolSize )
///Also since we are creating the resource out of the allocator
//that we came into this method with, we need not worry about
//matching
*/
ResourceHandle result = null;
long startTime = System.currentTimeMillis();
long elapsedWaitTime;
long remainingWaitTime = 0;
while (true) {
if (gateway.allowed()) {
// See comment #1 above
JavaEETransaction jtx = ((JavaEETransaction) txn);
Set resourcesSet = null;
if (jtx != null) {
resourcesSet = jtx.getResources(poolInfo);
}
// already obtained in the current transaction.
if (!blocked || (resourcesSet != null && resourcesSet.size() > 0)) {
try {
result = internalGetResource(spec, alloc, txn);
} finally {
gateway.acquiredResource();
}
}
}
if (result != null) {
// got one, return it
if (poolLifeCycleListener != null) {
poolLifeCycleListener.connectionAcquired(result.getId());
elapsedWaitTime = System.currentTimeMillis() - startTime;
poolLifeCycleListener.connectionRequestServed(elapsedWaitTime);
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "Resource Pool: elapsed time " + "(ms) to get connection for [" + spec + "] : " + elapsedWaitTime);
}
}
// return it
break;
} else {
// did not get a resource.
if (maxWaitTime > 0) {
elapsedWaitTime = System.currentTimeMillis() - startTime;
if (elapsedWaitTime < maxWaitTime) {
// time has not expired, determine remaining wait time.
remainingWaitTime = maxWaitTime - elapsedWaitTime;
} else {
if (!blocked) {
// wait time has expired
if (poolLifeCycleListener != null) {
poolLifeCycleListener.connectionTimedOut();
}
String msg = localStrings.getStringWithDefault("poolmgr.no.available.resource", "No available resource. Wait-time expired.");
throw new PoolingException(msg);
}
}
}
if (!blocked) {
// add to wait-queue
Object waitMonitor = new Object();
if (poolLifeCycleListener != null) {
poolLifeCycleListener.connectionRequestQueued();
}
synchronized (waitMonitor) {
waitQueue.addToQueue(waitMonitor);
try {
logFine("Resource Pool: getting on wait queue");
waitMonitor.wait(remainingWaitTime);
} catch (InterruptedException ex) {
// Could be system shutdown.
break;
}
// so the overhead for removing inexistant objects is low.
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "removing wait monitor from queue: " + waitMonitor);
}
if (waitQueue.removeFromQueue(waitMonitor)) {
if (poolLifeCycleListener != null) {
poolLifeCycleListener.connectionRequestDequeued();
}
}
}
} else {
// add to reconfig-wait-queue
Object reconfigWaitMonitor = new Object();
synchronized (reconfigWaitMonitor) {
reconfigWaitQueue.addToQueue(reconfigWaitMonitor);
try {
if (reconfigWaitTime > 0) {
if (_logger.isLoggable(Level.FINEST)) {
_logger.finest("[DRC] getting into reconfig wait queue for time [" + reconfigWaitTime + "]");
}
reconfigWaitMonitor.wait(reconfigWaitTime);
}
} catch (InterruptedException ex) {
// Could be system shutdown.
break;
}
// so the overhead for removing inexistent objects is low.
if (_logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST, "[DRC] removing wait monitor from reconfig-wait-queue: " + reconfigWaitMonitor);
}
reconfigWaitQueue.removeFromQueue(reconfigWaitMonitor);
if (_logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST, "[DRC] throwing Retryable-Unavailable-Exception");
}
RetryableUnavailableException rue = new RetryableUnavailableException("Pool Reconfigured, " + "Connection Factory can retry the lookup");
rue.setErrorCode(BadConnectionEventListener.POOL_RECONFIGURED_ERROR_CODE);
throw rue;
}
}
}
}
alloc.fillInResourceObjects(result);
return result;
}
Aggregations