org.apache.openejb.cdi.OpenEJBLifecycle Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.openejb.cdi;
import org.apache.openejb.AppContext;
import org.apache.openejb.BeanContext;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.Assembler;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.webbeans.component.BuiltInOwbBean;
import org.apache.webbeans.component.SimpleProducerFactory;
import org.apache.webbeans.component.WebBeansType;
import org.apache.webbeans.config.BeansDeployer;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.config.WebBeansFinder;
import org.apache.webbeans.container.BeanManagerImpl;
import org.apache.webbeans.el.ELContextStore;
import org.apache.webbeans.intercept.InterceptorResolutionService;
import org.apache.webbeans.portable.AbstractProducer;
import org.apache.webbeans.portable.InjectionTargetImpl;
import org.apache.webbeans.portable.ProviderBasedProducer;
import org.apache.webbeans.portable.events.discovery.BeforeShutdownImpl;
import org.apache.webbeans.spi.ContainerLifecycle;
import org.apache.webbeans.spi.ContextsService;
import org.apache.webbeans.spi.JNDIService;
import org.apache.webbeans.spi.ResourceInjectionService;
import org.apache.webbeans.spi.ScannerService;
import org.apache.webbeans.spi.adaptor.ELAdaptor;
import org.apache.webbeans.util.WebBeansConstants;
import org.apache.webbeans.util.WebBeansUtil;
import javax.el.ELResolver;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspApplicationContext;
import javax.servlet.jsp.JspFactory;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
/**
* @version $Rev:$ $Date:$
*/
public class OpenEJBLifecycle implements ContainerLifecycle {
public static final ThreadLocal CURRENT_APP_INFO = new ThreadLocal();
//Logger instance
private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_CDI, OpenEJBLifecycle.class);
/**
* Discover bean classes
*/
protected ScannerService scannerService;
protected final ContextsService contextsService;
/**
* Deploy discovered beans
*/
private final BeansDeployer deployer;
/**
* Using for lookup operations
*/
private final JNDIService jndiService;
/**
* Root container.
*/
private final BeanManagerImpl beanManager;
private final WebBeansContext webBeansContext;
/**
* Manages unused conversations
*/
public OpenEJBLifecycle(final WebBeansContext webBeansContext) {
this.webBeansContext = webBeansContext;
this.beanManager = webBeansContext.getBeanManagerImpl();
this.deployer = new BeansDeployer(webBeansContext);
this.jndiService = webBeansContext.getService(JNDIService.class);
this.scannerService = webBeansContext.getScannerService();
this.contextsService = webBeansContext.getContextsService();
}
@Override
public BeanManager getBeanManager() {
return this.beanManager;
}
@Override
public void startApplication(final Object startupObject) {
if (ServletContextEvent.class.isInstance( startupObject)) {
startServletContext(ServletContext.class.cast(getServletContext(startupObject))); // TODO: check it is relevant
return;
} else if (!StartupObject.class.isInstance(startupObject)) {
logger.debug("startupObject is not of StartupObject type; ignored");
return;
}
final StartupObject stuff = (StartupObject) startupObject;
final ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
// Initalize Application Context
logger.info("OpenWebBeans Container is starting...");
final long begin = System.currentTimeMillis();
try {
Thread.currentThread().setContextClassLoader(stuff.getClassLoader());
final AppContext appContext = stuff.getAppContext();
if (stuff.getWebContext() == null) { // do it before any other things to keep our singleton finder working
appContext.setWebBeansContext(webBeansContext);
}
//Load all plugins
webBeansContext.getPluginLoader().startUp();
//Get Plugin
final CdiPlugin cdiPlugin = (CdiPlugin) webBeansContext.getPluginLoader().getEjbPlugin();
cdiPlugin.setClassLoader(stuff.getClassLoader());
cdiPlugin.setWebBeansContext(webBeansContext);
//Configure EJB Deployments
cdiPlugin.configureDeployments(stuff.getBeanContexts());
//Resournce Injection Service
final CdiResourceInjectionService injectionService = (CdiResourceInjectionService) webBeansContext.getService(ResourceInjectionService.class);
// todo use startupObject allDeployments to find Comp in priority (otherwise we can keep N times comps and loose time at injection time
injectionService.setAppContext(stuff.getAppContext(), stuff.getBeanContexts() != null ? stuff.getBeanContexts() : Collections.emptyList());
//Deploy the beans
CdiScanner cdiScanner = null;
try {
//Scanning process
logger.debug("Scanning classpaths for beans artifacts.");
if (CdiScanner.class.isInstance(scannerService)) {
cdiScanner = CdiScanner.class.cast(scannerService);
cdiScanner.setContext(webBeansContext);
cdiScanner.init(startupObject);
} else {
cdiScanner = new CdiScanner();
cdiScanner.setContext(webBeansContext);
cdiScanner.init(startupObject);
}
//Scan
this.scannerService.scan();
// just to let us write custom CDI Extension using our internals easily
CURRENT_APP_INFO.set(stuff.getAppInfo());
addInternalBeans(); // before next event which can register custom beans (JAX-RS)
SystemInstance.get().fireEvent(new WebBeansContextBeforeDeploy(webBeansContext));
//Deploy bean from XML. Also configures deployments, interceptors, decorators.
deployer.deploy(scannerService);
contextsService.init(startupObject); // fire app event and also starts SingletonContext and ApplicationContext
} catch (final Exception e1) {
SystemInstance.get().getComponent(Assembler.class).logger.error("CDI Beans module deployment failed", e1);
throw new OpenEJBRuntimeException(e1);
} finally {
CURRENT_APP_INFO.remove();
}
final Collection> ejbs = new ArrayList<>(stuff.getBeanContexts().size());
for (final BeanContext bc : stuff.getBeanContexts()) {
ejbs.add(bc.getManagedClass());
final CdiEjbBean cdiEjbBean = bc.get(CdiEjbBean.class);
if (cdiEjbBean == null) {
continue;
}
if (AbstractProducer.class.isInstance(cdiEjbBean)) {
AbstractProducer.class.cast(cdiEjbBean).defineInterceptorStack(cdiEjbBean, cdiEjbBean.getAnnotatedType(), cdiEjbBean.getWebBeansContext());
}
bc.mergeOWBAndOpenEJBInfo();
bc.set(InterceptorResolutionService.BeanInterceptorInfo.class, InjectionTargetImpl.class.cast(cdiEjbBean.getInjectionTarget()).getInterceptorInfo());
cdiEjbBean.initInternals();
}
//Start actual starting on sub-classes
if (beanManager instanceof WebappBeanManager) {
((WebappBeanManager) beanManager).afterStart();
}
for (final Class> clazz : cdiScanner.getStartupClasses()) {
if (ejbs.contains(clazz)) {
continue;
}
starts(beanManager, clazz);
}
} finally {
Thread.currentThread().setContextClassLoader(oldCl);
// cleanup threadlocal used to enrich cdi context manually
OptimizedLoaderService.ADDITIONAL_EXTENSIONS.remove();
}
logger.info("OpenWebBeans Container has started, it took {0} ms.", Long.toString(System.currentTimeMillis() - begin));
}
private void addInternalBeans() {
beanManager.getInjectionResolver().clearCaches();
if (!hasBean(beanManager, HttpServletRequest.class)) {
beanManager.addInternalBean(new HttpServletRequestBean(webBeansContext));
}
if (!hasBean(beanManager, HttpSession.class)) {
beanManager.addInternalBean(new InternalBean<>(webBeansContext, HttpSession.class, HttpSession.class));
}
if (!hasBean(beanManager, ServletContext.class)) {
beanManager.addInternalBean(new InternalBean<>(webBeansContext, ServletContext.class, ServletContext.class));
}
beanManager.getInjectionResolver().clearCaches(); // hasBean() usage can have cached several things
}
private static boolean hasBean(final BeanManagerImpl beanManagerImpl, final Class> type) {
return !beanManagerImpl.getInjectionResolver().implResolveByType(false, type).isEmpty();
}
private void starts(final BeanManager beanManager, final Class> clazz) {
final Bean> bean = beanManager.resolve(beanManager.getBeans(clazz));
if (!beanManager.isNormalScope(bean.getScope())) {
throw new IllegalStateException("Only normal scoped beans can use @Startup - likely @ApplicationScoped");
}
final CreationalContext
© 2015 - 2025 Weber Informatics LLC | Privacy Policy