Discussions

Web tier: servlets, JSP, Web frameworks: Tomcat 5.5 embedded

  1. Tomcat 5.5 embedded (3 messages)

    hi all,

    could someone point me to some sample code on how to start tomcat 5.5 in embedded mode? creating the engine, host, connectors, etc..

    tia,

    patrick
  2. There has been some api changes in the Embedded class along with a bug in the Embedded.createConnector(...) method see (here) After fiddling with the Catalina classes around all morning, I have been able to get the the Embedded Tomcat to work so here is the code. Note: This is using the Tomcat 5.5.4 embed version.

    import java.io.File;
    import java.net.InetAddress;

    import org.apache.catalina.Context;
    import org.apache.catalina.Engine;
    import org.apache.catalina.Host;
    import org.apache.catalina.Session;
    import org.apache.catalina.connector.Connector;
    import org.apache.catalina.realm.MemoryRealm;
    import org.apache.catalina.startup.Embedded;
    import org.apache.tomcat.util.IntrospectionUtils;

    /**
     * @author placson
     */
    public class Tomcat55 {

        private String path = null;
        private Embedded embedded = null;
        private Host host = null;
        private Context rootcontext;
        public Tomcat55() {
        }

        /**
         * Set Session scope variable
         *
         * @param name
         * Session variable name
         * @param obj
         * Session variable value
         */
        public void setRootContextSessionAttribute(String name, Object obj) {
            try {
                Session sessions[] = this.rootcontext.getManager().findSessions();

                for (int i = 0, size = sessions.length; i < size; i++) {
                    sessions[i].getSession().setAttribute(name, obj);
                }
            } catch (Exception x) {
            }
        }

        /**
         * Get Application scope variable
         *
         * @param name
         * Application variable name
         * @return Application variable value
         */
        public Object getRootContextAttribute(String name) {
            return this.rootcontext.getServletContext().getAttribute(name);
        }

        /**
         * Set Application scope variable
         *
         * @param name
         * Application variable name
         * @param obj
         * Application variable value
         */
        public void setRootContextAttribute(String name, Object obj) {
            this.rootcontext.getServletContext().setAttribute(name, obj);
        }

        /**
         * Remove Application scope variable
         *
         * @param name
         * Application variable name
         */
        public void removeRootContextAttribute(String name) {
            this.rootcontext.getServletContext().removeAttribute(name);
        }

        /**
         * Basic Accessor setting the value of the context path
         *
         * @param path -
         * the path
         */
        public void setPath(String path) {

            this.path = path;
        }

        /**
         * Basic Accessor returning the value of the context path
         *
         * @return - the context path
         */
        public String getPath() {
            return this.path;
        }

        /**
         * This method Starts the Tomcat server.
         */
        public void startTomcat() throws Exception {
            Engine engine = null;

            // Create an embedded server
            this.embedded = new Embedded();
            this.embedded.setCatalinaHome(getPath());

            // set the memory realm
            MemoryRealm memRealm = new MemoryRealm();
            this.embedded.setRealm(memRealm);

            // Create an engine
            engine = this.embedded.createEngine();
            engine.setDefaultHost("localhost");

            // Create a default virtual host
            this.host = this.embedded.createHost("localhost", getPath()
                    + "/webapps");
            engine.addChild(this.host);


            // Create the ROOT context
            this.rootcontext = this.embedded.createContext("", getPath()
                    + "/webapps/ROOT");
            this.rootcontext.setReloadable(false);
            this.rootcontext.addWelcomeFile("index.jsp");
            this.host.addChild(this.rootcontext);

            // create another application Context
            Context appCtx = this.embedded.createContext("/manager", getPath() + "/webapps/manager");
            appCtx.setPrivileged(true);
            this.host.addChild(appCtx); // add context to host

            

            // Install the assembled container hierarchy
            this.embedded.addEngine(engine);

            int port = 8080;
            String addr = null;
            Connector connector = null;//this.embedded.createConnector(addr, port, false);
            /*
             * embedded.createConnector(...)
             * seems to be broken.. it always returns a null connector.
             * see work around below
             */
            InetAddress address = null;
            try {
                connector = new Connector();
                //httpConnector.setScheme("http");
                connector.setSecure(false);
                address = InetAddress.getLocalHost();
                if (address != null) {
                    IntrospectionUtils.setProperty(connector, "address", ""
                            + address);
                }
                IntrospectionUtils.setProperty(connector, "port", "" + port);
                
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            connector.setEnableLookups(false);

            this.embedded.addConnector(connector);
            // Start the embedded server
            this.embedded.start();
        }

        /**
         * Refresh ROOT context
         *
         */
        public void reloadRoot() {
            this.rootcontext.reload();
        }

        /**
         * Remove ROOT context
         *
         */
        public void removeRoot() {
            this.host.removeChild(this.rootcontext);
        }

        /**
         * Add ROOT context
         *
         */
        public void addRoot() {
            this.host.addChild(this.rootcontext);
        }

        /**
         * This method Stops the Tomcat server.
         */
        public void stopTomcat() throws Exception {
            // Stop the embedded server
            this.embedded.stop();
        }

        /**
         * Registers a WAR with the container.
         *
         * @param contextPath -
         * the context path under which the application will be
         * registered
         * @param warFile -
         * the URL of the WAR to be registered.
         */
        public void registerWAR(String contextPath, String absolutePath)
                throws Exception {
            Context context = this.embedded
                    .createContext(contextPath, absolutePath);
            context.setReloadable(false);
            this.host.addChild(context);
        }

        /**
         * Unregisters a WAR from the web server.
         *
         * @param contextPath -
         * the context path to be removed
         */
        public void unregisterWAR(String contextPath) throws Exception {

            Context context = this.host.map(contextPath);
            if (context != null) {
                this.embedded.removeContext(context);
            } else {
                throw new Exception("Context does not exist for named path : "
                        + contextPath);
            }
        }

        
        public static void main(String[] args) {
            Tomcat55 tomcat = new Tomcat55();
            /* jdk15 verify */
            java.util.LinkedList<Integer> list = new java.util.LinkedList<Integer>();
            tomcat.setPath(new File(".").getAbsolutePath());
            try {
                tomcat.startTomcat();
                
                // unload root after 5 seconds
                Thread.currentThread().sleep(5*1000);
                tomcat.removeRoot();
                System.out.println("Root context removed!");

                // wait another 5 seconds and add again
                Thread.currentThread().sleep(5*1000);
                tomcat.addRoot();
                System.out.println("Root context added!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
  3. Patrick,

    is there a way to define the servlets and mappings without defining an application. eg without having to define an web.xml path but entering the data directly into the source code. In jetty this would be:

    ServletHttpContext context = (ServletHttpContext)
    server.getContext("/");
    ServletHolder servlet = context.addServlet("Test","/hello/test",
    "TestServlet");
    servlet.put("home-class", "test.TestService");
    servlet.put("home-api", "test.TestServiceInterface");
  4. The bug in createConnector()[ Go to top ]

    As mentioned above, ther is a bug in Embedded.createConnector (Revision: 1.25). It was fixed in Revision 1.26. The problem was the missing 'if statement' for http :(

    Poor testing I assume..

    This is the previous code:

    try {

                if (protocol.equals("ajp")) {
                    connector = new Connector("org.apache.jk.server.JkCoyoteHandler");
                } else if (protocol.equals("memory")) {
                    connector = new Connector("org.apache.coyote.memory.MemoryProtocolHandler");
                } else if (protocol.equals("https")) {
                    connector = new Connector();
                    connector.setScheme("https");
                    connector.setSecure(true);
                    // FIXME !!!! SET SSL PROPERTIES
                }

                if (address != null) {
                    IntrospectionUtils.setProperty(connector, "address",
                                                   "" + address);
                }
                IntrospectionUtils.setProperty(connector, "port", "" + port);

            } catch (Exception e) {
                log.error("Couldn't create connector.");
            }

            return (connector);