apache_maven

 cargo-banner-left
A ready to use example on how you can deploy your web application to a Tomcat 6 container using Maven Cargo. Cargo is a thin wrapper that allows you to manipulate Java EE containers in a standard way. 

Cargo provides the following Tools and APIs:

  • A Java API to start/stop/configure Java Containers and deploy modules into them.
  • A Java API to parse/create/merge Java EE Modules
  • Ant tasks, Maven 1, Maven 2 plugins.
  • Intellij IDEA and Netbeans plugins are in the sandbox.

First you have to decide if your tomcat server run locally or remotely as this influence the way you’ll configure your pom.xml

Below is an example of a standard architecture

|---MyApplication
|           |- ear       (ear)
|           |- service (jar)
|           |- client    (jar)
|           |- web      (war)
|           |- integration (jar)

The most interesting Maven module, which will be the subject of this article, and the next one is describing how to automate the deployment of a war to Tomcat and later on running integration tests using Selenium.

'Integration testing'  is the activity of software testing in which individual software modules are combined and tested as a group. It occurs after unit testing and before system testing. Integration testing takes as its input modules that have been unit tested, groups them in larger aggregates, applies tests defined in an integration test plan to those aggregates, and delivers as its output the integrated system ready for system testing. [WikiPedia]

Deploying to Tomcat running locally

Locally mean running on your development machine, at localhost 8080 or on any other port. Maven has the concept of a 'phase' which can be thought of a collection of goals. Hence here we are specifying that during the
’pre-integration-test’ phase first deploy the web app to the container specific folder and then start the container. Both 'deployer-deploy' and 'start' are cargo specific goals. The code below is already ready for integration testing!

<!—Example of Configuration –>

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven2-plugin</artifactId>
            <configuration>
                <wait>true</wait>
                <container>
                    <containerId>tomcat6x</containerId>
                    <type>installed</type>
                    <home>${catalina.home}</home>
                </container>
                <configuration>
                    <type>existing</type> 
                    <home>${catalina.home}</home>
                <properties>
                        <cargo.tomcat.manager.url>https://yourhost/manager</cargo.tomcat.manager.url>
                        <cargo.remote.username>ManagerAdminLogin</cargo.remote.username>
                        <cargo.remote.password>ManagerAdminPassword</cargo.remote.password>
                    </properties>
                </configuration>
                <deployer>
                    <type>installed</type>
                    <deployables>
                        <deployable>
                            <groupId>com.waltercedric</groupId>
                            <artifactId>myapplication-web</artifactId>
                            <type>war</type>
                        </deployable>
                    </deployables>
                </deployer>
            </configuration>
            <executions>
                <execution>
                    <id>start-container</id>
                    <phase>pre-integration-test</phase>
                    <goals>
                        <goal>deployer-deploy</goal>
                        <!--  Only local containers can be started  
                        <goal>start</goal>
                        -->
                    </goals>
                </execution>
                <execution>
                    <id>stop-container</id>
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>deployer-undeploy</goal>
                        <!--  Only local containers can be started  
                        <goal>stop</goal>
                        -->
                    </goals>
                </execution>
                <execution>
                    <id>verify-deploy</id>
                    <phase>install</phase>
                    <goals>
                        <goal>deployer-deploy</goal>
                    </goals>
                </execution> 
                <execution>
                    <id>clean-undeploy</id>
                    <phase>pre-clean</phase>
                    <goals>
                        <goal>deployer-undeploy</goal>
                        <!--  Only local containers can be started  
                        <goal>stop</goal>
                        -->
                    </goals>
                </execution> 

            </executions>
        </plugin>
    </plugins>
</build>

Deploying to Tomcat running remotely

The code slightly change:

  • You can NOT start and stop Tomcat running remotely, only deploy and un deploy your web application
  • ‘installed’ is replaced by ‘remote’
