Search in sources :

Example 1 with AsynchronousPool

use of org.apache.openejb.async.AsynchronousPool in project tomee by apache.

the class Assembler method destroyApplication.

public void destroyApplication(final AppInfo appInfo) throws UndeployException {
    final ReentrantLock l = lock;
    l.lock();
    try {
        deployedApplications.remove(appInfo.path);
        logger.info("destroyApplication.start", appInfo.path);
        final Context globalContext = containerSystem.getJNDIContext();
        final AppContext appContext = containerSystem.getAppContext(appInfo.appId);
        if (null == appContext) {
            logger.warning("Application id '" + appInfo.appId + "' not found in: " + Arrays.toString(containerSystem.getAppContextKeys()));
            return;
        }
        final ClassLoader classLoader = appContext.getClassLoader();
        SystemInstance.get().fireEvent(new AssemblerBeforeApplicationDestroyed(appInfo, appContext));
        // noinspection ConstantConditions
        final WebBeansContext webBeansContext = appContext.getWebBeansContext();
        if (webBeansContext != null) {
            final ClassLoader old = Thread.currentThread().getContextClassLoader();
            Thread.currentThread().setContextClassLoader(classLoader);
            try {
                final ServletContext context = appContext.isStandaloneModule() && appContext.getWebContexts().iterator().hasNext() ? appContext.getWebContexts().iterator().next().getServletContext() : null;
                webBeansContext.getService(ContainerLifecycle.class).stopApplication(context);
            } finally {
                Thread.currentThread().setContextClassLoader(old);
            }
        }
        final Map<String, Object> cb = appContext.getBindings();
        for (final Entry<String, Object> value : cb.entrySet()) {
            String path = value.getKey();
            if (path.startsWith("global")) {
                path = "java:" + path;
            }
            if (!path.startsWith("java:global")) {
                continue;
            }
            if (IvmContext.class.isInstance(globalContext)) {
                IvmContext.class.cast(globalContext).setReadOnly(false);
            }
            unbind(globalContext, path);
            unbind(globalContext, "openejb/global/" + path.substring("java:".length()));
            unbind(globalContext, path.substring("java:global".length()));
        }
        if (appInfo.appId != null && !appInfo.appId.isEmpty() && !"openejb".equals(appInfo.appId)) {
            unbind(globalContext, "global/" + appInfo.appId);
            unbind(globalContext, appInfo.appId);
        }
        final EjbResolver globalResolver = new EjbResolver(null, EjbResolver.Scope.GLOBAL);
        for (final AppInfo info : deployedApplications.values()) {
            globalResolver.addAll(info.ejbJars);
        }
        SystemInstance.get().setComponent(EjbResolver.class, globalResolver);
        final UndeployException undeployException = new UndeployException(messages.format("destroyApplication.failed", appInfo.path));
        final WebAppBuilder webAppBuilder = SystemInstance.get().getComponent(WebAppBuilder.class);
        if (webAppBuilder != null && !appInfo.webAppAlone) {
            try {
                webAppBuilder.undeployWebApps(appInfo);
            } catch (final Exception e) {
                undeployException.getCauses().add(new Exception("App: " + appInfo.path + ": " + e.getMessage(), e));
            }
        }
        // get all of the ejb deployments
        List<BeanContext> deployments = new ArrayList<>();
        for (final EjbJarInfo ejbJarInfo : appInfo.ejbJars) {
            for (final EnterpriseBeanInfo beanInfo : ejbJarInfo.enterpriseBeans) {
                final String deploymentId = beanInfo.ejbDeploymentId;
                final BeanContext beanContext = containerSystem.getBeanContext(deploymentId);
                if (beanContext == null) {
                    undeployException.getCauses().add(new Exception("deployment not found: " + deploymentId));
                } else {
                    deployments.add(beanContext);
                }
            }
        }
        // Just as with startup we need to get things in an
        // order that respects the singleton @DependsOn information
        // Theoreticlly if a Singleton depends on something in its
        // @PostConstruct, it can depend on it in its @PreDestroy.
        // Therefore we want to make sure that if A dependsOn B,
        // that we destroy A first then B so that B will still be
        // usable in the @PreDestroy method of A.
        // Sort them into the original starting order
        deployments = sort(deployments);
        // reverse that to get the stopping order
        Collections.reverse(deployments);
        // stop
        for (final BeanContext deployment : deployments) {
            final String deploymentID = String.valueOf(deployment.getDeploymentID());
            try {
                final Container container = deployment.getContainer();
                container.stop(deployment);
            } catch (final Throwable t) {
                undeployException.getCauses().add(new Exception("bean: " + deploymentID + ": " + t.getMessage(), t));
            }
        }
        // undeploy
        for (final BeanContext bean : deployments) {
            final String deploymentID = String.valueOf(bean.getDeploymentID());
            try {
                final Container container = bean.getContainer();
                container.undeploy(bean);
                bean.setContainer(null);
            } catch (final Throwable t) {
                undeployException.getCauses().add(new Exception("bean: " + deploymentID + ": " + t.getMessage(), t));
            } finally {
                bean.setDestroyed(true);
            }
        }
        if (webAppBuilder != null && appInfo.webAppAlone) {
            // now that EJB are stopped we can undeploy webapps
            try {
                webAppBuilder.undeployWebApps(appInfo);
            } catch (final Exception e) {
                undeployException.getCauses().add(new Exception("App: " + appInfo.path + ": " + e.getMessage(), e));
            }
        }
        // get the client ids
        final List<String> clientIds = new ArrayList<>();
        for (final ClientInfo clientInfo : appInfo.clients) {
            clientIds.add(clientInfo.moduleId);
            clientIds.addAll(clientInfo.localClients);
            clientIds.addAll(clientInfo.remoteClients);
        }
        for (final WebContext webContext : appContext.getWebContexts()) {
            containerSystem.removeWebContext(webContext);
        }
        TldScanner.forceCompleteClean(classLoader);
        // Clear out naming for all components first
        for (final BeanContext deployment : deployments) {
            final String deploymentID = String.valueOf(deployment.getDeploymentID());
            try {
                containerSystem.removeBeanContext(deployment);
            } catch (final Throwable t) {
                undeployException.getCauses().add(new Exception(deploymentID, t));
            }
            final JndiBuilder.Bindings bindings = deployment.get(JndiBuilder.Bindings.class);
            if (bindings != null) {
                for (final String name : bindings.getBindings()) {
                    try {
                        globalContext.unbind(name);
                    } catch (final Throwable t) {
                        undeployException.getCauses().add(new Exception("bean: " + deploymentID + ": " + t.getMessage(), t));
                    }
                }
            }
        }
        // stop this executor only now since @PreDestroy can trigger some stop events
        final AsynchronousPool pool = appContext.get(AsynchronousPool.class);
        if (pool != null) {
            pool.stop();
        }
        for (final CommonInfoObject jar : listCommonInfoObjectsForAppInfo(appInfo)) {
            try {
                globalContext.unbind(VALIDATOR_FACTORY_NAMING_CONTEXT + jar.uniqueId);
                globalContext.unbind(VALIDATOR_NAMING_CONTEXT + jar.uniqueId);
            } catch (final NamingException e) {
                if (EjbJarInfo.class.isInstance(jar)) {
                    undeployException.getCauses().add(new Exception("validator: " + jar.uniqueId + ": " + e.getMessage(), e));
                }
            // else an error but not that important
            }
        }
        try {
            if (globalContext instanceof IvmContext) {
                final IvmContext ivmContext = (IvmContext) globalContext;
                ivmContext.prune("openejb/Deployment");
                ivmContext.prune("openejb/local");
                ivmContext.prune("openejb/remote");
                ivmContext.prune("openejb/global");
            }
        } catch (final NamingException e) {
            undeployException.getCauses().add(new Exception("Unable to prune openejb/Deployments and openejb/local namespaces, this could cause future deployments to fail.", e));
        }
        deployments.clear();
        for (final String clientId : clientIds) {
            try {
                globalContext.unbind("/openejb/client/" + clientId);
            } catch (final Throwable t) {
                undeployException.getCauses().add(new Exception("client: " + clientId + ": " + t.getMessage(), t));
            }
        }
        // mbeans
        final MBeanServer server = LocalMBeanServer.get();
        for (final Object objectName : appInfo.jmx.values()) {
            try {
                final ObjectName on = new ObjectName((String) objectName);
                if (server.isRegistered(on)) {
                    server.unregisterMBean(on);
                }
                final CreationalContext cc = creationalContextForAppMbeans.remove(on);
                if (cc != null) {
                    cc.release();
                }
            } catch (final InstanceNotFoundException e) {
                logger.warning("can't unregister " + objectName + " because the mbean was not found", e);
            } catch (final MBeanRegistrationException e) {
                logger.warning("can't unregister " + objectName, e);
            } catch (final MalformedObjectNameException mone) {
                logger.warning("can't unregister because the ObjectName is malformed: " + objectName, mone);
            }
        }
        // destroy PUs before resources since the JPA provider can use datasources
        for (final PersistenceUnitInfo unitInfo : appInfo.persistenceUnits) {
            try {
                final Object object = globalContext.lookup(PERSISTENCE_UNIT_NAMING_CONTEXT + unitInfo.id);
                globalContext.unbind(PERSISTENCE_UNIT_NAMING_CONTEXT + unitInfo.id);
                // close EMF so all resources are released
                final ReloadableEntityManagerFactory remf = (ReloadableEntityManagerFactory) object;
                remf.close();
                persistenceClassLoaderHandler.destroy(unitInfo.id);
                remf.unregister();
            } catch (final Throwable t) {
                undeployException.getCauses().add(new Exception("persistence-unit: " + unitInfo.id + ": " + t.getMessage(), t));
            }
        }
        for (final String id : appInfo.resourceAliases) {
            final String name = OPENEJB_RESOURCE_JNDI_PREFIX + id;
            ContextualJndiReference.followReference.set(false);
            try {
                final Object object;
                try {
                    object = globalContext.lookup(name);
                } finally {
                    ContextualJndiReference.followReference.remove();
                }
                if (object instanceof ContextualJndiReference) {
                    final ContextualJndiReference contextualJndiReference = ContextualJndiReference.class.cast(object);
                    contextualJndiReference.removePrefix(appContext.getId());
                    if (contextualJndiReference.hasNoMorePrefix()) {
                        globalContext.unbind(name);
                    }
                // else not the last deployed application to use this resource so keep it
                } else {
                    globalContext.unbind(name);
                }
            } catch (final NamingException e) {
                logger.warning("can't unbind resource '{0}'", id);
            }
        }
        for (final String id : appInfo.resourceIds) {
            final String name = OPENEJB_RESOURCE_JNDI_PREFIX + id;
            try {
                destroyLookedUpResource(globalContext, id, name);
            } catch (final NamingException e) {
                logger.warning("can't unbind resource '{0}'", id);
            }
        }
        for (final ConnectorInfo connector : appInfo.connectors) {
            if (connector.resourceAdapter == null || connector.resourceAdapter.id == null) {
                continue;
            }
            final String name = OPENEJB_RESOURCE_JNDI_PREFIX + connector.resourceAdapter.id;
            try {
                destroyLookedUpResource(globalContext, connector.resourceAdapter.id, name);
            } catch (final NamingException e) {
                logger.warning("can't unbind resource '{0}'", connector);
            }
            for (final ResourceInfo outbound : connector.outbound) {
                try {
                    destroyLookedUpResource(globalContext, outbound.id, OPENEJB_RESOURCE_JNDI_PREFIX + outbound.id);
                } catch (final Exception e) {
                // no-op
                }
            }
            for (final ResourceInfo outbound : connector.adminObject) {
                try {
                    destroyLookedUpResource(globalContext, outbound.id, OPENEJB_RESOURCE_JNDI_PREFIX + outbound.id);
                } catch (final Exception e) {
                // no-op
                }
            }
            for (final MdbContainerInfo container : connector.inbound) {
                try {
                    containerSystem.removeContainer(container.id);
                    config.containerSystem.containers.remove(container);
                    this.containerSystem.getJNDIContext().unbind(JAVA_OPENEJB_NAMING_CONTEXT + container.service + "/" + container.id);
                } catch (final Exception e) {
                // no-op
                }
            }
        }
        for (final ContainerInfo containerInfo : appInfo.containers) {
            if (!containerInfo.applicationWide) {
                removeContainer(containerInfo.id);
            }
        }
        containerSystem.removeAppContext(appInfo.appId);
        if (!appInfo.properties.containsKey("tomee.destroying")) {
            // destroy tomee classloader after resources cleanup
            try {
                final Method m = classLoader.getClass().getMethod("internalStop");
                m.invoke(classLoader);
            } catch (final NoSuchMethodException nsme) {
            // no-op
            } catch (final Exception e) {
                logger.error("error stopping classloader of webapp " + appInfo.appId, e);
            }
            ClassLoaderUtil.cleanOpenJPACache(classLoader);
        }
        ClassLoaderUtil.destroyClassLoader(appInfo.appId, appInfo.path);
        if (undeployException.getCauses().size() > 0) {
            // logging causes here otherwise it will be eaten in later logs.
            for (Throwable cause : undeployException.getCauses()) {
                logger.error("undeployException original cause", cause);
            }
            throw undeployException;
        }
        logger.debug("destroyApplication.success", appInfo.path);
    } finally {
        l.unlock();
    }
}
Also used : IvmContext(org.apache.openejb.core.ivm.naming.IvmContext) WebContext(org.apache.openejb.core.WebContext) ArrayList(java.util.ArrayList) AsynchronousPool(org.apache.openejb.async.AsynchronousPool) JMXContainer(org.apache.openejb.assembler.monitoring.JMXContainer) Container(org.apache.openejb.Container) WebBeansContext(org.apache.webbeans.config.WebBeansContext) ServletContext(javax.servlet.ServletContext) NamingException(javax.naming.NamingException) LocalMBeanServer(org.apache.openejb.monitoring.LocalMBeanServer) MBeanServer(javax.management.MBeanServer) ReentrantLock(java.util.concurrent.locks.ReentrantLock) WebContext(org.apache.openejb.core.WebContext) SimpleBootstrapContext(org.apache.openejb.core.transaction.SimpleBootstrapContext) Context(javax.naming.Context) ServletContext(javax.servlet.ServletContext) MethodContext(org.apache.openejb.MethodContext) IvmContext(org.apache.openejb.core.ivm.naming.IvmContext) AppContext(org.apache.openejb.AppContext) InitialContext(javax.naming.InitialContext) WebBeansContext(org.apache.webbeans.config.WebBeansContext) BeanContext(org.apache.openejb.BeanContext) CreationalContext(javax.enterprise.context.spi.CreationalContext) DeploymentContext(org.apache.openejb.DeploymentContext) GeronimoBootstrapContext(org.apache.geronimo.connector.GeronimoBootstrapContext) BootstrapContext(javax.resource.spi.BootstrapContext) MalformedObjectNameException(javax.management.MalformedObjectNameException) AppContext(org.apache.openejb.AppContext) InstanceNotFoundException(javax.management.InstanceNotFoundException) AssemblerBeforeApplicationDestroyed(org.apache.openejb.assembler.classic.event.AssemblerBeforeApplicationDestroyed) Method(java.lang.reflect.Method) InvalidObjectException(java.io.InvalidObjectException) NameAlreadyBoundException(javax.naming.NameAlreadyBoundException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) ObjectStreamException(java.io.ObjectStreamException) ResourceAdapterInternalException(javax.resource.spi.ResourceAdapterInternalException) URISyntaxException(java.net.URISyntaxException) UndeployException(org.apache.openejb.UndeployException) DefinitionException(javax.enterprise.inject.spi.DefinitionException) ConstructionException(org.apache.xbean.recipe.ConstructionException) MBeanRegistrationException(javax.management.MBeanRegistrationException) InstanceNotFoundException(javax.management.InstanceNotFoundException) ValidationException(javax.validation.ValidationException) MalformedObjectNameException(javax.management.MalformedObjectNameException) DuplicateDeploymentIdException(org.apache.openejb.DuplicateDeploymentIdException) TimeoutException(java.util.concurrent.TimeoutException) NamingException(javax.naming.NamingException) OpenEJBException(org.apache.openejb.OpenEJBException) DeploymentException(javax.enterprise.inject.spi.DeploymentException) NoSuchApplicationException(org.apache.openejb.NoSuchApplicationException) MalformedURLException(java.net.MalformedURLException) OpenEJBRuntimeException(org.apache.openejb.OpenEJBRuntimeException) ContainerLifecycle(org.apache.webbeans.spi.ContainerLifecycle) ObjectName(javax.management.ObjectName) BeanContext(org.apache.openejb.BeanContext) CreationalContext(javax.enterprise.context.spi.CreationalContext) MBeanRegistrationException(javax.management.MBeanRegistrationException) ContextualJndiReference(org.apache.openejb.core.ivm.naming.ContextualJndiReference) UndeployException(org.apache.openejb.UndeployException)

Aggregations

IOException (java.io.IOException)1 InvalidObjectException (java.io.InvalidObjectException)1 ObjectStreamException (java.io.ObjectStreamException)1 Method (java.lang.reflect.Method)1 MalformedURLException (java.net.MalformedURLException)1 URISyntaxException (java.net.URISyntaxException)1 ArrayList (java.util.ArrayList)1 ExecutionException (java.util.concurrent.ExecutionException)1 TimeoutException (java.util.concurrent.TimeoutException)1 ReentrantLock (java.util.concurrent.locks.ReentrantLock)1 CreationalContext (javax.enterprise.context.spi.CreationalContext)1 DefinitionException (javax.enterprise.inject.spi.DefinitionException)1 DeploymentException (javax.enterprise.inject.spi.DeploymentException)1 InstanceNotFoundException (javax.management.InstanceNotFoundException)1 MBeanRegistrationException (javax.management.MBeanRegistrationException)1 MBeanServer (javax.management.MBeanServer)1 MalformedObjectNameException (javax.management.MalformedObjectNameException)1 ObjectName (javax.management.ObjectName)1 Context (javax.naming.Context)1 InitialContext (javax.naming.InitialContext)1