Search in sources :

Example 6 with Operation

use of org.apache.openejb.core.Operation in project tomee by apache.

the class EntityInstanceManager method poolInstance.

public void poolInstance(final ThreadContext callContext, final EntityBean bean, final Object primaryKey) throws OpenEJBException {
    if (bean == null) {
        return;
    }
    // primary key is null if its a servicing a home methods (create, find, ejbHome)
    final TransactionPolicy txPolicy = callContext.getTransactionPolicy();
    if (primaryKey != null && txPolicy != null && txPolicy.isTransactionActive()) {
        final Key key = new Key(callContext.getBeanContext().getDeploymentID(), primaryKey);
        SynchronizationWrapper wrapper = (SynchronizationWrapper) txPolicy.getResource(key);
        if (wrapper != null) {
            if (callContext.getCurrentOperation() == Operation.REMOVE) {
                /*
                    * The bean is being returned to the pool after it has been removed. Its
                    * important at this point to mark the bean as disassociated to prevent
                    * it's ejbStore method from bean called (see SynchronizationWrapper.beforeCompletion() method)
                    * and that subsequent methods can not be invoked on the bean identity (see obtainInstance() method).
                    */
                wrapper.disassociate();
                /*
                    * If the bean has been removed then the bean instance is no longer needed and can return to the methodReadyPool
                    * to service another identity.
                    */
                final Stack methodReadyPool = poolMap.get(callContext.getBeanContext().getDeploymentID());
                methodReadyPool.push(bean);
            } else {
                if (callContext.getCurrentOperation() == Operation.CREATE) {
                    // Bean is being recreated (new-delete-new) so we need to reassociate it
                    wrapper.associate();
                }
                wrapper.setEntityBean(bean);
            }
        } else {
            /*
                A wrapper will not exist if the bean is being returned after a create operation.
                In this case the transaction scope is broader then the create method itself; its a client
                initiated transaction, so the bean must be registered with the tranaction and moved to the
                tx ready pool
                */
            wrapper = new SynchronizationWrapper(callContext.getBeanContext(), primaryKey, bean, true, key, txPolicy);
            txPolicy.registerSynchronization(wrapper);
            txPolicy.putResource(key, wrapper);
        }
    } else {
        if (primaryKey != null && callContext.getCurrentOperation() != Operation.REMOVE) {
            /*
                * If the bean has a primary key; And its not being returned following a remove operation;
                * then the bean is being returned to the method ready pool after successfully executing a business method or create
                * method. In this case we need to call the bean instance's ejbPassivate before returning it to the pool per EJB 1.1
                * Section 9.1.
                */
            final Operation currentOp = callContext.getCurrentOperation();
            callContext.setCurrentOperation(Operation.PASSIVATE);
            try {
                /*
                    In the event of an exception, OpenEJB is required to log the exception, evict the instance,
                    and mark the transaction for rollback.  If there is a transaction to rollback, then the a
                    javax.transaction.TransactionRolledbackException must be throw to the client.
                    See EJB 1.1 specification, section 12.3.2
                    */
                bean.ejbPassivate();
            } catch (final Throwable e) {
                if (txPolicy.isTransactionActive()) {
                    txPolicy.setRollbackOnly(e);
                    throw new ApplicationException(new TransactionRolledbackException("Reflection exception thrown while attempting to call ejbPassivate() on the instance", e));
                }
                throw new ApplicationException(new RemoteException("Reflection exception thrown while attempting to call ejbPassivate() on the instance. Exception message = " + e.getMessage(), e));
            } finally {
                callContext.setCurrentOperation(currentOp);
            }
        }
        /*
            * The bean is returned to the method ready pool if its returned after servicing a find, ejbHome, business or create
            * method and is not still part of a tx.  While in the method ready pool the bean instance is not associated with a
            * primary key and may be used to service a request for any bean of the same class.
            */
        final Stack methodReadyPool = poolMap.get(callContext.getBeanContext().getDeploymentID());
        methodReadyPool.push(bean);
    }
}
Also used : ApplicationException(org.apache.openejb.ApplicationException) TransactionPolicy(org.apache.openejb.core.transaction.TransactionPolicy) Operation(org.apache.openejb.core.Operation) TransactionRolledbackException(org.apache.openejb.core.transaction.TransactionRolledbackException) RemoteException(java.rmi.RemoteException) LinkedListStack(org.apache.openejb.util.LinkedListStack) Stack(org.apache.openejb.util.Stack)

Example 7 with Operation

use of org.apache.openejb.core.Operation in project tomee by apache.

the class EntityInstanceManager method getPooledInstance.

