Some application servers do a better job of this than others, but overall the current state of the art in this area is still as described in the Ant manual:
<wlrun ... >
<junit fork="true" forkmode="once" ... >
This example represents a typical pattern for testing a server application. In one thread the server is started (the <wlrun> task). The other thread consists of a three tasks which are performed in sequence. The <sleep> task is used to give the server time to come up. Another task which is capable of validating that the server is available could be used in place of the <sleep> task. The <junit> test harness then runs, again in its own JVM. Once the tests are complete, the server is stopped (using <wlstop> in this example), allowing both threads to complete. The <parallel> task will also complete at this time and the build will then continue.
Let's stop for a bit and critique this approach:
- First, we have the complexity of the <parallel> and <sequential> tasks, which are complicated and intricate. As the Ant manual itself says,
Anyone trying to run large Ant task sequences in parallel ... is implicitly taking on the task of identifying and fixing all concurrency bugs [in] the tasks that they run. ... Accordingly, while this task has uses, it should be considered an advanced task ...
- Secondly, consider the ugly <sleep> call: why did we have to sleep? How long do we need to sleep? What happens if we sleep for too long, or for not long enough? As the Ant manual notes, there are sometimes ways around this, but they require assistance from the application server.
- Lastly, what happens when something fails? How do you ensure that, having started the application server, you can reliably shut it down? What happens if you try to shut it down, but it never actually started up? And so forth.
Furthermore, there are many other interactions that one needs to have with an application server beyond just starting and stopping it:
- What's the status of this application server? Is it up or down?
- Deploy or undeploy an application to the server. Query the current version of a deployed application; re-deploy a different version of an application, either with or without stopping and re-starting the application and/or the server
- Find out if the server has encountered any errors; capture the diagnostic error logs from the server.
- Adjust the configuration of the server: give it different resources, change its operating parameters, etc.
- Install or un-install an application server from scratch.
And many more.
All of these tasks are routine jobs that I'd like to be able to reliably automate, and over the years (decades!!) I have made some progress in doing so.
But still, all those hours spent in trying to write and maintain reliable Ant automation scripts for application server integration.
Is there a better way?