use of org.jboss.ejb.server.InvocationRequest 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();
final InvocationRequest.Resolved requestContent;
try {
requestContent = invocationRequest.getRequestContent(classLoader);
} catch (IOException | ClassNotFoundException e) {
invocationRequest.writeException(new EJBException(e));
return CancelHandle.NULL;
}
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 boolean isAsync = componentView.isAsynchronous(invokedMethod);
final boolean oneWay = isAsync && invokedMethod.getReturnType() == void.class;
if (oneWay) {
// send immediate response
requestContent.writeInvocationResult(null);
}
final CancellationFlag cancellationFlag = new CancellationFlag();
Runnable runnable = () -> {
if (!cancellationFlag.runIfNotCancelled()) {
if (!oneWay)
invocationRequest.writeCancelResponse();
return;
}
// invoke the method
final Object result;
// the Remoting connection that is set here is only used for legacy purposes
SecurityActions.remotingContextSetConnection(invocationRequest.getProviderInterface(Connection.class));
try {
result = invokeMethod(componentView, invokedMethod, invocationRequest, requestContent, cancellationFlag);
} catch (EJBComponentUnavailableException ex) {
// if the EJB is shutting down when the invocation was done, then it's as good as the EJB 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 EJB component unavailability exception. Returning a no such EJB 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 EJB component stopped exception. Returning a no such EJB 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 {
// attach any weak affinity if available
Affinity weakAffinity = null;
if (ejbLocator.isStateful() && componentView.getComponent() instanceof StatefulSessionComponent) {
final StatefulSessionComponent statefulSessionComponent = (StatefulSessionComponent) componentView.getComponent();
weakAffinity = getWeakAffinity(statefulSessionComponent, ejbLocator.asStateful());
} else if (componentView.getComponent() instanceof StatelessSessionComponent) {
final StatelessSessionComponent statelessSessionComponent = (StatelessSessionComponent) componentView.getComponent();
weakAffinity = statelessSessionComponent.getWeakAffinity();
}
if (weakAffinity != null && !weakAffinity.equals(Affinity.NONE)) {
attachments.put(Affinity.WEAK_AFFINITY_CONTEXT_KEY, weakAffinity);
}
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);
return cancellationFlag::cancel;
}
Aggregations