dotCMS / dotCMS/core

Document The steps of system startup and what defines their order

Open
#31,031 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

OKR : Evergreen Team : Platform
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

There has seemed to be confusion that persists in the context of a tomcat Web Application to the order code is processed during startup and where additional logic should go. This includes a proper understanding of what point the application will start handling requests and whether underlying services are available in code being processed during startup

  1. Difficult for developers to know where to put new code, or to understand where existing code gets triggered.
  2. Possible dependency issues with code during startup or startup taking longer than needed
  3. Issues internally knowing when the server is actually available to handle requests for use in probes

The base of this is currently defined in the web.xml

The Key is

  1. All ServletContextListeners.contextInitialized get called before any servlet is started up in order they are defined in the web.xml. (These can also be loaded using annotations, we currently do not do this, but some 3rd party dependencies may)

org.jboss.weld.environment.servlet.Listener
com.dotmarketing.listeners.ContextLifecycleListener
com.dotmarketing.listeners.ClickstreamListener
org.apache.felix.http.proxy.impl.ProxyServletContextListener
com.dotcms.listeners.SessionMonitor
com.twelvemonkeys.servlet.image.IIOProviderContextListener
com.dotcms.listeners.RegisterMBeansListener
com.dotcms.listeners.SwitchSiteListener
com.dotcms.api.web.RequestThreadLocalListener
com.dotmarketing.listeners.HibernateSessionsListener

  1. Servlets that have load-on-startup defined are loaded in order of the numeric value. No requests will be accepted till they all are initialized.

com.liferay.portal.servlet.InitServlet - 1. (Has No mapping and has been created only to run startup tasks)
org.glassfish.jersey.servlet.ServletContainer - 1
com.liferay.portal.servlet.MainServlet - 2
com.dotmarketing.servlets.InitServlet - 8
com.dotmarketing.servlets.UpdateQuartzCronJobsServlet - 98
com.dotmarketing.servlets.BinaryExporterServlet - 100
com.liferay.portal.servlet.ImageServlet - 400

  1. After all servlets with load-on-startup set are initialized, the server will be able to accept requests

  2. Remaining servlets will only initialize on demand by which time requests to other servlets may already be processing.

com.bradmcevoy.http.MiltonServlet
com.dotmarketing.servlets.ajax.AjaxDirectorServlet
com.dotmarketing.servlets.JSONTagsServlet
com.dotcms.csspreproc.CSSPreProcessServlet
com.dotcms.csspreproc.SassPreProcessServlet
com.dotcms.graphql.DotGraphQLHttpServlet

Things to note
  • We cannot respond to probe endpoints until after step 3.
  • Lazy loading endpoints is preferable for speedy startup but we still need the minimum initialiaation and need to be aware of what needs to be completed successfully before we can start accepting the most basic requests.

For identifying when all startup tasks are complete and the server is ready to accept requests we could make use of a Tomcat Lifecycle Listener e.g.

import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;

public class ServerStartupListener implements LifecycleListener {

    @Override
    public void lifecycleEvent(LifecycleEvent event) {
        if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
            // This is called after the server has fully started
            System.out.println("Server has fully started!");

            // Execute your task here
            executePostStartupTask();
        }
    }

    private void executePostStartupTask() {
        // Your custom logic here
        System.out.println("Running post-startup task...");
        // e.g., initializing a background job, scheduling tasks, etc.
    }
}

The downside to this is that it is explicitly tied to Tomcat and is not representative of core WebApp functionality. An alternative is to create a servlet that is set to initialize on startup after all others, the server will start accepting requests just after this. Using a load-on-startup value guaranteed to be higher than all others will make sure it is initialized after all the other context listeners and servlets that initialize before startup.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the web.xml startup declarations and compare the listed ServletContextListeners and load-on-startup servlets with the current application configuration. Document their ordering, when requests become available, and the readiness implications for probe endpoints. Done means the startup sequence and placement guidance are recorded clearly, including the lazy-loading behavior and readiness alternative described in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
documentation
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.