Sunday, 1 March 2015

Getting Started with JEE 8 MVC

Java JEE 8 MVC

The JEE community have finally turned up to the MVC party; perhaps a little too late some might say. I think the young and trendy have already moved on to more exciting parties where they don't serve fruit punch and cheese on sticks.

Anyway, lets look at the new JSR371 and its reference implementation from oracle coded named Ozark. For this example you will need Java 8, Maven, Eclipse (Luna) and Glassfish.

The Ozark implementation comes bundled with the two pre-configured view engines of JSP and Facelets and extensions for Velocity, Mustache and Freemarker. For this example we're going to use standard jsp. However, if you wish to use one of the other view engines, just add the dependency to your maven project.

For anyone who is knows their way around JAX-RS, this should all seem very familiar. The new MVC JSR leverages the existing JAX-RS technology.

Getting Started

You will need to download and compile the snapshot of both the API and reference implementation, compile and install as into your local repository.

1. MVC API

git clone git://java.net/mvc-spec~git
cd mvc-spec-git/api
mvn install

2. Ozark

git clone git://java.net/ozark~sources
cd ozark-sources
mvn install

3. Eclipse

Create a new Maven project and choose webapp-javaee7 archetype. This will get you stated with a pre-built project. You will also want to install and configure the Glassfish server from the Eclipse market place.

Dependencies

Add the following dependencies to your project:

  • com.oracle.ozark:ozark:1.0-SNAPSHOT
  • javax:javaee-web-api:7.0 (provided)

4. Configure

Create a webapp/META-INF folder if this does not already exist and ensure it contains the following files:

Views Directory

By default, Ozark looks for views in META-INF/views. You will need to create this directory.

web.xml

The default Servlet mappings will prevent us from mapping our views to the root unless we override this for both the default and jsp servlet.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
 version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee">

 <servlet>
  <servlet-name>default</servlet-name>
  <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>default</servlet-name>
  <url-pattern>/WEB-INF/views/</url-pattern>
 </servlet-mapping>

 <servlet>
  <servlet-name>jsp</servlet-name>
  <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>jsp</servlet-name>
  <url-pattern>/WEB-INF/views/*</url-pattern>
 </servlet-mapping>

</web-app>
beans.xml

CDI is just the best thing since sliced bread. In fact you could call it the peanut butter that holds the bread together. In order to enable CDI you must include a beans.xml.

<?xml version="1.0" encoding="UTF-8"?>
<beans 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/beans_1_0.xsd">
</beans>

Example

1. Initialise JAX-RS

There are a number of ways to initialise JAX-RS in your project. You can use the web.xml, or as I prefer, an annotated application scoped bean.

@ApplicationPath("/")
@ApplicationScoped
public class MvcApplication extends Application {

}

2. Create a view

Create a new view in META-INF/views called hello.jsp. You will notice the page has one EL expression tag for our model value.

<html>
<body>
    <h1>Hello World!</h1>
    <p>My name is ${name}.</p>
</body>
</html>

3. Create a controller

A controller must define itself using the @Controller annotation. As per JAX-RS, all resources must also specify a path using @Path. For a controller that has more than one view-handler method, each method must also be annotated with a path.

You'll have noticed that Models is injected into the controller. Models are are just a key-pair in the form of a Map<String, Object>. The key-pairs are made available to the view. Ozark, will use all Models in the current scope (Request) and fill the view with their values.

The @View annotation is used on void methods to determine the view to be rendered. Alternatively you may return a String of the view name, but I prefer the more declarative nature of the @View tag. The only job of the method is to build the model for the view.

@Controller
@RequestScoped
@Path("/")
public class MyController {
    @Inject
    Models models;
 
    @GET
    @Path("/hello")
    @View("hello.jsp")
    public void hello() {
        models.put("name", "Marvin");
    }
}

4. Publish to Glassfish

I published to my local Glassfish installation using the Eclipse server plugin. This was my first time using Glassfish (v4) having worked with Wildfly for so many years. It was quick to get up and going with zero server configuration required for this example.

5. Browse

Open your browser and paste in the following link:

http://localhost:8080/mvc/hello

Once up and going, MVC is pretty elegant and simple. There is still more to explore, but I'll save this for future posts.