DevOps Zone is brought to you in partnership with:

I'm an experienced systems/devops engineer, looking for contract work in Central London or anywhere, actually. I've been working on so many technologies over the years, Puppet, Python, Linux, HPC, Cloud computing to name but a few. Check out my website for the latest information what I've been doing. Tom is a DZone MVB and is not an employee of DZone and has posted 34 posts at DZone. You can read more from them at their website. View Full User Profile

A Sensible Java Build Tool

01.23.2012
| 9772 views |
  • submit to reddit

I've been writing Java in one sense or another for a few years now.  I learnt stuff at university, then used it in a few jobs.  I've written Beans and Applets, and various bits of stuff in between. 

It's fairly safe to say, that I like Java.  

One thing however, that's been a pretty consistent bugbear in all the time I've been writing Java, has been the classpath, and dependency resolution.  Luckily, all that can now change.  

I used to think that Ant was a pretty neat build tool.  All the IDEs supported it, it kinda worked most of the time, but sometimes, building was a bit of a ballache - Some stuff had to be in your lib/ folder, sometimes in Ant's lib/ too.  

Lately though, and this week in particular, I've been playing with Maven.  

Maven is a pretty fucking cool build tool for Java applications.  I suspect it probably works with other languages, but it's "designed" for Java. 

I don't think I really have the expertise or knowledge to explain how Maven works, partly because I haven't studied the inner workings that deeply, but also, because it's far better explained here (http://maven.apache.org/what-is-maven.html).

Instead, I'm going to dive right in, and explain what I've been working on this week.  

The company I work for currently, is making a pretty radical shift away from using PHP for everything.  Instead, we've been investigating Java for creating a middleware layer that everything can talk to.

I'm pretty chuffed with this, but I do wish that it had come a lot earlier on.  If it had, I might not have been so decisive to leave when offered a better job.

Basically, when we came up with this project, I insisted that we do it properly, for a change.  

