Get to Know Jakarta MVC

To help you get to know the Jakarta MVC specification, here’s a recap of its history and status, and a brief introduction to the technology.

Jakarta MVC History and Status

The story of Jakarta MVC started back in 2014 when Java Specification Request (JSR) 371 was proposed in the Java Community Process. The work progressed very well, and the specification became popular in the community as a frequently requested addition to Java EE. When the specification was dropped for Java EE 8, the community took over and released MVC 1.0 as an independent specification in January 2020. After this release, it was transferred to the Eclipse Foundation and renamed to Jakarta MVC. 

Jakarta MVC 1.1 was released in September 2020 under the Eclipse Foundation Specification License. Just three months later, in December 2020, Jakarta MVC 2.0 was released with the jakarta.mvc.* namespace and aligned with Jakarta EE 9.

Jakarta MVC 2.0 is the most recent version of the specification, and there are currently two compatible implementations: 

Work on Jakarta MVC 2.1 is ongoing, and it is expected to be released in the Jakarta EE 10 timeframe. The Jakarta MVC project will continue to seek inclusion in the Jakarta EE Web Profile

MVC Styles 

In the Model-View-Controller (MVC) design pattern, the controller responds to a request by updating the model and selecting which view to display. The view then retrieves the data to display from the updated model (Figure 1).

MVC-1
Figure 1: Model-View-Controller Relationships

This widely used design pattern can be used in two ways: component-based and action-based. 

Component-Based MVC

Component-based MVC is made popular by component frameworks, such as Jakarta Server Faces. In this style of MVC, the framework provides the controller. This allows application developers to focus on implementing models and views, leaving controller logic to be handled by the framework (Figure 2).

MVC-2
igure 2: Component-Based MVC


Action-Based MVC

In the action-based style of MVC, the application defines the controller, giving application developers a little more fine-grained control (Figure 3).

MVC-3
Figure 3: Action-Based MVC


Jakarta MVC is an action-based MVC framework, which makes it complementary to the component-based MVC framework provided by Jakarta Server Faces. Other examples of action-based MVC include Spring MVC and Apache Struts.

Jakarta MVC Basics

Jakarta MVC is built on top of Jakarta RESTful Web Services. That means everything you know about Jakarta RESTful Web Services can be applied to your Jakarta MVC application as well.

Let’s take a closer look at what you can do with Jakarta MVC. 

The Controller

The @Controller annotation defined by Jakarta MVC marks a resource as the controller. If the annotation is applied to the resource class, all resource methods in the class become controllers. 

@Controller
@Path("hello")
public class Hello {
 
    @Path("one")

    public String oneController() {
    }

    @Path("another")
    public String anotherController() {
    }
}

The annotation can also be applied to a specific resource method. This approach is useful if you want to combine MVC controllers with REST resources in the same class.

@Path("hello")
public class Hello {

    @Controller
    @Path("one")
    public String oneController() {
    }

    @Controller
    @Path("another")
    public String anotherController() {
    }
 
    @Path("not-a-controller")
    public String notAController() {
    }
}

There are three ways to define which view a controller should select in a Jakarta MVC application:

  • First, if a controller returns void, it must be decorated with an @View annotation 
  • Second, a String returned is interpreted as a view path
  • Third, a Jakarta RESTful Web Services Response object where the entity is one of the first two 

The example below illustrates all three approaches.

@Controller
@Path("hello")
public class HelloController {

    @GET @Path("void")
    @View("hello.jsp")
    public void helloVoid() {
    }

    @GET @Path("string")
    public String helloString() {
        return "hello.jsp";
    }

    @GET @Path("response")
    public Response helloResponse() {
        return Response.status(Response.Status.OK)
            .entity("hello.jsp")
            .build();
    }
}


That’s all there is to the controller in Jakarta MVC. The rest is exactly as you know from Jakarta RESTful Web Services, such as how to handle and validate path parameters, query parameters, and bean parameters.

The Model

Jakarta MVC supports two ways of handling models:

  • Use any CDI @Named beans as your model
  • Use the provided Models interface as your model

For the CDI approach, you simply inject the CDI @Named bean into the controller, update it as needed, and return the view, as shown in the example below.

@Named("greeting")
@RequestScoped
public class Greeting {
    private String message;
    // getters and setters
}

