Java MVC tutorial
last modified July 6, 2020
Java MVC tutorial is an introductory tutorial to Java MVC framework. We create a simple web application with Java MVC and deploy it on Tomcat and Glassfish.
MVC
Model Miew Controller (MVC) architectural pattern separates an application into three parts: a model, a view, and a controller. The model represents the data in the application, the view is the visual representation of the data, and the controller processes and responds to events, typically user actions, and may invoke changes on the model. The idea is to separate the data access and business logic from data presentation and user interaction, by introducing an intermediate component: the controller.
Java MVC
Java MVC is a specification (JSR-371) for a new Java action-based web framework. It is an alternative to the traditional component-based JSF. The MVC API is layered on top of JAX-RS and integrates with existing Java EE technologies like CDI and Bean Validation. Eclipse Ozark is an implementation of Java MVC. It currently contains support for RESTEasy, Jersey, and Apache CXF.
A MVC controller is a JAX-RS resource method decorated by @Controller
. MVC controllers
are responsible for combining data models and views (templates) to produce web application pages.
A model carries data that is displayed in the view. Models are created with @Named
annotation or by injecting Models
interface.
A view defines the structure of the output page and can refer to one or more models. It is the responsibility of a view engine to render a view by extracting the information in the models and producing the output page.
Java MVC example in Tomcat
We create a simple web application with Java MVC and deploy it on Tomcat. From the JAX-RS libraries, we chose Jersey.
$ tree . ├── nb-configuration.xml ├── pom.xml └── src ├── main │ ├── java │ │ └── com │ │ └── zetcode │ │ ├── conf │ │ │ └── ApplicationConfig.java │ │ ├── controller │ │ │ └── HelloController.java │ │ └── model │ │ └── Message.java │ ├── resources │ └── webapp │ ├── index.html │ ├── META-INF │ │ └── context.xml │ └── WEB-INF │ ├── beans.xml │ └── views │ └── hello.jsp └── test └── java
This is the project structure.
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zetcode</groupId> <artifactId>JavaMvcTomcatEx</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>JavaMvcTomcatEx</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey</groupId> <artifactId>jersey-bom</artifactId> <version>2.26</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.ext.cdi</groupId> <artifactId>jersey-cdi1x</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.ext</groupId> <artifactId>jersey-bean-validation</artifactId> </dependency> <dependency> <groupId>javax.enterprise</groupId> <artifactId>cdi-api</artifactId> <version>2.0-EDR1</version> </dependency> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-shaded</artifactId> <version>3.0.2.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.2.Final</version> </dependency> <dependency> <groupId>javax.mvc</groupId> <artifactId>javax.mvc-api</artifactId> <version>1.0-pr</version> </dependency> <dependency> <groupId>org.mvc-spec.ozark</groupId> <artifactId>ozark-core</artifactId> <version>1.0.0-m03</version> </dependency> <dependency> <groupId>org.mvc-spec.ozark</groupId> <artifactId>ozark-jersey</artifactId> <version>1.0.0-m03</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> </project>
In order to run Java MVC on Tomcat, we need to include several dependencies for Java MVC, Jersey, Bean Validation, and CDI.
<?xml version="1.0" encoding="UTF-8"?> <Context path="/JavaMvcTomcatEx"> <Resource name="BeanManager" auth="Container" type="javax.enterprise.inject.spi.BeanManager" factory="org.jboss.weld.resources.ManagerObjectFactory" /> </Context>
In the Tomcat's context.xml
file, we define the context path and register
Weld's BeanManager factory.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" 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/beans_1_1.xsd" bean-discovery-mode="all"> </beans>
In the WEB-INF
directory, we have an empty beans.xml
file. It is a deployment descriptor for CDI. It can be used for configuring interceptors,
decorators, and other things. Even if we do no configurations, we need to add
an empty beans.xml
for registering CDI.
package com.zetcode.conf; import com.zetcode.controller.HelloController; import java.util.HashSet; import java.util.Set; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("mvc") public class ApplicationConfig extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> set = new HashSet<>(); set.add(HelloController.class); return set; } }
ApplicationConfig
is the application configuration class. It is possible to
omit the web.xml
file since Servlet 3.0. In Jersey, we create
a configuration class that extends the abstract Application
and use the @ApplicationPath
annotation. The Application
defines the components of a JAX-RS application and supplies additional meta-data.
Here we register resource classes, providers, or properties the application needs.
set.add(HelloController.class);
We register the HelloController
.
package com.zetcode.model; import javax.enterprise.context.RequestScoped; import javax.inject.Named; @Named("message") @RequestScoped public class Message { private String text; public String getText() { return text; } public void setText(String text) { this.text = text; } }
This is a model class. It holds data for the view. The @Named
annotation gives a model a name. We will refer to the model in the view.
The @RequestScoped
makes the model valid for the life of the request.
package com.zetcode.controller; import com.zetcode.model.Message; import javax.inject.Inject; import javax.mvc.annotation.Controller; import javax.ws.rs.GET; import javax.ws.rs.Path; @Path("hello") @Controller public class HelloController { @Inject private Message message; @GET public String hello() { message.setText("Today is a sunny day"); return "hello.jsp"; } }
A class decorated with a @Controller
is a Java MVC controller.
With @Path
, it is bound to the hello
path segment.
@Inject private Message message;
With @Inject
, we inject the model object. It carries
data from the controller to the view.
@GET public String hello() { message.setText("Today is a sunny day"); return "hello.jsp"; }
The hello()
method reacts to a GET request. It sets data
to the model and returns a view. A string returned from a controller method
is interpreted as a view path. The view engine's default directory for
views is WEB-INF/views
.
<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JSP Page</title> </head> <body> <p> The message: ${message.text} </p> </body> </html>
This is the view. It displays the data with the ${}
syntax.
<!DOCTYPE html> <html> <head> <title>Home Page</title> <meta charset="UTF-8"> </head> <body> <p> <a href="mvc/hello">Get message</a> </p> </body> </html>
This is a home page. It contains a link to call the controller.
Java MVC example in Glassfish
To run the example on Glassfish, we do not need the context.xml
file
and we need the following three dependencies:
<dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.mvc</groupId> <artifactId>javax.mvc-api</artifactId> <version>1.0-pr</version> </dependency> <dependency> <groupId>org.mvc-spec.ozark</groupId> <artifactId>ozark-jersey</artifactId> <version>1.0.0-m03</version> </dependency> </dependencies>
Glassfish already contains many libraries that are not present in Tomcat. No other modifications are necessary.
In this tutorial, we have introduced the Java MVC framework.
List all Java tutorials.