Archive

Posts Tagged ‘maven’

Apache Maven 3 Cookbook

November 13th, 2011 No comments

This review is about Apache Maven 3 Cookbook from Srirangan from Packt Publishing.

Facts

  1. 9 chapters, 208 pages, $35.99
  2. This book covers Apache Maven 3

Pros

Each recipe is structured in 3 steps:

  1. “Getting ready”
  2. “How to do it”
  3. “See also” for references on associated recipes

Cons

  1. The scope of the book is too large for only 200 pages. It spans from Java to Scala and Groovy through Android, GWT and Flex.
  2. Most products installation processes (Sonatype Nexus, Hudson) are documented with a few screenshots. It would have been better to reference the product installation on the Web or to go in detail. In the current state of thing, most readers are left wondering what to do with it.
  3. The recipe structure is well adapted for… recipes. When talking about general Maven principles like compiling a project, it feels convoluted and artificial.
  4. Writing a whole chapter about native Maven reporting when there’s Sonar? Come on…

Conclusion

I was expecting much from this book, because I’m a daily Maven user and because Maven is regularly misused (see here and here for a start). I’m sorry to say I’m disappointed: there’s not much regarding how to resolve daily Maven problems provided. The concept is a good idea but IMHO the result is a failure.

Disclaimer: I was provided the book freely, courtesy of Packt Publishing

Send to Kindle
Categories: Book review Tags: ,

Maven doesn’t suck, your POM does

October 9th, 2011 6 comments

Maven bashing is an all-time favorite: there are plenty of articles telling how Maven downloads the whole Internet, or how POMs are bloated and so on.

While I agree that Maven could be perfected, I’m also aware that some (if not most) of its shortcomings are not intrinsic but are caused by (very) bad configuration. Worse, even if used correctly in your projects, problems sometimes come from third-party dependencies! You do not believe me? Well, two examples follow, from standard libraries.

Log4J

Coming from the classic logging framework, this may seem a surprise but log4j POM is a mess. Just look at its dependencies section:


  
    javax.mail
    mail
    1.4
  
  
    javax.jms
    jms
    1.1
  
  ...

Interestingly enough, Log4J depends on the Java Mail and JMS API! If you are using your application in an application server, you may be in for a rude surprise as conflicts may arise between your dependencies and the libraries available on the server.

Moreover, while some users may have the need of mail or JMS appenders, this is not the case for all of us. As such, there’s clearly a lack of appropriate modularization in the design of the library. Luckily, the above POM is an excerpt of version 1.2.15. Version 1.2.16 uses the optional tag for those libraries (which breaks transitivity): it addresses our application server use-case but is still a problem for those needing the dependencies as they have to add the dependency manually. See here for a thought or two on optional dependencies.

If we need version 1.2.15, there are basically two solutions.

  • Clean but cumbersome: we have to manually exclude JMS and Mail from each POM using Log4J. Who said software development was fun?
  • Gruesome but effective: if we have a Maven enterprise repository, we correct the POM (i.e. we add optional tags) on the repository.

Jasper reports

The Log4J example was straightforward: just the side-effects of bad modularization. Jasper’s POM has another twist, just look at a typical dependency:


  com.lowagie
  itext
  [1.02b,)
  compile

The version part means the dependency’s version should be between 1.02b included and the latest version. This obviously has two drawbacks:

  • From an architectural point of view, how can the POM provider guarantee there won’t be an API break with the latest version?
  • From a Maven POV, it means Maven will try to download the latest version. In order to do that, it will try to contact repo1… You’re beginning to see the problem? If you’re behing a corporate proxy that isolates you from the Internet, you’re toast.

The POM excerpt comes from version 2.0.4. Starting from version 2.0.5, Jasper’s designers used only single version dependencies.

If you’re stuck with older versions, the only solution here is to replace the POM with a manually crafted one that do not use unboundedversion dependencies on your enterprise repository.

Conclusion

Despite the constant noise on the Internet, Maven is a wonderful tool. Yet, even if I take the utmost care to design my POM, some external dependencies make my life harder. It would be better to stop losing time complaining about the tool and invest this time helping the developers of those dependencies to provide better POMs.

