Search in sources :

Example 6 with CancellationFlag

use of org.jboss.as.ejb3.component.interceptors.CancellationFlag in project wildfly by wildfly.

the class AssociationImpl method receiveInvocationRequest.

@Override
public CancelHandle receiveInvocationRequest(@NotNull final InvocationRequest invocationRequest) {
    final EJBIdentifier ejbIdentifier = invocationRequest.getEJBIdentifier();
    final String appName = ejbIdentifier.getAppName();
    final String moduleName = ejbIdentifier.getModuleName();
    final String distinctName = ejbIdentifier.getDistinctName();
    final String beanName = ejbIdentifier.getBeanName();
    final EjbDeploymentInformation ejbDeploymentInformation = findEJB(appName, moduleName, distinctName, beanName);
    if (ejbDeploymentInformation == null) {
        invocationRequest.writeNoSuchEJB();
        return CancelHandle.NULL;
    }
    final ClassLoader classLoader = ejbDeploymentInformation.getDeploymentClassLoader();
    ClassLoader originalTccl = WildFlySecurityManager.getCurrentContextClassLoaderPrivileged();
    WildFlySecurityManager.setCurrentContextClassLoaderPrivileged(classLoader);
    final InvocationRequest.Resolved requestContent;
    try {
        requestContent = invocationRequest.getRequestContent(classLoader);
    } catch (IOException | ClassNotFoundException e) {
        invocationRequest.writeException(new EJBException(e));
        return CancelHandle.NULL;
    } finally {
        WildFlySecurityManager.setCurrentContextClassLoaderPrivileged(originalTccl);
    }
    final Map<String, Object> attachments = requestContent.getAttachments();
    final EJBLocator<?> ejbLocator = requestContent.getEJBLocator();
    final String viewClassName = ejbLocator.getViewType().getName();
    if (!ejbDeploymentInformation.isRemoteView(viewClassName)) {
        invocationRequest.writeWrongViewType();
        return CancelHandle.NULL;
    }
    final ComponentView componentView = ejbDeploymentInformation.getView(viewClassName);
    final Method invokedMethod = findMethod(componentView, invocationRequest.getMethodLocator());
    if (invokedMethod == null) {
        invocationRequest.writeNoSuchMethod();
        return CancelHandle.NULL;
    }
    final Component component = componentView.getComponent();
    try {
        component.waitForComponentStart();
    } catch (RuntimeException e) {
        invocationRequest.writeException(new EJBException(e));
        return CancelHandle.NULL;
    }
    final EJBLocator<?> actualLocator;
    if (component instanceof StatefulSessionComponent) {
        if (ejbLocator.isStateless()) {
            final SessionID sessionID = ((StatefulSessionComponent) component).createSessionRemote();
            try {
                invocationRequest.convertToStateful(sessionID);
            } catch (IllegalArgumentException e) {
                // cannot convert (old protocol)
                invocationRequest.writeNotStateful();
                return CancelHandle.NULL;
            }
            actualLocator = ejbLocator.withSession(sessionID);
        } else {
            actualLocator = ejbLocator;
        }
    } else {
        if (ejbLocator.isStateful()) {
            invocationRequest.writeNotStateful();
            return CancelHandle.NULL;
        } else {
            actualLocator = ejbLocator;
        }
    }
    final boolean isAsync = componentView.isAsynchronous(invokedMethod);
    final boolean oneWay = isAsync && invokedMethod.getReturnType() == void.class;
    if (oneWay) {
        // send immediate response
        updateAffinities(invocationRequest, attachments, ejbLocator, componentView);
        requestContent.writeInvocationResult(null);
    } else if (isAsync) {
        invocationRequest.writeProceedAsync();
    }
    final CancellationFlag cancellationFlag = new CancellationFlag();
    Runnable runnable = () -> {
        if (!cancellationFlag.runIfNotCancelled()) {
            if (!oneWay)
                invocationRequest.writeCancelResponse();
            return;
        }
        // invoke the method
        final Object result;
        try {
            final Map<String, Object> contextDataHolder = new HashMap<>();
            result = invokeMethod(componentView, invokedMethod, invocationRequest, requestContent, cancellationFlag, actualLocator, contextDataHolder);
            attachments.putAll(contextDataHolder);
        } catch (EJBComponentUnavailableException ex) {
            // if the Jakarta Enterprise Beans are shutting down when the invocation was done, then it's as good as the Jakarta Enterprise Beans not being available. The client has to know about this as
            // a "no such EJB" failure so that it can retry the invocation on a different node if possible.
            EjbLogger.EJB3_INVOCATION_LOGGER.debugf("Cannot handle method invocation: %s on bean: %s due to Jakarta Enterprise Beans component unavailability exception. Returning a no such Jakarta Enterprise Beans available message back to client", invokedMethod, beanName);
            if (!oneWay)
                invocationRequest.writeNoSuchEJB();
            return;
        } catch (ComponentIsStoppedException ex) {
            EjbLogger.EJB3_INVOCATION_LOGGER.debugf("Cannot handle method invocation: %s on bean: %s due to Jakarta Enterprise Beans component stopped exception. Returning a no such Jakarta Enterprise Beans available message back to client", invokedMethod, beanName);
            if (!oneWay)
                invocationRequest.writeNoSuchEJB();
            return;
        // TODO should we write a specifc response with a specific protocol letting client know that server is suspending?
        } catch (CancellationException ex) {
            if (!oneWay)
                invocationRequest.writeCancelResponse();
            return;
        } catch (Exception exception) {
            if (oneWay)
                return;
            // write out the failure
            final Exception exceptionToWrite;
            final Throwable cause = exception.getCause();
            if (componentView.getComponent() instanceof StatefulSessionComponent && exception instanceof EJBException && cause != null) {
                if (!(componentView.getComponent().isRemotable(cause))) {
                    // Avoid serializing the cause of the exception in case it is not remotable
                    // Client might not be able to deserialize and throw ClassNotFoundException
                    exceptionToWrite = new EJBException(exception.getLocalizedMessage());
                } else {
                    exceptionToWrite = exception;
                }
            } else {
                exceptionToWrite = exception;
            }
            invocationRequest.writeException(exceptionToWrite);
            return;
        }
        // invocation was successful
        if (!oneWay)
            try {
                updateAffinities(invocationRequest, attachments, actualLocator, componentView);
                requestContent.writeInvocationResult(result);
            } catch (Throwable ioe) {
                EjbLogger.REMOTE_LOGGER.couldNotWriteMethodInvocation(ioe, invokedMethod, beanName, appName, moduleName, distinctName);
            }
    };
    // invoke the method and write out the response, possibly on a separate thread
    execute(invocationRequest, runnable, isAsync, false);
    return cancellationFlag::cancel;
}
Also used : ComponentIsStoppedException(org.jboss.as.ee.component.ComponentIsStoppedException) SessionBeanComponent(org.jboss.as.ejb3.component.session.SessionBeanComponent) StatefulSessionComponent(org.jboss.as.ejb3.component.stateful.StatefulSessionComponent) StatelessSessionComponent(org.jboss.as.ejb3.component.stateless.StatelessSessionComponent) Component(org.jboss.as.ee.component.Component) EJBComponentUnavailableException(org.jboss.as.ejb3.component.EJBComponentUnavailableException) EjbDeploymentInformation(org.jboss.as.ejb3.deployment.EjbDeploymentInformation) InvocationRequest(org.jboss.ejb.server.InvocationRequest) StatefulSessionComponent(org.jboss.as.ejb3.component.stateful.StatefulSessionComponent) IOException(java.io.IOException) Method(java.lang.reflect.Method) EJBComponentUnavailableException(org.jboss.as.ejb3.component.EJBComponentUnavailableException) CancellationException(java.util.concurrent.CancellationException) EJBException(javax.ejb.EJBException) ComponentIsStoppedException(org.jboss.as.ee.component.ComponentIsStoppedException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) ComponentView(org.jboss.as.ee.component.ComponentView) CancellationException(java.util.concurrent.CancellationException) CancellationFlag(org.jboss.as.ejb3.component.interceptors.CancellationFlag) EJBException(javax.ejb.EJBException) EJBIdentifier(org.jboss.ejb.client.EJBIdentifier) SessionID(org.jboss.ejb.client.SessionID) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Aggregations

SessionBeanComponent (org.jboss.as.ejb3.component.session.SessionBeanComponent)5 InterceptorContext (org.jboss.invocation.InterceptorContext)5 HashMap (java.util.HashMap)4 Map (java.util.Map)4 SecurityIdentity (org.wildfly.security.auth.server.SecurityIdentity)4 CancellationFlag (org.jboss.as.ejb3.component.interceptors.CancellationFlag)3 Method (java.lang.reflect.Method)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 Component (org.jboss.as.ee.component.Component)2 ComponentView (org.jboss.as.ee.component.ComponentView)2 StartupCountdown (org.jboss.as.ee.component.deployers.StartupCountdown)2 EjbDeploymentInformation (org.jboss.as.ejb3.deployment.EjbDeploymentInformation)2 SecurityDomain (org.wildfly.security.auth.server.SecurityDomain)2 IOException (java.io.IOException)1 Serializable (java.io.Serializable)1 UnknownHostException (java.net.UnknownHostException)1 PrivilegedAction (java.security.PrivilegedAction)1 CancellationException (java.util.concurrent.CancellationException)1 ExecutionException (java.util.concurrent.ExecutionException)1 ExecutorService (java.util.concurrent.ExecutorService)1