@Path("hello")
public class HelloController {

    @Inject
    private Greeting greeting;

    @GET
    @Controller
    public String hello() {
        greeting.setMessage("Hello there!");
        return "hello.jsp";
    }
}

If the view model does not support CDI, or you want to use the provided Models interface for a different reason, you can inject the Models map and update it as shown below.

@Path("hello")
public class HelloController {

    @Inject
    private Models models;

    @GET
    @Controller
    public String hello() {
        models.put("string_greeting", "Howdy!");
        return "hello.jsp";
    }
}

The View

Views in Jakarta MVC applications are processed by a mechanism called view engines. View engines for Jakarta Server Pages and Facelets must be supported by all implementations, although the requirement to support Facelets is likely to be removed in future versions of Jakarta MVC. Additional view engines can be added using a well-defined CDI extension mechanism.

In Jakarta Server Pages views, the model is available using the Jakarta Expression Language, as shown in the example below.

<!DOCTYPE html>
<html>
    <head>
        <title>Hello</title>
    </head>
    <body>
        <h1>${greeting.message}</h1>
        <h1>${string_greeting}</h1>
    </body>
</html>

The rendered view would look something like this:

Hello   
Hello there!
Howdy!

Advanced Jakarta MVC Topics

The Jakarta MVC specification document provides a very good overview of what’s included in Jakarta MVC. I introduce some of the items here, but please refer to the specification document for details.

Data Binding

Jakarta MVC extends the data binding provided by Jakarta RESTful Web Services with support for internationalization and handling of binding errors within the controller. The Jakarta MVC-specific data binding is enabled by adding the @MvcBinding annotation to the relevant field or method parameter. Binding errors are handled in the controller by injecting BindingResult and using it to handle the error before the next view is rendered. 

@Controller
@Path("form")
public class FormController {

    @MvcBinding
    @FormParam("age")
    @Min(18)
    private int age;

    @Inject
    private BindingResult bindingResult;

    @POST
    public String processForm() {

        if( bindingResult.isFailed() ) {

            // handle the failed request
        }
 

        // process the form request
    }
}

Security

Jakarta MVC provides support to protect applications from Cross-Site Request Forgery (CSRF). To provide this support, the Jakarta MVC implementation generates a CSRF token that is available via the MvcContext object. To verify a request, simply add the @CsrfProtected annotation to the controller, as shown below.

@Path("csrf")
@Controller
public class CsrfController {

    @GET
    public String getForm() {
        return "csrf.jsp"; // Injects CSRF token
    }

    @POST
    @CsrfProtected // Required for CsrfOptions.EXPLICIT
    public void postForm(@FormParam("greeting") String greeting) {
        // Process greeting
    }
}

Events

Jakarta MVC specifies a number of events that occur while processing requests. The event mechanism is based on Jakarta Contexts and Dependency Injection (CDI), and can be observed using the @Observer annotation defined by Jakarta CDI.

Internationalization

Jakarta MVC uses the term “request locale,” which can be used for locale-dependent operations. Example use cases for locale-dependent operations include data binding, data formatting, and language-specific validation error messages. The request locale is available through the MvcContext object.

@Controller
@Path("/foobar")
public class MyController {

    @Inject
    private MvcContext mvc;

    @GET
    public String get() {
        Locale locale = mvc.getLocale();
        NumberFormat format = NumberFormat.getInstance(locale);
    }
}

For more insight into Jakarta MVC:

Learn More About Jakarta MVC and Get Involved

We welcome everyone who would like to get involved in Jakarta MVC. To discover the many different ways you can contribute to the project, click here.

This article was first published in the Eclipse Newsletter, November 29, 2021.

Summing up Jakarta MVC 2.0

This post concludes the mini-series about how Jakarta MVC 2.0 moves through the steps involved in the Jakarta EE Specification Process (JESP).

All the posts are listed here, so bookmark this page for reference if you are involved in, or planning to be involved in a Jakarta EE specification.

Jakarta MVC 2.0 Plan Review
Jakarta MVC 2.0 Progress
Jakarta MVC 2.0 TCK
Jakarta MVC 2.0 Release Review
Jakarta MVC 2.0 Released

