JavaData & JavaIntroduction to the New MVC 1.0 (Ozark RI)

Introduction to the New MVC 1.0 (Ozark RI)

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

MVC 1.0 is one of the new Java EE 8 specifications available under JSR 371. It is designed to be an action-oriented framework layered on top of JAX-RS API (until some point, Servlet API was also in discussion) that wishes to be an alternative, not a replacement, to the component-oriented JSF. In other words, MVC 1.0 is a different standardized Java EE approach for building Web applications on the Java EE platform (rather close to Spring MVC). If you want the controller logic in your hands and you want to provide a full control of the URI space, MVC 1.0 may be the right choice.

The M, V, and C in MVC 1.0

We assume that you know by now that, generally speaking, the model refers to the application’s data, the view to the application’s data presentation, and the controller to the part of the system responsible for managing input, calling business logic, updating the model and deciding which view should be rendered. In MVC 1.0, they are related as shown in Figure 1.

Ozark1
Figure 1: MVC 1.0

The Model (M)

The model imposed by MVC 1.0 is basically a simple HashMap defined in javax.mvc.Models, as demonstrated below. Most commonly, you will manipulate this map from your controllers (JAX-RS classes) for providing a map between names and objects:

// MVC 1.0 - source code of javax.mvc.Models
public interface Models extends Map<String,
   Object>, Iterable<String> {
}

This HashMap will be manipulated from the controller, and will update the view.

Note: If you decide to write a MVC 1.0 implementation, you must provide an implementation for the Models interface.

Although the Models model must be supported by all view engines, MVC comes with another model based on CDI (@Named). The CDI model is RECOMMENED against the Models, but OPTIONAL! As you will see later, the official implementation of MVC 1.0 supports the CDI model, also. Other implementation are not forced to have the CDI model!

The View (V)

The data stored in the model should be reflected by the view (template). For this, the view can use placeholders specific to the view type. Each placeholder will be replaced by the pointed data from the model. For example, if you provide a Book object that has an author property to the following views, you will obtain the same result (most commonly you will use EL to point data from the model):

JSP view: ${book.author}

Facelets view: #{book.author}

Handlebars view: {{book.author}}

Thymeleaf view: #{book.author}

As you saw in Figure 1, the view is represented by the ViewEngine interface listed below:

// MVC 1.0 - source code of javax.mvc.engine.ViewEngine
public interface ViewEngine {
   String VIEW_FOLDER =
      "javax.mvc.engine.ViewEngine.viewFolder";
   String DEFAULT_VIEW_FOLDER = "/WEB-INF/views/";

   boolean supports(String view);
   void processView(ViewEngineContext context)
      throws ViewEngineException;
}

ViewEngine‘s task is to merge model and view, and, as you will see, the official MVC 1.0 implementation comes with several view engines (the mandatory view engines are for JSP and Facelets). In other words, the view engine is capable of fetching data from different models and render (produce the HTML markup) the required view. Developers also can write their own engines, and, as you will see in this article, it is not a very difficult task.

The Controller (C)

The controller is the “brain” of the application; it is responsible for combining data models and views to serve the user requests (display application’s pages). In MVC 1.0, the controllers are implemented in JAX-RS style. This seriously reduces the learning curve for both newcomers and experienced Java EE developers. Once you learn how to write JAX-RS resources, you will also learn how to write MVC 1.0 controllers and vice versa. However, there are a few major differences and similarities between them.

MVC 1.0 and JAX-RS Major Differences

The major differences between MVC 1.0 and JAX-RS are as follows:

  • An MVC controller is a JAX-RS resource annotated with the type/method @Controller annotation (javax.mvc.annotation.Controller).
  • The @Controller can be used at type or method level. This is useful if you have a JAX-RS resource with a subset of methods that are actually MVC controllers. This is a hybrid class acting as a JAX-RS resource and as an MVC controller.
  • MVC classes must be CDI-managed beans only (not JAX-RS native classes, EJBs, managed beans, and so forth). This restriction is true for hybrid classes, also. Such classes must be CDI-managed beans.
  • A String returned by an MVC controller is interpreted as a view path rather than text content (for example, pointing to a JSP page). So, pay attention to this aspect because a JAX-RS resource may return content text, whereas MVC controllers don’t.
  • The default media type for a response is assumed to be text/html, but otherwise can be declared using @Produces just like in JAX-RS.
  • A MVC controller that returns void must be decorated with the type/method @View annotation to indicate the view to display.
  • We can encapsulate a view path as well as additional information related to its processing via the javax.mvc.Viewable class.
  • The method toString() is called on other Java types and the result interpreted as a view path.
  • An MVC controller that returns a non-void type may also be decorated with @View. In this case, the @View points to the default view for the controller. The default view will be used ONLY if you return null from your non-void controller.

