If you're interested in trying out Chef - which seems like a good fit from your comment - read on.
For tomcat you could take a look at this community-provided cookbook, which contains resources that make it simple:
https://github.com/opscode-cookbooks/application_java
If you explicitly need to stop/start tomcat beforehand (I believe this resource does a restart after deploying your app) you can do that with the "service" resource built into Chef - though doing so may mean that you're restarting every time you converge the node, which is probably not what you're looking for.
You WANT to stop the service? Really? Stopping the service is an actual headline-level goal, and not a behind-the-scenes detail?
Personally I tell puppet "make sure that the latest version of X is running", because that's what I actually want, and I don't care how it does it...
Maybe puppet has hooks to integrate with the rest of your setup, I don't know - either way, caring about how things are restarted isn't that crazy imo.
There are numerous dependencies to that task - one of which may be stopping the service before upgrading. There are dependencies to stopping the service - maybe telling the load-balancers or your monitoring system. When the service has been upgraded, you can trigger notifications that other items within your config can depend upon (for example, when an upgrade is complete, restart the service, when the service restarts, add it back to the monitoring system etc).
All of these can be modelled in these config-management tools, as explicit dependencies within your manifest file - as opposed to implicit and ad-hoc dependencies within your script.
Specify the service declaratively, and subscribe it to the package that provides the payload.
service { 'myservice':
ensure => running,
enable => true,
subscribe => Package['myservice'],
}
Then when you upgrade the package on that node, either by using ensure => latest, or by manually specifying the new version, Puppet will automatically restart the service.Perhaps I'm missing some obvious detail but I would think you would just update your repository with the new version of your application and/or Tomcat package and that would cause the service to restart on the next Puppet run, after the new version has been installed.
The app was already documented, source-controlled, version-controlled, and tested by developers and QA. There wasn't much benefit to adding anything to the configuration management repository unless there were platform/infrastructure changes.
So puppet has these beautiful (sounding) properties. But declaratively describing the state of my servers isn't a real problem I have.
I need to deal with the way that my servers change. I need to upgrade services, including starting and stopping. Puppet absolutely fails at this. Any attempt to describe a process is antagonistic to puppet at a fundamental level.
Whenever people seek a solution to these problems they always get fed that line. That puppet is declarative and idempotent, which is fine. But we should be _very_ clear that puppet does a spectacularly bad job of solving a very ordinary problem that I have, and which I would expect almost everyone else working with large numbers of servers to have too.