Search in sources :

Example 11 with InterceptorData

use of org.apache.openejb.core.interceptor.InterceptorData in project tomee by apache.

the class SingletonContainer method invokeWebService.

private Object invokeWebService(final Object[] args, final BeanContext beanContext, final Method runMethod, final Instance instance) throws Exception {
    if (args.length < 2) {
        throw new IllegalArgumentException("WebService calls must follow format {messageContext, interceptor, [arg...]}.");
    }
    final Object messageContext = args[0];
    if (messageContext == null) {
        throw new IllegalArgumentException("MessageContext is null.");
    }
    // This object will be used as an interceptor in the stack and will be responsible
    // for unmarshalling the soap message parts into an argument list that will be
    // used for the actual method invocation.
    //
    // We just need to make it an interceptor in the OpenEJB sense and tack it on the end
    // of our stack.
    final Object interceptor = args[1];
    if (interceptor == null) {
        throw new IllegalArgumentException("Interceptor instance is null.");
    }
    final Class<?> interceptorClass = interceptor.getClass();
    //  Add the webservice interceptor to the list of interceptor instances
    final Map<String, Object> interceptors = new HashMap<String, Object>(instance.interceptors);
    {
        interceptors.put(interceptorClass.getName(), interceptor);
    }
    //  Create an InterceptorData for the webservice interceptor to the list of interceptorDatas for this method
    final List<InterceptorData> interceptorDatas = new ArrayList<InterceptorData>();
    {
        final InterceptorData providerData = new InterceptorData(interceptorClass);
        List<Method> aroundInvokes = interceptorCache.get(interceptorClass);
        if (aroundInvokes == null) {
            aroundInvokes = new ClassFinder(interceptorClass).findAnnotatedMethods(AroundInvoke.class);
            if (SingletonContainer.class.getClassLoader() == interceptorClass.getClassLoader()) {
                // use cache only for server classes
                final List<Method> value = new CopyOnWriteArrayList<Method>(aroundInvokes);
                // ensure it to be thread safe
                aroundInvokes = interceptorCache.putIfAbsent(interceptorClass, value);
                if (aroundInvokes == null) {
                    aroundInvokes = value;
                }
            }
        }
        providerData.getAroundInvoke().addAll(aroundInvokes);
        interceptorDatas.add(0, providerData);
        interceptorDatas.addAll(beanContext.getMethodInterceptors(runMethod));
    }
    final InterceptorStack interceptorStack = new InterceptorStack(instance.bean, runMethod, Operation.BUSINESS_WS, interceptorDatas, interceptors);
    final Object[] params = new Object[runMethod.getParameterTypes().length];
    if (messageContext instanceof javax.xml.rpc.handler.MessageContext) {
        ThreadContext.getThreadContext().set(javax.xml.rpc.handler.MessageContext.class, (javax.xml.rpc.handler.MessageContext) messageContext);
        return interceptorStack.invoke((javax.xml.rpc.handler.MessageContext) messageContext, params);
    } else if (messageContext instanceof javax.xml.ws.handler.MessageContext) {
        AddressingSupport wsaSupport = NoAddressingSupport.INSTANCE;
        for (int i = 2; i < args.length; i++) {
            if (args[i] instanceof AddressingSupport) {
                wsaSupport = (AddressingSupport) args[i];
            }
        }
        ThreadContext.getThreadContext().set(AddressingSupport.class, wsaSupport);
        ThreadContext.getThreadContext().set(javax.xml.ws.handler.MessageContext.class, (javax.xml.ws.handler.MessageContext) messageContext);
        return interceptorStack.invoke((javax.xml.ws.handler.MessageContext) messageContext, params);
    }
    throw new IllegalArgumentException("Uknown MessageContext type: " + messageContext.getClass().getName());
}
Also used : HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) ArrayList(java.util.ArrayList) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Method(java.lang.reflect.Method) InterceptorData(org.apache.openejb.core.interceptor.InterceptorData) InterceptorStack(org.apache.openejb.core.interceptor.InterceptorStack) ClassFinder(org.apache.xbean.finder.ClassFinder) EJBObject(javax.ejb.EJBObject) EJBLocalObject(javax.ejb.EJBLocalObject) ArrayList(java.util.ArrayList) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) NoAddressingSupport(org.apache.openejb.core.webservices.NoAddressingSupport) AddressingSupport(org.apache.openejb.core.webservices.AddressingSupport)