protected EntityBean getPooledInstance(final ThreadContext callContext) throws OpenEJBException {
    final BeanContext beanContext = callContext.getBeanContext();
    final Stack methodReadyPool = poolMap.get(beanContext.getDeploymentID());
    if (methodReadyPool == null) {
        throw new SystemException("Invalid deployment id " + beanContext.getDeploymentID() + " for this container");
    }
    EntityBean bean = (EntityBean) methodReadyPool.pop();
    if (bean == null) {
        try {
            bean = (EntityBean) beanContext.getBeanClass().newInstance();
        } catch (final Exception e) {
            logger.error("Bean instantiation failed for class " + beanContext.getBeanClass(), e);
            throw new SystemException(e);
        }
        final Operation currentOp = callContext.getCurrentOperation();
        callContext.setCurrentOperation(Operation.SET_CONTEXT);
        try {
            /*
                * setEntityContext executes in an unspecified transactional context. In this case we choose to
                * allow it to have what every transaction context is current. Better then suspending it
                * unnecessarily.
                *
                * We also chose not to invoke EntityContainer.invoke( ) method, which duplicate the exception handling
                * logic but also attempt to manage the begining and end of a transaction. It its a container managed transaciton
                * we don't want the TransactionScopeHandler commiting the transaction in afterInvoke() which is what it would attempt
                * to do.
                */
            bean.setEntityContext(createEntityContext());
        } catch (final Exception e) {
            /*
                * The EJB 1.1 specification does not specify how exceptions thrown by setEntityContext impact the
                * transaction, if there is one.  In this case we choose the least disruptive operation, throwing an
                * application exception and NOT automatically marking the transaciton for rollback.
                */
            logger.error("Bean callback method failed ", e);
            throw new ApplicationException(e);
        } finally {
            callContext.setCurrentOperation(currentOp);
        }
    } else {
        reusingBean(bean, callContext);
    }
    if (callContext.getCurrentOperation() == Operation.BUSINESS || callContext.getCurrentOperation() == Operation.REMOVE) {
        /*
            * When a bean is retrieved from the bean pool to service a client's business method request it must be
            * notified that its about to enter service by invoking its ejbActivate( ) method. A bean instance
            * does not have its ejbActivate() invoked when:
            * 1. Its being retreived to service an ejbCreate()/ejbPostCreate().
            * 2. Its being retrieved to service an ejbFind method.
            * 3. Its being retrieved to service an ejbRemove() method.
            * See section 9.1.4 of the EJB 1.1 specification.
            */
        final Operation currentOp = callContext.getCurrentOperation();
        callContext.setCurrentOperation(Operation.ACTIVATE);
        try {
            /*
                In the event of an exception, OpenEJB is required to log the exception, evict the instance,
                and mark the transaction for rollback.  If there is a transaction to rollback, then the a
                javax.transaction.TransactionRolledbackException must be throw to the client.
                See EJB 1.1 specification, section 12.3.2
                */
            bean.ejbActivate();
        } catch (final Throwable e) {
            logger.error("Encountered exception during call to ejbActivate()", e);
            final TransactionPolicy txPolicy = callContext.getTransactionPolicy();
            if (txPolicy != null && txPolicy.isTransactionActive()) {
                txPolicy.setRollbackOnly(e);
                throw new ApplicationException(new TransactionRolledbackException("Reflection exception thrown while attempting to call ejbActivate() on the instance", e));
            }
            throw new ApplicationException(new RemoteException("Exception thrown while attempting to call ejbActivate() on the instance. Exception message = " + e.getMessage(), e));
        } finally {
            callContext.setCurrentOperation(currentOp);
        }
    }
    return bean;
}
Also used : BeanContext(org.apache.openejb.BeanContext) ApplicationException(org.apache.openejb.ApplicationException) SystemException(org.apache.openejb.SystemException) EntityBean(javax.ejb.EntityBean) TransactionPolicy(org.apache.openejb.core.transaction.TransactionPolicy) Operation(org.apache.openejb.core.Operation) TransactionRolledbackException(org.apache.openejb.core.transaction.TransactionRolledbackException) RemoteException(java.rmi.RemoteException) OpenEJBException(org.apache.openejb.OpenEJBException) NoSuchObjectException(org.apache.openejb.core.NoSuchObjectException) RemoteException(java.rmi.RemoteException) InvalidateReferenceException(org.apache.openejb.InvalidateReferenceException) SystemException(org.apache.openejb.SystemException) TransactionRolledbackException(org.apache.openejb.core.transaction.TransactionRolledbackException) ApplicationException(org.apache.openejb.ApplicationException) NoSuchEntityException(javax.ejb.NoSuchEntityException) LinkedListStack(org.apache.openejb.util.LinkedListStack) Stack(org.apache.openejb.util.Stack)

Example 8 with Operation

use of org.apache.openejb.core.Operation in project tomee by apache.

the class EntityInstanceManager method obtainInstance.

