Publish binaries, source, and JavaDoc using Maven

So you’re using Maven, like a smart Java developer. Wouldn’t your life be easier if your IDE was linked to your source code and JavaDocs? Maven makes publishing these very easy. Once correctly configured, a simple command (mvn publish) will automatically publish your artifacts to the repository of your choice. Let me show you how.

Why?

You may ask yourself, “Why do I need to publish binaries, source, and JavaDoc? My users already have the source code.” Here are the reasons:

  1. Increase the chance of people using your code. By publishing your artifacts to a repository, particularly for secondary modules and dependencies, you save your users the trouble of doing so. At ISG, we have products that depend on in-house libraries. Before we started publishing artifacts to a standard repository, a user would have to download and build three libraries just to build one project. You want people to actually use your product, right? Make it easer and more convenient for them.
  2. Increase the chance of the build executing correctly. By building the prerequisites jars for your users and pushing them to a repository, you don’t have to worry about them forgetting to update the sources of the dependencies. Many times, I have had coworkers yell out, “Hey, Product A isn’t compiling” to which an engineer would yell back, “Update your source for Module B.” Now that we have our own Maven repository, a user only has to worry about updating the module he or she is interested in building as all dependencies are published to our repo.
  3. Eclipse will automatically import your source and JavaDocs. This is my favorite reason. By hitting F3, while selecting a class, variable, or method, you can view its source. By hitting Shift+F2, you can view the JavaDoc in your web browser. It makes it much more convenient to traverse through code and view documentation.  Now when you build your eclipse project using mvn eclipse:eclipse, it’ll download your source and JavaDoc jars automatically.
  4. Increase the chances of your code being used correctly. As mentioned above, the easier it is for people to read your documentation, the less likely they are to ask you stupid questions or dismiss your product as defective.

You greatly increase the probability of adoption if your product is convenient to build, easy to use, and the reference documentation is readily available.

How?

So if you’re still reading than perhaps I’ve persuaded you to give it a try.  The process is simple:

  1. Tell maven to assemble a JavaDoc and source jar.
  2. Put a link to your repository in your project or one of it’s parents to enable automatic uploading.
  3. Put your security info in .m2/setting.xml, so your credentials to your repository don’t get committed into version control

Configuring your POM

Unfortunately source and JavaDoc are not enabled by default, so you have to tell maven-javadoc-plugin and maven-source-plugin to package both into a Jar.

<build>
...
<plugins>
...
 <!-- Package source to JAR to upload to repo-->
 <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <executions>
       <execution>
          <!-- Restrict execution of source compilation to install or deploy. -->
          <!-- The default is package. -->
          <phase>install</phase>
          <goals>
             <goal>jar</goal>
          </goals>
       </execution>
    </executions>
 </plugin>
 <!-- Package JavaDocs to JAR to upload to repo -->
 <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <executions>
       <execution>
          <id>attach-javadocs</id>
          <!-- Restrict execution of source compilation to install -->
          <phase>install</phase>
          <goals>
             <goal>jar</goal>
          </goals>
       </execution>
    </executions>
 </plugin>
...
</plugins>
</build>

If you don’t already have a repository

If you’re going to share your code with users, you’ll obviously need a place to put files. For maven, this is simply a web-accessible folder where artifacts are organized using a strict directory naming convention. The bare minimum for a repository is simply a web-accessible folder with a means of remote access. Most first repos are simply a directory on an Apache HTTP server. Most users choose FTP, SSH, or WebDAV to publish their files.

Editing your POM to tell your project where to shove those files

WebDAV is the easiest method to get automatic publishing working. If your repository supoprts WebDAV, Just paste the following into your pom.xml file:

<distributionManagement>
   <repository>
      <id>mycompany.releases</id>
      <name>A friendly description of your release repo</name>
      <url>http://your.webdav.url/releases</url>
   </repository>
   <snapshotRepository>
      <id>mycompany.snapshots</id>
      <name>A friendly description of your snapshots repo</name>
      <url>http://your.webdav.url/snapshots</url>
   </snapshotRepository>
</distributionManagement>

Configuring your ~/.m2/settings.xml file to authenticate with your server.

Technically, your credentials don’t have to be in your settings.xml. You can omit credentials and Maven will prompt you for a username and password for each connection. This is quite tedious and I’d recommend using the settings.xml file. The settings.xml file is designed specifically for workstation-level settings, like security credentials.

Add the servers snippet below to your settings.xml.

<settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
...
<servers>
   <server>
      <id>mycompany.releases</id>
      <username>your.username</username>
      <password>your.password</password>
   </server>
   <server>
      <id>mycompany.snapshots</id>
      <username>your.username</username>
      <password>your.password</password>
   </server>
</servers>
...
</settings>

Additional Options:

Publish to SSH or FTP

Apache has an excellent reference at http://maven.apache.org/plugins/maven-deploy-plugin/project-deployment.html explaining how to publish using SSH and FTP. You can even deploy using SSH from Windows.

Publish to Nexus

Nexus is an open source repository manager and a powerful tool for Maven users.  It acts as a proxy and aggregator and downloads dependencies from multiple sites. This is my personal choice for managing dependencies. The main benefit is the proxy that allows me to retrieve jars from dozens of repositories, but only expose one URL to our users. It also makes uploading third party dependencies very easy for those situations where you have a great library you want to use, but no repository to download them from. By default, Nexus uses WebDAV to allow easy uploads and is easy to install. It is simply a war and can be deployed to Tomcat or run from embedded Jetty (see my previous post to learn how to enable it yourself).

Settings for Eclipse Users

If you’re using Netbeans or IntelliJ, congratulations, you’re done. Your IDE natively recognizes Maven projects. Eclipse users have one extra step.

