Adventures in JSF 2.0: Hello World Tutorial using Maven 2, JSF 2, Facelets 2, and Weld

In the first of many posts regarding the recently finalized JSF 2.0, I will be showing you what you need to do to write a simple Hello World Application. Instead of traditional JSF backing beans, this application will use Weld, an open-source implementation of JSR-299: Contexts and Dependency Injection for the Java EE platform. JSR-299 will be part of the upcoming JEE 6 specification.

Prerequisites:

Install Sun’s JDK 6, the latest version of Maven (presently 2.2.1), and the IDE of your choice.  I use Eclipse, but GEdit or notepad would work just fine. For this demo, I’ll be using Jetty, so you won’t need to install a container of any sort.

Getting Started:

Create Empty Project

Our first step is to create an ordinary empty WAR project in Maven using the

archetype:generate

command in the directory of your choice.

cd ~/workspace #this can obviously be anywhere.
mvn archetype:generate -DinteractiveMode=n -DarchetypeArtifactId=maven-archetype-webapp -Dversion=0.0.1-SNAPSHOT -DgroupId=org.bogus -DartifactId=jsf2_tutorial

Unfortunately, the default Maven archetype falls short of what we need, so we need to make a few extra directories.  We need a java directory and the test java and resources directory. I’ve also added the commands that an eclipse user would use to generate an importable eclipse project. Netbeans and IntellJ users can simply import the pom.xml.

#create a few extra directories for the project.
mkdir jsf2_tutorial/src/test jsf2_tutorial/src/test/java jsf2_tutorial/src/test/resources jsf2_tutorial/src/main/java
cd jsf2_tutorial
#if you're using *NIX, you can create empty files with this command.
mkdir src/main/java/org/ src/main/java/org/bogus/ #need to create package first.
touch pom.xml src/main/webapp/WEB-INF/web.xml src/main/webapp/WEB-INF/beans.xml src/main/java/org/bogus/HelloWorld.java src/main/webapp/index.xhtml src/test/resources/jetty-env.xml

Overview

I was very impressed that a simple Hello World project can be created with as little as five artifacts.

  1. /pom.xml
  2. /src/main/webapp/WEB-INF/web.xml
  3. /src/main/webapp/WEB-INF/beans.xml
  4. /src/main/java/org/bogus/HelloWorld.java
  5. /src/main/webapp/index.xhtml
  6. /src/test/resources/jetty-env.xml (for Jetty users).

Writing the actual Code

pom.xml

The first step is to the pom.xml file. Afterwards it can be easily imported into any modern IDE.

<project 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/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.bogus</groupId>
	<artifactId>helloworld</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>JSF 2.0 Tutorial</name>
	<repositories>
		<!-- As of October 2009, a few of the weld dependencies were not yet on the main maven repo.  We can add JBoss repo as it is updated more frequently.  -->
		<repository>
			<id>repository.jboss.org</id>
			<name>JBoss Repository</name>
			<url>http://repository.jboss.org/maven2</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>
	<dependencies>
		<!-- Common -->
		<dependency>
			<groupId>javax.enterprise</groupId>
			<artifactId>cdi-api</artifactId>
			<scope>provided</scope>
			<version>1.0-CR1</version>
		</dependency>
 
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>jsr250-api</artifactId>
			<version>1.0</version>
		</dependency>
 
		<dependency>
			<groupId>javax.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>2.0.0-RC</version>
		</dependency>
 
		<!-- Jetty-specific scopes and artifacts -->
		<dependency>
			<groupId>javax.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<scope>runtime</scope>
			<version>2.0.0-RC</version>
		</dependency>
 
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
			<scope>runtime</scope>
		</dependency>
 
		<dependency>
			<groupId>org.jboss.weld.servlet</groupId>
			<artifactId>weld-servlet</artifactId>
			<version>1.0.0-CR1</version>
			<scope>runtime</scope>
		</dependency>
 
		<dependency>
			<groupId>org.glassfish.web</groupId>
			<artifactId>el-impl</artifactId>
			<version>2.1.2-b04</version>
			<scope>runtime</scope>
			<exclusions>
				<exclusion>
					<groupId>javax.el</groupId>
					<artifactId>el-api</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>
	<build>
		<finalName>jsf2</finalName>
		<plugins>
			<!-- Compiler plugin enforces Java 1.6 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
 
			<!-- Eclipse plugin enforces download of source and JavaDoc jars -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-eclipse-plugin</artifactId>
				<configuration>
					<wtpversion>2.0</wtpversion>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
				</configuration>
			</plugin>
			<!-- Embedded Jetty (jetty:run) -->
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
				<configuration>
					<!-- force friendly name instead of artifact name + version -->
					<contextPath>${build.finalName}</contextPath>
					<!-- Where the BeanManager is constructed.  This is where we'll later declare datasource. -->
					<jettyEnvXml>${basedir}/src/test/resources/jetty-env.xml</jettyEnvXml>
					<!-- This parameter will auto-deploy modified classes...my personal favorite Jetty feature. -->
					<scanIntervalSeconds>3</scanIntervalSeconds>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Now that your pom is complete, you can import it into the IDE of your choice. Eclipse requires users to either install m2eclipse or run:

