1
votes

I have been experimenting recently on several Java Servlet technology aspects. Recently, I came across the load-on-startup tag of web.xml which comes under the Servlet specification. I experimented how load-on-startup works in Apache Tomcat and realized through logs that the order of executing servlet init() methods for each servlet occurs based most probably on the alphabetical order of the servlet names rather than the order of which the servlets were defined in web.xml.

The web.xml is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <display-name>Hello-World-Servlet</display-name>

    <servlet>
        <servlet-name>hello-world</servlet-name>
        <servlet-class>org.wso2.carbon.HelloWorld</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>all-is-well</servlet-name>
        <servlet-class>org.wso2.carbon.HelloWorld</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>bonjour-monde</servlet-name>
        <servlet-class>org.wso2.carbon.HelloWorld</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>hello-world</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>all-is-well</servlet-name>
        <url-pattern>/well</url-pattern>
        <url-pattern>/alright</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>bonjour-monde</servlet-name>
        <url-pattern>/bonjour</url-pattern>
    </servlet-mapping>

</web-app>

The servlet class is follows:

public class HelloWorld extends HttpServlet {
    private static final Logger logger = Logger.getLogger(HelloWorld.class.getName());

    @Override
    public void init() throws ServletException {
        logger.log(Level.INFO, "The servlet " + getServletName() + " is starting...");
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().println(getServletName());
        if (getServletName().equals("hello-world")) {
            response.getWriter().println("Hello World!!!");
        } else if (getServletName().equals("bonjour-monde")) {
            response.getWriter().println("Bonjour monde!!!");
        } else if (getServletName().equals("all-is-well")) {
            response.getWriter().println("All izz well!!!");
        }
    }

    @Override
    public void destroy() {
        logger.log(Level.INFO, "The servlet " + getServletName() + " is getting destroyed...");
    }
}

When I checked the Tomcat logs it was as follows:

15-Apr-2016 14:41:12.678 INFO [localhost-startStop-1] org.wso2.carbon.HelloWorld.init The servlet all-is-well is starting...
15-Apr-2016 14:41:12.680 INFO [localhost-startStop-1] org.wso2.carbon.HelloWorld.init The servlet bonjour-monde is starting...
15-Apr-2016 14:41:12.680 INFO [localhost-startStop-1] org.wso2.carbon.HelloWorld.init The servlet hello-world is starting...

I came across several resources which contradicts this behavior and mentions that if load-on-startup is equal for several servlets, the order they appear in the descriptor decides the order. But when referring to the following What does the servlet <load-on-startup> value signify, the spec seems to bear a different idea which states that it depends on the container implementation. This matches with what I experienced

What is the most accurate mechanism defined for this case?

3

3 Answers

2
votes

Read JSR 340:

The element load-on-startup indicates that this servlet should be loaded (instantiated and have its init() called) on the startup of the Web application. The element content of this element must be an integer indicating the order in which the servlet should be loaded. If the value is a negative integer, or the element is not present, the container is free to load the servlet whenever it chooses. If the value is a positive integer or 0, the container must load and initialize the servlet as the application is deployed. The container must guarantee that servlets marked with lower integers are loaded before servlets marked with higher integers. The container may choose the order of loading of servlets with the same load-on-startup value.

[Emphasis mine]

1
votes

Well, you have the specification which states that it's container dependent and you've observed behaviour where it's container dependent.

So, don't write code that depends on any specific implementation.

1
votes

Servlet is not getting loaded on the alphabetical order for same load-on-startup value. It depends on the container, refer the attached screenshot for same code with Tomcat 8.Execution Screenshot