43

I want to deploy two applications foo.war and bar.war to the same Tomcat instance. Is it possible for them to listen for connections on different ports, e.g. foo listens on port 81 and bar listens on port 82? If so, how can I configure this? I realise that it is not necessary for the applications to listen on different ports, but that is what I want to achieve.

Also, am I right in saying that if I rename foo.war to ROOT.war such that it runs in the root context, then all requests to this Tomcat instance will be handled by the foo app and therefore bar would have to be deployed to a separate Tomcat instance?

Dónal
  • 185,044
  • 174
  • 569
  • 824
  • 4
    Related: http://stackoverflow.com/questions/8823290/how-to-run-different-apps-on-single-tomcat-instance-behind-different-ports – sleske May 12 '14 at 13:46
  • i may missed the point why we might need to listen to different ports ? – shareef Nov 25 '17 at 20:20

4 Answers4

86

If you want Tomcat to listen to multiple ports, you need to setup a connector for each port. To get each port mapped to a different application, you need need to wrap each connector in a service and create a host with it's own appBase.

Example of service definition in server.xml:

<Service name="foo">
    <Connector port="80" protocol="org.apache.coyote.http11.Http11NioProtocol" />
    <Engine name="Catalina80" defaultHost="localhost">
        <Host name="localhost" appBase="foo" unpackWARs="true" autoDeploy="true" />
    </Engine>
</Service>

<Service name="bar">
    <Connector port="81" protocol="org.apache.coyote.http11.Http11NioProtocol" />
    <Engine name="Catalina81" defaultHost="localhost">
        <Host name="localhost" appBase="bar" unpackWARs="true" autoDeploy="true" />
    </Engine>
</Service>

Instead of dropping the war files in the webapps directory, you need to create the directory foo for port 80 and bar for port 81. Name both war files ROOT.war and drop them in their own base directory. You can of course have multiple apps in each directory if you need.

The directory defined in appBase is relative to the tomcat directory. By using an absolute path, it could be anywhere on your system. From the documentation:

appBase

The Application Base directory for this virtual host. This is the pathname of a directory that may contain web applications to be deployed on this virtual host. You may specify an absolute pathname, or a pathname that is relative to the $CATALINA_BASE directory. [...] If not specified, the default of webapps will be used.

Another option is to keep the default tomcat configuration and use another http server (apache, nginx, lighttpd,...) to map a port to the internal path of a tomcat application.

The root application won't receive requests that match other applications, e.g. /foo/example will go to foo.war, /example/example will go to ROOT.war.

Community
  • 1
  • 1