I have used Jakarta MVC as an example for a specification going through the steps involved in the JESP and blogged about them here. Check out the Jakarta MVC tag to get them all.

Jakarta MVC 2.0 Released

Jakarta MVC 2.0 passed the release review ballot and is now ratified as a final specification according to the Jakarta EE Specification Process (JESP).

The last steps for the project team after the ballot are to release the staged artifacts to Maven Central and verify that all published information is correct. That has now been done, and I have listed information about how to obtain the artifacts below.

The MVC 2.0 API maven coordinates are:

<dependency>
  <groupId>jakarta.mvc</groupId>
  <artifactId>jakarta.mvc-api</artifactId>
  <version>2.0.0</version>
</dependency>

The Eclipse Krazo 2.0.0 maven coordinates are:

<dependency>
  <groupId>org.eclipse.krazo</groupId>
  <artifactId>krazo-core</artifactId>
  <version>2.0.0</version>
</dependency>

In addition to the core component, you will also need a dependency specific to the Jakarta EE 9 implementation you are using. See Eclipse Krazo 2.0.0 download page for more information about this.

The MVC 2.0 TCK can be downloaded from the Eclipse Download area. It can also be obtained from Maven Central.

I have used Jakarta MVC as an example for a specification going through the steps involved in the JESP and blogged about it here. Follow the Jakarta MVC tag to get them all.

Jakarta MVC 2.0 Release Review

Before a Jakarta EE specification can be released under the Jakarta EE Specification Process (JESP), it has to go through a release review. The ballot for Jakarta MVC 2.0 can be followed in this ballot thread.

The release review is initiated by creating a Pull Request to the Jakarta EE Specifications repository and request a release review by sending an email to the Jakarta EE Specification Committee. See the Jakarta MVC 2.0 pull request to check out the details and follow the ballot on the public Jakarta EE Specification Committee mailing list. It took a while from the request-email until the ballot was started for Jakarta MVC 2.0, but the specification committee now has a streamlined process established for assigning a mentor responsible for starting the ballot.

I will use Jakarta MVC as an example for a specification going through the steps involved in the JESP and blog about it here. Follow the Jakarta MVC tag to get them all.

Jakarta MVC 2.0 TCK

A specification must, according to the Jakarta EE Specification Process (JESP), provide a test suite to verify that an implementation implements the specification correctly. This test suite is called a Test Compatibility Kit (TCK). There must be at least one compatible implementation, i.e. an implementation that passes the TCK, for a spec to be ratified as a final specification.

Eclipse Krazo 2.0.0 is a compatible implementation of Jakarta MVC 2.0. In the following video, I show how the TCK is run to verify that Krazo passes the Jakarta MVC 2.0 TCK.

I will use Jakarta MVC as an example for a specification going through the steps involved in the JESP and blog about it here. Follow the Jakarta MVC tag to get them all.

Jakarta MVC 2.0 Progress

The work with Jakarta MVC 2.0 goes forward. According to the Jakarta EE Specification Process (JESP), we are now in the development phase where we will release as many milestones as we need until we are satisfied to move on to finalize the specification.

There are already Milestone 1 releases available of both the Spec+API and the TCK in Jakarta Staging in which the namespace switch from javax.mvc.* to jakarta.mvc.* is done. The ongoing work is to update Eclipse Krazo to the new namespace and pass the TCK.

I will use Jakarta MVC as an example for a specification going through the steps involved in the JESP and blog about it here. Follow the Jakarta MVC tag to get them all.

Jakarta MVC 2.0 Plan Review

We are ready to move forward with the namespace change from javax.mvc.* to jakarta.mvc.* for Jakarta MVC. This will be released as Jakarta MVC 2.0.

According to the Jakarta EE Specification Process (JESP), we need to engage in a plan review with the Specification Committee.

The key goal of this release is to switch the namespace for the API from javax.mvc.* to jakarta.mvc.*. No additional features are included in order to make the transition from Jakarta MVC 1.1 easier.

The plan review is initiated by submitting a Pull Request to the Jakarta EE Specifications repository. See Plan Review for Jakarta MVC 2.0 to follow the progress and join the mvc-dev mailing list to participate in the release.

I will use Jakarta MVC as an example for a specification going through the steps involved in the JESP and blog about it here. Follow the Jakarta MVC tag to get them all.