build

Build may refer to: read more at WikiPedia

  • Apache Maven 3 Cookbook

     

    First a big thanks toPackt 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 3 Cookbook is a clear, precise, well-written book that gives readers clear recipes for the release process using Apache Maven 3. The authors give a step-by-step account of expectations and hurdles for software development.

    The first few chapters quickly bring you to the point to be comfortable using Maven on straightforward projects, and the later chapters provide even more recipes examples on subjects like running a Repository Manager, Writing Plugins, and details on various techniques. The book also covers numerous real world software delivery issues such as multi-module projects, web/enterprise projects, dependency management, automatic testing and documentation.

    To sum up key points from this 224 pages book in a few bullets:

  • Chapter 1: Basics of Apache Maven: Setting up Apache Maven on Windows/Linux/Mac, Creating a new project, Understanding the Project Object Model, build lifecycle and build profiles,
  • Chapter 2: Software Engineering Techniques: Build automation, modularization, Dependency management, Source code quality check, Test Driven Development (TDD), Acceptance testing automation and Deployment automation,
  • Chapter 3: Agile Team Collaboration: Creating centralized remote repositories, Performing continuous integration with Hudson, Integrating source code management, Team integration with Apache Maven, Implementing environment integration, Distributed development and Working in offline mode,
  • Chapter 4: Reporting and Documentation: javadocs, unit tests, coverage reports and Maven dashboard setup,
  • Chapter 5: Java Development with Maven: Java web application, J2EE, Spring, Hibernate and JBoss SEAM development,
  • Chapter 6: Google Development with Maven: Android and GWT (Google Web Toolkit), Google App Engine deployment,
  • Chapter 7: Scala, Groovy, and Adobe Flex
  • Chapter 8: IDE Integration
  • Chapter 9: Extending Apache Maven: creating plugins using Java, Apache ANT or Ruby,
  • The author Srirangan go into detail in describing each of these themes. 

    I recommend you this book if

  • If you need to learn Apache Maven quickly, you can go through the recipes and examples and come away with a good knowledge of Maven.
  • If you are currently implementing Apache Maven for the first time in your development process and feel a bit lost by the lack of clear examples that just run.
  • If you want to use proven solutions to real common engineering challenges: this book will save you a lot of time!
  •  

    if you want to be able to deliver your software to any target environment, using continuous delivery processes, chances are high that Apache Maven is the right tool for this job, and this book should be part of your technical library, beside also of course the free online book of Sonatype Maven: The Complete Reference

  • 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

    Apache_Maven3_Cookbook

    You may also consider reading all my articles related to Apache Maven

  • Apache Maven Cargo deploy with Tomcat 7

    apache_maven

    cargo-banner-left

    Following the post about Deploy to Tomcat 6 using Maven, here is a ready to use example with the main differences explained in the table below

      Tomcat 7 Tomcat 6
    containerId <containerId>tomcat7x</containerId> <containerId>tomcat6x</containerId>
    Url of Tomcat manager <cargo.remote.uri> <cargo.tomcat.manager.url>
    example http://host..com/manager/text/ http://host..com/manager/
    tomcat-users.xml

    <tomcat-users>
    <role rolename="manager-gui"/>
    <role rolename="manager-script"/>
    <role rolename="manager-jmx"/>
    <role rolename="manager-status"/>
    <user username="admin" password="admin" roles="manager-gui,manager-script"/>
    </tomcat-users>

    <tomcat-users>
      <role rolename="manager"/>
      <user username="admin" password="admin" roles="manager"/>
    </tomcat-users>

    And finally a snippet of an Apache Maven pom.xml ready to use in a profile, so you can reuse this profile like a method call

    <profile>
     <id>deployTomcat</id>
    <activation>
      <activeByDefault>false</activeByDefault>
    </activation>
    <build>
     <plugins>
        <plugin>
         <groupId>org.codehaus.cargo</groupId>
         <artifactId>cargo-maven2-plugin</artifactId>
         <version>1.1.0</version>
        <configuration>
         <wait>true</wait>
         <container>
          <containerId>tomcat7x</containerId>
          <type>remote</type>
         </container>
         <configuration>
          <type>runtime</type>
          <properties>
           <cargo.remote.uri>
             ${tomcat.url}
           </cargo.remote.uri>
           <cargo.remote.username>
              ${tomcat.user}     
           </cargo.remote.username>
            <cargo.remote.password>
              ${tomcat.pwd}
            </cargo.remote.password>
          </properties>
          </configuration>
          <deployer>
           <type>remote</type>
           <deployables>
           <deployable>
            <groupId>${deploy.groupid}</groupId>
            <artifactId>${deploy.artifactid}</artifactId>
            <type>war</type>
            <properties>
             <context>${deploy.context}</context>
            </properties>
           </deployable>
          </deployables>
         </deployer>
        </configuration>
        <executions>
         <execution>
          <id>verify-deploy</id>
          <phase>pre-integration-test</phase>
          <goals>
           <goal>deployer-undeploy</goal>
           <goal>deployer-deploy</goal>
          </goals>
         </execution>
        </executions>
        </plugin>
     </plugins>
    </build>
    </profile>

    Place as many profiles as you have machine to deploy in settings.xml and declare some variables as properties, as shown below:

    <profile>
     <id>serverA</id>
     <activation>
        <activeByDefault>false</activeByDefault>
     </activation>
     <properties>
        <tomcat.url>http://host.com/manager/text</tomcat.url>
        <tomcat.user>admin</tomcat.user>
        <tomcat.pwd>admin</tomcat.pwd>
        <!-- these properties must be defined
           as system property or -D -->
        <!-- - deployable.artifactid:
             artifactId of web application to be deployed -->
        <!-- - deployable.context: web context name -->
     </properties>
    </profile>

    So you can run, and traget multiple host by just exchanging the name of the profile serverA to something else.

    mvn integration-test –PdeployTomcat,serverA
       –Ddeployable.artifactid=demo
       -Ddeploy.groupid=com.mycompany
       –Ddeployable.context=showcase
  • 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 add as many ant task and push to many server the same file during the reactor build.

    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.7</version>
    <executions>
    <execution>
        <id>server-copy</id>
        <goals>
            <goal>run</goal>
        </goals>
        <phase>package</phase>
        <configuration>
            <target>
                <echo message="Push to server/home/"/>
                <scp trust="yes"
                    todir="user:password@server:/home/">
                    <fileset dir="${basedir}/target">
                        <include name="**/*.tar.gz"/>
                    </fileset>
                </scp>
            </target>
        </configuration>
    </execution>
    </executions>
    <dependencies>
    <dependency>
        <groupId>org.apache.ant</groupId>
        <artifactId>ant-jsch</artifactId>
        <version>1.8.2</version>
    </dependency>
    </dependencies>
    </plugin>

    Solution with maven-deploy-plugin

    The maven-deploy-plugin allows you to configure the deploy phase to deploy to a server using scp. There is a page in the documentation that describes how it can be done.

    Deploy maven artifact using Maven Wagon SCP

    Another alternative would be to use Maven Wagon SCP like described in this post for example

  • Apache Maven profiles order in multi modules projects

    apache_maven

    In which order are Apache Maven profiles executed? are Apache Maven profiles ordered? how can you insured that Apache Maven profiles are activated in the right order?

    You normally don’t end up with these questions, issues may only appear if

    • Some profiles are dependent each other,
    • Some profiles can not run in any order,

    The use case behind this article is very simple, as I have a a continuous build were:

    • 5 web applications have  to be deployed into a remote tomcat in phase pre-integration-test,
    • 2 databases are created for test cases in phase generate-test-resources
    • 1 more database is created and needed for runtime, done in phase pre-integration-test
    • One of these web applications is able to inject data into database using web services, a profile do this in a profile in phase pre-integration-test
    • Selenium test cases are run in phase integration-test

    All these steps are done using several Apache Maven pom profiles.

    As it is a bit complicated to explain, lets first refresh some Apache Maven concepts

    Apache Maven Goals

    First you’ll have to keep in the mind Apache Maven lifecycle of modules, 21 goals out of the box:

    • 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. This often results in an unpacked, processed version of the package    
      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     (selenium test cases for example)
      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    code is deployed in artifactory or copied with ftp/scp for distribution

    if you run the goal compile

    mvn compile

    on a simple multi module project, EVERY modules, one after the others,  will go through these phases
    validate –> generate-sources –> process-sources –> generate-resources –> process-resources –> compile

    Apache Maven reactor

    The reactor is the part of Apache Maven that allows to execute a goal on a set of modules. As mentioned in the Apache Maven 1.x documentation on multi-modules builds, while modules are discreet unit of work, they can be gathered together using the reactor to build them simultaneously and:

    The reactor determines the correct build order from the dependencies stated by each project in their respective project descriptors, and will then execute a stated set of goals. It can be used for both building projects and other goals, such as site generation.

    The reactor is what makes multi-modules build possible: it computes the oriented graph of dependencies between modules, derive the build order from this graph and then execute goals on the modules. In other words, a "multi-modules build" is a "reactor build" and a "reactor build" is a "multi-modules build".

    A simple multi modules project

    For the sake of the exmaple, it has modules and profiles dependencies, in myProject/pom.xml


    remoting
    web
    monitoring
    common
    services

    or if you prefer the directory layout

    myProject
        |_ pom.xml
        |_common
                     |_src
                     |_pom.xml
        |_ web
                     |_src
                     |_pom.xml
        |_ remoting
                     |_src
                     |_pom.xml
        |_ services
                     |_src
                     |_pom.xml
        |_ web
                     |_src
                     |_pom.xml

    Lets assume also I would like to apply a list of profiles named

    • deployWeb, deploy the war module using cargo to a running tomcat instance
    • createDatabase, create a mysql database from scratch
    • runSelenium, run selenium test in phase integration test against web, assume database is created first
    • deployMonitoring, deploy the war module using cargo to a running tomcat instance, query the web at startup to get some infos.

    Maven calculate the module order in reactor based on dependencies, as seen in logs file after running

    mvn compile

    [INFO] Reactor build order:  Unnamed - com.waltercedric:myproject:pom:0.0.1-SNAPSHOT
    Unnamed - com.waltercedric:common:jar:0.0.1-SNAPSHOT
    Unnamed - com.waltercedric:services:jar:0.0.1-SNAPSHOT
    Unnamed - com.waltercedric:remoting:ear:0.0.1-SNAPSHOT
    Unnamed - com.waltercedric:web:war:0.0.1-SNAPSHOT
    Unnamed - com.waltercedric:monitoring:war:0.0.1-SNAPSHOT

    Example

    It start to be complicated when you provide a list of profile using Apache Maven command line like this

    mvn post-integration-test –PdeployWeb,createDatabase,runSelenium,deployMonitoring

    Chances are high that you will get profile executed in wrong order, too early or too late..

    Rule #1 profiles are activated (if found) following reactor modules order

    The first rule is that profiles are activated in module reactor order first, if myProject is first it will go through all 18 phases of  Apache Maven (from validate to post-integration-test in my example). Keep in mind also that the list of profiles will be applied to EVERY modules in EVERY phase starting at the top most module in reactor.

    • On modules myproject:
      •  Apache Maven will activate profiles PdeployWeb,createDatabase,runSelenium,deployMonitoring if one or more in the list are present in myproject/pom.xml
    • On modules common,
      • Apache Maven will activate profiles PdeployWeb,createDatabase,runSelenium,deployMonitoring if one or more in the list are present in common/pom.xml
    • and so on….

    Rule #2  Reactor modules order “may” be changed

    And now the tricky part, you can normally NOT change the module order in reactor, that’s ok but….

    The order you define in myProject/pom.xml for   (=module aggregation) is still kept if the maven dependencies resolver don't see any problems

    Not clear enough? look at the 2 examples below:

    myProject/pom.xml mvn post-integration-test
    Reactor build order (seen in logs)
    Remarks

    remoting
    web
    monitoring

    common
    services
    1. myProject
    2. common
    3. services
    4. remoting
    5. web
    6. monitoring
    Maven adapt the order based on oriented graph of dependencies between modules.

    remoting
    monitoring
    web

    common
    services
    1. myProject
    2. common
    3. services
    4. remoting
    5. monitoring
    6. web
    Swapping module having no direct connections each others and having no conflicting dependencies to other may result in a different order in reactor!!!! and also different profile execution order.

    Since Apache Maven has detected that the module monitoring and web have no connections, it accept the “human/natural” order found in myproject/pom.xml.

    You may have to use this technique to distribute your profiles in pom.xml while still keeping the profile order execution under control.

    Rule #3 Maven profile order is not taken from command line

    The order of profile in the Apache Maven command line  –P list is not taken into account, running the expected profiles order

    mvn post-integration-test –PdeployWeb,createDatabase,runSelenium,deployMonitoring

    is equivalent to

    mvn post-integration-test –PcreateDatabase,deployMonitoring, deployWeb,runSelenium

     

     

    It is a good things, as it  simply make no sense across all modules and all Maven phase all combined together.

    Rule #4 You can force profiles to run in an order if you SORT them accordingly into ONE pom.xml

    Apache Maven recommend to place profiles into the module where they are acting.

    If I want to insure that profiles deployWeb, createDatabase are run before the profiles runSelenium you have to keep that order in the pom.xml even if these profiles are acting in different Maven phase

    • createDatabase  may run in phase generate-test-resources 
    • deployWeb run in phase pre-integration-test
    • runSelenium run in phase integration-test

    Considering the module ordering in reactor, a good pom.xml candidate could be web/pom.xml like this



        createDatabase
     


        deployWeb
     


        runSelenium
     

    References

    http://maven.apache.org/pom.html#Profiles

  • Auto deployment of Maven artifacts to Oracle Weblogic

    apache_maven

    I found  this time a  new way to deploy Maven artefacts using the Oracle Weblogic Ant API!

    If you remember my previous post, there is many ways to deploy your war/ear to Oracle Weblogic

    1. Using Oracle Weblogic development mode, a mode in which a simple copy of your files in a specific autodeploy directory trigger the update/install of these
    2. Using Maven Cargo, this work only if your Oracle Weblogic container is local (see here) on the same machine, where Apache Maven is running
    3. Using a very old Maven plugin (2008), local and remote container are supported, but our builds were sometimes hanging during pre integration phase for no apparent reasons.

    And now using the official ANT API of Oracle, by far the MOST stable of all!

  • Keep your software stack up to date with the Apache Maven Versions Plugin

    apache_maven

    It is not unusual in a project to have a huge number of third party artifacts and Plug-in. Apache Maven help you keep track of them, along with their transitive dependencies.

    But how do you know when a new version of an artifact is available?  This is where the Maven Versions plug-in come hand in.

    The Versions Plug-in is used when you want to manage the versions of artifacts in a project's POM.

    By running

    mvn versions:display-dependency-updates

    in any Apache Maven project or modules, you’ll get for example (we have a lot of 25 Maven modules, here is only one presented as an example, the list being too long)

    [INFO] --------------------------------------------------------------------------------------------------
    [INFO] Building Unnamed - com.innoveo:skye-services-api:jar:2.2.0-M-06
    [INFO] --------------------------------------------------------------------------------------------------
    [INFO]
    [INFO] The following dependencies in Dependency Management have newer versions:
    [INFO]   junit:junit............................................. 4.4 -> 4.8.1
    [INFO]   log4j:log4j......................................... 1.2.15 -> 1.2.16
    [INFO]   org.springframework:spring...................... 2.5.6 -> 2.5.6.SEC02
    [INFO]   org.springframework:spring-test............... 2.5.6 -> 3.0.4.RELEASE

    Attention:

    It is not always an easy task to update some core components or 3rd party libraries in a complex software, as it may introduce some regressions, incompatibilities..

    At least thanks to this Versions plug in, you are aware that they may be something newer to try. What this plug in do not report is why you may want to update some artifacts libraries:

    • Do I have to use the latest version x.y.z because of  security issues?
    • Will i get more performances by updating to x.y.z?
    • New Version x.y.z resolve bug xxxx, will I have other annoying issues?

    In all the above case, you are on your own, but this is not the scope of this plug in. You’ll have anyway to

    1. Carefully decide which library can be updated,
    2. Match it to your software roadmap,
    3. Have enough confidence in your test suite (unit test, BDD, integration tests) and testing team,
    4. Communicate with your customer (for security issues in 3rd party library)
    5. .. and the list goes on

    The Versions Plug-in has a lot of interesting goals.

    Some are also updating values across all pom.xml for you.

    • versions:update-parent updates the parent section of a project so that it references the newest available version. For example, if you use a corporate root POM, this goal can be helpful if you need to ensure you are using the latest version of the corporate root POM.
    • versions:update-properties updates properties defined in a project so that they correspond to the latest available version of specific dependencies. This can be useful if a suite of dependencies must all be locked to one version.
    • versions:update-child-modules updates the parent section of the child modules of a project so the version matches the version of the current project. For example, if you have an aggregator pom that is also the parent for the projects that it aggregates and the children and parent versions get out of sync, this mojo can help fix the versions of the child modules. (Note you may need to invoke Maven with the -N option in order to run this goal if your project is broken so badly that it cannot build because of the version mis-match).
    • versions:lock-snapshots searches the pom for all -SNAPSHOT versions and replaces them with the current timestamp version of that -SNAPSHOT, e.g. -20090327.172306-4
    • versions:unlock-snapshots searches the pom for all timestamp locked snapshot versions and replaces them with -SNAPSHOT.
    • versions:resolve-ranges finds dependencies using version ranges and resolves the range to the specific version being used.
    • versions:set can be used to set the project version from the command line.
    • versions:use-releases searches the pom for all -SNAPSHOT versions which have been released and replaces them with the corresponding release version.
    • versions:use-next-releases searches the pom for all non-SNAPSHOT versions which have been a newer release and replaces them with the next release version.
    • versions:use-latest-releases searches the pom for all non-SNAPSHOT versions which have been a newer release and replaces them with the latest release version.
    • versions:use-next-snapshots searches the pom for all non-SNAPSHOT versions which have been a newer -SNAPSHOT version and replaces them with the next -SNAPSHOT version.
    • versions:use-latest-snapshots searches the pom for all non-SNAPSHOT versions which have been a newer -SNAPSHOT version and replaces them with the latest -SNAPSHOT version.
    • versions:use-next-versions searches the pom for all versions which have been a newer version and replaces them with the next version.
    • versions:use-latest-versions searches the pom for all versions which have been a newer version and replaces them with the latest version.
    • versions:commit removes the pom.xml.versionsBackup files. Forms one half of the built-in "Poor Man's SCM".
    • versions:revert restores the pom.xml files from the pom.xml.versionsBackup files. Forms one half of the built-in "Poor Man's SCM".

    The easiest way to live dangerously is to try to update all 3rd parties in one shot by issuing

    mvn versions:use-latest-versions

    but that’s another story :-)

  • Maven project filtering

    apache_maven

    Depending on your project requirements/number of customers, you may have to support different target environment. This article will help you to make your Maven build a bit more portable in that sense. Maven can help you avoiding having stage dependent data across all your Maven projects/ modules very easily thanks to resources filtering.

    Let’s imagine you want to build your software against many different runtime stack:

    • One is against your developer environment: eclipse, Tomcat, Mysql
    • One is running in a server with Tomcat, Mysql.
    • One is running in JBOSS 

    And that your software is somehow configurable, can be through properties files, xml files, environment variables. Some of your configurations files are containing data that are depending on runtime (paths, password, login, connection settings to database, profiling/tuning settings)

    Some guidelines about resources filtering

    Rules 1  you can’t filter pom.xml use profile keys

    if you have stage specific values pair key (login/password/paths) in pom.xml, you have to

    • use key/value pair properties in pom.xml (between <properties></properties>) or
    • use key/value pair properties that you override in pom.xml/settings.xml profiles or
    • use environment variables (not very efficient by the way and messy if you have too many)

    Rules 2 you can filter resources

    If you have stage specific values pair key (login/password/paths) in resources located at

    • src/main/ressources
    • src/test/resources
    • src/main/webapps
    • Anywhere else depending on your module archetype (an archetype is an helper to create a standardized Maven module)

    Then Maven filtering is the solution for your issues.

    Rules 3 profiles at rescue for new runtime

    Profiles can be defined in settings.xml or pom.xml. Maven has a very good documentation online HERE. Never forget that many profiles can be active at a time, either because you want it (start build with –P profilename1, profilename2) or based on external conditions (can be OS, path, existence/absence of files, etc..)

    Rules 4 Learn the hard way

    ATTENTION: resources  in module with packaging pom are not filtered nor copied to target directories. Don’t use src/main/resources in modules with packaging pom as it wont be copied and filtered to /target

    Tell Maven what to filter

    In order to use filters you must specify a resource directory and set filtering to true. The remaining elements are not required. Activate filtering for all files found in /src/main/resources. All files which contains the denotation ${some.property.name} will be replaced by the building property value defined in <properties></properties>

    Warning: Do not filter files with binary content like images, PDF, ZIP, GIF, JPG:  This will most likely result in corrupt output. If you have both text files and binary files as resources, you need to declare two mutually exclusive resource sets.

    Notes

    • Resources filtering definition has to be place between <build> and </build> , If you have a Maven project and a parent pom, it may belong to that particular pom.xml in order to avoid redundant definitions in all child pom.
    • if you want to filter all *.xxx files at any level in directory hierarchy you need both *.xxx (current level) and **/*.xxx (any level deeper)
    • The first resource set defines the files to be filtered and the other resource set defines the files to copy unaltered as illustrated below:

     

           <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
                <includes>
                      <include>*.properties</include>
                      <include>*.xml</include>
                      <include>**/*.xml</include>
                      <include>**/*.properties</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>false</filtering>
                <excludes>
                    <exclude>*.properties</exclude>
                      <exclude>*.xml</exclude>
                      <exclude>**/*.xml</exclude>
                      <exclude>**/*.properties</exclude>
                </excludes>
            </resource>    
            
            <resource>
                <directory>src/main/webapp/WEB-INF</directory>
                <filtering>true</filtering>
                <includes>
                    <include>*.properties</include>
                      <include>*.xml</include>
                      <include>**/*.xml</include>
                      <include>**/*.properties</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/webapp/WEB-INF</directory>
                <filtering>false</filtering>
                <excludes>
                    <exclude>*.properties</exclude>
                      <exclude>*.xml</exclude>
                      <exclude>**/*.xml</exclude>
                      <exclude>**/*.properties</exclude>
                </excludes>
            </resource>
        </resources>
        
        <testResources>
                <testResource>
                <directory>src/test/resources</directory>
                <filtering>true</filtering>
                <includes>
                    <include>*.properties</include>
                      <include>*.xml</include>
                      <include>**/*.xml</include>
                      <include>**/*.properties</include>
                </includes>
            </testResource>
            <testResource>
                <directory>src/test/resources</directory>
                <filtering>false</filtering>
                <excludes>
                    <exclude>*.properties</exclude>
                      <exclude>*.xml</exclude>
                      <exclude>**/*.xml</exclude>
                      <exclude>**/*.properties</exclude>
                </excludes>
            </testResource>
        </testResources>

     

    With the above configuration, we tell Maven that any files .xml, .properties files has to be processed and filtered.

    Give filter definitions to Maven

    Maven let you define N filters per modules as default: you can have different filters for every pom.xml. This may create some management issues. You can still decide to use one file (per runtime stack, or per profile) but you’ll have to use an absolute path to it.

    You can add a filters in your parent pom.xml by adding, I name these filter static, as they exist or not. You can also define dynamic filer in profile: the profile is active, the filter is added.

    <filters>
            <filter>${filter1}</filter>
            <filter>${filter2}</filter>
            <filter>${filter3}</filter>
        </filters>

    <filter> should be a file, usually a properties file that contains key/values pair that will be replaced at runtime.

    Note here that in order to be able to build against different target runtime, I do use a profile key/value pair properties

    Using Maven profiles to target multiple runtime environment

    Definition and motivation of using profiles

    Maven 2.0 goes to great lengths to ensure that builds are portable. Among other things, this means allowing build configuration inside the POM, avoiding all file system references (in inheritance, dependencies, and other places), and leaning much more heavily on the local repository to store the metadata needed to make this possible.

    However, sometimes portability is not entirely possible. Under certain conditions, plugin may need to be configured with local file system paths. Under other circumstances, a slightly different dependency set will be required, and the project's artifact name may need to be adjusted slightly. And at still other times, you may even need to include a whole plugin in the build lifecycle depending on the detected build environment.

    To address these circumstances, Maven 2.0 introduces the concept of a build profile. Profiles are specified using a subset of the elements available in the POM itself (plus one extra section), and are triggered in any of a variety of ways. They modify the POM at build time, and are meant to be used in complementary sets to give equivalent-but-different parameters for a set of target environments (providing, for example, the path of the app server root in the development, testing, and production environments). As such, profiles can easily lead to differing build results from different members of your team. However, used properly, profiles can be used while still preserving project portability. This will also minimize the use of -f option of maven which allows user to create another POM with different parameters or configuration to build which makes it more maintainable since it is running with one POM only. [from http://maven.apache.org/guides/introduction/introduction-to-profiles.html]

    In eclipse, you may want also to run your application against a simplified stack, for example by using Tomcat/Mysql. I propose you a strategy that should be able to target many runtime.

    First I replace all specific values through my application with keys ${aaaa.bbb.ccc} you determine the value of aaaa and bbb an ccc if you want to categorize them, but nothing stop you to just use ${aaa}

    examples:

    • ${database.mysql.url}
    • ${log4j.default.level} but it can be also only
    • ${log4jdefaultlevel}

    I create

    • a file in my Maven project at /etc/filter/eclipse.properties, I populate this file with keys/values that I use across all my configurations files in my application.
    • another file at /etc/filter/common.properties, I populate this file with keys/values that are independent of the runtime: can be logging information, timeout, etc..
    • another file at /etc/filter/jboss.properties, it contains all specific keys/values pair for that stage.

    You will have to put keys and their values to have the following valid configurations

    • common.properties + jboss.properties –> replace all keys and make your application work in Jboss
    • common.properties + eclipse.properties –> replace all keys and make your application work in eclipse

    I now define in settings.xml  the following profiles

    • id “Common” that will be always active, it make sense to have a common filter for all runtime or stack as long as you only put common key/values pair. The key ${filter1} has the value /etc/filter/common.properties
    • id “Eclipse” that will be active only If I detect an  eclipse environment,  the key ${filter2} has the value /etc/filter/eclipse.properties
    • id “Jboss” that will be not active as default, it will contains a properties key ${filter2} has the value /etc/filter/jboss.properties

    Lets look at the profile “common” in your globals settings.xml (you can also add it to your pom.xml)

    <profile>
        <id>common</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <filter1>${basedir}/etc/filter/common.properties</filter1>
        </properties>
    </profile>

    It define the filter1 and is always active

    The “eclipse” profile, only active when eclipse.exe is detected activate another filter

    <profile>
        <id>eclipse</id>
        <activation>
            <file>
                <exists>c:\eclipse\eclipse.exe</exists>
            </file>    
        </activation>
        <properties>
            <filter2>${basedir}/etc/filter/eclipse.properties</filter2>
        </properties>
    </profile>

     

    Note that the above filters are using ${basedir} reserved property, this is replaced by maven by the current artificatid (or module), so with the example above, you will have to create an etc/filter in all your modules (if you have a multi module setup). If you want to avoid this, you will have to use an absolute path instead of ${basedir}

    The Jboss profile use the same principle as the “eclipse” profile, detect a file or a hostname (jbossbuildagent)

    Make this run in Teamcity/Hudson/Bamboo

    If you activate your profile based on activation settings, you will have nothing to do. If some of your profiles are not activated as default, don’t forget to add a –P profilename1, profilename2, .. in your maven goals list.

     

    References

  • Maven Tips and Tricks: Optimizing with the Maven Dependency Plugin

    apache_maven

    On larger projects, additional dependencies often tend to creep into a POM as the number of dependencies grow. As dependencies change, you are often left with dependencies that are not being used, and just as often, you may forget to declare explicit dependencies for libraries you require. Because Maven 2.x includes transitive dependencies in the compile scope, your project may compile properly but fail to run in production. Consider a case where a project uses classes from a widely used project such as Jakarta Commons BeanUtils. Instead of declaring an explicit dependency on BeanUtils, your project simply relies on a project like Hibernate that references BeanUtils as a transitive dependency. Your project may compile successfully and run just fine, but if you upgrade to a new version of Hibernate that doesn’t depend on BeanUtils, you’ll start to get compile and runtime errors, and it won’t be immediately obvious why your project stopped compiling.

    Read mote at Sonatype Blog

  • Speeding up Apache Maven Builds

    apache_maven

    The obvious things to do first in no particular order

    • Use a better build server, CPU power is cheap today,
    • Throw more memory, as Maven run in a JVM the more you have the better it may behave, you may want also to increased the perm gen space,
    • Use the latest  version of JVM!
    • Switch as many plugins as possible as long as there are not needed in the main build loop: Use profile to modularize your build and trigger some additional build/reporting plugins when needed. You want your build to be fast to provide fast feedback to your developers.
    • Optimize your test cases, some may take longer than other, use @BeforeClass or Lazy initialization to cache some heavy to create objects,
    • Tune the garbage collector according to your build behavior, number of CPU core:  use parallel garbage collector for example,
    • Carefully review your dependencies as the less Apache Maven has to load while building the faster it will get.
      • Are they all needed?
      • No duplicates dependencies?
      • Do you miss some <exclusions>? are all these transitive dependencies to your 3rd party needed?
      • No dependencies cycles? check the order in reactor. A developer should understand, and not be surprised by  the order of the modules calculated by Maven (as long as you have layers in your software, you expect some modules to be build before some others) .
    • Review ALL logs files
      • The one created by Maven to avoid any warnings and
      • All your application logs (do you log too much data during the build?)
  • Technology management using artifact life cycles

    I forgot to blog about this presentation at JAZOON 2008, but I did never forget the added value of this plugin. It is not currently in Apache Maven  core but will for sure find its way as an official plugin one day, since it solve elegantly a common problem: technology management

    Maven does not know the concept of an artifact life cycle. Such life cycle status information would allow to extend the dependency management in a new dimension. One could declare whether certain dependencies are actually allowed/forbidden/restricted to be used in a project, enabling effective technology management.

    Currently a plugin is available to achieve this goal:The AssertDepend plugin. It work by adding metadata, additional xml files in artifact group directory.

    The AssertDepend plugin is a Maven extension to perform effective technology management. The plugin checks at build time against lifecycle states defined in metadata on remote repositories in order to inform the developer about inappropriate technology usage (dependency enforcement). Based on a flag the build would either fail or print a warning.


    Technology management benefits and means

    The capability to manage dependencies and technologies on a mature level is essential for software organizations of a certain size. Technology management becomes a key discipline and must be introduced in a careful way to allow for mutual benefits among its stakeholder including developer, management, and customers.

    Artifact lifecycle management

    To perform effective technology management, you should keep the number of approved artifacts as small as possible. You cannot remove artifacts from the repository if you want to sustain reproducible builds. Therefore, each artifact in the repository should be marked with a corresponding lifecycle state.

    The proposed main states are (but the plugin is not limited, you can create your own)

    • approved
    • prohibited
    • investigating

    With these states, it solve elegantly the following use cases.

    Scenario 1: Flawed versions
    It turns out that my-app-1.4.2.jar contains a serious security issue and is therefore flawed. Clients of this JAR should actually switch to a newer version my-app-1.4.3.jar which fixes the bug and which is safe to use.

    Scenario 2: Decommissioning
    Let's assume that my-app-1.4.2.jar is not supported anymore and projects should actually switch to a new release stream
    (my-app-2.x.y.jar).

    Scenario 3: Restricted usage
    Consider a library which has a restricted set of client projects, e.g. only certain projects are allowed to depend on a specific artifact.

    Usage

    Artifact lifecycle metadata must be placed in a file named maven-artifact-lifecycle.xml in the corresponding group directory. For instance, if you want to define lifecycle information for struts, the corresponding metadata file is located here: struts/struts/maven-artifact-lifecycle.xml

    This plugin can be downloaded at http://madp.sourceforge.net/index.html