I suggested that a good workflow would be something like: Netbeans IDE -> Maven Project -> Git SCM -> Jenkins CI -> Maven Repository (We chose Artifactory, but I did test Sonatype Nexus too, but didn't like it).

This is a good pattern for the Joel Test's "Can you make a build in one step?"

I basically wanted to create a demo project that can be used as the basis for all future FR projects, I do the R&D to make the initial POM work, then everyone else can clone this, or inherit from it.. 

This decision was twofold, I also wanted to figure out JPA/Hibernate and have some clue how that works for reverse engineering the classes from an existing database, the answer to that is: Pretty well, actually. - But that's another story.

My IDE of choice is Netbeans.  I've been using it since I was at university, except for a small android-related foray into Eclipse, and an experimental nosing around IntelliJ IDEA.

Stuff I did:

  1. Created a new Netbeans Maven project from the quickstart archetype.
  2. Added the Dependencies on Hibernate (all the sub-dependencies get resolved, and added)
  3. Added the <scm></scm> and <ciManagement></ciManagement> lines to the POM
  4. Added maven-shade-plugin to allow us to build a fat JAR, which makes the jar bigger - it includes all the dependency JARs, but does make deployment a damnsight easier.
  5. Configured <distributionManagement></distributionManagement> to contain the url of the repository we're using.

That's pretty much it.  Here's the finished POM, with various bits of secret removed. 

When I edit something in Netbeans, and commit a change, there's a post-commit hook (post-receive) that calls the Jenkins API, and builds the project.  Jenkins then deploys the artifacts (a fat JAR and a POM) to the Artifactory.

Epic.

Published at DZone with permission of Tom O'connor, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Mykel Alvis replied on Mon, 2012/01/23 - 1:09am

Suggestions for making your [maven-related] life easier to deal with:
  • Make a company parent super POM (or make a hierarchy of POMs) that contain(s) the boilerplate elements of the POM and a dependencyManagement and pluginManagement section that configures dependencies and plugins.
    This saves a ton of time later and keep versions consistent across your working project set
  • Use properties to set widely used values (eg. ${spring.version} to set the version of Spring you're using ). Obviously you'd want to set those properties in your super POM.
    This way when a developer wants to use a new version of something, he can just over-ride the property (that his POM inherited from the parent you built) and if it becomes necessary, feed that altered version back up the chain to the company parent..
  • Overcome the urge to make monolithic projects. If your POM hierarchy is good, then series of multi-module builds are simple and easy to maintain and promote breaking applications up into more testable pieces.
  • Document using the site plugin.
    This can be a pain, but I suggest using Xdoc. It's slightly more foolproof than APT but YMMV.
  • Use Sonar. It's awesome.
  • Go to the effort to create separate integration test projects.
    Besides making integration testing possible, the separate POM prevents a form to test-dependency pollution from occurring in your actual codebase
  • Use the release plugin to make releases
  • Pick nexus over artifactory.
    The search interface is much better..

    Meh. Pick whatever repo manager you want. Just pick one and use it.
I also suggest reading Kief Morris' whining somewhat slanted article about Maven's weaknesses. His article is chock full of examples, both of how not to use maven and how to exploit its weaknesses to make your life harder.
General things to remember that aren't suggestions:
  • Creating repeatable builds for non-trivial applications in any language is itself non-trivial
  • Dependency management is painful on any platform. Anyone who says otherwise needs to show up with charts and graphs to back up their lie. Maven's answer definitely isn't perfect but it's at least as good as any other and better than most.
  • Like most tools, Maven can be used wisely or foolishly.
  • Remember that my suggestions above are not comprehensive.

Lance Semmens replied on Mon, 2012/01/23 - 5:01am

It pains me to see people discovering (and loving) maven in the year 2012!!

I have seen days and days of development time be wasted with Maven for tasks that could be done in 30 minutes with ant. I urge you to give Gradle a try.

Hibernate have switched from maven to gradle (https://community.jboss.org/wiki/GradleWhy) and so have tapestry (https://issues.apache.org/jira/browse/TAP5-116).

"Gradle combines the power and flexibility of Ant with the dependency management and conventions of Maven into a more effective way to build. Powered by a Groovy DSL and packed with innovation, Gradle provides a declarative way to describe all kinds of builds through sensible defaults. Gradle is quickly becoming the build system of choice for many open source projects, leading edge enterprises and legacy automation challenges."

Mark Unknown replied on Mon, 2012/01/23 - 11:10am

I know you are saving this for later... " I also wanted to figure out JPA/Hibernate and have some clue how that works for reverse engineering the classes from an existing database" ... While you can do this - I suggest you don't. You will have lots of clean up - Class Names, property names, Class hierarchy, Class relationships, etc.

John J. Franey replied on Mon, 2012/01/23 - 12:00pm in response to: Lance Semmens

@Lance. I will be more careful next time. I did not know that our use of maven would be painful to anyone. When I started projects with maven, I was considering only the needs of my growing team, selfish, I guess. When hibernate's developer said 'in many cases the cause [of frustration with maven] is simply an assumption or concept in Maven itself which did not line up cleanly with how I wanted to do build stuff in Hibernate', and when he said 'maven 3 is on the horizon', I thought he was referring to maven 2 and that other teams may have success. He should have said that using maven would cause pain to other developers. Sorry, I hope you would get better even though my team continues to use maven. It has been a valuable tool for us.

Lance Semmens replied on Tue, 2012/01/24 - 9:00am

Maven is great for it's conventions... simply use src/main/java, src/main/resources, src/test/java etc and you get a lot for free

Gradle uses the exact same conventions and like maven, you get a lot for free when you use the conventions.

Where you really notice the difference is when you want to perform an extra step or do something slightly different. Maven will usually fight you tooth and nail and waste your precious development time whereas gradle is much more versatile.

There's a discussion on stack overflow here

Jason Hatton replied on Tue, 2012/01/24 - 2:30pm

My suggestions for making your Maven life easier is don't use Maven. Lance is spot on with his assessment. Gradle is the best of both worlds in ways that are unimaginable. I am still learning Gradle and we have been using it for a couple years now. We have teams in our department using Maven and I would say it is not liked by them either but, they deal with it.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.