Example 12 with InterceptorData

use of org.apache.openejb.core.interceptor.InterceptorData in project tomee by apache.

the class MdbInstanceFactory method freeInstance.

/**
     * Frees an instance no longer needed by the resource adapter.  This method makes all the necessary lifecycle
     * callbacks and decrements the instance count.  This method should not be used to disposed of beans that have
     * thrown a system exception.  Instead the discardInstance method should be called.
     *
     * @param instance             the bean instance to free
     * @param ignoredInstanceCount
     */
public void freeInstance(final Instance instance, final boolean ignoredInstanceCount) {
    if (instance == null) {
        throw new NullPointerException("bean is null");
    }
    // decrement the instance count
    if (!ignoredInstanceCount) {
        synchronized (this) {
            instanceCount--;
        }
    }
    final ThreadContext callContext = ThreadContext.getThreadContext();
    final Operation originalOperation = callContext == null ? null : callContext.getCurrentOperation();
    final BaseContext.State[] originalAllowedStates = callContext == null ? null : callContext.getCurrentAllowedStates();
    try {
        // call post destroy method
        if (callContext != null) {
            callContext.setCurrentOperation(Operation.PRE_DESTROY);
        }
        final Method remove = instance.bean instanceof MessageDrivenBean ? MessageDrivenBean.class.getMethod("ejbRemove") : null;
        final List<InterceptorData> callbackInterceptors = beanContext.getCallbackInterceptors();
        final InterceptorStack interceptorStack = new InterceptorStack(instance.bean, remove, Operation.PRE_DESTROY, callbackInterceptors, instance.interceptors);
        interceptorStack.invoke();
        if (instance.creationalContext != null) {
            instance.creationalContext.release();
        }
    } catch (final Throwable re) {
        MdbInstanceFactory.logger.error("The bean instance " + instance.bean + " threw a system exception:" + re, re);
    } finally {
        if (callContext != null) {
            callContext.setCurrentOperation(originalOperation);
            callContext.setCurrentAllowedStates(originalAllowedStates);
        }
    }
}
Also used : MessageDrivenBean(javax.ejb.MessageDrivenBean) InterceptorData(org.apache.openejb.core.interceptor.InterceptorData) InterceptorStack(org.apache.openejb.core.interceptor.InterceptorStack) ThreadContext(org.apache.openejb.core.ThreadContext) Operation(org.apache.openejb.core.Operation) Method(java.lang.reflect.Method)

Example 13 with InterceptorData

use of org.apache.openejb.core.interceptor.InterceptorData in project tomee by apache.

the class InterceptorBindingBuilder method build.