Send to Kindle
Categories: Java Tags:

Free eBook: Apache Maven 3 Cookbook

October 4th, 2011 No comments

Dear readers,

In order to celebrate the release of Apache Maven 3 Cookbook, Packt Publishing contacted me in order to hold a contest to grab a free copy of the eBook!

To be frank, I haven’t a clue toward organizing a contest so the first three who send me a mail at nicolas at frankel dot ch with the subject “Apache Maven 3 Cookbook” will be sent the eBook for free. Don’t waste your time: on your mark, ready, go!

And thanks Packt for these gifts.

Update[10h20]: Sorry folks, all three eBooks have already been given. Winners will be contacted shortly by a Packt representative. Thanks for participating!

Send to Kindle
Categories: Book review Tags:

Migrating from m2eclipse to m2e

September 25th, 2011 5 comments

Since Indigo, the Maven Ecliple plugin formerly known as m2eclipse became part of Eclipse release (at least in the pure Java release). The name of the plugin also changed from m2eclipse to m2e. This was not the sole change, however:

  • The number of tabs on the POM has shrinked drastically, and the features as well. This will probably be the subject of a later post since I feel quite cheated by the upgrade.
  • The POM configuration has been more integrated with Eclipse build (which can cause unwanted side-effects as I described in my last article).

More importantly, projects that began with m2eclipse can be built in Indigo but no contextual Maven menu is accessible on the project itself (though a contextual menu is available on the POM).

In order to migrate flawlessly and have our contextual menu back, some actions are necessary. They are gruesome because it involves updating by hand Eclipse configuration file.

Warning: at this point, you have the choice to stop reading. If you decide to continue and use the process described below, it’s at your own risk!

The Maven plugin recognizes a project as a Maven one based the .project Eclipse proprietary configuration file. To display it, go to the Project Explorer view, click on the scrolling menu at the top right and choose Customize View. You have to uncheck *.resources: along the .project file , you should see a .classpath file as well as a .settings folder.

  1. In the .project:
    • Replace org.maven.ide.eclipse.maven2Builder by org.eclipse.m2e.core.maven2Builder in the buildSpec section
    • Replace org.maven.ide.eclipse.maven2Nature by org.eclipse.m2e.core.maven2Nature in the natures section
  2. In the .classpath, replace org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER by org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER
  3. Finally, in the .settings folder, rename the org.maven.ide.eclipse.prefs file to org.eclipse.m2e.core.prefs. Contents should be left unchanged.

Now, the contextual menu should appear and work accordingly.

Remember, this is a big hack you should only use with the right parachute (at least a source control management system) since it will hurt you plenty if it fails. For me, it has always worked… yet.

Send to Kindle
Categories: Java Tags: , ,

Better Maven integration leads to unforeseen consequences (bugs)

September 11th, 2011 7 comments

This week, I was faced with what seemed an near-insuperable problem. I was called by one of my dev: as soon as he upgraded his Eclipse (or more precisely, our own already-configured Eclipse), he couldn’t deploy to Tomcat through WTP. Here are the steps I took to resolve the problem and more general thoughts about upgrading and tooling.

The log displayed a ClassNotFoundException, one involving Spring. So, the first step is to look under the hood. Provided you used the default configuration – to use workspace metadata – it should be located under /.metadata/.plugins/org.eclipse.wst.server.core/tmp/wtpwebapps where WORKSPACE is your workspace location and i is an incremental number beginning with 0 assigned by Eclipse to each virtual application server in WTP. There you should see the applications deployed in Eclipse. When I checked, I realized the application was deployed alright, but found no WEB-INF/lib folder.

I had already experienced such deployment problems: I solved them by first forcing publish (right-click on the server and choose Publish) and if not successful, cleaning (it removes all deployment and starts again from scratch). Well, this didn’t work.

Also, sometimes classes are not deployed because there aren’t there in the first place: compilation doesn’t occur (because of bad code or Eclipse may be playful) and this prevents generating .class files. This didn’t seem like the problem but hell, this was a lead like any other. In order to force compilation, clean the project and check recompile afterwards (or check auto build is on). This didn’t work too…

