You have finished your first iteration in your project and in order to get feedback from the business you wish to have your application deployed on the test environment. In many projects the test environment is maintained by the developers. That is fine, but the acceptance and production environment are not. Why not start packaging and delivering your project artifacts like you would with a production release? This way you have a chance to fine-tune this process. When the time comes that you will have to deliver to an acceptance or production release you will have automated this process, aligned it with the expectations of the department responsible for deployment and, hopefully, made it less fallible. Where to start?
I’ll be assuming in this blog that you use Maven2 for building the different parts of your Java application. If this is not the case I advise you to have a look at Maven2. With release 2.0.4 Maven2 has come to a maturity level that I feel I can safely recommend it to customers. Maven2 advocates one artifact for each project. A typical Java application has more than one sub-artifact: several jar files, a web archive and finally an ear file to package the lot. This typical setup is supported by Maven through the use of sub-modules. First you begin with a top level pom.xml where you define all the global configurations of your application. These normally would include things like:
The next thing to configure in your top pom.xml are the sub-modules of your project. The following xml fragment specifies that your application has five sub modules (oh, not the petshop again…):
<modules>
<module>xebia-petshop-core-jar</module>
<module>xebia-petshop-util-jar</module>
<module>xebia-petshop-war</module>
<module>xebia-petshop-statistices-war</module>
<module>xebia-petshop-ear</module>
</modules>
Good descriptive names of your sub-modules, including their artifact type, are always helpful and especially as their number grow. I have found it good practice to have the artifactId of a module equal the name of the module minus the type definition. Following this rule the artifactId name of the xebia-petshop-util-jar module would be xebia-petshop-util resulting in the artifact xebia-petshop-util-0.1-SNAPSHOT.jar. The pom.xml configuration of this sub-module would be something like this:
<parent>
<groupId>com.xebia.petshop</groupId>
<artifactId>xebia-petshop</artifactId>
<version>0.1-SNAPSHOT</version>
</parent>
<artifactId>xebia-petshop-util</artifactId>
<packaging>jar</packaging>
Looking at the names of the sub-modules it is not too difficult to guess what the content would be. The xebia-petshop-core module has a dependency on the xebia-petshop-util module. The xebia-petshop-war module is dependent on the xebia-petshop-core module (this way the artifact of xebia-petshop-core will end up in the WEB-INF/lib directory of the xebia-petshop-0.1-SNAPSHOT.war. Finally the xebia-petshop-ear is dependent on the two war modules. The final deployable artifact is the xebia-petshop-0.1-SNAPSHOT.ear. I have found it also good practice to have an environment independent deployable artifact. So with this multi-module setup all the tests will be run and the -sub- artifacts will be created and deployed to your local and company repository when issuing the following Maven2 command:
$ mvn clean install deploy
Using the excellent Maven2 release plugin you can perform a release saving a lot of repetitive, manual work like updating the version, tagging the source code and deploying the artifacts to your repository. Now basically here should end your tasks as developer or not? The department or person responsible for deploying the
xebia-petshop-0.1-SNAPSHOT.ear probably needs additional information to succesfully deploy the application. For this reason we introduce a new module:
<module>xebia-petshop-dist</module>
The xebia-petshop-dist module will produce a tar archive including our ear and everything else needed for configuring the target environment. The choice of your application server of course has a significant impact on the required configuration. Let us assume that the IT department has developed a hardened configuration of the open source JBoss server. A hardened configuration of the JBoss server should at least address the following issues:
It is out-of-scope to discuss in detail how to configure this. Based on a company specific configuration the developers of the xebia-petshop application must specify to the deployer which additional resources the application depends on. Let us assume that the application uses the following environment specific resources:
It is a matter of taste where to store these additional configuration files. Basically you will have to choose between the xebia-petshop-dist or xebia-petshop-ear module. Lets choose the second option and configure the pom.xml of the xebia-petshop-dist to use the assembly plug-in of Maven2 to build a tar archive including the ear file and the additional configuration files in order for the deployer to do his work:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>attached</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<descriptor>src/main/assembly/dep.xml</descriptor>
</configuration>
</plugin>
</plugins>
</build>
</build>
<dependencies>
<dependency>
<groupId>com.xebia.petshop</groupId>
<artifactId>xebia-petshop-ear</artifactId>
<type>ear</type>
</dependency>
</dependencies>
The xebia-petshop-ds.xml and the jndi.properties files contains placeholders for the variables that need to be replaced by the deployer.
<datasources>
<local-tx-datasource>
<jndi-name>PetshopDS</jndi-name>
<connection-url>@petshop.jdbc.url@</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name>@petshop.jdbc.user@</user-name>
<password>@petshop.jdbc.password@</password>
</local-tx-datasource>
</datasources>
One additional file is necessary to include in our final archive: a README.html file that sums up the content of the archive and contains a list of all placeholders that need to replaced by the deployment team. The assembly plugin source file ‘dep.xml’ sums up all the content to be placed in the final archive.
<?xml version="1.0"?>
<assembly>
<id>bin</id>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<fileSet>
<directory>src/main/html/</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>README.html</include>
</includes>
</fileSet>
<fileSet>
<directory>../xebia-petshop-ear/src/jboss4x/deploy</directory>
<outputDirectory>jboss/deploy</outputDirectory>
<includes>
<include>**/*.*</include>
</includes>
</fileSet>
<fileSet>
<directory>../xebia-petshop-ear/src/jboss4x/conf</directory>
<outputDirectory>jboss/conf</outputDirectory>
<includes>
<include>**/*.*</include>
</includes>
</fileSet>
<fileSet>
<directory>../xebia-petshop-ear/src/main/sql</directory>
<outputDirectory>db</outputDirectory>
<includes>
<include>**/*.*</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<unpack>false</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
When the xebia-petshop-dist module is installed the xebia-petshop-dist-0.1-SNAPSHOT-bin.tar.gz will be uploaded to your local company maven2 repository where the deployer can pick it up and actually start his/their deployment procedure. One could even use the docbook plugin of Maven2 to generate the README.html based on a docbook xml source file.
Having an ‘dist’ module in your Maven2 project structure that uses the assembly plugin to archive all necessary resources and artifacts is a good step to a more controlled and automated release procedure.
Filed under Java | 2 Comments »
Altough 2.0.4 looks relatively stable – it is the multi module project reporting which is a real pain. Have you managed to set things up, so reporting – aggregated and not aggregated works for:
– javadoc
– jxr
– surefire
– changelog
– changes
– jdepend
– cobertura
– pmd
– checkstyle
Your blog software seems to have stripped all the XML tags out of your post; any chance you could re-post a corrected version please?