use of org.apache.openejb.ApplicationException in project tomee by apache.
the class StatefulContainer 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 CdiEjbBean cdiEjbBean = beanContext.get(CdiEjbBean.class);
if (cdiEjbBean != null) {
final Class scope = cdiEjbBean.getScope();
if (callMethod.getDeclaringClass() != BeanContext.Removable.class && scope != Dependent.class) {
throw new UnsupportedOperationException("Can not call EJB Stateful Bean Remove Method without scoped @Dependent. Found scope: @" + scope.getSimpleName());
}
}
final boolean internalRemove = BeanContext.Removable.class == callMethod.getDeclaringClass();
final ThreadContext callContext = new ThreadContext(beanContext, primKey);
final ThreadContext oldCallContext = ThreadContext.enter(callContext);
Object runAs = null;
try {
if (oldCallContext != null) {
final BeanContext oldBc = oldCallContext.getBeanContext();
if (oldBc.getRunAsUser() != null || oldBc.getRunAs() != null) {
runAs = AbstractSecurityService.class.cast(securityService).overrideWithRunAsContext(callContext, beanContext, oldBc);
}
}
// Security check
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, callMethod, beanContext.isPassivatingScope());
// 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
final CdiEjbBean<Object> bean = beanContext.get(CdiEjbBean.class);
if (bean != null) {
// TODO: see if it should be called before or after next call
bean.getInjectionTarget().preDestroy(instance.bean);
}
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 (runAs != null) {
try {
securityService.associate(runAs);
} catch (final LoginException e) {
// no-op
}
}
if (!retain) {
try {
callContext.setCurrentOperation(Operation.PRE_DESTROY);
final List<InterceptorData> callbackInterceptors = beanContext.getCallbackInterceptors();
if (instance != null) {
final InterceptorStack interceptorStack = new InterceptorStack(instance.bean, null, Operation.PRE_DESTROY, callbackInterceptors, instance.interceptors);
interceptorStack.invoke();
}
} catch (final Throwable t) {
final String logMessage = "An unexpected exception occured while invoking the preDestroy method on the Stateful SessionBean instance: " + (null != instance ? instance.bean.getClass().getName() : beanContext.getBeanClass().getName());
logger.error(logMessage, t);
} finally {
callContext.setCurrentOperation(Operation.REMOVE);
}
discardInstance(primKey, instance);
}
// un register EntityManager
final Map<EntityManagerFactory, JtaEntityManagerRegistry.EntityManagerTracker> unregisteredEntityManagers = unregisterEntityManagers(instance, callContext);
// Commit transaction
afterInvoke(callContext, txPolicy, instance);
// Un register and close extended persistence contexts
/*
7.6.2 Container-managed Extended Persistence Context
A container-managed extended persistence context can only be initiated within the scope of a stateful
session bean. It exists from the point at which the stateful session bean that declares a dependency on an
entity manager of type PersistenceContextType.EXTENDED is created, and is said to be bound
to the stateful session bean. The dependency on the extended persistence context is declared by means
of the PersistenceContext annotation or persistence-context-ref deployment descriptor element.
The persistence context is closed by the container when the @Remove method of the stateful session
bean completes (or the stateful session bean instance is otherwise destroyed).
*/
closeEntityManagers(unregisteredEntityManagers);
}
return returnValue;
} finally {
ThreadContext.exit(oldCallContext);
}
}
use of org.apache.openejb.ApplicationException in project tomee by apache.
the class StatefulContainer method handleException.
private void handleException(final ThreadContext callContext, final TransactionPolicy txPolicy, final Throwable e) throws ApplicationException {
if (e instanceof ApplicationException) {
throw (ApplicationException) e;
}
final ExceptionType type = callContext.getBeanContext().getExceptionType(e);
if (type == ExceptionType.SYSTEM) {
discardInstance(callContext.getPrimaryKey(), null);
EjbTransactionUtil.handleSystemException(txPolicy, e, callContext);
} else {
EjbTransactionUtil.handleApplicationException(txPolicy, e, type == ExceptionType.APPLICATION_ROLLBACK);
}
}
use of org.apache.openejb.ApplicationException in project tomee by apache.
the class EndpointHandler method deliverMessage.
public Object deliverMessage(final Method method, final Object[] args) throws Throwable {
boolean callBeforeAfter = false;
// verify current state
switch(state) {
case NONE:
try {
beforeDelivery(method);
} catch (final ApplicationServerInternalException e) {
throw (EJBException) new EJBException().initCause(e.getCause());
}
callBeforeAfter = true;
state = State.METHOD_CALLED;
break;
case BEFORE_CALLED:
state = State.METHOD_CALLED;
break;
case RELEASED:
throw new IllegalStateException("Message endpoint factory has been released");
case METHOD_CALLED:
case SYSTEM_EXCEPTION:
throw new IllegalStateException("The last message delivery must be completed with an afterDeliver before another message can be delivered");
}
Throwable throwable = null;
Object value = null;
try {
// deliver the message
value = container.invoke(instance, method, null, wrapMessageForAmq5(args));
} catch (final SystemException se) {
throwable = se.getRootCause() != null ? se.getRootCause() : se;
state = State.SYSTEM_EXCEPTION;
} catch (final ApplicationException ae) {
throwable = ae.getRootCause() != null ? ae.getRootCause() : ae;
} finally {
// if the adapter is not using before/after, we must call afterDelivery to clean up
if (callBeforeAfter) {
try {
afterDelivery();
} catch (final ApplicationServerInternalException e) {
throwable = throwable == null ? e.getCause() : throwable;
} catch (final UnavailableException e) {
throwable = throwable == null ? e : throwable;
}
}
}
if (throwable != null) {
throwable.printStackTrace();
if (isValidException(method, throwable)) {
throw throwable;
} else {
throw new EJBException().initCause(throwable);
}
}
return value;
}
use of org.apache.openejb.ApplicationException in project tomee by apache.
the class MdbContainer method afterDelivery.
public void afterDelivery(final Object instance) throws SystemException {
// get the mdb call context
final ThreadContext callContext = ThreadContext.getThreadContext();
final MdbCallContext mdbCallContext = callContext.get(MdbCallContext.class);
// invoke the tx after method
try {
afterInvoke(mdbCallContext.txPolicy, callContext);
} catch (final ApplicationException e) {
throw new SystemException("Should never get an Application exception", e);
} finally {
ThreadContext.exit(mdbCallContext.oldCallContext);
}
}
use of org.apache.openejb.ApplicationException in project tomee by apache.
the class MdbContainer method invoke.
public Object invoke(final Object instance, final Method method, final InterfaceType type, Object... args) throws SystemException, ApplicationException {
if (args == null) {
args = NO_ARGS;
}
// get the context data
final ThreadContext callContext = ThreadContext.getThreadContext();
final BeanContext deployInfo = callContext.getBeanContext();
final MdbCallContext mdbCallContext = callContext.get(MdbCallContext.class);
if (mdbCallContext == null) {
throw new IllegalStateException("beforeDelivery was not called");
}
// verify the delivery method passed to beforeDeliver is the same method that was invoked
if (!mdbCallContext.deliveryMethod.getName().equals(method.getName()) || !Arrays.deepEquals(mdbCallContext.deliveryMethod.getParameterTypes(), method.getParameterTypes())) {
throw new IllegalStateException("Delivery method specified in beforeDelivery is not the delivery method called");
}
// remember the return value or exception so it can be logged
Object returnValue = null;
OpenEJBException openEjbException = null;
final Operation oldOperation = callContext.getCurrentOperation();
callContext.setCurrentOperation(type == InterfaceType.TIMEOUT ? Operation.TIMEOUT : Operation.BUSINESS);
try {
if (logger.isDebugEnabled()) {
logger.info("invoking method " + method.getName() + " on " + deployInfo.getDeploymentID());
}
// determine the target method on the bean instance class
final Method targetMethod = deployInfo.getMatchingBeanMethod(method);
callContext.set(Method.class, targetMethod);
// invoke the target method
returnValue = _invoke(instance, targetMethod, args, deployInfo, type, mdbCallContext);
return returnValue;
} catch (final ApplicationException | SystemException e) {
openEjbException = e;
throw e;
} finally {
callContext.setCurrentOperation(oldOperation);
// Log the invocation results
if (logger.isDebugEnabled()) {
if (openEjbException == null) {
logger.debug("finished invoking method " + method.getName() + ". Return value:" + returnValue);
} else {
final Throwable exception = openEjbException.getRootCause() != null ? openEjbException.getRootCause() : openEjbException;
logger.debug("finished invoking method " + method.getName() + " with exception " + exception);
}
}
}
}
Aggregations