28

Currently if i deploy a war file on tomcat named say myapp.war, I can access its url by http://localhost/myapp/MyServlet.

However what I want is to deploy a war with a version number in the war file name and still have the same url. For eg, I want to deploy myapp-1.1.0.war and still have the url be http://localhost/myapp/MyServlet

Of course I need to keep updating the war and the version number will keep changing, so I cant hardcode the war filename anywhere. Is there any setting in web.xml I can use to keep the same url for the app regardless of the war filename?

pdeva
  • 43,605
  • 46
  • 133
  • 171
  • If you just want to add a version information to your file name, check my answer to this question: http://stackoverflow.com/a/33822607/1458639 – Peter Clause Dec 03 '15 at 10:49

7 Answers7

14

The solution is to stop using the automatic deployment feature of Tomcat, which takes the shortcut of setting the "context name" (the /myapp part of the URL) to the portion of the WAR filename before ".war".

Instead, extract the WAR contents to the filesystem yourself and setup an XML file at TOMCAT_HOME/conf/[enginename]/[hostname]/[contextname].xml which points the desired context path (such as /myapp) to the location of the application on disk (such as /opt/webapps/myapp-1.1.0/).

The Tomcat reference docs provide a good explanation of how Tomcat deploys applications automatically, and how you can configure customized logic for the mapping of context path to application file location (there are a handful of alternate ways to set this up other than the one I suggest above).

matt b
  • 138,234
  • 66
  • 282
  • 345
  • 3
    does this mean i will also have to update the .xml file each time i deploy a new version of the war with the updated filename? – pdeva May 03 '11 at 22:28
  • 1
    i am a little confused. in this case what should the content of the 'myapp.xml' file be to make it point to the location of the war? – pdeva May 04 '11 at 08:50
  • 1
    something like ``. Tomcat will use the name of the file, without the `.xml` extension, as the context path. Also in regards to my symlink suggestion I just noticed in the docs that it states `If a symbolic link is used for docBase then changes to the symbolic link will only be effective after a Tomcat restart or by undeploying and redeploying the context. A context reload is not sufficient.` – matt b May 04 '11 at 12:03
8

You can use YOUR_WAR/META-INF/context.xml for this. Here is a sample:

<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/MyServlet"/>
Karthik Ramachandran
  • 11,925
  • 10
  • 45
  • 53
  • 1
    @Matthew Gillard As far as I know the tomcat docs say not to put a Context element in Server.xml. They have no problem with META-INF/context.xml. The docs even tell you how context.xml works. From the docs: "Context elements may be explicitly defined: * In the $CATALINA_BASE/conf/context.xml file: the Context element information will be loaded by all webapps." – Karthik Ramachandran May 03 '11 at 21:03
  • 2
    Am I misreading it then? The "path" section says: "The value of this field must not be set except when statically defining a Context in server.xml" – Matthew Gilliard May 03 '11 at 21:08
  • I think tomcat's behaviour (and documentation!) in this area is very confusing. Not least of which: if you decide you want to change the context-root of your webapp you have to manually delete a file from $CATALINA_BASE/conf (4th of 5 bullet points in the Introduction section on that page) – Matthew Gilliard May 03 '11 at 21:13
  • 1
    @Matthew Gillard The only time I've hand trouble getting META-INF/context.xml to do the right thing is when I'm trying to set the root context. In that case I've found I have to delete the pre-bundled root webapp. Other than it seems to work fine. But you're right there do seem to be some inconsistencies in the docs/behavior. Possibly worth submitting a ticket to them? – Karthik Ramachandran May 03 '11 at 21:17
4

When using Maven you can control your deployment's path by doing the followings:

Tomcat's conf/tomcat-users.xml:

<tomcat-users>
  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <role rolename="manager-jmx"/>
  <role rolename="manager-status"/>
  <role rolename="admin-gui"/>
  <role rolename="admin-script"/>

  <user username="root" password="root" roles="manager-gui,manager-script,manager-jmx,manager-status,admin-gui,admin-script"/>

</tomcat-users>

~/.m2/settings.xml :

...
<server>
  <id>tomcat</id>
  <username>root</username>
  <password>root</password>
</server>
...

pom.xml :

...
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>myapp</artifactId>
  <version>1.1.0</version>
  <packaging>war</packaging>
...
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>tomcat-maven-plugin</artifactId>
        <configuration>
          <!-- neglect /html below Tomcat7: -->
          <url>http://server:8080/manager/html</url>
          <!-- Refer to the server settings in your ~/.m2/settings.xml -->
          <server>tomcat</server>
          <path>/myWebApp</path>
        </configuration>
      </plugin>
      ....
    </plugins>
  </build>
...

Start your tomcat first Then build and deploy your application..

mvn clean install tomcat:deploy

..it will be accessible under http://server:8080/myWebApp

nir
  • 3,743
  • 4
  • 39
  • 63
Lorand Bendig
  • 10,630
  • 1
  • 38
  • 45
2

I prefer to use "##" symbols for noting version of *.war files in the tomcat.
For example:
myapp.war -> URL: http://localhost:8080/myapp/MyServlet
myapp##1.1.0 -> URL: http://localhost:8080/myapp/MyServlet (still the same, because all symbols after "##" are ignoring by tomcat)

Maksym
  • 2,650
  • 3
  • 32
  • 50
2

There is no setting in web.xml for this. I do not believe that it is possible to set this inside the war file in a cross-container way - there is no mention of it in the spec anyway - so each container does it differently. jboss-web.xml, sun-web.xml, context.xml etc.

Matthew Gilliard
  • 9,298
  • 3
  • 33
  • 48
0

I run into the same issue, and indeed, as @matt mentioned, the Tomcat reference docs provide a good explanation of how Tomcat deploys applications automatically, and how you can configure customized logic for the mapping of context path to application file location.

In my case, I used this advice (in 'path' explanation):

Even when statically defining a Context in server.xml, this attribute (/path) must not be set unless either the docBase is not located under the Host's appBase or both deployOnStartup and autoDeploy are false. If this rule is not followed, double deployment is likely to result.

so in my case, I switched both deployOnStartup and autoDeploy to false, so my WAR (e.g. a.WAR) was not auto-exploded to 'a' directory under webapps, but instead into 'b' directory, due to these settings:

<Host name="localhost"  appBase="webapps"
            autoDeploy="false" deployOnStartup="false" 
            unpackWARs="true" deployIgnore="${ignore.context}">

   <Context docBase="a" path="/b" />

</Host>
Community
  • 1
  • 1
OhadR
  • 8,276
  • 3
  • 47
  • 53
0

I found all the advice on this subject somewhat terse and confusing. The below method works for me using a default tomcatee installation.

Suppose I have a war file named mywar.war. This holds a servlet mapping to '/hello'. I want to access this servlet from a url like localhost:8080/myapp/hello

This method avoids any changes to server.xml which is not advised as this requires tomcat restarts.

This method will fail is you deploy to /webapps as it will try and deploy the same war twice. Therefore I start by creating a new directory to deploy into. I use /apps but the dir name is arbitrary.

I now copy mywar.war into apps. Tomcat ignores this action. I now create a simple deployment file named myapp.xml. Note that the name of this file defines the URL context the war will be deployed under. I believe you can use ROOT.xml to deploy under . The contents are as follows:

As described this needs to be copied into /conf/Catalina/localhost This causes tomcat to expand and deploy the /apps/mywar.war and set the correct URL context. The servlet is now available on localhost://myapp/hello (or :8080//myapp/hello from a remote client).

Note that for a relative address the docBase URL identifies the location of the war from the webapps directory - hence the leading ..