kapex
  • 28,903
  • 6
  • 107
  • 121
  • 2
    thanks for the response, should the `foo` and `bar` directories you mentioned be created under `webapps` ? – Dónal May 12 '14 at 15:10
  • 2
    I would create them elsewhere, otherwise the apps could get deployed twice if `webapps` is still used as `appBase` by some another connector. – kapex May 12 '14 at 15:49
  • Given the configuration above, where should the `foo` and `bar` directories be located? – Dónal May 12 '14 at 15:53
  • 1
    The path should be relative to the tomcat directory (`$CATALINA_HOME`), where exactly that is depends on your system. You can also use absolute paths, like `/usr/home/foo`. – kapex May 12 '14 at 15:59
  • So using the config above, `foo` and `bar` should be siblings of `webapps`? – Dónal May 12 '14 at 16:02
  • 1
    Correct. I updated the answer with some info from the documentation. – kapex May 12 '14 at 16:05
  • I am having [this issue here](http://stackoverflow.com/questions/31746396/can-i-merge-these-two-servers-to-become-one-using-gwt-servlet-and-restful-api) but reading this question/answer I was wondering if I could do the same as you described in your answer. – Stefan Falk Jul 31 '15 at 14:42
38

No need to change ports

Juggling multiple incoming requests and outgoing responses across many users using any of multiple running web apps is the purpose of Java Servlet technology. All that traffic can be handled on a single port.

Simply drop both war files into Tomcat's webapps folder. That is all you need to do.

By default, Tomcat expands ("explodes" some say) each war (technically a zip file) into a folder and automatically deploys the app for you. This happens on the fly if Tomcat is already running, or on startup when you launch Tomcat. Some people turn off the auto-deploy feature for production to save Tomcat the work of scanning for new war files.

No need for multiple ports. A Servlet container's job is to examine the URL and determine which Servlet should be invoked.

By default, the name of the war file determines the URL. Given your example:

All the web apps can be served on the same port. Your only concern with ports is if you use Unix-style operating system that protects access to low-numbered ports. This includes Mac OS X, BSD, Linux, and Solaris. Either use a high-numbered port in your URL (Tomcat defaults to 8080), or use port-forwarding to send incoming requests on port 80 (web browsers’ default) to Tomcat’s port (such as 8080).

If you want the war files served by using different domains, learn about "virtual host" settings in Tomcat.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 2
    I appreciate the time you put into this, but it doesn't answer either of my questions (1) is it possible to have different apps deployed to the same Tomcat instance listen on different ports? (2) if an app is deployed to Tomcat's root context, will it handle all HTTP requests sent to that Tomcat instance? – Dónal May 12 '14 at 12:51
  • @Dónal RE:(1) I don't know about separate ports. Look at the `Connector` tag for the `Service` tag in `server.xml` file. But there is **no need for separate ports**. The URL is all the web server / servlet container needs to separate requests for different web apps. (2) The most specific URLs (longer, meaning more components) get handled by their defined servlets. The bullet list of three items posted above in my Answer could all be deployed together. If the the URL specifies "foo" you get the "foo" servlet. If the URL does not specify, it falls back to the ROOT servlet. – Basil Bourque May 12 '14 at 13:59
  • I realise it is not necessary to have each app listening on a separate port, but that is what I want to achieve – Dónal May 12 '14 at 14:47
  • 7
    though it does not address the specific points of the question, but is a nice explanation and clarifies some fundamental concept of working of a servlet container in general. Thanks for the effort and time @Dónal – Mrinmoy May 20 '17 at 17:24
  • Is it safe to deploy 3 war files in a single tomcat? Are there any pros or cons of it? Somebody please explain. – Suraj Gautam Jul 30 '18 at 10:34
  • 1
    @SurajGautam Certainly, you can deploy as many WAR files as you have web apps. Each has its own URL to be called by the users. – Basil Bourque Jul 30 '18 at 16:38
  • OK, @BasilBourque! But is there any concurrency issue or something like that that I may face while doing so? – Suraj Gautam Jul 30 '18 at 16:42
  • @SurajGautam I suggest you read up on the basics of Java Servlet technology. Start with [Wikipedia](https://en.wikipedia.org/wiki/Java_servlet), then the [Oracle Tutorial](https://docs.oracle.com/javaee/6/tutorial/doc/bnafd.html). Creating the concurrent multithreaded environment to handle many simultaneous incoming requests and outgoing responses is the core purpose of Java Servlet technology. You need to be very aware of this. If your threads share any resources then you are responsible for proper concurrent programming. If so, study the book by Goetz et al., *Java Concurrency in Practice*. – Basil Bourque Jul 30 '18 at 16:58
5

I have successfully configured Tomcat to run apps on multiple ports. I don't know if this is the best way to do this, but I simply duplicated contents of

<Service>...</Service>

in conf/server.xml and changed the ports for the Connector tags and changed the appBase attribute of the Host tag. You control which port your app runs on based upon the appBase that it is deployed to.

Jeff Miller
  • 1,424
  • 1
  • 10
  • 19
0

I was already doing what Basil mentions above.

As it turned out I needed to wildcard my sites-enabled/blah.conf file, to not reference the first (and only) .war I deployed months before adding another app.

Here's what I wildcarded:

  • DocumentRoot
  • JkMount
  • Directory
  • DirectoryIndex

So fyi, ya'll. :)

  • What is sites-enabled/blah.conf can you elaborate and where are the DocumentRoot,JkMount etc... – m b Jan 29 '21 at 11:45