Is there a way to enforce a deployment order in tomcat6?

Viewed 24779

I have 3 wars in my webapp folder. Two of them are built on services of the third one. I'm in a testing environment, i.e. I don't have control over their architectures, so I'm no able to change a thing. So...

Question: Is there a way to enforce a deployment order in tomcat?

I've ran into one question here in stackoverflow, but there's no solution.

Well, actually the guy suggests that changing the name of the webapps to an alphabetical order would help. However, I'm not willing to do that everytime I need to test those and different wars.

I'm positive that there's a way of doing that configuring one of the tomcat conf .xml files. I just don't know which one.

8 Answers

Building on from @Luiz's answer for Tomcat 9 (in which children is now final), we had to override several methods, copying the basic functionality in some instances.

This isn't optimised for anything, but it does load the contexts in the order they're defined in your server.xml.

// DeterministicDeployOrderHost.java

import java.lang.Override;
import java.lang.String;
import java.util.LinkedHashSet;
import javax.management.ObjectName;
import org.apache.catalina.Container;

public class DeterministicDeployOrderHost extends org.apache.catalina.core.StandardHost {
    private final LinkedHashSet<String> childrenOrder = new LinkedHashSet<>();

    @Override
    public void addChild(Container container) {
        synchronized (children) {
            super.addChild(container);
            childrenOrder.add(container.getName());
        }
    }

    @Override
    public void removeChild(Container container) {
        synchronized (children) {
            super.removeChild(container);
            childrenOrder.remove(container.getName());
        }
    }

    @Override
    public Container[] findChildren() {
        synchronized (children) {
            var list = new java.util.ArrayList<Container>(children.size());
            for (var childName : childrenOrder) {
                list.add(children.get(childName));
            }
            return list.toArray(new Container[0]);
        }
    }

    @Override
    public ObjectName[] getChildren() {
        var names = new java.util.ArrayList<ObjectName>(children.size());
        for (var childName : childrenOrder) {
            var next = children.get(childName);
            if (next instanceof org.apache.catalina.core.ContainerBase) {
                names.add(next.getObjectName());
            }
        }
        return names.toArray(new ObjectName[0]);
    }
}

Get the tomcat-catalina-*.jar, e.g. from Maven Repository and compile this into DeterministicDeployOrderHost.class:

javac DeterministicDeployOrderHost.java -cp tomcat-catalina-9.0.65.jar

Then copy the compiled .class file into $CATALINA_HOME/lib and add the following to the host:

<Host ... className="DeterministicDeployOrderHost">
  <Context .../>
  <Context .../>
</Host>
Related