public void build(final BeanContext beanContext, final EnterpriseBeanInfo beanInfo) {
    Class<?> clazz = beanContext.getBeanClass();
    final InterceptorData beanAsInterceptor = new InterceptorData(clazz);
    if (beanInfo instanceof StatelessBeanInfo || beanInfo instanceof MessageDrivenBeanInfo) {
        /*
             * 4.3.10.2 and 4.5.8
             * If the stateless session bean or MDB instance has an ejbCreate method,
             * the container treats the ejbCreate method as the instance’s PostConstruct method,
             *  and, in this case, the PostConstruct annotation (or deployment descriptor metadata)
             *  can only be applied to the bean’s ejbCreate method.
             */
        final NamedMethodInfo info = new NamedMethodInfo();
        info.className = clazz.getName();
        final Method createMethod = beanContext.getCreateMethod();
        info.methodName = (createMethod != null) ? createMethod.getName() : "ejbCreate";
        info.methodParams = new ArrayList<String>();
        try {
            final Method ejbcreate = MethodInfoUtil.toMethod(clazz, info);
            if (ejbcreate != null) {
                final CallbackInfo ejbcreateAsPostConstruct = new CallbackInfo();
                ejbcreateAsPostConstruct.className = ejbcreate.getDeclaringClass().getName();
                ejbcreateAsPostConstruct.method = ejbcreate.getName();
                beanInfo.postConstruct.add(ejbcreateAsPostConstruct);
            }
        } catch (final IllegalStateException e) {
        // there's no ejbCreate method in stateless bean.
        }
    }
    toMethods(clazz, beanInfo.aroundInvoke, beanAsInterceptor.getAroundInvoke());
    toCallback(clazz, beanInfo.postConstruct, beanAsInterceptor.getPostConstruct());
    toCallback(clazz, beanInfo.preDestroy, beanAsInterceptor.getPreDestroy());
    if (beanInfo instanceof StatefulBeanInfo) {
        final StatefulBeanInfo stateful = (StatefulBeanInfo) beanInfo;
        toCallback(clazz, stateful.postActivate, beanAsInterceptor.getPostActivate());
        toCallback(clazz, stateful.prePassivate, beanAsInterceptor.getPrePassivate());
        toCallback(clazz, stateful.afterBegin, beanAsInterceptor.getAfterBegin());
        toCallback(clazz, stateful.beforeCompletion, beanAsInterceptor.getBeforeCompletion());
        toCallback(clazz, stateful.afterCompletion, beanAsInterceptor.getAfterCompletion(), boolean.class);
    } else {
        toMethods(clazz, beanInfo.aroundTimeout, beanAsInterceptor.getAroundTimeout());
    }
    while (clazz != null && clazz != Object.class) {
        for (final Method method : clazz.getDeclaredMethods()) {
            final List<InterceptorData> methodInterceptors = createInterceptorDatas(method, beanInfo.ejbName, this.bindings);
            // The bean itself gets to intercept too and is always last.
            beanContext.setMethodInterceptors(method, methodInterceptors);
            beanContext.getMethodContext(method).setSelfInterception(beanAsInterceptor);
        }
        clazz = clazz.getSuperclass();
    }
    final List<InterceptorData> callbackInterceptorDatas = createInterceptorDatas(null, beanInfo.ejbName, this.packageAndClassBindings);
    // The bean itself gets to intercept too and is always last.
    callbackInterceptorDatas.add(beanAsInterceptor);
    beanContext.setCallbackInterceptors(callbackInterceptorDatas);
}
Also used : Method(java.lang.reflect.Method) InterceptorData(org.apache.openejb.core.interceptor.InterceptorData)

Example 14 with InterceptorData

use of org.apache.openejb.core.interceptor.InterceptorData 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);
    }
}
Also used : BeanTransactionPolicy(org.apache.openejb.core.transaction.BeanTransactionPolicy) SystemInstance(org.apache.openejb.loader.SystemInstance) CdiEjbBean(org.apache.openejb.cdi.CdiEjbBean) Dependent(javax.enterprise.context.Dependent) SessionBean(javax.ejb.SessionBean) EJBHome(javax.ejb.EJBHome) ThreadContext(org.apache.openejb.core.ThreadContext) JtaTransactionPolicy(org.apache.openejb.core.transaction.JtaTransactionPolicy) TransactionPolicy(org.apache.openejb.core.transaction.TransactionPolicy) BeanTransactionPolicy(org.apache.openejb.core.transaction.BeanTransactionPolicy) Method(java.lang.reflect.Method) SuspendedTransaction(org.apache.openejb.core.transaction.BeanTransactionPolicy.SuspendedTransaction) EJBLocalHome(javax.ejb.EJBLocalHome) BeanContext(org.apache.openejb.BeanContext) InvalidateReferenceException(org.apache.openejb.InvalidateReferenceException) ApplicationException(org.apache.openejb.ApplicationException) RemoveException(javax.ejb.RemoveException) InterceptorData(org.apache.openejb.core.interceptor.InterceptorData) InterceptorStack(org.apache.openejb.core.interceptor.InterceptorStack) EntityManagerFactory(javax.persistence.EntityManagerFactory) LoginException(javax.security.auth.login.LoginException)

Example 15 with InterceptorData

use of org.apache.openejb.core.interceptor.InterceptorData in project tomee by apache.

the class StatefulContainer method businessMethod.