<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.cargo</groupId>
            <artifactId>cargo-maven2-plugin</artifactId>
            <configuration>
                <wait>true</wait>
                <container>
                    <containerId>tomcat6x</containerId>
                    <type>remote</type>
                </container>
                <configuration>
                    <type>remote</type> 
                    <properties>
                        <cargo.tomcat.manager.url>https://yourhost/manager</cargo.tomcat.manager.url>
                        <cargo.remote.username>ManagerAdminLogin</cargo.remote.username>
                        <cargo.remote.password>ManagerAdminPassword</cargo.remote.password>
                    </properties>
                </configuration>
                <deployer>
                    <type>installed</type>
                    <deployables>
                        <deployable>
                            <groupId>com.waltercedric</groupId>
                            <artifactId>myapplication-web</artifactId>
                            <type>war</type>
                        </deployable>
                    </deployables>
                </deployer>
            </configuration>
            <executions>
                <execution>
                    <id>start-container</id>
                    <phase>pre-integration-test</phase>
                    <goals>
                        <goal>deployer-deploy</goal>
                    </goals>
                </execution>
                <execution>
                    <id>stop-container</id>
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>deployer-undeploy</goal>
                    </goals>
                </execution>
                <execution>
                    <id>verify-deploy</id>
                    <phase>install</phase>
                    <goals>
                        <goal>deployer-deploy</goal>
                    </goals>
                </execution> 
                <execution>
                    <id>clean-undeploy</id>
                    <phase>pre-clean</phase>
                    <goals>
                        <goal>deployer-undeploy</goal>
                    </goals>
                </execution> 
            </executions>
        </plugin>
    </plugins>
</build>

If you don’t want to let cargo deploy your web application artefact under the default name myapplication-web-0.0.1.SNAPSHOT.war, you can add the following to the deployable section of cargo

<plugin>
    <groupId>org.codehaus.cargo</groupId>
    <artifactId>cargo-maven2-plugin</artifactId>
    <configuration>
        <deployer>
            <deployables>
                <deployable>
                    <properties>
                        <context>mywebapp</context>
                    </properties>
                </deployable>
            </deployables>
        </deployer>
    </configuration>
</plugin>

So you’ll be able to access your web application with http://localhost/mywebapp instead of http://localhost/myapplication-web-0.0.1.SNAPSHOT

From now on, any phase higher than ’pre-integration-test’ will trigger the deployment to your web application to any tomcat, jboss or weblogic container. As a reminder, here are the major phase of Maven, You can put many of them just separate by a space in run as - goals

  • validate - validate the project is correct and all necessary information is available
  • generate-sources - generate any source code for inclusion in compilation
  • process-sources - process the source code, for example to filter any values
  • generate-resources - generate resources for inclusion in the package
  • process-resources - copy and process the resources into the destination directory, ready for packaging
  • compile - compile the source code of the project
  • process-classes - post-process the generated files from compilation, for example to do byte code enhancement on Java classes
  • generate-test-sources - generate any test source code for inclusion in compilation
  • process-test-sources - process the test source code, for example to filter any values
  • generate-test-resources - create resources for testing
  • process-test-resources - copy and process the resources into the test destination directory
  • test-compile - compile the test source code into the test destination directory
  • test - run tests using a suitable unit testing framework. These tests should not require the code be packaged or deployed
  • prepare-package - perform any operations necessary to prepare a package before the actual packaging.
  • package - take the compiled code and package it in its distributable format, such as a JAR
  • pre-integration-test - perform actions required before integration tests are executed. This may involve things such as setting up the required environment
  • integration-test - process and deploy the package if necessary into an environment where integration tests can be run
  • post-integration-test - perform actions required after integration tests have been executed. This may including cleaning up the environment
  • verify - run any checks to verify the package is valid and meets quality criteria
  • install - install the package into the local repository, for use as a dependency in other projects locally
  • deploy - done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects

I recommend you also to use:

  • Maven profiles (triggered by environment, Linux, Windows, DEV, TEST, PROD)
  • Key value pair for sensitive data (login, password)
  • Key value pair for contextual data (URL’s of management console)

All of these data can be saved in your Maven settings.xml or given by system variables at build time.

You might like also