mvn eclipse:eclipse

Boilerplate

web.xml

Since JSF 1.2, the web.xml page got a lot smaller. This is where convention over configuration pays off. Also, faces-config.xml is now optional!

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
	<!-- Standard JSF 2.0 Configuration Paramters. -->
	<!-- No Joke!!...This is all you need now! -->
	<context-param>
		<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
		<param-value>.xhtml</param-value>
	</context-param>
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.jsf</url-pattern>
	</servlet-mapping>
 
	<!-- Weld Jetty Configuration parameters -->
	<listener>
		<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
	</listener>
	<resource-env-ref>
		<description>Object factory for the CDI Bean Manager</description>
		<resource-env-ref-name>BeanManager</resource-env-ref-name>
		<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
	</resource-env-ref>
</web-app>

beans.xml

In order to indicate to weld to initialize dependency injection, you’ll need to create an empty file named beans.xml. The mere presence of this file in your WEB-INF folder tells the container that your WEB-INF/classes folder is a bean deployment archive.

Application-Specific Code

HelloWorld.java

To confirm that Weld (A.K.A. JSR 299 or WebBeans) Dependency Injection works, we’re going to write an incredibly simple bean. In contrast to Spring, you don’t need to declare the package or bean. Simply adding the @Named annotations and declaring a scope is all that is needed to have your bean registered with the dependency injection container and visible to your facelets view pages.

package org.bogus;
 
import java.io.Serializable;
 
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
 
@Named //assigns this bean the name of "helloWorld"...its "de-caplitalized" class name
@SessionScoped  //creates one bean for each user session.
public class HelloWorld implements Serializable {
	private final String text = "Hello World!";
 
	public String getText() {
		return text;
	}
 
	private static final long serialVersionUID = 1L;
}

index.xhtml

Now we want to actually view the bean we created. Below is an incredibly simple xhtml/facelets page.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">
<h:head>
	<title>JSF Demo</title>
</h:head>
<h:body>
	<h1>Does Weld Work?</h1>
	<!-- Your bean can be easily accessed via Expression Language -->
	<p>My weld-injected bean says: #{helloWorld.text}</p>
</h:body>
</html>

jetty-env.xml

Since we’re not using a full JEE container, we need to configure Jetty to prepare the BeanManager.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
   "http://jetty.mortbay.org/configure.dtd">
<Configure id="webAppCtx" class="org.mortbay.jetty.webapp.WebAppContext">
	<New id="appManager" class="org.mortbay.jetty.plus.naming.Resource">
		<Arg>
			<Ref id="webAppCtx" />
		</Arg>
		<Arg>BeanManager</Arg>
		<Arg>
			<New class="javax.naming.Reference">
				<Arg>javax.enterprise.inject.spi.BeanManager</Arg>
				<Arg>org.jboss.weld.resources.ManagerObjectFactory</Arg>
				<Arg />
			</New>
		</Arg>
	</New>
</Configure>

Start up Jetty

Jetty is an embedded servlet container that can be easily launched from Maven. Since we added that small snippet to the pom, we can simply type:

mvn war:inplace jetty:run

…and maven will download Jetty and run it with the configuration file we passed.

Test Your Application

Simply load http://localhost:8080/jsf/index.jsf

firefox http://localhost:8080/jsf/index.jsf

Screenshot of your application
If you see the hello world text, everything has worked. Now that you’ve confirmed your configuration is setup correctly, you can explore the more interesting features of Weld and JSF 2, which I’ll be covering in future posts.

Download the Code

The source code to this tutorial is available via subversion here

UPDATE: Tomcat Users

With the addition of a context.xml, this example runs perfectly on Tomcat.
Please see this article for details.

Further Reading

Many thanks to the JBoss staff on the forums who helped me get started in Weld. The artifacts in this article were modeled after their examples.

Introducing Clickframes!

I’m sure at least a few people have been wondering where we’ve been the last few weeks. We’ve been busy on a number of products, and we released one of them at the end of June. It’s called Clickframes,  and it’s a set of frameworks for building usable, reliable, scalable software faster, better and cheaper.  The original Clickframes concept was based on three observations:

  • Good software requirements can be very useful.
  • Most software requirements aren’t very good.
  • Even when requirements are well thought out, they’re generally created in a format that limits their usefulness.

At ISG, we develop software using a design methodology that focuses on understanding user needs through interviews, observations and deep research. We learn as much about the problem space up-front, do as much work as possible to validate our designs with real users, and only then proceed with the implementation.  This approach works very well for us (and the one time we allowed ourselves to be persuaded to approach a problem differently the results were a lot more typical for the industry), but it requires a lot of agility. Clickframes helps give us that agility by turning static software requirements into a dynamic specification of how the application should work.

Here’s how it works: at some point during the design process we start building an application specification (or “appspec”), which is a description of the web application we want to build. The early iterations can be very schematic – identifying a couple of pages, perhaps a form or two, and a few buttons. As we learn more about the application we can extend the appspec to include additional detail, including specific requirements, security, and flows between different pages in the application.

That’s actually all pretty standard, so here’s where things get a little different. The appspec isn’t a Microsoft Word document, or a stack of index cards, or a drawing on a wall. It’s an XML file, and it’s maintained by the application’s lead designer. By managing requirements in XML, we can generate a whole range of useful artifacts on the fly. The most important is the Clickframes Interactive Preview (click the link for a sample from our Issue Tracker demo), which provides an easy to navigate HTML representation of the application. As requirements change the CLIPs can be easily regenerated. Clickframes also provides generators for conventional requirements documents (the system shall…) and a visualization tool that generates interaction maps of the application. Here’s the Issue Tracker example, generated from the same appspec as the CLIPs linked to above:

A Clickframes Project Map

Once the design stabilizes, we move on to implementing the software itself. Clickframes helps here too. We’ve built code generators for three different web architectures – PHP, JBoss Seam, and Spring WebFlow (the latter two, for the non-technical reader who has stuck it out this far, are Enterprise Java platforms, and the first is a very common scripting language for web applications). This is an area where conventional prototyping tools break down – they don’t provide a bridge to development.  With Clickframes, the plugins give us a skeleton of the application immediately, and our developers and designers can go in and immediately start creating content and the final look and feel, rather than worrying about details like implementing edit checks on form fields.  If you want to see the Clickframes Issue Tracker demo, just click on the link (to log in, enter anything for the username and password).  This isn’t a complete application, by the way – it’s just the generated code, before being customized by a programmer.

We’ve spent a lot of time on the Clickframes code generators and on the architecture of the underlying applications. We’ve implemented a range of features we call “CodeSync” that allow us to regenerate applications even after the development team has started to customize them. This is critically important, because it keeps the requirements from becoming out of date. If a business user, or a a designer, wants a change made, they can have the appspec updated and the programmer can re-run the code generator. It creates a feedback loop that’s often missing.

The final step in the Clickframes project lifecyle is testing. Since we have a version of the software requirements that a computer can understand, we can use it to generate a suite of automated tests, as well as templates for test strategies and manual test scripts. It’s not magic – the quality assurance team still has to do some work, and we can’t automatically generate every single test, but we can save a tremendous amount of up-front work. And developers can have access to automated tests of the final application almost from the first day of development. It saves a tremendous amount of time.

Clickframes is software to streamline development of enterprise applications.  So how much would you pay? Don’t answer, because it’s free – we’re releasing Clickframes as Open Source Software under the LGPL.  You can download Preview Release 1, sign up for the mailing lists, and see some demo screencasts at www.clickframes.org, and you can find a lot of documentation on The Clickframes Wiki, including instructions on how to get started without downloading anything.  The Preview Release is out there to gather feedback – we’ll be releasing new versions at a pretty rapid clip over the next two months, with a goal of 1.0 by the end of the summer. We’re also rolling out some new web site features in July that will make it easier to explore the Clickframes model.

This has been a long road for all of us – we started working on Clickframes back in May of 2008, so it’s been over a year to get to this point. So give it a try and let us know what you think!

(And if you like it, or like what we build, give us a call – we’re always looking for interesting new projects).

Oracle, Sun and Open Source

The Wall Street Journal ran an article today (registration required) on Oracle’s acquisition of Sun and it’s impact on open source, particularly MySQL. From my perspective, the coolest thing about this article is that I’m quoted in the third to last paragraph. Of course, they took a fifteeen minute conversation and boiled it down to the idea that while many people would likely be willing to pay a small fee for MySQL, if the costs get too high they’ll switch to something free.

I’m not as worked up about this as the general open source community seems to be. The trend towards inexpensive, open-source, commodity databases is here to stay. MySQL happens to be the leader right now, but there are several other options out there, including PostgreSQL (and it’s commercial variant, EnterpriseDB), Apache’s Derby, Oracle own open source BerkleyDB embedded database, and a few others.  Each of these fits very different niches, but it’s not an ecosystem of one. If Oracle was to take extreme measures against MySQL now they might be able to delay the commoditization of the database market by a year or two, but no more than that.

But I don’t think they’ll even do that. Oracle didn’t buy Sun for MySQL – they bought it for Java and, possibly, for the hardware business. They could have had MySQL for a lot less a year ago, and they’ve owned an important MySQL component, InnoDB, for several years with no negative impact on MySQL.  Picking up MySQL was just a bonus, and it could open up some interesting opportunities for Oracle. Not so much at the low end of the market, where they already have products, but as MySQL users find themselves needing some of the very high-end features where Oracle leads the market. One example that’s particularly important in healthcare: Oracle supports a feature called “Transparent Data Encryption”, that allows seamless encryption of database tables on disk. It’s an expensive, enterprise-edition add-on, and MySQL doesn’t have anything like it.  As healthcare organizations gear up to meet the new breach disclosure guidelines from FTC and HHS, that’s going to become an attractive feature.

One small correction to the WSJ article is that I’m not “an IT Director at Children’s Hospital, Boston”. I’m the Director of the Informatics Solutions Group at CHB, which is actually quite different – we’re not part of the IT department at all (we came out of the informatics research world).  We’re still substantial users of both Oracle and MySQL, and the CHB IT department has been very helpful over the years as we’ve juggled various bits of infrastructure for different projects.

Oracle Buys Sun

Tremendous implications for open source:

Oracle Agrees to Acquire Sun Microsystems – WSJ.com. (Login required)

Sun owns MySQL, the leading open-source competitor to Oracle’s relational database system. This is probably not as scary to MySQL users as it might initially seem. Oracle has been supportive of the BekeleyDB open-source embedded database (which they acquired several years ago), and have owned InnoDB for several years as well. InnoDB created a critical piece of core software (a “storage manager”) that is used by most MySQL implementations already. I met with some of the BerkeleyDB for Java people a few months ago, and was pretty impressed with Oracle’s overall commitment. Of course, BDB is a small product – MySQL isn’t.

As for the implications for Java, I think it’s probably a good thing as well. Oracle has been deeply involved in Java’s development for years, and has a major investment in the language. Since Oracle is much healthier, financially, than Sun has been recently, the deal should ensure that the platform is actively developed over the next several years.

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