Chariot Training Classes

Training Courses

I run Chariot's training and mentoring services. We provide training in AngularJS, HTML5, Spring, Hibernate, Maven, Scala, and more.

Chariot Education Services

Technology

Chariot Emerging Tech

Learn about upcoming technologies and trends from my colleagues at Chariot Solutions.

Resources

Chariot Conferences

Podcasts

« RESTing with Roo - adding Content Negotiation and REST in two easy steps (well, kinda) | Main | Spring UG Meeting recap - Oleg Zhurakousky on Spring Integration, Rabbit MQ, and GemFire »
Thursday
Jun242010

Kickin' Butt with Spring Roo at the command line with Maven shade plugin

Note: I just noticed, maybe it's something just added in 1.1.0 or later builds, but they have the assembly plugin integrated with the Roo Shell perform command. So you can do perform assembly and actually get an assembled jar with all dependencies. WOOT. Anyway, this is still useful for those who want to run Maven headless projects.Let's say you want to use Spring Roo to do persistence work, but you don't need a website. Maybe it's just a utility, something that, say uses iText to generate PDF files, or does some data processing, job execution, or some other headless task.

Spring Roo is built using Maven, and the build target generally start in an initial Roo project by deploying a JAR file, until you add Spring MVC by adding a controller. In Maven, the output of a given build is generally one thing, (the jar) so running the project might involve downloading a ton of JAR files to add to a very big classpath. That's a lot of work.

Alternatives - Maven Packaging Plugins

There are a number of maven packaging plugins that can assemble a Jar that includes all of your classes and property files from various source Jars. Several, including the Maven assembly plugin, and the one-jar plugin, didn't work for me out of the gate due to some problems loading some of the SpringSource XML schemas and extender languages.

The challenge is that these special files, META-INF/spring.handlers and META-INF/spring.schemas, are included in each of the extension JARs (like Spring Security, Spring MVC, JMS, etc) so that you can issue commands like this:

<mvc:annotation-driven />

These tools generally copy files into a temp directory and then jar it up, so they overwrite these files each time.

The Shade Plugin

The Maven shade plugin has a nice feature called a transformer. There is a special AppendingTransformer class that can be configured to continue to append data into a file specified in the configuration. Based on this article from Hagel Blog, I added two entries to the plugin configuration (as commented below) to fix the two META-INF files and we were in business.

So, without further adieu, here are the steps to single-jar happiness (at least so far) with Spring Roo and the Maven Shade plugin:

Step 1: Install the Shade Plugin to your pom.xml file

Using your STS or favorite editor, go to your maven build file, pom.xml, and add the following entry to the build -> plugins section (THANK YOU, Hagel Blog, for figuring out the problem with Spring's namespace files!):

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>1.3.3</version>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
      <transformers>      
      <transformer implementation="org.apache.maven.plugins.shade.
             resource.AppendingTransformer">
        <resource>META-INF/spring.handlers</resource>
      </transformer>
      <transformer implementation="org.apache.maven.plugins.shade.
             resource.AppendingTransformer">
        <resource>META-INF/spring.schemas</resource>
      </transformer>
    </transformers>
  </configuration>
</plugin>

Step 2: Run your maven build

Now you can just issue a mvn package command, which will package up your content in the JAR file directly.

Step 3: Execute your JAR

Go ahead now and cd to target, and issue a command like:

java -classpath ./artifact-jar-file-name.jar package.path.and.mainclassname

And that's it. Pretty nifty feature, no? Let me know if you've had success or problems with this approach.

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments (2)

Very helpfull, thanks.

June 25, 2010 | Unregistered CommenterAlois Belaska

Re step 3, you can define an additional org.apache.maven.plugins.shade.resource.ManifestResourceTransformer, and set its "mainClass" property to "package.path.and.mainclassname". This makes your JAR fully executable. I'd include the XML for this but I doubt your blog would let me. Still, you can probably figure out what to add from what I've said above...

October 12, 2010 | Unregistered CommenterAndrew Swan

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>