Create a runnable war with embedded tomcat or run a maven tomcat war project without maven and a tomcat installation

I know the title of this post is a bit of a contradiction, running a maven tomcat webapp without maven and a tomcat installation WTF?.

So before we begin let me clarify what I mean. You will need maven on your development environment and you will be using the tomcat7 maven plugin to deploy and run your application-.

When delivering a small to medium sized java web application it could be nice to have it as a self contained application allowing you to just drop-it anywhere and just run it without having to install/upgrade Maven, Apache Tomcat, etc. (of course you'll still need java :p )

What I would like to accomplish is to develop a web application using my usual tools and stack and then deliver the application in it's most simple way, without having to install and configure tomcat and maven on the target system.

Running a WAR project without a Tomcat installation is not very complicated you just use the maven tomcat plugin and run the appropriate goal (ex: tomcat7:run).

But running the app on a given system will require to have a local maven installation. Now this can avoid this by writing your own runner using the tomcat API(especially Tomcat Runner cli ) and including the appropriate tomcat JARs in your CLASSPATH.

Luckily, as often, there's an app plugin for that which honestly does pretty much all the job.

I'm talking of the tomcat7 maven plugin which you probably already use in some of your projects.Well as it turns out it has a very useful mojo that allows you to accomplish the task at hand.

The process of generating the runnable WAR is pretty simple (thank you Apache):

1. Add the tomcat plugin to your maven configuration





   com.ufasoli
    runnable-war
    1.0-SNAPSHOT
     war
...
   
     ...

     
        runnable-war
        
            
                
                    org.apache.tomcat.maven
                    tomcat7-maven-plugin
                    2.1
                    
                        
                            tomcat-run
                            
                                exec-war-only
                            
                            package
                            
                                /                               
                                exec-war
                                jar
                            
                        
                    
                

            
            
        
    

Here I'm configuring the generation of the runnable war inside a maven profile. If you do not want to do this just extract the build part of my runnable-war maven profile into your main maven configuration


2. Build your maven project with the optional profiles

Run the maven command in order to build your war and runnable JAR

  mvn clean package -Prunnable-war

This will generate 3 extra files on your target folder (additionally to your packaged war file) :

  • ${yourapp-version-war-exec}.jar : A runnable JAR file that contains the tomcat embedded runtime/li>
  • war.exec.manifest : a manifest file containing the main class to run
  • war-exec.properties : a properties file containing some tomcat config options and info

3. Run your WAR file

Once the project is packaged, you can go inside the target folder and run the following command to start the tomcat server


 java -jar ${yourapp-version-war-exec}.jar

I find this approach pretty useful as you can control your server environment and configuration directly from your app, but of course it's not applicable to all projects.

As usual you can find the code source for this project over at github

5 comments:

  1. Great idea. I was looking for something like this to share serverside development with client side interface without going into too much setup

    Thanks for sharing.

    ReplyDelete
  2. I am using this approach for some time now, but currently I was asked by co-worker to help her connect to app (remote debugging). And here is the problem: nothing that comes to my mind seems to work :(

    Any ideas?

    ReplyDelete
    Replies
    1. Hi,
      I'm not sure this can be done easily since you are using tomcat's classes directly to start your app.
      Maybe you can try this approach
      http://stackoverflow.com/questions/3835612/remote-debugging-tomcat-with-eclipse
      by setting those environment variables and see if the tomcat starts in debug mode...
      but I'm not really sure that this would work...

      Delete
  3. Hi,
    Thanks for this nice approach.

    Just curious - what is the semantics of -Prunnable-war? Does not seem to be a standard way of invoking a plugin as in tomcat7:exec-war-only, tomcat7:run , etc. How does this invoke the plugin's goal?

    ReplyDelete
  4. Hi the -P it's only to tell maven to use the "runnable-war" profile where I have configured the tomcat7 plugin with specific options.
    I've done it this way so I can also create a normal WAR package; since the runnable WAR configuration has to be done during the package phase.

    ReplyDelete

OSX show used ports or listening applications with their PID

On OSX you can display applications listening on a given port using the lsof the commands described below will show listening application...