protected Object businessMethod(final BeanContext beanContext, final Object primKey, final Class callInterface, final Method callMethod, final Object[] args, final InterfaceType interfaceType) throws OpenEJBException {
    final ThreadContext callContext = new ThreadContext(beanContext, primKey);
    final ThreadContext oldCallContext = ThreadContext.enter(callContext);
    final CurrentCreationalContext currentCreationalContext = beanContext.get(CurrentCreationalContext.class);
    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
        checkAuthorization(callMethod, interfaceType);
        // Start transaction
        final TransactionPolicy txPolicy = EjbTransactionUtil.createTransactionPolicy(callContext.getBeanContext().getTransactionType(callMethod, interfaceType), callContext);
        Object returnValue = null;
        Instance instance = null;
        try {
            // Obtain instance
            instance = obtainInstance(primKey, callContext, callMethod, true);
            // Resume previous Bean transaction if there was one
            if (txPolicy instanceof BeanTransactionPolicy) {
                final SuspendedTransaction suspendedTransaction = instance.getBeanTransaction();
                if (suspendedTransaction != null) {
                    instance.setBeanTransaction(null);
                    final BeanTransactionPolicy beanTxEnv = (BeanTransactionPolicy) txPolicy;
                    beanTxEnv.resumeUserTransaction(suspendedTransaction);
                }
            }
            // Register the entity managers
            registerEntityManagers(instance, callContext);
            // Register for synchronization callbacks
            registerSessionSynchronization(instance, callContext);
            // Setup for business invocation
            callContext.setCurrentOperation(Operation.BUSINESS);
            callContext.setCurrentAllowedStates(null);
            callContext.setInvokedInterface(callInterface);
            final Method runMethod = beanContext.getMatchingBeanMethod(callMethod);
            callContext.set(Method.class, runMethod);
            if (currentCreationalContext != null) {
                currentCreationalContext.set(instance.creationalContext);
            }
            // Initialize interceptor stack
            final List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod);
            final InterceptorStack interceptorStack = new InterceptorStack(instance.bean, runMethod, Operation.BUSINESS, interceptors, instance.interceptors);
            // Invoke
            returnValue = interceptorStack.invoke(args);
        } catch (final Throwable e) {
            handleException(callContext, txPolicy, e);
        } finally {
            // un register EntityManager
            unregisterEntityManagers(instance, callContext);
            // Commit transaction
            afterInvoke(callContext, txPolicy, instance);
        }
        return returnValue;
    } finally {
        if (runAs != null) {
            try {
                securityService.associate(runAs);
            } catch (final LoginException e) {
            // no-op
            }
        }
        ThreadContext.exit(oldCallContext);
        if (currentCreationalContext != null) {
            currentCreationalContext.remove();
        }
    }
}
Also used : BeanTransactionPolicy(org.apache.openejb.core.transaction.BeanTransactionPolicy) SystemInstance(org.apache.openejb.loader.SystemInstance) ThreadContext(org.apache.openejb.core.ThreadContext) JtaTransactionPolicy(org.apache.openejb.core.transaction.JtaTransactionPolicy) TransactionPolicy(org.apache.openejb.core.transaction.TransactionPolicy) BeanTransactionPolicy(org.apache.openejb.core.transaction.BeanTransactionPolicy) SuspendedTransaction(org.apache.openejb.core.transaction.BeanTransactionPolicy.SuspendedTransaction) Method(java.lang.reflect.Method) CurrentCreationalContext(org.apache.openejb.cdi.CurrentCreationalContext) BeanContext(org.apache.openejb.BeanContext) InterceptorData(org.apache.openejb.core.interceptor.InterceptorData) InterceptorStack(org.apache.openejb.core.interceptor.InterceptorStack) LoginException(javax.security.auth.login.LoginException)

Aggregations

InterceptorData (org.apache.openejb.core.interceptor.InterceptorData)21 InterceptorStack (org.apache.openejb.core.interceptor.InterceptorStack)16 Method (java.lang.reflect.Method)14 TransactionPolicy (org.apache.openejb.core.transaction.TransactionPolicy)10 BeanContext (org.apache.openejb.BeanContext)9 ThreadContext (org.apache.openejb.core.ThreadContext)9 SystemInstance (org.apache.openejb.loader.SystemInstance)8 BeanTransactionPolicy (org.apache.openejb.core.transaction.BeanTransactionPolicy)6 JtaTransactionPolicy (org.apache.openejb.core.transaction.JtaTransactionPolicy)6 HashMap (java.util.HashMap)5 SessionBean (javax.ejb.SessionBean)5 ArrayList (java.util.ArrayList)4 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)4 InstanceContext (org.apache.openejb.core.InstanceContext)4 EJBLocalObject (javax.ejb.EJBLocalObject)3 EJBObject (javax.ejb.EJBObject)3 EntityManagerFactory (javax.persistence.EntityManagerFactory)3 LoginException (javax.security.auth.login.LoginException)3 ApplicationException (org.apache.openejb.ApplicationException)3 SuspendedTransaction (org.apache.openejb.core.transaction.BeanTransactionPolicy.SuspendedTransaction)3