use of org.apache.openejb.ApplicationException in project tomee by apache.
the class ManagedContainer method removeEJBObject.
protected Object removeEJBObject(final BeanContext beanContext, final Object primKey, final Class callInterface, final Method callMethod, Object[] args, final InterfaceType interfaceType) throws OpenEJBException {
if (primKey == null) {
throw new NullPointerException("primKey is null");
}
final ThreadContext callContext = new ThreadContext(beanContext, primKey);
final ThreadContext oldCallContext = ThreadContext.enter(callContext);
try {
// Security check
final boolean internalRemove = BeanContext.Removable.class == callMethod.getDeclaringClass();
if (!internalRemove) {
checkAuthorization(callMethod, interfaceType);
}
// If a bean managed transaction is active, the bean can not be removed
if (interfaceType.isComponent()) {
final Instance instance = checkedOutInstances.get(primKey);
/**
* According to EJB 3.0 "4.4.4 Restrictions for Transactions" any remove methods
* from home or component interfaces must not be allowed if the bean instance is
* in a transaction. Unfortunately, the Java EE 5 TCK has tests that ignore the
* restrictions in 4.4.4 and expect beans in transactions can be removed via their
* home or component interface. The test to see if the bean instance implements
* javax.ejb.SessionBean is a workaround for passing the TCK while the tests in
* question can be challenged or the spec can be changed/updated.
*/
if (instance != null && instance.bean instanceof SessionBean) {
throw new ApplicationException(new RemoveException("A stateful EJB enrolled in a transaction can not be removed"));
}
}
// Start transaction
final TransactionPolicy txPolicy = EjbTransactionUtil.createTransactionPolicy(callContext.getBeanContext().getTransactionType(callMethod, interfaceType), callContext);
Object returnValue = null;
boolean retain = false;
Instance instance = null;
Method runMethod = null;
try {
// Obtain instance
instance = obtainInstance(primKey, callContext);
// Resume previous Bean transaction if there was one
if (txPolicy instanceof BeanTransactionPolicy) {
// Resume previous Bean transaction if there was one
final SuspendedTransaction suspendedTransaction = instance.getBeanTransaction();
if (suspendedTransaction != null) {
instance.setBeanTransaction(null);
final BeanTransactionPolicy beanTxEnv = (BeanTransactionPolicy) txPolicy;
beanTxEnv.resumeUserTransaction(suspendedTransaction);
}
}
if (!internalRemove) {
// Register the entity managers
registerEntityManagers(instance, callContext);
// Register for synchronization callbacks
registerSessionSynchronization(instance, callContext);
// Setup for remove invocation
callContext.setCurrentOperation(Operation.REMOVE);
callContext.setCurrentAllowedStates(null);
callContext.setInvokedInterface(callInterface);
runMethod = beanContext.getMatchingBeanMethod(callMethod);
callContext.set(Method.class, runMethod);
// Do not pass arguments on home.remove(remote) calls
final Class<?> declaringClass = callMethod.getDeclaringClass();
if (declaringClass.equals(EJBHome.class) || declaringClass.equals(EJBLocalHome.class)) {
args = new Object[] {};
}
// Initialize interceptor stack
final List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod);
final InterceptorStack interceptorStack = new InterceptorStack(instance.bean, runMethod, Operation.REMOVE, interceptors, instance.interceptors);
// Invoke
if (args == null) {
returnValue = interceptorStack.invoke();
} else {
returnValue = interceptorStack.invoke(args);
}
}
} catch (final InvalidateReferenceException e) {
throw new ApplicationException(e.getRootCause());
} catch (final Throwable e) {
if (interfaceType.isBusiness()) {
retain = beanContext.retainIfExeption(runMethod);
handleException(callContext, txPolicy, e);
} else {
try {
handleException(callContext, txPolicy, e);
} catch (final ApplicationException ae) {
// Don't throw application exceptions for non-business interface removes
}
}
} finally {
if (!retain) {
try {
callContext.setCurrentOperation(Operation.PRE_DESTROY);
final List<InterceptorData> callbackInterceptors = beanContext.getCallbackInterceptors();
final InterceptorStack interceptorStack = new InterceptorStack(instance.bean, null, Operation.PRE_DESTROY, callbackInterceptors, instance.interceptors);
interceptorStack.invoke();
} catch (final Throwable callbackException) {
final String logMessage = "An unexpected exception occured while invoking the preDestroy method on the removed Stateful SessionBean instance; " + callbackException.getClass().getName() + " " + callbackException.getMessage();
/* [1] Log the exception or error */
logger.error(logMessage);
} finally {
callContext.setCurrentOperation(Operation.REMOVE);
}
// todo destroy extended persistence contexts
discardInstance(callContext);
}
// Commit transaction
afterInvoke(callContext, txPolicy, instance);
}
return returnValue;
} finally {
ThreadContext.exit(oldCallContext);
}
}
use of org.apache.openejb.ApplicationException in project tomee by apache.
the class TxBeanManaged method commit.
public void commit() throws ApplicationException, SystemException {
try {
// The Container must detect the case in which a transaction was started, but
// not completed, in the business method, and handle it as follows:
final Transaction currentTx = getTransaction();
if (currentTx != null) {
final String message = "The EJB started a transaction but did not complete it.";
/* [1] Log this as an application error ********/
logger.error(message);
/* [2] Roll back the started transaction *******/
try {
rollbackTransaction(currentTx);
} catch (final Throwable t) {
// no-op
}
/* [3] Throw the RemoteException to the client */
throw new ApplicationException(new RemoteException(message));
}
fireNonTransactionalCompletion();
} finally {
resumeTransaction(clientTx);
}
}
use of org.apache.openejb.ApplicationException in project tomee by apache.
the class StatefulContainer method obtainInstance.
@SuppressWarnings("LockAcquiredButNotSafelyReleased")
private Instance obtainInstance(final Object primaryKey, final ThreadContext callContext, final Method callMethod, final boolean checkOutIfNecessary) throws OpenEJBException {
if (primaryKey == null) {
throw new SystemException(new NullPointerException("Cannot obtain an instance of the stateful session bean with a null session id"));
}
final Transaction currentTransaction = getTransaction(callContext);
// Find the instance
Instance instance;
synchronized (this) {
instance = checkedOutInstances.get(primaryKey);
if (instance == null) {
// no need to check for extended persistence contexts it shouldn't happen
try {
instance = cache.checkOut(primaryKey, checkOutIfNecessary);
} catch (final OpenEJBException e) {
throw e;
} catch (final Exception e) {
throw new SystemException("Unexpected load exception", e);
}
// Did we find the instance?
if (instance == null) {
throw new InvalidateReferenceException(new NoSuchObjectException("Not Found"));
}
// remember instance until it is returned to the cache
checkedOutInstances.put(primaryKey, instance);
}
}
final Duration accessTimeout = getAccessTimeout(instance.beanContext, callMethod);
final LockFactory.StatefulLock currLock = instance.getLock();
final boolean lockAcquired;
if (accessTimeout == null || accessTimeout.getTime() < 0) {
// wait indefinitely for a lock
currLock.lock();
lockAcquired = true;
} else if (accessTimeout.getTime() == 0) {
// concurrent calls are not allowed, lock only once
lockAcquired = currLock.tryLock();
} else {
// try to get a lock within the specified period.
try {
lockAcquired = currLock.tryLock(accessTimeout.getTime(), accessTimeout.getUnit());
} catch (final InterruptedException e) {
throw new ApplicationException("Unable to get lock.", e);
}
}
// Did we acquire the lock to the current execution?
if (!lockAcquired) {
throw new ApplicationException(new ConcurrentAccessTimeoutException("Unable to get lock."));
}
if (instance.getTransaction() != null) {
if (!instance.getTransaction().equals(currentTransaction) && !instance.getLock().tryLock()) {
throw new ApplicationException(new RemoteException("Instance is in a transaction and cannot be invoked outside that transaction. See EJB 3.0 Section 4.4.4"));
}
} else {
instance.setTransaction(currentTransaction);
}
// Mark the instance in use so we can detect reentrant calls
instance.setInUse(true);
return instance;
}
use of org.apache.openejb.ApplicationException in project tomee by apache.
the class MdbContainer method beforeDelivery.
public void beforeDelivery(final BeanContext deployInfo, final Object instance, final Method method, final XAResource xaResource) throws SystemException {
// intialize call context
final ThreadContext callContext = new ThreadContext(deployInfo, null);
final ThreadContext oldContext = ThreadContext.enter(callContext);
// create mdb context
final MdbCallContext mdbCallContext = new MdbCallContext();
callContext.set(MdbCallContext.class, mdbCallContext);
mdbCallContext.deliveryMethod = method;
mdbCallContext.oldCallContext = oldContext;
// call the tx before method
try {
mdbCallContext.txPolicy = createTransactionPolicy(deployInfo.getTransactionType(method), callContext);
// if we have an xaResource and a transaction was not imported from the adapter, enlist the xaResource
if (xaResource != null && mdbCallContext.txPolicy.isNewTransaction()) {
mdbCallContext.txPolicy.enlistResource(xaResource);
}
} catch (final ApplicationException e) {
ThreadContext.exit(oldContext);
throw new SystemException("Should never get an Application exception", e);
} catch (final SystemException e) {
ThreadContext.exit(oldContext);
throw e;
} catch (final Exception e) {
ThreadContext.exit(oldContext);
throw new SystemException("Unable to enlist xa resource in the transaction", e);
}
}
use of org.apache.openejb.ApplicationException in project tomee by apache.
the class EjbMethodInvoker method preEjbInvoke.
private Object preEjbInvoke(Exchange exchange, Method method, List<Object> params) {
EjbMessageContext ctx = new EjbMessageContext(exchange.getInMessage(), Scope.APPLICATION);
WebServiceContextImpl.setMessageContext(ctx);
Map<String, Object> handlerProperties = removeHandlerProperties(ctx);
exchange.put(HANDLER_PROPERTIES, handlerProperties);
try {
EjbInterceptor interceptor = new EjbInterceptor(params, method, this.bus, exchange);
Object[] arguments = { ctx, interceptor };
RpcContainer container = (RpcContainer) this.beanContext.getContainer();
Class callInterface = this.beanContext.getServiceEndpointInterface();
method = getMostSpecificMethod(beanContext, method, callInterface);
Object res = container.invoke(this.beanContext.getDeploymentID(), InterfaceType.SERVICE_ENDPOINT, callInterface, method, arguments, null);
if (exchange.isOneWay()) {
return null;
}
return new MessageContentsList(res);
} catch (ApplicationException e) {
// when no handler is defined, EjbInterceptor will directly delegate
// to #directEjbInvoke. So if an application exception is thrown by
// the end user, when must consider the ApplicationException as a
// web fault if it contains the @WebFault exception
Throwable t = e.getCause();
if (t != null) {
if (RuntimeException.class.isAssignableFrom(t.getClass()) && t.getClass().isAnnotationPresent(javax.ejb.ApplicationException.class)) {
// it's not a checked exception so it can not be a WebFault
throw (RuntimeException) t;
} else if (!t.getClass().isAnnotationPresent(WebFault.class)) {
// not a web fault even if it's an EJB ApplicationException
exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
throw createFault(t, method, params, false);
}
} else {
// may not occurs ...
t = e;
}
// TODO may be we can change to FaultMode.CHECKED_APPLICATION_FAULT
exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
throw createFault(t, method, params, false);
} catch (Exception e) {
exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
throw createFault(e, method, params, false);
} finally {
WebServiceContextImpl.clear();
}
}
Aggregations