org.apache.openejb.cdi.OpenEJBLifecycle Maven / Gradle / Ivy
The newest version!
/*
* 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.config.BeansDeployer;
import org.apache.webbeans.config.OpenWebBeansConfiguration;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.config.WebBeansFinder;
import org.apache.webbeans.container.BeanManagerImpl;
import org.apache.webbeans.intercept.InterceptorResolutionService;
import org.apache.webbeans.portable.AbstractProducer;
import org.apache.webbeans.portable.InjectionTargetImpl;
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 org.apache.webbeans.xml.WebBeansXMLConfigurator;
import javax.el.ELResolver;
import javax.enterprise.inject.spi.BeanManager;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.jsp.JspApplicationContext;
import javax.servlet.jsp.JspFactory;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* @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);
public static final String OPENEJB_CDI_SKIP_CLASS_NOT_FOUND = "openejb.cdi.skip-class-not-found";
/**
* Discover bean classes
*/
protected ScannerService scannerService;
protected final ContextsService contextsService;
/**
* Deploy discovered beans
*/
private final BeansDeployer deployer;
/**
* XML discovery.
*/
//XML discovery is removed from the specification. It is here for next revisions of spec.
private final WebBeansXMLConfigurator xmlDeployer;
/**
* Using for lookup operations
*/
private final JNDIService jndiService;
/**
* Root container.
*/
private final BeanManagerImpl beanManager;
private final WebBeansContext webBeansContext;
/**
* Manages unused conversations
*/
private ScheduledExecutorService service;
public OpenEJBLifecycle(final WebBeansContext webBeansContext) {
this.webBeansContext = webBeansContext;
beforeInitApplication(null);
this.beanManager = webBeansContext.getBeanManagerImpl();
this.xmlDeployer = new WebBeansXMLConfigurator();
this.deployer = new BeansDeployer(this.xmlDeployer, webBeansContext);
this.jndiService = webBeansContext.getService(JNDIService.class);
this.beanManager.setXMLConfigurator(this.xmlDeployer);
this.scannerService = webBeansContext.getScannerService();
this.contextsService = webBeansContext.getContextsService();
initApplication(null);
}
@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());
//Before Start
beforeStartApplication(startupObject);
//Load all plugins
webBeansContext.getPluginLoader().startUp();
//Get Plugin
final CdiPlugin cdiPlugin = (CdiPlugin) webBeansContext.getPluginLoader().getEjbPlugin();
final AppContext appContext = stuff.getAppContext();
if (stuff.getWebContext() == null) {
appContext.setWebBeansContext(webBeansContext);
}
cdiPlugin.setClassLoader(stuff.getClassLoader());
cdiPlugin.setWebBeansContext(webBeansContext);
cdiPlugin.startup();
//Configure EJB Deployments
cdiPlugin.configureDeployments(stuff.getBeanContexts());
//Resournce Injection Service
final CdiResourceInjectionService injectionService = (CdiResourceInjectionService) webBeansContext.getService(ResourceInjectionService.class);
injectionService.setAppContext(stuff.getAppContext());
//Deploy the beans
try {
//Initialize contexts
this.contextsService.init(startupObject);
//Scanning process
logger.debug("Scanning classpaths for beans artifacts.");
if (CdiScanner.class.isInstance(scannerService)) {
final CdiScanner service = CdiScanner.class.cast(scannerService);
service.init(startupObject);
} else {
new CdiScanner().init(startupObject);
}
//Scan
this.scannerService.scan();
// just to let us write custom CDI Extension using our internals easily
CURRENT_APP_INFO.set(StartupObject.class.cast(startupObject).getAppInfo());
//Deploy bean from XML. Also configures deployments, interceptors, decorators.
deployer.deploy(scannerService);
} catch (final Exception e1) {
SystemInstance.get().getComponent(Assembler.class).getLogger().error("CDI Beans module deployment failed", e1);
throw new OpenEJBRuntimeException(e1);
} finally {
CURRENT_APP_INFO.remove();
}
for (final BeanContext bc : stuff.getBeanContexts()) {
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
afterStartApplication(startupObject);
} finally {
Thread.currentThread().setContextClassLoader(oldCl);
// cleanup threadlocal used to enrich cdi context manually
OptimizedLoaderService.ADDITIONAL_EXTENSIONS.remove();
CdiScanner.ADDITIONAL_CLASSES.remove();
}
logger.info("OpenWebBeans Container has started, it took {0} ms.", Long.toString(System.currentTimeMillis() - begin));
}
@Override
public void stopApplication(final Object endObject) {
logger.debug("OpenWebBeans Container is stopping.");
try {
//Sub-classes operations
beforeStopApplication(null);
//Fire shut down
if (WebappBeanManager.class.isInstance(beanManager)) {
WebappBeanManager.class.cast(beanManager).beforeStop();
}
this.beanManager.fireEvent(new BeforeShutdownImpl());
//Destroys context
this.contextsService.destroy(null);
//Unbind BeanManager
if (jndiService != null) {
jndiService.unbind(WebBeansConstants.WEB_BEANS_MANAGER_JNDI_NAME);
}
//Free all plugin resources
((CdiPlugin) webBeansContext.getPluginLoader().getEjbPlugin()).clearProxies();
webBeansContext.getPluginLoader().shutDown();
//Clear extensions
webBeansContext.getExtensionLoader().clear();
//Delete Resolutions Cache
beanManager.getInjectionResolver().clearCaches();
//Delete AnnotateTypeCache
webBeansContext.getAnnotatedElementFactory().clear();
//After Stop
afterStopApplication(null);
// Clear BeanManager
this.beanManager.clear();
// Clear singleton list
WebBeansFinder.clearInstances(WebBeansUtil.getCurrentClassLoader());
} catch (final Exception e) {
logger.error("An error occured while stopping the container.", e);
}
}
/**
* @return the scannerService
*/
protected ScannerService getScannerService() {
return scannerService;
}
/**
* @return the contextsService
*/
public ContextsService getContextService() {
return contextsService;
}
/**
* @return the xmlDeployer
*/
protected WebBeansXMLConfigurator getXmlDeployer() {
return xmlDeployer;
}
/**
* @return the jndiService
*/
protected JNDIService getJndiService() {
return jndiService;
}
@Override
public void initApplication(final Properties properties) {
afterInitApplication(properties);
}
protected void beforeInitApplication(final Properties properties) {
//Do nothing as default
}
protected void afterInitApplication(final Properties properties) {
//Do nothing as default
}
protected void afterStartApplication(final Object startupObject) {
if (WebappBeanManager.class.isInstance(beanManager)) {
WebappBeanManager.class.cast(beanManager).afterStart();
}
}
public void startServletContext(final ServletContext servletContext) {
service = initializeServletContext(servletContext, webBeansContext);
}
public static ScheduledExecutorService initializeServletContext(final ServletContext servletContext, final WebBeansContext context) {
final String strDelay = context.getOpenWebBeansConfiguration().getProperty(OpenWebBeansConfiguration.CONVERSATION_PERIODIC_DELAY, "150000");
final long delay = Long.parseLong(strDelay);
final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(final Runnable runable) {
final Thread t = new Thread(runable, "OwbConversationCleaner-" + servletContext.getContextPath());
t.setDaemon(true);
return t;
}
});
executorService.scheduleWithFixedDelay(new ConversationCleaner(context), delay, delay, TimeUnit.MILLISECONDS);
final ELAdaptor elAdaptor = context.getService(ELAdaptor.class);
final ELResolver resolver = elAdaptor.getOwbELResolver();
//Application is configured as JSP
if (context.getOpenWebBeansConfiguration().isJspApplication()) {
logger.debug("Application is configured as JSP. Adding EL Resolver.");
final JspFactory factory = JspFactory.getDefaultFactory();
if (factory != null) {
final JspApplicationContext applicationCtx = factory.getJspApplicationContext(servletContext);
applicationCtx.addELResolver(resolver);
} else {
logger.debug("Default JspFactory instance was not found");
}
}
// Add BeanManager to the 'javax.enterprise.inject.spi.BeanManager' servlet context attribute
servletContext.setAttribute(BeanManager.class.getName(), context.getBeanManagerImpl());
return executorService;
}
/**
* Conversation cleaner thread, that
* clears unused conversations.
*/
private static final class ConversationCleaner implements Runnable {
private final WebBeansContext webBeansContext;
private ConversationCleaner(final WebBeansContext webBeansContext) {
this.webBeansContext = webBeansContext;
}
public void run() {
webBeansContext.getConversationManager().destroyWithRespectToTimout();
}
}
protected void afterStopApplication(final Object stopObject) throws Exception {
//Clear the resource injection service
final ResourceInjectionService injectionServices = webBeansContext.getService(ResourceInjectionService.class);
if (injectionServices != null) {
injectionServices.clear();
}
//Comment out for commit OWB-502
//ContextFactory.cleanUpContextFactory();
CdiAppContextsService.class.cast(contextsService).removeThreadLocals();
WebBeansFinder.clearInstances(WebBeansUtil.getCurrentClassLoader());
}
/**
* Returns servlet context otherwise throws exception.
*
* @param object object
* @return servlet context
*/
private Object getServletContext(Object object) {
if (ServletContextEvent.class.isInstance(object)) {
object = ServletContextEvent.class.cast(object).getServletContext();
return object;
}
return object;
}
protected void beforeStartApplication(final Object startupObject) {
//Do nothing as default
}
protected void beforeStopApplication(final Object stopObject) throws Exception {
if (service != null) {
service.shutdownNow();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy