use of org.jboss.as.ejb3.component.session.SessionBeanComponent in project wildfly by wildfly.
the class LocalEjbReceiver method processInvocation.
@Override
protected void processInvocation(final EJBReceiverInvocationContext receiverContext) {
final EJBClientInvocationContext invocation = receiverContext.getClientInvocationContext();
final EJBLocator<?> locator = invocation.getLocator();
final EjbDeploymentInformation ejb = findBean(locator);
final EJBComponent ejbComponent = ejb.getEjbComponent();
final Class<?> viewClass = invocation.getViewClass();
final ComponentView view = ejb.getView(viewClass.getName());
if (view == null) {
throw EjbLogger.ROOT_LOGGER.viewNotFound(viewClass.getName(), ejb.getEjbName());
}
// make sure it's a remote view
if (!ejb.isRemoteView(viewClass.getName())) {
throw EjbLogger.ROOT_LOGGER.viewNotFound(viewClass.getName(), ejb.getEjbName());
}
final ClonerConfiguration paramConfig = new ClonerConfiguration();
paramConfig.setClassCloner(new ClassLoaderClassCloner(ejb.getDeploymentClassLoader()));
final ObjectCloner parameterCloner = createCloner(paramConfig);
//TODO: this is not very efficient
final Method method = view.getMethod(invocation.getInvokedMethod().getName(), DescriptorUtils.methodDescriptor(invocation.getInvokedMethod()));
final boolean async = view.isAsynchronous(method) || invocation.isClientAsync();
final Object[] parameters;
if (invocation.getParameters() == null) {
parameters = EMPTY_OBJECT_ARRAY;
} else {
parameters = new Object[invocation.getParameters().length];
for (int i = 0; i < parameters.length; ++i) {
parameters[i] = clone(method.getParameterTypes()[i], parameterCloner, invocation.getParameters()[i], allowPassByReference);
}
}
final InterceptorContext interceptorContext = new InterceptorContext();
interceptorContext.setParameters(parameters);
interceptorContext.setMethod(method);
interceptorContext.setTransaction(invocation.getTransaction());
interceptorContext.setTarget(invocation.getInvokedProxy());
// setup the context data in the InterceptorContext
final Map<AttachmentKey<?>, ?> privateAttachments = invocation.getAttachments();
final Map<String, Object> invocationContextData = invocation.getContextData();
if (invocationContextData == null && privateAttachments.isEmpty()) {
// no private or public data
interceptorContext.setContextData(new HashMap<String, Object>());
} else {
final Map<String, Object> data = new HashMap<String, Object>();
interceptorContext.setContextData(data);
// write out public (application specific) context data
if (invocationContextData != null)
for (Map.Entry<String, Object> entry : invocationContextData.entrySet()) {
data.put(entry.getKey(), entry.getValue());
}
if (!privateAttachments.isEmpty()) {
// now write out the JBoss specific attachments under a single key and the value will be the
// entire map of JBoss specific attachments
data.put(EJBClientInvocationContext.PRIVATE_ATTACHMENTS_KEY, privateAttachments);
}
// Note: The code here is just for backward compatibility of 1.0.x version of EJB client project
// against AS7 7.1.x releases. Discussion here https://github.com/jbossas/jboss-ejb-client/pull/11#issuecomment-6573863
final boolean txIdAttachmentPresent = privateAttachments.containsKey(AttachmentKeys.TRANSACTION_ID_KEY);
if (txIdAttachmentPresent) {
// we additionally add/duplicate the transaction id under a different attachment key
// to preserve backward compatibility. This is here just for 1.0.x backward compatibility
data.put(TransactionID.PRIVATE_DATA_KEY, privateAttachments.get(AttachmentKeys.TRANSACTION_ID_KEY));
}
}
interceptorContext.putPrivateData(Component.class, ejbComponent);
interceptorContext.putPrivateData(ComponentView.class, view);
if (locator.isStateful()) {
interceptorContext.putPrivateData(SessionID.class, locator.asStateful().getSessionId());
} else if (locator instanceof EntityEJBLocator) {
throw EjbLogger.ROOT_LOGGER.ejbNotFoundInDeployment(locator);
}
final ClonerConfiguration config = new ClonerConfiguration();
config.setClassCloner(new LocalInvocationClassCloner(WildFlySecurityManager.getClassLoaderPrivileged(invocation.getInvokedProxy().getClass())));
final ObjectCloner resultCloner = createCloner(config);
if (async) {
if (ejbComponent instanceof SessionBeanComponent) {
final CancellationFlag flag = new CancellationFlag();
final SessionBeanComponent component = (SessionBeanComponent) ejbComponent;
final boolean isAsync = view.isAsynchronous(method);
final boolean oneWay = isAsync && method.getReturnType() == void.class;
final boolean isSessionBean = view.getComponent() instanceof SessionBeanComponent;
if (isAsync && isSessionBean) {
if (!oneWay) {
interceptorContext.putPrivateData(CancellationFlag.class, flag);
}
}
final SecurityContext securityContext;
if (WildFlySecurityManager.isChecking()) {
securityContext = AccessController.doPrivileged((PrivilegedAction<SecurityContext>) SecurityContextAssociation::getSecurityContext);
} else {
securityContext = SecurityContextAssociation.getSecurityContext();
}
final StartupCountdown.Frame frame = StartupCountdown.current();
final Runnable task = () -> {
if (!flag.runIfNotCancelled()) {
receiverContext.requestCancelled();
return;
}
setSecurityContextOnAssociation(securityContext);
StartupCountdown.restore(frame);
try {
final Object result;
try {
result = view.invoke(interceptorContext);
} catch (Exception e) {
// WFLY-4331 - clone the exception of an async task
receiverContext.resultReady(new CloningExceptionProducer(invocation, resultCloner, e, allowPassByReference));
return;
}
// if the result is null, there is no cloning needed
if (result == null) {
receiverContext.resultReady(NULL_RESULT);
return;
}
// WFLY-4331 - clone the result of an async task
if (result instanceof Future) {
// blocking is very unlikely here, so just defer interrupts when they happen
boolean intr = Thread.interrupted();
Object asyncValue;
try {
for (; ; ) try {
asyncValue = ((Future<?>) result).get();
break;
} catch (InterruptedException e) {
intr = true;
} catch (ExecutionException e) {
// WFLY-4331 - clone the exception of an async task
receiverContext.resultReady(new CloningExceptionProducer(invocation, resultCloner, e, allowPassByReference));
return;
}
} finally {
if (intr)
Thread.currentThread().interrupt();
}
// if the return value is null, there is no cloning needed
if (asyncValue == null) {
receiverContext.resultReady(NULL_RESULT);
return;
}
receiverContext.resultReady(new CloningResultProducer(invocation, resultCloner, asyncValue, allowPassByReference));
return;
}
receiverContext.resultReady(new CloningResultProducer(invocation, resultCloner, result, allowPassByReference));
} finally {
StartupCountdown.restore(null);
clearSecurityContextOnAssociation();
}
};
invocation.putAttachment(CANCELLATION_FLAG_ATTACHMENT_KEY, flag);
interceptorContext.putPrivateData(CancellationFlag.class, flag);
final ExecutorService executor = component.getAsynchronousExecutor();
if (executor == null) {
receiverContext.resultReady(new EJBReceiverInvocationContext.ResultProducer.Failed(EjbLogger.ROOT_LOGGER.executorIsNull()));
} else {
// this normally isn't necessary unless the client didn't detect that it was an async method for some reason
receiverContext.proceedAsynchronously();
executor.execute(task);
}
} else {
throw EjbLogger.ROOT_LOGGER.asyncInvocationOnlyApplicableForSessionBeans();
}
} else {
final Object result;
try {
result = view.invoke(interceptorContext);
} catch (Exception e) {
//we even have to clone the exception type
//to make sure it matches
receiverContext.resultReady(new CloningExceptionProducer(invocation, resultCloner, e, allowPassByReference));
return;
}
//we do not marshal the return type unless we have to, the spec only says we have to
//pass parameters by reference
receiverContext.resultReady(new CloningResultProducer(invocation, resultCloner, result, allowPassByReference));
}
}
use of org.jboss.as.ejb3.component.session.SessionBeanComponent in project wildfly by wildfly.
the class AsyncFutureInterceptorFactory method create.
@Override
public Interceptor create(final InterceptorFactoryContext context) {
final SessionBeanComponent component = (SessionBeanComponent) context.getContextData().get(Component.class);
if (component.isSecurityDomainKnown()) {
return new Interceptor() {
@Override
public Object processInvocation(final InterceptorContext context) throws Exception {
if (!context.isBlockingCaller()) {
return context.proceed();
}
final InterceptorContext asyncInterceptorContext = context.clone();
asyncInterceptorContext.putPrivateData(InvocationType.class, InvocationType.ASYNC);
final CancellationFlag flag = new CancellationFlag();
final SecurityDomain securityDomain = context.getPrivateData(SecurityDomain.class);
final StartupCountdown.Frame frame = StartupCountdown.current();
final SecurityIdentity currentIdentity = securityDomain == null ? null : securityDomain.getCurrentSecurityIdentity();
final Connection remoteConnection = getConnection();
Callable<Object> invocationTask = () -> {
setConnection(remoteConnection);
StartupCountdown.restore(frame);
try {
return asyncInterceptorContext.proceed();
} finally {
StartupCountdown.restore(null);
clearConnection();
}
};
final AsyncInvocationTask task = new AsyncInvocationTask(flag) {
@Override
protected Object runInvocation() throws Exception {
if (currentIdentity != null) {
return currentIdentity.runAs(invocationTask);
} else {
return invocationTask.call();
}
}
};
asyncInterceptorContext.putPrivateData(CancellationFlag.class, flag);
asyncInterceptorContext.setBlockingCaller(false);
return execute(component, task);
}
};
} else {
return new Interceptor() {
@Override
public Object processInvocation(final InterceptorContext context) throws Exception {
if (!context.isBlockingCaller()) {
return context.proceed();
}
final InterceptorContext asyncInterceptorContext = context.clone();
asyncInterceptorContext.putPrivateData(InvocationType.class, InvocationType.ASYNC);
final CancellationFlag flag = new CancellationFlag();
final SecurityContext securityContext;
if (WildFlySecurityManager.isChecking()) {
securityContext = AccessController.doPrivileged(new PrivilegedAction<SecurityContext>() {
@Override
public SecurityContext run() {
return SecurityContextAssociation.getSecurityContext();
}
});
} else {
securityContext = SecurityContextAssociation.getSecurityContext();
}
// clone the original security context so that changes to the original security context in a separate (caller/unrelated) thread doesn't affect
// the security context associated with the async invocation thread
final SecurityContext clonedSecurityContext;
if (securityContext instanceof JBossSecurityContext) {
clonedSecurityContext = (SecurityContext) ((JBossSecurityContext) securityContext).clone();
} else {
// we can't do anything if it isn't a JBossSecurityContext so just use the original one
clonedSecurityContext = securityContext;
}
final Connection remoteConnection = getConnection();
final StartupCountdown.Frame frame = StartupCountdown.current();
final AsyncInvocationTask task = new AsyncInvocationTask(flag) {
@Override
protected Object runInvocation() throws Exception {
setSecurityContextOnAssociation(clonedSecurityContext);
setConnection(remoteConnection);
StartupCountdown.restore(frame);
try {
return asyncInterceptorContext.proceed();
} finally {
StartupCountdown.restore(null);
try {
clearSecurityContextOnAssociation();
} finally {
clearConnection();
}
}
}
};
asyncInterceptorContext.putPrivateData(CancellationFlag.class, flag);
asyncInterceptorContext.setBlockingCaller(false);
return execute(component, task);
}
};
}
}
use of org.jboss.as.ejb3.component.session.SessionBeanComponent in project wildfly by wildfly.
the class AssociationImpl method invokeMethod.
static Object invokeMethod(final ComponentView componentView, final Method method, final InvocationRequest incomingInvocation, final InvocationRequest.Resolved content, final CancellationFlag cancellationFlag) throws Exception {
final InterceptorContext interceptorContext = new InterceptorContext();
interceptorContext.setParameters(content.getParameters());
interceptorContext.setMethod(method);
interceptorContext.putPrivateData(Component.class, componentView.getComponent());
interceptorContext.putPrivateData(ComponentView.class, componentView);
interceptorContext.putPrivateData(InvocationType.class, InvocationType.REMOTE);
interceptorContext.setBlockingCaller(false);
// setup the contextData on the (spec specified) InvocationContext
final Map<String, Object> invocationContextData = new HashMap<String, Object>();
interceptorContext.setContextData(invocationContextData);
if (content.getAttachments() != null) {
// attach the attachments which were passed from the remote client
for (final Map.Entry<String, Object> attachment : content.getAttachments().entrySet()) {
if (attachment == null) {
continue;
}
final String key = attachment.getKey();
final Object value = attachment.getValue();
// application, so add these attachments to the privateData of the InterceptorContext
if (EJBClientInvocationContext.PRIVATE_ATTACHMENTS_KEY.equals(key)) {
final Map<?, ?> privateAttachments = (Map<?, ?>) value;
for (final Map.Entry<?, ?> privateAttachment : privateAttachments.entrySet()) {
interceptorContext.putPrivateData(privateAttachment.getKey(), privateAttachment.getValue());
}
} else {
// add it to the InvocationContext which will be visible to the target bean and the
// application specific interceptors
invocationContextData.put(key, value);
}
}
}
// add the session id to the interceptor context, if it's a stateful ejb locator
final EJBLocator<?> ejbLocator = content.getEJBLocator();
if (ejbLocator.isStateful()) {
interceptorContext.putPrivateData(SessionID.class, ejbLocator.asStateful().getSessionId());
}
// add transaction
if (content.hasTransaction()) {
interceptorContext.setTransactionSupplier(content::getTransaction);
}
// add security identity
final SecurityIdentity securityIdentity = incomingInvocation.getSecurityIdentity();
final boolean isAsync = componentView.isAsynchronous(method);
final boolean oneWay = isAsync && method.getReturnType() == void.class;
final boolean isSessionBean = componentView.getComponent() instanceof SessionBeanComponent;
if (isAsync && isSessionBean) {
if (!oneWay) {
interceptorContext.putPrivateData(CancellationFlag.class, cancellationFlag);
}
final Object result = invokeWithIdentity(componentView, interceptorContext, securityIdentity);
return result == null ? null : ((Future<?>) result).get();
} else {
return invokeWithIdentity(componentView, interceptorContext, securityIdentity);
}
}
Aggregations