How to remote deploy a Web service to Apache Tomcat from within a Java program

The deployment of servlets to a Servlet container like Tomcat is usually a simple task: Just copy the developed servlet to a specific target directory. The container will then hot deploy it. The proposed task is however more complex: The goal is to make a programmatical remote deployment of a Web service. In other words, an already developed Web service is to be deployed from a PC to a remote server which is running a Tomcat Servlet container. This task has three major requirements: - First, the deployment has to be remote: The Web service is to be deployed onto a different machine. - Second, it is to be accomplished programmatically, which means that it is necessary to develop a software component (for example in Java) which will carry out that task. - Third, the deployment has to be “hot”, which means that the deployed Web service has to run after a short time, without the need to restart the server or its Servlet container. As an addition to the above it is interesting to know, how to use a Servlet container like Tomcat for Web service deployment. In short the goal is to develop an application which can “hot deploy” a Servlet containing one or more Web services onto a remote machine, which is only known to run an Apache Tomcat Servlet container. The process could be called: “Programmatical-remote-hot-deployment of a Web service to an Apache Tomcat Servlet container.”
1 answer

How to remote deploy a Web service to Apache Tomcat from within a Java program

1. Introduction to the problem:
There are various possible ways to solve the problem, some major requirements are however:

1. To write a software application
2. To make it transfer the Webservice over the Internet
3. A Servlet is to be copied to the Webapps directory of Tomcat

Some of the ways to solve the problem are:
1. Development of additional software for the server (beside of Tomcat) for the data transfer
2. Development of a Webservice to be placed inside Tomcat for the data transfer
3. Use of Tomcats WWW Management Interface for the data transfer

All three approaches are practicable.
However, the first two approaches require additional software which is to be installed beforehand. The third approach only needs a running Tomcat Application Server on the remote machine.

Therefore the way to go, which is described in this article is "just" to utilize Tomcats WWW Management Interface in software. This approach is very versatile, but has also many pitfalls, and various considerations are necessary. The proposed approach is suitable for one ore more webservices. If in the following only one is mentioned, it also means that more could be in place.

This article does not provide an exhaustive description for solving the problem, but is meant to give some guidance to avoid some of the major problems encountered by solving this task.

2. Requirements
There are two basic requirements:
- An already developed and packaged Webservice
- A properly set up server running Apache Tomcat

An introduction into Webservices would exceed the scope of this article, some previous knowledge is required. It should be noted however, that there are two major ways to use Webservices with the proposed approach. One is to create a Webservice (for example using JAX-WS) and pack it into a .war archive (this is a .jar archive renamed to .war) which is then to be deployed, the other is to use a dedicated Webservice engine (Apache Axis2 can be used with Tomcat) together with a Webservice, and these are then to be packed into a .war archve containing both, which is then to be deployed. For details on compatibility and packaging Webservices (for Axis2 you would package .aar files, these are .jar archives renamed to .aar) into an engine see its documentation.

[Note: The .jar files are incompatible with .zip!]

Another basic requirement is a running Apache Tomcat. For Linux as an OS this is a simple task: Only the login credentials are to be set. For MS-Windows there is some additional work necessary: As of Tomcat Version 6.0.18 the parameters "antiJARLocking" and "antiResourceLocking", both (!) must be set, otherwise an undeployment would fail. For details on configuration and possible drawbacks see the Apache documentation.

3. Compression (in Java)

To execute a tool like Jar (from the JDK) directly from Java issue the following code:

Process p1 = Runtime.getRuntime().exec("CommandLineToBeExecuted");

Don't forget to wait (!) until the command is finished:

BufferedReader input1 = new BufferedReader(new InputStreamReader(p1.getInputStream()));
String line1;
while ((line1 = input1.readLine()) != null) {/*Must wait for the program to finish*/}
input1.close();

4. Programmatically accessing Tomcats WWW Management Interface
Accessing a Web Interface programmatically means to execute "clicks" on links or to start a file upload from a software. Various APIs exist for accessing an interface over HTTP. In Java the java.net.HttpURLConnection is sufficient. As the upload address "http://TomcatHost:8080/manager/html/upload" is to be used. In general it is necessary "to repeat" what would be otherwise performed by a web browser.

The exact procedures would again exceed the scope of this article. However lots of sample code is available on the net. The following description outlines some adaptations necessary to work with Tomcat:

For uploading a .war archive
- Create an HttpURLConnection to the upload address
- Set several properties, some of which are
- "Log in"
# conn.setRequestProperty("Authorization", "Basic " + new BASE64Encoder().encode(loginString.getBytes())); //loginString has the format: "name:password"
- Make sure the "RequestMethod" is "POST"
# conn.setRequestMethod("POST");
- Assemble the data to be send; See various resources on the net.
- Make sure the Content-Disposition is something like that: "Content-Disposition: form-data; name=\"deployWar\";" + " filename=\"" + "foo.war" + "\"" + "\r\n"
Using something different than exactly "deployWar" may lead to failure
- For authentication the "BASE64Encoder" is necessary. The undocumented "sun.misc.BASE64Encoder" should not be used. However one could copy the files "BASE64Encoder" and "CharacterEncoder" from the OpenJDK sources to gain the same functionality.

For following or executing ("clicking") links the procedure is very similar, but
- Use "GET" instead of "POST"
- Don't use multipart content type any more
- Use the URL that is to be "clicked"

The execution of links gives lots of management possibilites. The most important are

List of running Servlets:
[http://TomcatHost:8080/manager/html/]

Undeployment:
[http://TomcatHost:8080/manager/undeploy?path=/foo]

With the latter the deployed Servlet can be undeployed.

Taggings: