Deploying to WAS or Tomcat using the RTC build engine

The build engine capability of Rational Team Concert is capable of doing anything you want to do with Apache ANT, Maven, or even a shell script via the command line option.  On top of that it adds its own calls to so that you can get instrumentation on the status and history of your builds from the RTC interface. Builds can be automated so you have full continuous integration, which can help improve the overall quality of your project.

Build definitions are associated with an RTC project, and will call either ANT, Maven, CL, JCL, or command line scripts. A full build definition of any web app should also include a deployment target. You can deploy to just about any application server if you know the right calls.

In the case of WebSphere App Server, you need to know  a little about wsadmin scripting. The wsadmin interface is in the <WAS_HOME>\bin directory. It is the interactive scripting interface. This scripting interfaces uses your choice of Jython or JACL languages. Both of which are Java implementation of Python and TCL respectively. If you are writing a new script, start with Jython as it is the more powerful of the two, and JACL has been deprecated (but is still supported on WAS 7).  You can send interactive commands in wsadmin, or you can feed wsadmin with a script file using the -f command switch. From a command line, if you were to call a deployment script to automate the deployment of a Java EE app, your call may look like this:

C:\IBM\WebSphere\AppServer\profiles\AppSrv01\bin\wsadmin.bat -f -lang jython -user wasadmin -password waspassword -host localhost -port 8880 -connTYPE SOAP

Now, the various command params are available in the WAS InfoCenters, so I won't cover those in detail.  Suffice it to say, the above is a fairly close approximation to what you may see in a dev or prod environment.

Now, what you need to do is to put that into an ANT call:
<exec executable="${was.home}/bin/wsadmin.bat" failonerror="false" resultproperty="deploystatus">
            <arg value="-lang" />
            <arg value="jython" />
            <arg value="-user" />
            <arg value="${was.userid}" />
            <arg value="-password" />
            <arg value="${was.password}" />
            <arg value="-host" />
            <arg value="${}" />
            <arg value="-port" />
            <arg value="${was.port}" />
            <arg value="-f" />
            <arg value="" />
            <arg value="install" />
            <arg value="${path.ear.file}" />
            <arg value="${appname}" />
            <arg value="server1" />

Notice, we are passing in all the key parameters as ANT variables. Also, notice that we are storing the wsadmin command result in a property called 'deploystatus'. We will use that to confirm deployment of our application. This is a nice generic element. Next we want to inspect the property to ensure our deployment was a success. This all assumes that you've done a compile, a unit test, a war/ear, etc on the project before it gets to this target.

<condition property="isNotDeployed">
   <equals arg1="86" arg2="${deploystatus}" />
<fail if="isNotDeployed" message="Deployment Failed!!" />

If deployment succesds, and wsadmin exits normally, it will return a code 86 (at least on Linux it does). By checking to make sure we have that as our code, we can confirm that it has succeeded.

The script can be as complex as you need it. You can deploy and map your modules to your web servers, distribute across clusters, set custom JVM args and more. But the meat and potatoes of the  script is in two lines of code:

AdminApp.install(earfile, ['-verbose', '-appname', appname, '-server', server])

That is it! I've highlighted the variables I pass into it, and I've excluded some other options, but if you don't need anything fancy, you could hard code this into your script, or you could feed the parameters from the RTC build definition properties, to the jython script. Do so is a very convenient way of passing in the wsadmin user credentials. This allows you to pass in one set of credentials for a dev build definition, but force the user to manually enter credentials for a production definition. Deploying to Apache Tomcat is fairly similar.

<deploy localwar="${basedir}/${warfile}" url="${tomcat.manager}" username="${tomcat.user}" password="${tomcat.password}" path="${path}">

<import file="${catalina.home}/bin/catalina-tasks.xml" />
<taskdef name="deploy" classname="org.apache.catalina.ant.DeployTask" classpath="${catalina.home}/lib/catalina-ant.jar" > </taskdef>

In the case of Tomcat, we don't need a specific jython script, but we do need to include the task def from the catalina-tasks.xml found in the bin directory of Tomcat. 

One last thing to note, for continuous integration, you will need also to remove the applications if they are already installed before you install them, or you can call the appropriate update API's. Otherwise the installs will fail stating the application is already deployed. I would put all that in the list above, but then I don't want to give away all my secrets do I?

In closing, you should now be able to do some simple deployments with your build engines. 

Labels: , , , ,