public EntityBean obtainInstance(final ThreadContext callContext) throws OpenEJBException {
    // primary key is null if its a servicing a home methods (create, find, ejbHome)
    final Object primaryKey = callContext.getPrimaryKey();
    final TransactionPolicy txPolicy = callContext.getTransactionPolicy();
    if (callContext.getPrimaryKey() != null && txPolicy != null && txPolicy.isTransactionActive()) {
        final Key key = new Key(callContext.getBeanContext().getDeploymentID(), primaryKey);
        SynchronizationWrapper wrapper = (SynchronizationWrapper) txPolicy.getResource(key);
        if (wrapper != null) {
            if (!wrapper.isAssociated()) {
                /*
                    * If the bean identity was removed (via ejbRemove()) within the same transaction,
                    * then it's SynchronizationWrapper will be in the txReady pool but marked as disassociated.
                    * This allows us to prevent a condition where the caller removes the bean and then attempts to
                    * call a business method on that bean within the same transaction.  After a bean is removed any
                    * subsequent invocations on that bean with the same transaction should throw a NoSuchEntityException.
                    * its likely that the application server would have already made the reference invalid, but this bit of
                    * code is an extra precaution.
                    */
                throw new InvalidateReferenceException(new NoSuchObjectException("Entity not found: " + primaryKey));
            } else if (callContext.getCurrentOperation() == Operation.REMOVE) {
                /*
                    *  To avoid calling ejbStore( ) on a bean that after its removed, we can not delegate
                    *  the wrapper is marked as disassociated from the transaction to avoid processing the
                    *  beforeCompletion( ) method on the SynchronizationWrapper object.
                    */
                wrapper.disassociate();
            }
            if (wrapper.isAvailable() || wrapper.primaryKey.equals(primaryKey)) {
                return wrapper.getEntityBean();
            } else {
                // its simpler to implement.
                return wrapper.getEntityBean();
            }
        } else {
            /*
                * If no synchronized wrapper for the key exists
                * Then the bean entity is being access by this transaction for the first time,
                * so it needs to be enrolled in the transaction.
                */
            final EntityBean bean = getPooledInstance(callContext);
            wrapper = new SynchronizationWrapper(callContext.getBeanContext(), primaryKey, bean, false, key, txPolicy);
            if (callContext.getCurrentOperation() == Operation.REMOVE) {
                /*
                    *  To avoid calling ejbStore( ) on a bean that after its removed, we can not delegate
                    *  the wrapper is marked as disassociated from the transaction to avoid processing the
                    *  beforeCompletion( ) method on the SynchronizationWrapper object.
                    *
                    *  We have to still use a wrapper so we can detect when a business method is called after
                    *  a ejbRemove() and act to prevent it from being processed.
                    */
                wrapper.disassociate();
            }
            txPolicy.registerSynchronization(wrapper);
            loadingBean(bean, callContext);
            final Operation orginalOperation = callContext.getCurrentOperation();
            callContext.setCurrentOperation(Operation.LOAD);
            try {
                bean.ejbLoad();
            } catch (final NoSuchEntityException e) {
                wrapper.disassociate();
                throw new InvalidateReferenceException(new NoSuchObjectException("Entity not found: " + primaryKey, e));
            } catch (final Exception e) {
                logger.error("Exception encountered during ejbLoad():", e);
                //djencks not sure about this dissociate call
                wrapper.disassociate();
                throw new OpenEJBException(e);
            } finally {
                callContext.setCurrentOperation(orginalOperation);
            }
            txPolicy.putResource(key, wrapper);
            return bean;
        }
    } else {
        // returned to the pool -- depending on if the tx is a client initiated or container initiated.
        return getPooledInstance(callContext);
    }
}
Also used : InvalidateReferenceException(org.apache.openejb.InvalidateReferenceException) OpenEJBException(org.apache.openejb.OpenEJBException) EntityBean(javax.ejb.EntityBean) TransactionPolicy(org.apache.openejb.core.transaction.TransactionPolicy) NoSuchObjectException(org.apache.openejb.core.NoSuchObjectException) Operation(org.apache.openejb.core.Operation) NoSuchEntityException(javax.ejb.NoSuchEntityException) OpenEJBException(org.apache.openejb.OpenEJBException) NoSuchObjectException(org.apache.openejb.core.NoSuchObjectException) RemoteException(java.rmi.RemoteException) InvalidateReferenceException(org.apache.openejb.InvalidateReferenceException) SystemException(org.apache.openejb.SystemException) TransactionRolledbackException(org.apache.openejb.core.transaction.TransactionRolledbackException) ApplicationException(org.apache.openejb.ApplicationException) NoSuchEntityException(javax.ejb.NoSuchEntityException)

Example 9 with Operation

use of org.apache.openejb.core.Operation in project tomee by apache.

the class EntityContainer method ejbLoad_If_No_Transaction.