Fetching artifact programmatically through REST/API in Nexus 3.x
There is so many case where it is desirable to pull down artifact from Sonatype #Nexus using REST API, unfortunately #Nexus 3.x Rest API are still under development... Some use cases in Nexus 2.x: You have a script that uses #REST call to pull down the LATEST maven artifacts every night from Nexus and deploys them. You make extensive use of the #REST API in all your puppet modules You use the #Atlassian #Puppet module for Nexus for creating repository, …
899 Days ago
git-branch-renamer-maven-plugin
When working with many feature/release/bugix/hotfix branches, it is a bad idea to start changing the pom version as this will create merge conflicts using pull request. this plugin allow you to keep in ALL branches the same pom version for all your projects, for example MASTER-SNAPSHOT the version will be derived from branch name automagically :-) You may want to read more first these 2 short articles Update Maven pom version on GIT checkout in TeamCity maven-release-plugin with GIT git-branch-renamer-maven-plugin …
911 Days ago
Review: Getting Started with Apache Maven by Russell Gold
Some time ago I was asked if I would like to write a review about one of the new video courses from Packt Publishing. It was "Getting Started with Apache #Maven" http://bit.ly/1fycmpP by Russell Gold and since I have been using Maven for some years now (since 2007) and did publish some articles myself, I thought it would be nice to help them promote Apache #Maven. The course is organized in eight chapters, forty videos with a length between two …
2098 Days ago
Update Maven pom version on GIT checkout in TeamCity
Here is a solution to the following problems Deriving #Maven artifact version from #GIT branch, Update pom version on #GIT checkout automatically, Add the ability to use Pull request with Apache #Maven. You have a workflow requirement that require you to have the artifact version of a module externally defined from the current branch in #GIT. For example You want to start working on a new feature branch “feature-memory-improvement”, so you branch from master a new branch named feature/feature-memory-improvement Having …
2103 Days ago
Easily Compress Web Application Resources with EhCache
Resources such as #JavaScript and CSS files can be compressed before being sent to the browser, improving network efficiencies and application load time in certain case. If you are not using Apache with mod_deflate or nginx in front of your web application, you may need to implement resources compression yourself…. Wait! don’t start writing your own filter to compress files like CSS, html, txt, javascript it is way more difficult than you think to properly handle http response headers and …
2585 Days ago
Tomcat 7 and Apache Maven
Here is 3 different way to control the lifetime a local Tomcat 7 container using Apache #Maven. A typical scenario would be to start a servlet container prior to running integration tests (Selenium, SAHI or using any other framework you can think of ) With the following examples, you will be able to start an instance of Tomcat 7 running your web application in the pre-integration-test phase and stop the instance in the post-integration-test phase. You can also decide to …
2585 Days ago
Apache Maven copy local file to a remote server server using SSH
I will show you in an Apache #Maven configuration file how to copy files to server each time the package phase is executed. Solution with Ant SCP task This snippet of code is a ready to use code that make use of Apache Ant task scp, Just put this snippet of code in your #Maven module where the assembly is executed or anywhere else to push all tar.gz files to a server just run a #maven mvn package, you can …
2773 Days ago
Apache M2Eclipse: Get rid of Duplicate resources when opening resources and types
In this small post, I’ll show you how to remove duplicated resources in the Open Resource view of #Eclipse Eclipse – M2Eclipse – Subversive …
2779 Days ago
Apache Maven 3 Cookbook
  First a big thanks to Packt Publishing for having sent me this book to review! I did enjoy going through this book, while I did not learn a lot of new stuff (I am using Apache #Maven daily since 2006!), I found it to be concise and would recommend it anytime to any of my colleagues. But let’s go through my review of this cookbook of over 50 recipes towards optimal #Java Software Engineering with #Maven 3: Apache #Maven …
2921 Days ago
Apache Maven 3 Cookbook Review
Thanks to Packt Publishing for having sent me this book to review. I will publish a review in the next coming days Grasp the fundamentals and extend Apache #Maven 3 to meet your needs Implement engineering practices in your application development process with Apache #Maven Collaboration techniques for Agile teams with Apache #Maven Use Apache #Maven with #Java, Enterprise Frameworks, and various other cutting-edge technologies Develop for Google Web Toolkit, Google App Engine, and Android Platforms using Apache #Maven You …
2967 Days ago