Introduction

So we made it to the end of this tutorial. Now, It’s time to put all what we’ve learnt so far and build a real web application implementing the CRUD operations.

We’ll be building a tracking system for the orders. It’s just a simple application to get a fair idea about:

Setting up a web application from the scratch

Structuring your MVC web application

The workflow of the MVC web application

Implementing CRUD operations

Connecting to a database (we’re using Hibernate, but, you can follow the Spring Data Access for using JDBC).

Working with HTML form data & view pages (JSP)

… and a lot more.

Setting Up The Environment 💪

As usual, you need to create a new “Dynamic Web Project”, and add all the jar files to “WEB-INF/lib” folder, or use Maven for defining all the dependencies.

The dependencies we’ll need:

Spring Framework

Hibernate, JDBC Driver, and C3PO (Database)

Java Servlet + JSP + JSTL

If you’re using Maven, then your “pom.xml” should have the following:

Once you’re done, create orders table, and generate some fake data for testing.

Configurations

Dispatcher Servlet(s)

Create an XML file; “web.xml”, for defining and configuring Spring MVC dispatcher servlet(s).

💡We can add a welcome page. So, whenever we enter the root URL, the server will look for the welcome page file (if defined) in the root directory of the web application: “WebContent/index.jsp”.

The “dispatcher” Dispatcher Servlet

The configurations for our dispatcher is in“WEB-INF/spring-mvc-demo-servlet.xml” file.

Database Configurations

In this application, we are going to use Hibernate.

Instead of using “hibernate.cfg.xml” file, the configurations for connecting to database can be defined as a DataSource bean in the XML configuration file.

Hibernate make use of connection pool for connecting to the database. We’re using a third-party software for connection pooling.

Remember when we had to create a session object using SessionFactory? — Now, we can define SessionFactory as a bean in the XML configuration file, which has DataSource as a dependency.

Remember when we had to write code for starting and close transaction? — This can be eliminated by defining a bean for transaction manager (which has SessionFactory as a dependency), and enabling @Transactional annotation, unless you want to do the transaction code (begin, end, etc) manually.

This annotation auto-magically begin and end the transaction in your Hibernate code (as we’ll see later).

The Structure

There are many ways to structure your MVC application, and add layers as a way to segregate operations and tasks.

One of the most common ways is to use DAO Layer to perform database operations and map the result into objects (entities / DTOs).

💡The DTOs (Data Transfer Object) are simple objects that carries data between processes. DTOs are often used in conjunction with data access objects to retrieve data from a database.

The Service Layer is an intermediate layer between the controller and the DAO layer. It calls the DAO and perform for custom business logic. For example, It can integrate data from different resources (i.e. repositories, DAO, etc).

Packaging

So, first, let’s organize classes into groups of related types into packages as a way to avoid naming conflicts, and to control access.

💡 “types” refers to classes, interfaces, enumerations, and annotation types.

Create a package “com.demo.mvc” in “src” folder, and inside this package create:

Controllers : “com.demo.mvc.controllers”.

: “com.demo.mvc.controllers”. DAO : “com.demo.mvc.dao”.

: “com.demo.mvc.dao”. Services : “com.demo.mvc.services”.

: “com.demo.mvc.services”. Entities: “com.demo.mvc.entities”.

💡 Controller classes will go under com.demo.mvc.controllers package, and so on.

The Workflow

The workflow is as the following:

The user sends a request from the browser.

The dispatcher recieves the request and forward it to the corresponding controller method.

The controller talk to the service layer to complete the required work (i.e. ask for some data).

The service layer talk to DAOs for database operations and perform business operations.

The DAO layer performs database operations using map the data returned with Entities / DTOs of the application.

Now, In the controller, we can build the model object and return a view page to be displayed, redirect to another page, or return JSON data, etc.

Entities — Order

The order is an entity which represents the orders the database table. The data returned from the database will be mapped to order objects.

⚠ Don’t forget to define getters and setters for class object fields. 💡 GenerationType.IDENTITY means this field will be auto-incremented and will get assigned an id automatically whenever we save a new order. 💡The classes with @Entity annotation in com.demo.mvc.entities package will be scanned for mapping, and creating the session object.

DAO — OrderDAO & OrderDAOImpl

The OrderDAO interface provides a set of methods (list, add, update, delete) operations to be implemented by OrderDAOImpl class.

The code implementation for OrderDAOImpl will be explained later in the list, add, update, and delete operations. But, for now, lets see it’s basic structure.

The @Repository annotation inherits from @Component annotation (same as @Controller ). It used to identify the implementing class of DAO. This allows for auto scanning for these classes (thanks to component scanning defined in configuration), and any checked exception that will be thrown are translated into unchecked exceptions.

The DAO implementing classes needs a Hibernate SessionFactory object, which in turn needs a DataSource as a dependency (defined in configuration).

Service — OrderService & OrderServiceImpl

The OrderService interface has a set a methods that almost similar to methods in OrderDAO interface, and will be implemented by OrderServiceImpl class.

The implementation for OrderServiceImpl in our example is fairly simple. The service layer needs to talk to DAO layer and ask for the requested data.

The @Service annotation inherits from @Component annotation (same as @Controller and @Repository ). It used to identify the Service classes. It will be automatically scanned and registered as a bean thanks to component scanning.

The @Transactional annotation (configured and enabled in the XML configuration file) takes care of all transaction code needs to interact with the database in Hibernate.

💡If all class methods will run inside a transaction, then you can annotate the whole class with @Transactional annotation.

📣 One may ask a question, “Why we use this annotation in the Service layer instead of DAO layer? ”

Because we want the DAO classes to run within the transaction defined by the service layer. So, a service will start transaction, make calls to DAO class and other resources (if needed), and then end the transaction.

Controller — OrderController

💡The @GetMapping annotation is a shortcut for @RequestMapping(method = RequestMethod.GET) . The same idea applies for @PostMapping annotation.

Implementing The Operations — List

The first operation is to list all the orders. In the DAO layer, we will execute the query and return the result.

In the Service layer, just make a call to getOrders() method using the autowired orderDAO (dependency).

In the controller, also make a call getOrders() method of the Service layer. Then, add the orders to the model’s attribute to be displayed in view page.

💡We’ve defined in the configurations that all views page will be located in “/WEB-INF/view” folder. So, create “list-orders.jsp” page inside view folder.

The view page will simply loop over collection of orders using forEach tag.

💡One of the JSTL core tags (discussed before) is the iteration tag <c:forEach> with which we can loop over collection of items in our JSP pages.

Implementing The Operations — Add

The next operation is to add a new order. This can be done through a form submission.

So, basically we need to do two operations. In the first time, an empty form will be displayed, and then, we process the submitted data.

In the DAO layer, we will add a new order record to the database.

In the service layer, just call the saveOrder() method same as before.

In the controller, we need first to create a model object, and pass a new empty object of a order (using no argument constructor).

This object will be used to bind it with data when the form is submitted. So, we can fetch this object once form is submitted and save it to the database.

For the view page, we need to create a page with HTML form for creating a new order. So, create “order-form.jsp” page in view folder.

⚠ Since the data submitted is string. So, for dates, we need to map between the submitted string and actual date value.

The solution is, either use InitBinder, or @DateTimeFormat annotation. In case of using the annotation:

— [1] Add @DateTimeFormat(pattern = "MM-dd-yyyy") to dateOfOrder in Order class.

@Column(name="date_of_order")

@DateTimeFormat(pattern = "MM-dd-yyyy")

private Date dateOfOrder;

— [2] Change the form input field of date in “order-form.jsp” to:

<input type="text" path="dateOfOrder" name="dateOfOrder" value = "<fmt:formatDate value="${order.dateOfOrder}" pattern="MM-dd-yyyy" />"/>

— [3] Add reference to The JSTL formatting tags

It’s used to format and display text, the date, the time, and numbers.

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

⚠ You have to use the same format (MM-dd-yyyy), Otherwise use InitBinder.

Implementing The Operations — Update

The update operation is not so different from the Add operation. It also relies on a form submission.

So, also, there are two operations. The first, a form will be populated with order data to be updated (given order id), then, process the submitted data.

In the DAO layer, first, we need to fetch an order object given it’s id.

Then, we update an existing order object. For this, we just need to add a small modification to saveOrder() method to make it works in both cases; creating and updating an existing order .

💡The saveOrUpdate() method will add a new record if order object has no id (primary key), otherwise, it will update the given order in the table.

Similarly, In the Service layer, we have two operations; get a specific order given it’s id, and update an existing order.

For update, use the same method saveOrder() for creating and updating an existing order.

In the controller, we need first to display the HTML form populated with order data to be updated (given order id). The order id can be sent in the URL parameter (i.e. /order/viewOrder?orderId=125).

We’ll use the same HTML form we used before for creating a new order, thus, the submitted data will hit the same method saveOrder() we used for creating a new order. This method will behave the same in both ways.

In the view pages, we need to first, add an update link to each order in the “list-orders” page.

And, In the “order-form.jsp” view page, add a hidden input form field in the HTML form for the order id. So when the form is submitted, we know which order to be updated.

<form:hidden path="id" />

Implementing The Operations — Delete

The delete operation should seem easy now. All what we need to do is to delete an existing order given it’s id in the URL parameter.

In the DAO layer, delete an order given it’s id.

In the Service layer, as usual, make a call to deleteOrder() method.

In the controller, call deleteOrder() of that Service layer to delete the given order, and redirect to list all orders page.

In the view page “list-orders.jsp”, we need to add a delete link to each displayed order, same as we did with update.