public void ejbLoad_If_No_Transaction(final ThreadContext callContext, final EntityBean bean) throws Exception {
    final Operation orginalOperation = callContext.getCurrentOperation();
    if (orginalOperation == Operation.BUSINESS || orginalOperation == Operation.REMOVE) {
        final TransactionPolicy callerTxPolicy = callContext.getTransactionPolicy();
        if (callerTxPolicy != null && callerTxPolicy.isTransactionActive()) {
            return;
        }
        final BeanContext beanContext = callContext.getBeanContext();
        final TransactionPolicy txPolicy = beanContext.getTransactionPolicyFactory().createTransactionPolicy(TransactionType.Supports);
        try {
            // double check we don't have an active transaction
            if (!txPolicy.isTransactionActive()) {
                callContext.setCurrentOperation(Operation.LOAD);
                bean.ejbLoad();
            }
        } catch (final NoSuchEntityException e) {
            instanceManager.discardInstance(callContext, bean);
            throw new ApplicationException(new NoSuchObjectException("Entity not found: " + callContext.getPrimaryKey()));
        } catch (final Exception e) {
            instanceManager.discardInstance(callContext, bean);
            throw e;
        } finally {
            callContext.setCurrentOperation(orginalOperation);
            txPolicy.commit();
        }
    }
}
Also used : BeanContext(org.apache.openejb.BeanContext) EjbTransactionUtil.handleApplicationException(org.apache.openejb.core.transaction.EjbTransactionUtil.handleApplicationException) ApplicationException(org.apache.openejb.ApplicationException) TransactionPolicy(org.apache.openejb.core.transaction.TransactionPolicy) EjbTransactionUtil.createTransactionPolicy(org.apache.openejb.core.transaction.EjbTransactionUtil.createTransactionPolicy) NoSuchObjectException(java.rmi.NoSuchObjectException) Operation(org.apache.openejb.core.Operation) NoSuchEntityException(javax.ejb.NoSuchEntityException) NoSuchObjectException(java.rmi.NoSuchObjectException) EjbTransactionUtil.handleApplicationException(org.apache.openejb.core.transaction.EjbTransactionUtil.handleApplicationException) EjbTransactionUtil.handleSystemException(org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemException) ApplicationException(org.apache.openejb.ApplicationException) EJBAccessException(javax.ejb.EJBAccessException) NoSuchEntityException(javax.ejb.NoSuchEntityException) OpenEJBException(org.apache.openejb.OpenEJBException) InvocationTargetException(java.lang.reflect.InvocationTargetException) SystemException(org.apache.openejb.SystemException)

Example 10 with Operation

use of org.apache.openejb.core.Operation 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);
            }
        }
    }
}
Also used : BeanContext(org.apache.openejb.BeanContext) OpenEJBException(org.apache.openejb.OpenEJBException) EjbTransactionUtil.handleApplicationException(org.apache.openejb.core.transaction.EjbTransactionUtil.handleApplicationException) ApplicationException(org.apache.openejb.ApplicationException) SystemException(org.apache.openejb.SystemException) EjbTransactionUtil.handleSystemException(org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemException) ThreadContext(org.apache.openejb.core.ThreadContext) Operation(org.apache.openejb.core.Operation) Method(java.lang.reflect.Method)

Aggregations

Operation (org.apache.openejb.core.Operation)12 ApplicationException (org.apache.openejb.ApplicationException)9 SystemException (org.apache.openejb.SystemException)8 OpenEJBException (org.apache.openejb.OpenEJBException)7 RemoteException (java.rmi.RemoteException)6 TransactionPolicy (org.apache.openejb.core.transaction.TransactionPolicy)6 NoSuchEntityException (javax.ejb.NoSuchEntityException)5 BeanContext (org.apache.openejb.BeanContext)5 InvalidateReferenceException (org.apache.openejb.InvalidateReferenceException)5 EjbTransactionUtil.handleSystemException (org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemException)4 TransactionRolledbackException (org.apache.openejb.core.transaction.TransactionRolledbackException)4 InvocationTargetException (java.lang.reflect.InvocationTargetException)3 Method (java.lang.reflect.Method)3 NoSuchObjectException (java.rmi.NoSuchObjectException)3 EJBAccessException (javax.ejb.EJBAccessException)3 NoSuchObjectException (org.apache.openejb.core.NoSuchObjectException)3 InterceptorData (org.apache.openejb.core.interceptor.InterceptorData)3 InterceptorStack (org.apache.openejb.core.interceptor.InterceptorStack)3 EjbTransactionUtil.createTransactionPolicy (org.apache.openejb.core.transaction.EjbTransactionUtil.createTransactionPolicy)3 EjbTransactionUtil.handleApplicationException (org.apache.openejb.core.transaction.EjbTransactionUtil.handleApplicationException)3