So let's start with the Domain layer. The Domain layer typically consists of a domain model. So what is a domain model? A domain model is a representation of the data storage types required by the business logic. It describes the various domain objects (entities), their attributes, roles, and relationships, plus the constraints that govern the problem domain. You can look at the following order processing domain model diagram to get a quick idea about the domain model.
Each block in the previous diagram represents a business entity and the lines represent the associations between the entities. Based on this domain model diagram, you should understand that in an order processing domain, a Customer
can have many Order
and each order
can have many OrderItem
and each OrderItem
represents a single Product
.
During actual coding and development this domain model, will be converted into corresponding domain objects and associations by a developer. A domain object is a logical container of purely domain information. Since we are going to build an online web store application, in our domain the primary domain object might be a product. So let's start with the domain object to represent a product.
So far in our web store, we have displayed only a welcome message. It is time for us to show our first product on our web page. Let's do this by creating a domain object to represent the product information.
Product
under the com.packt.webstore.domain
package in the src/main/java
source folder and add the following code into it: package com.packt.webstore.domain;
import java.io.Serializable;
import java.math.BigDecimal;
public class Product implements Serializable {
private static final long serialVersionUID =
3678107792576131001L;
private String productId;
private String name;
private BigDecimal unitPrice;
private String description;
private String manufacturer;
private String category;
private long unitsInStock;
private long unitsInOrder;
private boolean discontinued;
private String condition;
public Product() {
super();
}
public Product(String productId, String name, BigDecimal
unitPrice) {
this.productId = productId;
this.name = name;
this.unitPrice = unitPrice;
}
// add setters and getters for all the fields here
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Product other = (Product) obj;
if (productId == null) {
if (other.productId != null)
return false;
} else if (!productId.equals(other.productId))
return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((productId == null) ? 0 :
productId.hashCode());
return result;
}
}
serialVersionUID
field.ProductController
under the com.packt.webstore.controller
package in the src/main/java
source folder. And add the following code into it:package com.packt.webstore.controller; import java.math.BigDecimal; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import com.packt.webstore.domain.Product; @Controller public class ProductController { @RequestMapping("/products") public String list(Model model) { Product iphone = new Product("P1234","iPhone 6s", new BigDecimal(500)); iphone.setDescription("Apple iPhone 6s smartphone with 4.00-inch 640x1136 display and 8-megapixel rear camera"); iphone.setCategory("Smartphone"); iphone.setManufacturer("Apple"); iphone.setUnitsInStock(1000); model.addAttribute("product", iphone); return "products"; } }
products.jsp
under the src/main/webapp/WEB-INF/views/
directory, add the following code snippets into it, and save it:<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"> <title>Products</title> </head> <body> <section> <div class="jumbotron"> <div class="container"> <h1>Products</h1> <p>All the available products in our store</p> </div> </div> </section> <section class="container"> <div class="row"> <div class="col-sm-6 col-md-3" style="padding- bottom: 15px"> <div class="thumbnail"> <div class="caption"> <h3>${product.name}</h3> <p>${product.description}</p> <p>${product.unitPrice} USD</p> <p>Available ${product.unitsInStock} units in stock</p> </div> </div> </div> </div> </section> </body> </html>
http://localhost:8080/webstore/products
You should be able to see a web page showing product information as shown in the following figure:Our aim is to show the details of a product in our web page. In order to do that, first we need a domain object to hold the details of a product. That's what we did in step 1; we just created a class called Product
(Product.java
) to store information about the product such as the name, description, price, and more.
As you have already learned in the Overview of Spring MVC request flow section, to show any dynamic data in a web page, prior to doing so we need to put that data in a model, then only the view can read that data from the model and will render it in the web page. So to put product information in a model, we just created one more controller called ProductController
(ProductController.java
) in step 3.
In ProductController
, we just have a single method called list
whose responsibility it is to create a product domain object to hold the information about Apple's iPhone 5s and add that object to the model. And finally, we return the view name as products
. That's what we were doing in the following lines of the list
method of ProductController
:
model.addAttribute("product", iphone); return "products";
Since we configured InternalResourceViewResolver
as our view resolver in the web application context configuration, during the process of resolving the view file for the given view name (in our case the view name is products
), the view resolver will try to look for a file called products.jsp
under /WEB-INF/views/
. That's why we created products.jsp
in step 4. If you skipped step 4, you will get a HTTP status 404 error while running the project.
For a better visual experience, products.jsp
contains lots of <div>
tags with Bootstrap CSS styles applied (Bootstrap is an open source CSS framework). So don't think that products.jsp
is very complex; as a matter of fact it is very simple-you don't need to bother about the <div>
tags, as those are present just to get an appealing look. You only need to observe the following four tags carefully in products.jsp
to understand the data retrieval from the model:
<h3>${product.name}</h3> <p>${product.description}</p> <p>${product.unitPrice} USD</p> <p>Available ${product.unitsInStock} units in stock</p>
Look carefully at the expression ${product.unitPrice}
. The product
text in the expression is nothing but the name of the key. We used this key to store the iphone
domain object in the model; (remember this line model.addAttribute("product", iphone)
from ProductController
) and the unitPrice
text is nothing but one of the fields from the Product
domain class (Product.java
). Similarly we are showing some important fields of the product
domain class in the products.jsp
file.
When I say that price
is the field name, I am actually making an assumption here that you have followed the standard Java bean naming conventions for the getters and setters of your domain class.
When Spring evaluates the expression ${product.unitPrice}
, it is actually trying to call the getter method of the field to get the value, so it would expect the getUnitPrice()
method to be in the Product.java
file.
After finishing step 4, if we run our application and enter the URL http://localhost:8080/webstore/products
, we are able to see a web page showing product information as shown in the screenshot after step 5.
So we created a domain class to hold information about a product, created a single product object in the controller and added it to the model, and finally showed that product's information in the view.