MVC 1.0 and JAX-RS Major Similarities

The major similarities between MVC 1.0 and JAX-RS are:

  • All parameter types injectable in JAX-RS resources are also available in MVC controllers.
  • The default resource class instance lifecycle is per-request in JAX-RS and MVC (implementations may support other lifecycles via CDI).
  • The same caveats that apply to JAX-RS classes in other lifecycles also apply to MVC classes.

The MVC Annotations Résumé

MVC 1.0 comes with the following annotations:

  • @Controller (javax.mvc.annotation.Controller): Applied to class level, it defines an MVC controller. Applied to method level, it defines a hybrid class (controller and JAX-RS resource).
  • @View (javax.mvc.annotation.View): Applied to class level, it points the view for all void controller methods. Applied to method level, it points the view for that void controller method, or for that non-void controller method when it returns null (default view).
  • @CsrfValid (javax.mvc.annotation.CsrfValid): Can be applied only at method level and requires that a CSRF token must be validated before invoking the controller. Validation failure is signaled via ForbiddenException.
  • @RedirectScoped (javax.mvc.annotation.RedirectScoped): Can be applied at type, method, or field level; it points that a certain bean is in redirect scope.

Action-based vs. Component-based

When we say action-based vs. component-based, we are referring to MVC 1.0 vs. JSF. Obviously, JSF is a mature technology with several major releases whereas MVC 1.0 is just one of the new specs that will debut in Java EE 8. Both are MVC based with different flavors. Well, we won’t insist too much on a MVC 1.0 and JSF comparison, but maybe it is good to keep in mind a few facts like the following figure and table. First, it is important to distinguish among model, view, and controllers from a MVC 1.0 and JSF perspective. Figure 2 speaks for itself.

Ozark2
Figure 2: JSF MVC

Action-based MVC Component-based MVC
The Web page design is in the developers’ hands (they can choose from a wide range of technologies, such as HTML5, JS, UI libraries, and so on). Components are rendered by the framework in HTML/JS code in Web pages. Page authors will use the set of UI components provided by the framework, and optionally plain HTML.
Manual request parameter processing Automatic request parameter processing
The weight of keeping track of the validations/conversions tasks has to be carried by the developer. The framework will accomplish conversions and validations with respect to the developer configurations.
No view kept around, no state across requests. By default, state is maintained over multiple requests (on client or server), but JSF also supports stateless.
Request centric Page centric
Limited support for re-usable behavior. Components implement re-usable behavior.

Table 1: Action-based vs. component-base

At a closer look, the MVC 1.0 design is as in Figure 3:

Ozark3
Figure 3: MVC 1.0 style

Each user request will be assigned by MVC to the proper controller, based on the specified path (an instance of a controller class is to be instantiated and initialized on every request). The controllers are written by the developer and there can be more than one in the same application. These can be pure MVC controllers or hybrid classes that acts as MVC controllers and JAX-RS resources, depending on the incoming request path. Moreover, the path may point the action method that should deal with the request. Commonly, the action method will manipulate the model and will point the view that should be rendered for the user. The view will reflect the current model data (most probably via EL). The JSF design is like what’s shown in Figure 4:

Ozark4
Figure 4: JSF-MVC style

In JSF the, controller is a servlet named FacesServlet and the user cannot modify/extend it. This is responsible to deal with all user requests that should pass through the JSF lifecycle or points to JSF resources. FacesServlet distinguishes between requests types and delegates the tasks accordingly. The JSF lifecycle is a complex “machinery” based on two stages: execution and rendering. The execution stage has five phases as follows: Restore View, Apply Request Values, Process Validations, Update Model Values, and Invoke Application. The rendering stage consists of one phase, named Render Response. This phase is responsible for rendering views for the user. Each request will pass through all or a subset of phases from execution stage and through the rendering stage.

Note: Choosing between JSF and MVC depends on many aspects, but you have to keep in mind that both of them provide additional templating engines and can be used stateless. Stacked up against an MVC framework, JSF actually performs rather well. Speaking about the code, there are quite a number of similarities. However, there are also a number of fundamental differences that are perhaps not immediately obvious. And, last but not least, you have take into account your expertise with JSF and MVC.

Ozark RI Overivew

The reference implementation of MVC 1.0 is named Ozark. In Figure 5, you can notice the main features of Ozark:

Ozark5
Figure 5: MVC 1.0 RI (Ozark)

Ozark comes with two models: the mandatory implementation of Models and the optional CDI model. Moreover, Ozark comes with three view engines: ServletViewEngine, JspViewEngine, and FaceletsViewEngine. Of course, you can implement more views by implementing ViewEngine or extending the existing view engines.

The HelloWorld Example

We start this section with a very simple Hello World example. Basically, we will have a HTML start page/view (index.html) that will contain a link (path) pointing an action of an Ozark controller. This action will simply return another page/view (hello.html).

First, we need to configure the Ozark application (like a JAX-RS application), which means setting the base URI from which an application’s controllers respond to requests. Later, we will dissect this aspect, but for now let’s take the simplest way to accomplish this task:

@ApplicationPath("resources")
public class HelloApplication extends Application {
}

Further, we can write the HTML pages, which are very simple. The index.html page’s relevant code is:

<a href="resources/hello">Hello World!</a>

The value of the href attribute represents a path that points to our controller/action. This path consists of the base URI (resources) and a relative URI (hello) separated by a slash, “/“:

 1: import javax.mvc.annotation.Controller;
 2: import javax.ws.rs.GET;
 3: import javax.ws.rs.Path;
 4:
 5: @Controller
 6: @Path("hello")
 7: public class HelloController {
 8:
 9:    @GET
10:    public String helloAction() {
11:       return "/hello.html";
12:    }
13: }

Line 5: At this line, you can notice the presence of a @Controller annotation. This annotation is specific to MVC 1.0 and is the landmark that this is an MVC 1.0 controller. You also can use it at method level, and annotate only the helloAction() method, but that practice is more common for hybrid classes (Ozark controllers/JAX-RS resources).

Line 6: Further, we use the @Path annotation to point the controller-relative URI. Because we have a single method (action), we can say that the @Path from class level will be resolved in the end to the helloAction() method. When you have multiple methods (actions) in the controller, you need to use @Path at method (action) level also. Each method (action) will have its own path. We will talk later about this topic.

Line 9: Because we intend to reach helloAction() via the HTML <a/> tag, we indicate that this action is capable of dealing only with GET requests. The HTML <a/> fires a GET request.

Line 11: There’s an interesting detail at this line. Here, we indicate the view that should be rendered to the user after this action effect is complete. In our case, this view is named hello.html. Because the view is stored in the same folder with index.html (in the webapp folder), we need to prefix its path with a slash, “/“. Without this slash, hello.html will not be located/found. This is another topic discussed later. So, the hello.html is embarrassingly simple:

<h1>Hello World! (HTML page)</h1>

The complete application is named HelloWorld.

In this example, we have used HTML pages, but as we said earlier, Ozark also has dedicated view engines for Servlets, JSP, and Facelets. This means that the HelloWorld application can be re-written using JSP, Facelets, or Servlet in a very easy manner.

In the JSP approach, we simply rename index.html and hello.html as index.jsp and hello.jsp. That’s it! Just for fun, you can write the index.jsp like this (the complete application is named, HelloWorldJSP):

<body>
   <% String str = "resources/hello";%>
   <a href="<%=str%>">Hello World!</a>
</body>

In the Servlet approach, the content that should be displayed to the user is returned by HelloServlet.

@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
   ...
   protected void processRequest(HttpServletRequest
         request, HttpServletResponse response)
      throws ServletException, IOException {
         response.setContentType("text/html;charset=UTF-8");
      try (PrintWriter out = response.getWriter()) {
         ...
         out.println("<h1>Hello World! (Servlet)</h1>");
         ...
      }
   }
   ...
}

And the controller simply points to this Servlet:

@GET
public String helloAction() {
   return "/HelloServlet";
}

The complete application is named HelloWorldServlet.

Now, the last case is reserved for Facelets. You have to be aware about the fact that Facelets support is not enabled by default. MVC applications that use Facelets are required to package a web.xml deployment descriptor with the following entry mapping the extension *.xhtml as shown next (you can use prefix mapping also (e.g. /faces/*):

<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>*.xhtml*</url-pattern>
</servlet-mapping>

If your application starts from a Facelet, you need to configure the welcome file, also. For example:

<welcome-file-list&gt
   <welcome-file>index.xhtml</welcome-file>
</welcome-file-list>

If you application doesn’t start from a Facelets page (for example, from a JSP/HTML page), you don’t need this part and still use Facelets for the rest of the pages, except the starting page.

Note: Conforming to MVC 1.0 specification, it is worth noting that if you opt to use Facelets as a view technology for your MVC application, regular JSF post-backs will not be processed by the MVC runtime.

 

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories