All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gravitee.node.container.spring.SpringBasedContainer Maven / Gradle / Ivy

There is a newer version: 7.0.0-alpha.13
Show newest version
/**
 * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
 *
 * 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 io.gravitee.node.container.spring;

import io.gravitee.common.component.LifecycleComponent;
import io.gravitee.kubernetes.client.spring.KubernetesClientConfiguration;
import io.gravitee.node.api.Node;
import io.gravitee.node.api.license.LicenseManager;
import io.gravitee.node.certificates.spring.NodeCertificatesConfiguration;
import io.gravitee.node.container.AbstractContainer;
import io.gravitee.node.container.spring.env.EnvironmentConfiguration;
import io.gravitee.node.container.spring.env.PropertiesConfiguration;
import io.gravitee.node.license.LicenseLoaderService;
import io.gravitee.node.management.http.spring.ManagementConfiguration;
import io.gravitee.node.monitoring.spring.NodeMonitoringConfiguration;
import io.gravitee.node.secrets.service.spring.SecretServiceConfiguration;
import io.gravitee.node.vertx.spring.VertxConfiguration;
import io.gravitee.plugin.core.internal.BootPluginEventListener;
import io.gravitee.plugin.core.internal.PluginRegistryImpl;
import io.gravitee.plugin.core.spring.BootPluginConfiguration;
import io.gravitee.plugin.core.spring.BootPluginHandlerBeanRegistryPostProcessor;
import io.gravitee.plugin.core.spring.PluginConfiguration;
import io.gravitee.plugin.core.spring.PluginHandlerBeanRegistryPostProcessor;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author David BRASSELY (david.brassely at graviteesource.com)
 * @author GraviteeSource Team
 */
@Slf4j
public abstract class SpringBasedContainer extends AbstractContainer {

    private AnnotationConfigApplicationContext ctx;

    @Override
    public void initialize() {
        if (!initialized) {
            initializeEnvironment();
            initializeLogging();
            initializeContext();
        }

        initialized = true;
    }

    protected void initializeContext() {
        log.info("Starting Boot phase.");

        final AnnotationConfigApplicationContext bootCtx = new AnnotationConfigApplicationContext();
        final List> bootstrapClasses = bootstrapClasses();

        // Register all the bootstrap classes into the boot spring context.
        bootstrapClasses.forEach(bootCtx::register);
        bootCtx.refresh();
        startBootstrapComponents(bootCtx);

        log.info("Boot phase done. Initializing context.");

        // Create an application context and inherit from boot context.
        ctx = new AnnotationConfigApplicationContext();
        ctx.setEnvironment(bootCtx.getEnvironment());
        ctx.setParent(bootCtx);

        List> classes = annotatedClasses();
        classes.forEach(ctx::register);

        ctx.refresh();

        log.info("Context initialized.");
    }

    protected void startBootstrapComponents(AnnotationConfigApplicationContext ctx) {
        final List>> componentClasses = bootstrapComponents();
        final PluginRegistryImpl pluginRegistry = ctx.getBean(PluginRegistryImpl.class);
        final List> components = componentClasses.stream().map(ctx::getBean).toList();

        try {
            // Start the components that a required before bootstrapping the plugin registry.
            for (LifecycleComponent component : components) {
                component.preStart();
            }

            for (LifecycleComponent component : components) {
                component.start();
            }

            // Bootstrap the plugin registry to load all boot plugins (e.g.: secret providers, ...).
            pluginRegistry.bootstrap();
        } catch (Exception e) {
            throw new RuntimeException("Unable to bootstrap the components.", e);
        }
    }

    protected void stopBootstrapComponents(AnnotationConfigApplicationContext ctx) {
        final List>> componentClasses = bootstrapComponents();
        final List> components = componentClasses.stream().map(ctx::getBean).toList();

        try {
            for (LifecycleComponent component : components) {
                component.preStop();
            }

            for (LifecycleComponent component : components) {
                component.stop();
            }
        } catch (Exception e) {
            log.error("Unable to shutdown the components.", e);
        }
    }

    protected List> bootstrapClasses() {
        // These classes represent the minimal list of Spring beans configuration to initialize during the boot phase.
        final List> bootstrapClasses = new ArrayList<>();
        bootstrapClasses.add(EnvironmentConfiguration.class);
        bootstrapClasses.add(PropertiesConfiguration.class);
        bootstrapClasses.add(NodeContainerConfiguration.class);
        bootstrapClasses.add(BootPluginConfiguration.class);
        bootstrapClasses.add(SecretServiceConfiguration.class);
        bootstrapClasses.add(NodeCertificatesConfiguration.class);
        bootstrapClasses.add(KubernetesClientConfiguration.class);

        // Bean registry post processors need to be manually registered as it MUST be taken in account before spring context is refreshed.
        bootstrapClasses.add(ContainerInitializerBeanRegistryPostProcessor.class);
        bootstrapClasses.add(BootPluginHandlerBeanRegistryPostProcessor.class);

        return bootstrapClasses;
    }

    protected List>> bootstrapComponents() {
        // These classes represent the list of Gravitee component to start during the boot phase (in order).
        final List>> bootstrapComponentClasses = new ArrayList<>();
        bootstrapComponentClasses.add(LicenseManager.class);
        bootstrapComponentClasses.add(LicenseLoaderService.class);
        bootstrapComponentClasses.add(BootPluginEventListener.class);

        return bootstrapComponentClasses;
    }

    protected List> annotatedClasses() {
        List> classes = new ArrayList<>();
        classes.add(VertxConfiguration.class);
        classes.add(PluginConfiguration.class);
        classes.add(ManagementConfiguration.class);
        classes.add(NodeMonitoringConfiguration.class);

        // Bean registry post processor needs to be manually registered as it MUST be taken in account before spring context is refreshed.
        classes.add(PluginHandlerBeanRegistryPostProcessor.class);
        return classes;
    }

    @Override
    protected void doStop() throws Exception {
        if (!stopped) {
            if (log.isInfoEnabled()) {
                log.info("Shutting-down {}...", name());
            }
            try {
                stopBootstrapComponents(ctx);
                node().stop();
            } catch (Exception ex) {
                LoggerFactory.getLogger(this.getClass()).error("Unexpected error", ex);
            } finally {
                ctx.close();
                stopped = true;
            }
        }
    }

    @Override
    public Node node() {
        // Get a reference to the node
        return ctx.getBean(Node.class);
    }

    public ApplicationContext applicationContext() {
        return ctx;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy