org.jboss.weld.module.ejb.SessionBeanInjectionTarget Maven / Gradle / Ivy
The newest version!
/*
* JBoss, Home of Professional Open Source
* Copyright 2012, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.weld.module.ejb;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Set;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.Decorator;
import jakarta.enterprise.inject.spi.InjectionPoint;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedConstructor;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.bean.SessionBean;
import org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler;
import org.jboss.weld.bean.proxy.MethodHandler;
import org.jboss.weld.bean.proxy.ProxyObject;
import org.jboss.weld.injection.producer.AbstractInstantiator;
import org.jboss.weld.injection.producer.BeanInjectionTarget;
import org.jboss.weld.injection.producer.DefaultInjector;
import org.jboss.weld.injection.producer.DefaultInstantiator;
import org.jboss.weld.injection.producer.DefaultLifecycleCallbackInvoker;
import org.jboss.weld.injection.producer.Injector;
import org.jboss.weld.injection.producer.Instantiator;
import org.jboss.weld.injection.producer.InterceptionModelInitializer;
import org.jboss.weld.injection.producer.LifecycleCallbackInvoker;
import org.jboss.weld.injection.producer.SubclassDecoratorApplyingInstantiator;
import org.jboss.weld.injection.producer.SubclassedComponentInstantiator;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.util.Types;
class SessionBeanInjectionTarget extends BeanInjectionTarget {
public static SessionBeanInjectionTarget of(EnhancedAnnotatedType type, SessionBean bean,
BeanManagerImpl beanManager) {
LifecycleCallbackInvoker invoker = DefaultLifecycleCallbackInvoker.of(type);
Injector injector;
if (bean.getEjbDescriptor().isStateless() || bean.getEjbDescriptor().isSingleton()) {
injector = new DynamicInjectionPointInjector(type, bean, beanManager);
} else {
injector = new DefaultInjector(type, bean, beanManager);
}
return new SessionBeanInjectionTarget(type, bean, beanManager, injector, invoker);
}
private final SessionBean bean;
private SessionBeanInjectionTarget(EnhancedAnnotatedType type, SessionBean bean, BeanManagerImpl beanManager,
Injector injector, LifecycleCallbackInvoker invoker) {
super(type, bean, beanManager, injector, invoker);
this.bean = bean;
}
@Override
public SessionBean getBean() {
return bean;
}
@Override
protected Instantiator initInstantiator(EnhancedAnnotatedType type, Bean bean, BeanManagerImpl beanManager,
Set injectionPoints) {
if (bean instanceof SessionBean>) {
EnhancedAnnotatedType implementationClass = SessionBeans.getEjbImplementationClass((SessionBean) bean);
AbstractInstantiator instantiator = null;
if (type.equals(implementationClass)) {
instantiator = new DefaultInstantiator(type, bean, beanManager);
} else {
// Session bean subclassed by the EJB container
instantiator = SubclassedComponentInstantiator.forSubclassedEjb(type, implementationClass, bean, beanManager);
}
injectionPoints.addAll(instantiator.getConstructorInjectionPoint().getParameterInjectionPoints());
return instantiator;
} else {
throw new IllegalArgumentException("Cannot create SessionBeanInjectionTarget for " + bean);
}
}
@Override
public void initializeAfterBeanDiscovery(EnhancedAnnotatedType annotatedType) {
initializeInterceptionModel(annotatedType);
List> decorators = beanManager.resolveDecorators(getBean().getTypes(), getBean().getQualifiers());
if (!decorators.isEmpty()) {
Instantiator instantiator = getInstantiator();
EnhancedAnnotatedType implementationClass = SessionBeans.getEjbImplementationClass(getBean());
instantiator = SubclassedComponentInstantiator.forInterceptedDecoratedBean(implementationClass, getBean(),
(AbstractInstantiator) instantiator, beanManager);
instantiator = new SubclassDecoratorApplyingInstantiator(getBeanManager().getContextId(), instantiator,
getBean(), decorators, implementationClass.getJavaClass());
setInstantiator(instantiator);
}
/*
* We only take care of @AroundConstructor interception. The EJB container deals with the other types of interception.
*/
setupConstructorInterceptionInstantiator(beanManager.getInterceptorModelRegistry().get(getType()));
}
@Override
protected void buildInterceptionModel(EnhancedAnnotatedType annotatedType, AbstractInstantiator instantiator) {
/*
* instantiator.getConstructorInjectionPoint() may represent the constructor of the SessionBean subclass which may not
* have annotations applied
* Therefore, use the component class constructor instead of the one from subclass.
*/
EnhancedAnnotatedConstructor constructor = annotatedType
.getDeclaredEnhancedConstructor(instantiator.getConstructorInjectionPoint().getSignature());
new InterceptionModelInitializer(beanManager, annotatedType, constructor, getBean()).init();
}
@Override
public T produce(CreationalContext ctx) {
T result = super.produce(ctx);
if (result instanceof ProxyObject) {
// if decorators are applied, use SessionBeanViewMethodHandler
ProxyObject proxy = (ProxyObject) result;
proxy.weld_setHandler(new SessionBeanViewMethodHandler(bean.getTypes(),
(CombinedInterceptorAndDecoratorStackMethodHandler) proxy.weld_getHandler()));
}
return result;
}
@Override
public void inject(T instance, CreationalContext ctx) {
// explicitly use bean's AnnotatedType, not InjectionPoint's as this.getAnnotated()
// may represent the annotated type for the EJB-container subclass (see SubclassedComponentDescriptor)
getInjector().inject(instance, ctx, beanManager, bean.getAnnotated(), this);
}
/**
* This {@link MethodHandler} assures that any method invoked on a decorated {@link SessionBean} is a method that belongs to
* a bean type of the bean. If the methods belongs to the bean implementation and the bean implementation is not a bean type
* the handler tries to replace the method with the equivalent method defined on a bean type.
*
* @author Jozef Hartinger
*
*/
private static class SessionBeanViewMethodHandler extends CombinedInterceptorAndDecoratorStackMethodHandler {
private static final long serialVersionUID = -8038819529432133787L;
private final Set> beanTypes;
public SessionBeanViewMethodHandler(Set types, CombinedInterceptorAndDecoratorStackMethodHandler delegate) {
this.beanTypes = Types.getRawTypes(types);
setOuterDecorator(delegate.getOuterDecorator());
setInterceptorMethodHandler(delegate.getInterceptorMethodHandler());
}
@Override
public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
if (beanTypes.contains(thisMethod.getDeclaringClass())) {
return super.invoke(self, thisMethod, proceed, args);
} else {
Method decoratedTypeMethod = getBeanTypeMethod(thisMethod);
return super.invoke(self, decoratedTypeMethod, proceed, args);
}
}
private Method getBeanTypeMethod(Method method) {
for (Class> c : beanTypes) {
try {
return c.getMethod(method.getName(), method.getParameterTypes());
} catch (NoSuchMethodException e) {
continue;
}
}
return method;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy