Build Engineering is an essential Configuration Management function that can significantly impact the Software Development effort in many important ways. I have worked extensively with building applications using Apache Ant, MS Build and GNU Make (along with other classic versions of Make). Another key build tool is Maven which seems to be gaining in popularity with many developers. I worked with Maven 1.0.2 and then, later, Maven 2 and found that Maven had many advantages and also a number of real challenges. This article is about reviewing an existing Maven build and looking for ways to improve and refactor the existing build. Closely related activities are “mavenizing” an existing non-maven build and addressing Maven build anomalies.
Getting Started is easy Maven provides a convenient command to generate the XML based templates, called POMs, needed to get started with all of the right patterns and usage.
$ mvn archetype:generate
The command above will produce a list of 41 possible POMs that you can choose to help get you started. Some of the possible choices are a simple J2EE application, Java web application, JSF and mojo – a Maven java plugin development project. Generating the archetype POM is the best way to get started, but that is often not possible.
Mavenizing an existing build You may have an existing build that is currently being handled by Ant. If the application is setup in a way that is similar to the structure shown in the archetype POMs, then you may be able to convert the application to Maven with a reasonable amount of effort. However, you also may find that the structure of the application does not fit Maven’s expectations and that means that converting this application will be very difficult to accomplish within a reasonable period of time. You may then decide that it is just not worth converting an existing application to Maven.
Improving an existing Maven build I have had the experience of reviewing a number of existing Maven builds and looking for ways to improve the existing build, or in some cases, address build anomalies. In some ways, Maven is elegant in the way that it handles the build process and at other times, I have found it to be obtuse and very painful to troubleshoot. Here are a few things that I have learned the hard way about refactoring a Maven build:
- Understand what Maven is doing in the background
- Be careful with the structure of the directories being built (and POM inheritance)
- Follow the cycle carefully as things may be happening in a different step in the lifecycle than you realize
- Declare your dependencies in a clear and consistent way
- Be careful to make sure that you don’t have dependencies in the local repository that cannot be rebuilt
- Watch out for inconsistent jars/wars that have been created
- Optimize plugins
- Control external repositories that may impact your build
- Corrupted build artifacts may go undetected (and might not be backed up)
- Right-size your multimodule enterprise projects
1. Understand what maven is doing in the background Maven does a lot of the heavy lifting for you, however this often means that you are just trusting that Maven is doing the right thing for you and that is just a bad idea. Here’s how you can not only trust but actually verify that you are getting what you expected.
$ mvn help:effective-pom
The above command will show you how your POM is being interpreted including the declarations in the Super (top level) POM that your POM is inheriting from.
2. Be careful with the structure of the directories being built (and POM inheritance) Structure matters in Maven. Make sure that you are carefully deciding how subdirectories should be organized. You may find that you have a utility that you always think of as being a child of another module, but from a build perspective it may just be a sibling. Once again look at the effective POM and understand how your application is being built.
3. Follow the cycle carefully as things may be happening in a different step in the lifecycle than you realize You should always test each phase of the lifecycle to understand what is happening in each step. I have downloaded the source code and added some tracing to get a better idea of what Maven is doing at each stage. This can get even more confusing when you are using plugins that only affect one or more stages.
4. Declare your dependencies in a clear and consistent way This is a common mistake for beginners who often declare all of their dependencies when they are first getting started with Maven. Then when they think that they understand Maven, they cut corners and assume that Maven is making the right choices. This may work for a while and then later produce unexpected results. You should determine your dependencies and declare them in the parent POM where possible.
5. Be careful to make sure that you don’t have dependencies in the local repository that cannot be rebuilt I have seen Maven used to build dependencies that were stored in the local .m2 repository. Then a few changes later, the dependency is no longer being built and just being pulled in from the .m2 repository. This is bad because it means that you can’t really build your code from source and if you try the build from another account, you will not be able to build the application. This happened once to me with a particularly obtuse Maven build and we had to copy the .m2 repository from one account to another just to get our builds done. This was obviously unacceptable and eventually we had to rewrite the entire build process.
6. Watch out for inconsistent jars/wars that have been created Another painful anomaly that I have seen is jars and wars that are named the same but actually different sizes. In this case there was a complex circular dependency and we had to know which copy of the jar (or war) was the real package that could be deployed.
7. Optimizing plugins Plugins are great and Maven relies heavily upon plugins for much of the work. I have seen many organizations where they built their own plugins to add required functionality to maven. Plugins need to be reviewed and optimized just like POMs. Don’t assume that a plugin knows what you want done.
8. Control external repositories that may impact your build The external repository needs to have controlled access to the Internet. Otherwise a change at an external website can adversely impact your build for production!
9. Corrupted build artifacts may go undetected (and might not be backed up) The contents of the Maven repository needs to be under version control just like any other build artifact. I have seen developers surprised to learn that the Maven repository was just a plain file system and the contents could be corrupted or inadvertently deleted. There are efforts to improve the Maven external repository and we will cover these in future articles including Nexus and Archiva.
10. Right-size your multimodule enterprise projects I have seen developers get excited by the power of the multimodule enterprise project in Maven. This is indeed a powerful feature, but sometimes you may have some modules of the application that can really be handled separately. Be careful not to make your Maven build any more complicated than it needs to be. Taking a lean and pragmatic approach to rightsizing your Maven build will help improve your own productivity and the quality of the application that you are building.
Conclusion Maven is an exciting build framework that is becoming increasingly popular among expert build engineers. I have highlighted a few of the items that I always consider when reviewing a Maven build and I hope that you will send your own suggestions for improving the Maven build!
I used two excellent books in writing this article the first is O’Reilly’s Maven: The Definitive Guide (from Sonatype) and Packt’s Apache Maven 2: Effective Implementation by Maria Odea Ching and Brett Porter along with the Better Builds with Maven that we all know and love. Drop me a line if you would like the ISBN number for these books.
Bob Aiello is the Editor-in-Chief for CM Crossroads and a consultant at Yellow Spider, Inc. (www.yellowspiderinc.com) specializing in Software Process Improvement including Software Configuration and Release Management. Mr. Aiello has over 25 years experience as a technical manager in several top NYC Financial Services firms where he had had company-wide responsibility for CM, often providing hands-on technical support for enterprise Source Code Management tools, SOX/Cobit compliance, build engineering, continuous integration and automated application deployment. Bob is the Vice Chair of the IEEE 828 Standards working group (CM Planning) and is a member of the IEEE Software and Systems Engineering Standards Committee (S2ESC) Management Board. He is a long standing member of the Steering Committee of the NYC Software Process Improvement Network (CitySPIN), where he serves as the chair of the CM SIG. Mr. Aiello holds a Masters in Industrial Psychology from NYU and a B.S. in Computer Science and Math from Hofstra University. You may contact Mr. Aiello at raiello@acm.org or link with him at http://www.linkedin.com/in/bobaiello
Trackback(0)
Comments 
Write comment
 |