It happened before that closing the project and reopening it resolved some code-unrelated compilation problems. Closing and restarting Eclipse may yield the same results. I did both to no avail. At this point, I was disappointed because all previous steps should have resolved the problem… yet they hadn’t.

Since the project used Maven (and we had m2eclipse installed), I also checked the Maven Dependencies library was correctly referenced: it was. Just to be sure, I disabled and re-enabled dependencies management. Guess what? Nothing changed.

Desperate, I hopelessly browsed through the POM and the following caught my attention:


 maven-war-plugin
 
 WEB-INF/lib/*.jar
 

This configuration creates skinny WARs so that libraries are not packaged in the WAR but are in the EAR, provided they are referenced, of course (for the right way to create such WARs, see my post from last week). With a faint gleam of hope, I removed the configuration part and it worked, the libraries were finally deployed.

Yes, dear readers, it seems newer versions of the m2eclipse plugin are able to parse some portions of the POM that were not parsed before and act accordingly. Although this is a good news in general, it means we have to carefully check about potential side-effects of upgrading to those newer versions. Of course, this was stupid to upgrade in the first place but think that sometimes it’s mandatory for a newer project.

However, the problem is much more widespread than m2eclipse. It’s very similar to issues adressed in Andrew Spencer’s post, only more so since if we don’t upgrade, we may have to keep an Eclipse instance for each project, that has to be shared between all team members. Right now, I don’t have any solutions for this problem, apart from changing the code to keep in synch with the tool.

PS : since we still wanted to have skinny WARs, I just moved the configuration part in a profile… which was what was configured in the archetype provided by the support team :-)

Send to Kindle
Categories: JavaEE Tags: ,

Skinny WAR done right

September 4th, 2011 3 comments

In a previous post, I wrote about how to create skinny WAR with Maven the DRY way: it was not the DRYier way to do it, as was demonstrated to me this week by my colleague Olivier Chapiteau (credit where credit is due).

His solution is far more elegant; it is reproduced below for reference’s sake.


  ...
  
    
      ch.frankel.blog.ear-war
      war-example
      1.0.0
      war
    
    
      ch.frankel.blog.ear-war
      war-example
      pom 
      1.0.0
    
  
...

That’s it! The beauty lies in using the WAR’s POM as a dependency as well as the WAR itself: it’s simple, DRY and effective.

Send to Kindle
Categories: JavaEE Tags: ,

Maven repositories in anger!

June 19th, 2011 2 comments

Every build systems worth his salt acknowledges Maven dependencies repository. Even those vehemently opposed to the way Maven does things, like Gradle, still uses repo1.

Wait, repo1? If there was only repo1. But nowadays, every project publishes its artifacts in its own repository. For some providers, like SpringSource and JBoss, I think it may be for marketing reasons. But whatever the reasons are, it only makes the job of the enterprise repository manager harder, since he has to reference all those repositories.

I also stumbled upon another serious glitch in repositories this week. My client bought JBoss Enterprise Application Platform (JBoss EAP) 5.0. Now, suppose we want to compile our code against JBoss EAP’s libraries using Maven. Guess what? Those libraries are available in no accessible repository: check this issue if you don’t believe me. Now, support proposes two solutions:

  • Either manually put EAP’s libraries in our own repository, reconstructing each POM
  • Or use Maven’s system path to point to a local (or network) JBoss EAP

Is this really the level of support we are expecting from a major player like Red Hat? Unfortunately, this is only a single real-world example of things going awry regarding Maven repositories. I’m afraid there are more going around beyond my meager knowledge, and even more to come.

Repo1 was meant to ease our life. I really wish we could go back to this simple scheme once again: stop tackling problems brought by providers and provide answers to problems brought by the business.

Send to Kindle
Categories: Java Tags: , ,

Mixing Vaadin and Scala (with a touch of Maven)

January 24th, 2011 6 comments

People who are familiar with my articles know that I’m interested in Vaadin (see the “Go further” section below) and also more recently in Scala since both can increase your productivity.

Environment preparation

Thus it is only natural that I tried to embed the best of both worlds, so to speak, as an experience. As an added challenge, I also tried to add Maven to the mix. It wasn’t as successful as I had wished, but the conclusions are interesting (at least to me).

I already showed how to create Scala projects in Eclipse in a previous post, so this was really a no-brainer. However, layering Maven on top of that was trickier. The scala library was of course added to the dependencies list, but I didn’t found how to make Maven compile Scala code so that each Eclipse save does the compilation (like it is the case with Java). I found the maven-scala-plugin provided by Scala Tools. However, I wasn’t able to use it to my satisfaction with m2eclipse. Forget the Maven plugin… Basically what I did was create the Maven project, then update the Eclipse configuration from Maven with m2eclipse and finally add the Scala builder: not very clean and utterly brittle since any update would overwrite Eclipse files. I’m all ears if anyone knows the “right” way to do!

Development time

Now to the heart of the matter: I just want a text field and a button that, when pressed, displays the content of the field. Simple enough? Not really. The first problem I encountered was to create an implementation of the button click listener in Scala. In Vaadin, the listener interface has a single method void buttonClick(Button.ClickEvent event). Notice the type of the event? It is an inner class of Button and wasn’t able to import it in Scala! Anyone who has the solution is welcome to step forward and tell it.

Faced with this limitation, I decided to encapsulate both the listener and the event class in two standard Java classes, one in each. In order to be decoupled, not to mention to ease my life, I created a parent POM project, and two modules, one for the Java workaround classes, the other for the real application.

Next obstacle is also Scala-related, and due to a lack of knowledge on my part. I’m a Java boy so, in order to pass a Class instance, I’m used to write something like this:

eventRouter.addListenerVisibleClickEvent.class, this, "displayMessage")

Scala seems to frown upon it and refuses to compile the previous code. The message is “identifier expected but ‘class’ found”. The correct syntax is:

eventRouter.addListener(classOf[VisibleClickEvent], this, "displayMessage")

Moreover, while developing, I wrote a cast the Java way:

getWindow().showNotification(button.getCaption() + " " + (String) field.getValue())

My friend Scala loudly complained that “object String is not a value” and I corrected the code like so:

getWindow().showNotification(button.getCaption() + " " + field.getValue().asInstanceOf[String])

Astute readers should have remarked that concatenating strings render this cast unnecessary and I gladly removed it in the end.

Conclusion

In the end, it took more time than if I had done the example in Java.

  • For sure, some of the lost time is due to a lack of Scala knowledge on my part.
  • However, I’m not sure the number of code lines would have been lower in Java, due to the extra-code in order to access inner classes .
  • In fact, I’m positive that the project would have been simpler with Java instead of Scala (one project instead of a parent and 2 modules).

The question I ask myself is, if Scala cannot extend Java inner classes – and that being no mistake on my part, should API evolve with this constraint? Are inner classes really necessary in order to achieve a clean design or are they only some nice-to-have that are not much used?

In all cases, developers who want to code Vaadin applications in Scala should take extra care before diving in and be prepared to have a lower productivity than in Java because there are many inner classes in Vaadin component classes.

You can find the sources for this article here in Maven/Eclipse format.

To go further:

Send to Kindle
Categories: JavaEE Tags: , ,

Managing POM versions

July 26th, 2010 1 comment

This article won’t be long but can be a lifesaver. If you use Maven, how many times did you need to manually update POM versions in an entire modules hierarchy? For me, the answer is: “too many”.

When you project grows to include many Maven modules, releasing a new version can be a nightmare. Sure, you have the maven-release-plugin. It does many things under the cover but in some cases, I saw it fail. What do you do then? You manually change your POM version in your modules hierarchy:

  • the version of the module’s POM
  • the version of the parent’s POM

It’s not only a boring taks, it’s also an error-prone one. Imagine my surprise when I found the maven-version-plugin and its little jewel of a command line:

mvn versions:set -DnewVersion=1.0.1-SNAPSHOT

And presto, the plugin does it all for you, entering each module and changing the previous informations:

[INFO] [versions:set]
[INFO] Searching for local aggregator root...
[INFO] Local aggregation root: D:\workspace\Champion Utilities
[INFO] Processing ch.frankel.champions.license:license
[INFO]     Updating project ch.frankel.champions.license:license
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]
[INFO] Processing ch.frankel.champions.license:license-check
[INFO]     Updating parent ch.frankel.champions.license:license
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]     Updating project ch.frankel.champions.license:license-check
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]
[INFO] Processing ch.frankel.champions.license:license-common
[INFO]     Updating parent ch.frankel.champions.license:license
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]     Updating project ch.frankel.champions.license:license-common
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]
[INFO] Processing ch.frankel.champions.license:license-generation
[INFO]     Updating parent ch.frankel.champions.license:license
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT
[INFO]     Updating project ch.frankel.champions.license:license-generation
[INFO]         from version 1.0.0 to 1.0.1-SNAPSHOT

Give it a try, it’s a real powerful yet easy!

Send to Kindle
Categories: Java Tags:

DRY and skinny war

April 21st, 2010 1 comment

In this article, I will show you how the DRY principle can be applied when using the skinny war configuration of the maven-war-plugin.

While packaging an EAR, it is sometimes suitable that all libraries of the different WARs be contained not in their respective WEB-INF/lib folders but at the EAR level so they are usable by all WARs. Some organizations even enforce this rule so that this is not merely desiarable but mandatory.

Using Maven, nothing could be simpler. The maven-war-plugin documents such a use case and calls it skinny war. Briefly, you have two actions to take:

  • you have to configure every WAR POM so that the artifact will not include any library like so:
    
      ...
      
        
          
            maven-war-plugin
            
              WEB-INF/lib/*.jar
              
                
                  true
                  lib/
                
              
            
          
        
      
    
  • you have to add every dependency of all you WARs in the EAR

The last action is the real nuisance since you have to do it manually. In the course of the project, a desynchronization is sure to happen as you add/remove dependencies from the WAR(s) and forget to repeat the action on the EAR. The DRY principle should be applied here, the problem lies in how to realize it.

There’s an easy solution to this problem: if a POM could regroup all my WAR dependencies, I would only have to draw a dependency from the WAR to it, and another from the EAR to it and it would fulfill my DRY requirement. Let’s do it!

The pomlib itself

Like I said before, the pomlib is just a project whose packaging is POM and that happens to have dependencies. To be simple, our only dependency will be Log4J 1.2.12 (so as not have transitive dependency, let’s keep it simple).

The POM will be:


  4.0.0
  
    ch.frankel.blog.pomlib
    pomlib-parent
    1.0.0
  
  pomlib-lib
  pom
  
    
      log4j
      log4j
    
  

Like for any other project module, I put the versions in the parent POM.

The EAR and the WAR

Both should now add a dependency to the pomlib. For brevity, only the EAR POM is displayed, the WAR POM can be found in the sources if the need be.


  4.0.0
  
    ch.frankel.blog.pomlib
    pomlib-parent
    1.0.0
  
  pomlib-ear
  ear
  
    
      ${project.groupId}
      pomlib-lib
      pom
      import
    
    
      ${project.groupId}
      pomlib-war
      war
    
  

Likewise, versions are put in the parent POM. Notice the import scope on the pomlib dependency, it’s the only magic.

Using mvn install from this point on will put the log4j dependency at the root of the generated EAR artifact and not in the WEB-INF/lib folder of the WAR.

Conclusion

Now that all dependencies are described in the pomlib, should you need to add/remove a dependency, it’s the only place you’ll need to modify. With just a little configuration, you’ve streamlined you delivery process and saved yourself from a huge amount of stress in the future.

By the way, if you use a simple Servlet container (like Tomcat or Jetty) as your development application server, you could even put the skinny war configuration in a profile. Maven will produce “fat” WARs by default, at development time. At delivery time, just activate the profile and here’s your EAR product, bundling skinny WARs.

You can find the source of this article in Maven/Eclipse format here.

Send to Kindle
Categories: Java Tags: ,