There are presently two popular ways to use a Maven project in eclipse: maven-eclipse, the built-in plugin, and m2eclipse (http://m2eclipse.codehaus.org/).
Maven-eclipse will create eclipse .project and .classpath files for you to import into any eclipse install. M2eclipse requires you to download and eclipse plugin, but adds many powerful features, including the ability to automatically update your classpath as your POM changes as well as launch and debug Maven processes, such as Jetty or the Maven test runner.

If you use maven-eclipse (mvn eclipse:eclipse), make sure the following parameters are set in your pom.xml build section:

<build>
   <plugins>
      <!-- eclipse plugin -->
      <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-eclipse-plugin</artifactId>
         <configuration>
...
            <downloadSources />
            <downloadJavadocs />
         </configuration>
      </plugin>
   </plugins>
</build>

For our POMs, we also add WTP and Spring IDE support:

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-eclipse-plugin</artifactId>
 <configuration>
    <additionalProjectnatures>
       <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
    </additionalProjectnatures>
    <additionalBuildcommands>
       <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
    </additionalBuildcommands>
    <wtpversion>2.0</wtpversion>
    <downloadSources />
    <downloadJavadocs />
 </configuration>
</plugin>

If you use m2eclipse (mvn eclipse:m2eclipse), you can enable source and JavaDoc retrieval in the settings tab.

Check Download Artifact Sources and Download Artifact JavaDocs

Check Download Artifact Sources and Download Artifact JavaDocs

Conclusion

It’s quick and easy to publish binaries, source, and JavaDocs using Maven.  With minimal effort, you can dramatically increase the probability of the adoption and successful use of your product.  This is just one of the many menial programmers’ tasks that can be automated using Maven, allowing you to focus your attention on pleasing your customer and not worrying about your build.

References:

Increasing your productivity by using an embedded container in Maven

The Old Days

If you’ve ever developed a web application in Java, you’ve spent a considerable amount of time configuring your container and your IDE. For some applications, this is a small and reasonable sacrifice: “the cost of doing business.” For more complex applications, it’s a brutal time-sink that requires having every engineer that builds your application go through a training session just to get the application started.

With every project I’ve been assigned to, I’ve often had to spend the first day just configuring my environment so it will function exactly like everyone else’s. Typically the procedure has been:

  1. Download and install essential prerequisites : Java, a version control program (SVN, CVS, P4, etc), ANT, and an IDE.
  2. Download source code
  3. Download tomcat (often a very specific version which is no longer the latest version)
  4. Install tomcat
  5. Configure the server.xml and tomcat-users.xml
  6. Configure some local build properties for someone’s ANT script.
  7. Build the application
  8. Deploy

Isn’t this a huge waste?  In my experience, this is a full day for most developers when put on a project for the first time. Some of the really productive ones can do all these steps in a half day.

The New Procedure with Maven

What if you could eliminate most of this? Maven offers the promise to do so.  Here’s the procedure actual we use here at ISG:

  1. Download and install essential prerequisites : Java, a version control program, Maven, and an IDE.
  2. Download source code
  3. Run mvn compile tomcat:run (for JEE5 projects it’s glassfish:run)

Now you can log into the application.   Maven downloads all of the dependencies, builds the application, downloads a container, configures it based on our pom.xml and and deploys it to an embedded container.

To configure your application to use the embedded container, simply edit your Maven pom.xml and add the plugins below to your build section.

<build>
   <plugins>
      <!-- Embedded Glassfish v3 prelude (glassfish:run) -->
      <plugin>
         <groupId>org.glassfish</groupId>
         <artifactId>maven-glassfish-plugin</artifactId>
         <version>1.0-alpha-4</version>
         <configuration>
            <!-- technically optional, but helpful to declare explicitly. -->
            <!-- I personally put all 3 containers on different ports. -->
            <!-- This allows me to test them simultaneously. -->
            <httpPort>8070</httpPort>   
         </configuration>
      </plugin>
      <!-- Jetty Launcher Plug-in -->
      <plugin>
         <groupId>org.mortbay.jetty</groupId>
         <artifactId>maven-jetty-plugin</artifactId>
         <configuration>
            <contextPath>${project.artifactId}</contextPath>
            <!-- This parameter will auto-deploy modified classes -->
            <scanIntervalSeconds>3</scanIntervalSeconds>
            <connectors>
               <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
                  <port>8090</port>
                  <maxIdleTime>60000</maxIdleTime>
               </connector>
            </connectors>
         </configuration>
      </plugin>
      <!-- embedded tomcat (tomcat:run) -->
      <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>tomcat-maven-plugin</artifactId>
      </plugin>
   </plugins>
</build>

Now your application can run in Tomcat, Jetty, or Glassfish without any configuration on the user’s part.

Try it yourself:

I recently had to learn how to use Spring WebFlow. Fortunately, their booking sample application (SVN URL) has been configured to build with Maven. I added the snippet above to their POM and was running and modifying their application less than 15 minutes after downloading their sample. All I had to do was paste in the lines of code above and execute one command via command-line (mvn compile jetty:run).

Real-time Editing of Static Resources

Not only can your users launch the application without installing a container, but they can edit most of the application and view the results in real-time. All three containers will automatically publish static resources, such as JSP, CSS, or HTML files to the running application so that the files are instantly viewable. For example, a graphic designer could edit a CSS file, using Dreamweaver, Notepad, or the tool of their choice, and see the results in real-time, in your dynamic JEE application.

Real-time Publishing of Java Code

Jetty supports publishing of Java code automatically. Now you can see your Java code automatically redeployed to the container, on edit. This eliminates the need for contributors to configure an IDE to publish changes to the underlying Java code and view them in the container. While Glassfish doesn’t have auto-publishing support like Jetty, it will do a full redeploy if the user hits enter in the terminal window, which is almost as convenient. Glassfish is also incredibly speedy.

Development Server Atrophy

In the old days, every team had a development server they’d use to deploy their application to after making edits on their machine. Often the developer would code on a local server install and deploy the to the development server when demoing their work-in-progress or collaborating with another contributor.

As soon as we discovered these plugins, we started using our development server less and less. Eventually the company repurposed our development server. When I want another person to view an application’s progress before it hits our staging server, I can have him or her simply type “mvn jetty:run” and start using the application locally.

Conclusion

Maven is not only a powerful tool for building an application and handling its dependencies, but it can even run the application for you. This greatly lowers the barrier to contribution on a Java project as it allows people who aren’t as familiar with IDE’s like, graphic designers, business analysts, and programmers who don’t usually work in Java, to modify files on their local machines and see the results, in real-time, in a dynamic web application. It’s also very handy for demo-ing applications as the app can be setup on new machines very quickly.

Further Reading

Here’s links to the plugins I used:
The embedded Tomcat Plugin
Kohsuke Kawaguchi’s post on embedded glassfish
The Jetty Plugin