Hello! What is the reason to use Java based Spring configuration instead of familiar XML config? I can describe it simply with the next slide:
In my opinion XML is a legacy part of java application and it is much better to use Java in Java app :) What do you think?
Today I want to make a review of Java config in Spring 4 with all benefits of using Annotation approach!

First, let's start from a project structure.
In your IDE add the Maven support and right folders structure with empty 'pom' file will be automaticaly created.
This web-app will be consist of the next parts:
- Configuration classes for managing Spring MVC ('java.com.web.config' and 'java.com.web.controll' packages);
- The main programming logic : interfaces and implementations, the Order entity and mocking storage classes. ('java.order.api' and 'java.order.impl' packages)
- The storage for JSP (webapp.WEB-INF.pages)
We'll implement one functionality: the customer makes order and sees the order information. The order is saved in storage. Customer can go back to the first page and make more orders.
Second, let's add dependencies:
Order.class:
/*Getters, setters, equals and hashCode goes here...*/
We have implementation of OrderManagement and OrderDAO (representation of Business layer and DAO layer).
You can see @Autowired and @Component annotations. They are required for bean initialization in future. We need those annotations and empty constructor in our case. Read more about IoC and dependency injection(Spring IoC).
OrderManagementImpl.class
OrderDAOImpl.class
And our mocking storage. (it looks like some kind of real cache :))
Orders.class
Now it's a time to create Spring Java configuration. We need two files for this: WebbAppConfig and Initializer.
WebbAppConfig.class
First, we'll define the path to JSP within ViewResolver initialization. Second, we'll create all Beans we need. Defining beans is much more easier then in XML configuration. There are couple of ways for bean initialization and dependency injection.
To create Beans we use the plain setter methods. In addition we can define bean scope like "prototype" which allow to use more then one object of this type. By default Beans фку created as singleton (We use the scope by default in our project).
Also we must add file path to package which stores our controllers-classes. It can be done using @ComponentScan annotation:
Initializer.class
This class is used instead of old-fashioned web.xml.
We need to register WebAppConfig.class as source for Annotation based Spring configuration. All things we did in web.xml file now we'll make here using pure java code:
In my opinion XML is a legacy part of java application and it is much better to use Java in Java app :) What do you think?
Today I want to make a review of Java config in Spring 4 with all benefits of using Annotation approach!

First, let's start from a project structure.
In your IDE add the Maven support and right folders structure with empty 'pom' file will be automaticaly created.
This web-app will be consist of the next parts:
- Configuration classes for managing Spring MVC ('java.com.web.config' and 'java.com.web.controll' packages);
- The main programming logic : interfaces and implementations, the Order entity and mocking storage classes. ('java.order.api' and 'java.order.impl' packages)
- The storage for JSP (webapp.WEB-INF.pages)
We'll implement one functionality: the customer makes order and sees the order information. The order is saved in storage. Customer can go back to the first page and make more orders.
Second, let's add dependencies:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>7.0.47</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>
Order.class:
public class Order {
private String customerName;
private String productName;
private int orderID;
public Order() {
}
/*Getters, setters, equals and hashCode goes here...*/
We have implementation of OrderManagement and OrderDAO (representation of Business layer and DAO layer).
You can see @Autowired and @Component annotations. They are required for bean initialization in future. We need those annotations and empty constructor in our case. Read more about IoC and dependency injection(Spring IoC).
OrderManagementImpl.class
@Component
@Qualifier("OrderManagementImpl")
public class OrderManagementImpl implements OrderManagement {
private OrderDAO orderDAO;
public OrderManagementImpl() {
}
@Autowired
public void setOrderDAO(OrderDAO orderDAO) {
this.orderDAO = orderDAO;
}
@Override
public Order makeOrder(Order order) {
// Validating the input
if (Validator.isOrderCorrect(order) == true) {
String customerName = order.getCustomerName();
// Checking whether customer already exists in db
boolean customerExist = orderDAO.isCustomerExist(customerName);
if (!customerExist) {
// Adding new customer
orderDAO.putNewCustomer(customerName);
// Saving id for customer order
order.setOrderID(1);
} else {
// Retrieving customer's orders
Orders customerOrders = orderDAO.getCustomerOrders(customerName);
Order lastOrder = customerOrders.getListOfOrders().getLast();
int lastId = lastOrder.getOrderID();
// Defining and saving id for customer order
order.setOrderID(++lastId);
}
// Putting new order in db
orderDAO.putNewOrder(customerName, order);
return order;
}
return null;
}
OrderDAOImpl.class
@Component
@Qualifier("OrderDAOImpl")
public class OrderDAOImpl implements OrderDAO {
private HashMap<String, Orders> allOrders;
public OrderDAOImpl() {
}
public HashMap<String, Orders> getOrders() {
return allOrders;
}
@Autowired
public void setOrders(HashMap<String, Orders> orders) {
this.allOrders = orders;
}
@Override
public boolean isCustomerExist(String customerName) {
return allOrders.containsKey(customerName);
}
@Override
public Orders putNewCustomer(String customerName) {
allOrders.put(customerName, new Orders());
return getCustomerOrders(customerName);
}
@Override
public Orders getCustomerOrders(String customerName) {
return allOrders.get(customerName);
}
@Override
public void putNewOrder(String customerName, Order order) {
Orders orders = allOrders.get(customerName);
orders.addNewOrder(order);
}
}
And our mocking storage. (it looks like some kind of real cache :))
Orders.class
public class Orders {
private LinkedList<Order> customerOrders = new LinkedList<Order>();
public Orders() {
}
public LinkedList<Order> getListOfOrders() {
return customerOrders;
}
public void addNewOrder(Order order) {
customerOrders.add(order);
}
}
Now it's a time to create Spring Java configuration. We need two files for this: WebbAppConfig and Initializer.
WebbAppConfig.class
First, we'll define the path to JSP within ViewResolver initialization. Second, we'll create all Beans we need. Defining beans is much more easier then in XML configuration. There are couple of ways for bean initialization and dependency injection.
To create Beans we use the plain setter methods. In addition we can define bean scope like "prototype" which allow to use more then one object of this type. By default Beans фку created as singleton (We use the scope by default in our project).
Also we must add file path to package which stores our controllers-classes. It can be done using @ComponentScan annotation:
@ComponentScan(basePackages = "com.web.controll")
@Configuration
@EnableWebMvc
public class WebAppConfig extends WebMvcConfigurerAdapter {
@Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
return resolver;
}
@Bean
public HashMap<String, Orders> databaseInit() {
HashMap<String, Orders> database = new HashMap<String, Orders>();
return database;
}
@Bean(name = "OrderDAOImpl")
public OrderDAOImpl initOrderDAO() {
OrderDAOImpl orderDAO = new OrderDAOImpl();
orderDAO.setOrders(databaseInit());
return orderDAO;
}
@Bean(name = "OrderManagementImpl")
public OrderManagementImpl initOrderManagement() {
OrderManagementImpl management = new OrderManagementImpl();
management.setOrderDAO(initOrderDAO());
return management;
}
}
Initializer.class
This class is used instead of old-fashioned web.xml.
We need to register WebAppConfig.class as source for Annotation based Spring configuration. All things we did in web.xml file now we'll make here using pure java code:
public class Initializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(WebAppConfig.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
ServletRegistration.Dynamic servlet =
servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
}
OrderController.class
Here we'll handle the url-requests. Some basic things:
- @Controller annotation gives this class 'controller role'. Read more about Spring MVC (link)
- @RequestMapping annotation allows the method to handle the defined url request
- @ModelAttribute annotation refers to a property of the object from Model. If we use this annotation we can bind the object directly from form on JSP page. We make the injection of the OrderManagement object to our Controller using @Autowired annotation.
More about Spring annotations and other useful staff (Spring docs):
@Controller
public class OrderController {
@Autowired
@Qualifier("OrderManagementImpl")
public OrderManagement management;
@RequestMapping(value = "/order_page", method = RequestMethod.GET)
public String openOrderPage(ModelMap model) {
model.addAttribute("message", "Order page");
// Creating a Map of products. The key will be a variable name on JSP page, the value - a product name
Map<String, String> products = new LinkedHashMap<String, String>();
products.put("Good_product", "Good product");
products.put("Wonderful_product", "Wonderful product");
products.put("The_best_one", "The best one");
products.put("Beautiful_product", "Beautiful product");
// Adding the Map to a model for displaying variables on JSP
model.addAllAttributes(products);
return "order_page";
}
@RequestMapping(value = "/make_order", method = RequestMethod.POST)
public String makeOrder(@ModelAttribute("order") Order order,
ModelMap model) {
// Invoking Business logic method with reference to a bound Order object as argument
Order customerOrder = management.makeOrder(order);
if (customerOrder == null) {
return "redirect:order_page";
}
// Creating a map for representing order information on JSP page
Map<String, String> orderInfo = new HashMap<String, String>();
orderInfo.put("product_name", order.getProductName());
orderInfo.put("order_id", String.valueOf(order.getOrderID()));
orderInfo.put("customer_name", order.getCustomerName());
model.addAllAttributes(orderInfo);
model.addAttribute("message", "Order info");
return "customer_order_info";
}
}
order_page.jsp
Here we'll be make the order. All input from form will be bound in object of Order type. We load "form" taglib to render special spring forms in JSP:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<!-- Here is a link to your external CSS page -->
<link rel="stylesheet" type="text/css" href="http://localhost:8080/css/main.css">
</head>
<body>
<title>${message}</title>
<div id="container" style="height:500px;width:500px">
<div id="banner" style="background-color:#66CDAA;height:100px;width:500px;"><br>
<b style="font-family:arial;color:#FFFFFF;font-size:20px;">Let's see whether this strange code works...</b>
</div>
<div id="page" style="background-color:#F5F5F5;height:400px;width:500px;float:left;">
<h1 style="font-family:arial;color:#66CDAA;font-size:15px;">Please, make your order!</h4>
<br>
<!-- Here we are binding input fields in Order - type object -->
<form:form method="post" action="make_order" modelAttribute="order" >
<label><span>Pick the product:</span>
<label><select name="productName" style="width:152px;font-family:arial;color:grey;font-size:12px;">
<option>${Good_product}</option>
<option>${Wonderful_product}</option>
<option>${The_best_one}</option>
<option>${Beautiful_product}</option>
</select>
</label>
<label><span>Your name:</span></label>
<label> <input type="text" name="customerName"/></label>
<label><input type="submit" value="Try this code ;)"/></label>
</form:form>
<br>
</div>
</div>
</body>
</html>
<html>
<head>
<!-- Here is a link to your external CSS page -->
<link rel="stylesheet" type="text/css" href="http://localhost:8080/css/main.css">
</head>
<body>
<title>${message}</title>
<div id="container" style="height:500px;width:500px">
<div id="banner" style="background-color:#66CDAA;height:100px;width:500px;"><br>
<b style="font-family:arial;color:#FFFFFF;font-size:20px;">Let's see whether this strange code works...</b>
</div>
<div id="page" style="background-color:#F5F5F5;height:400px;width:500px;float:left;">
<h1 style="font-family:arial;color:#66CDAA;font-size:15px;">Please, make your order!</h4>
<br>
<!-- Here we are binding input fields in Order - type object -->
<form:form method="post" action="make_order" modelAttribute="order" >
<label><span>Pick the product:</span>
<label><select name="productName" style="width:152px;font-family:arial;color:grey;font-size:12px;">
<option>${Good_product}</option>
<option>${Wonderful_product}</option>
<option>${The_best_one}</option>
<option>${Beautiful_product}</option>
</select>
</label>
<label><span>Your name:</span></label>
<label> <input type="text" name="customerName"/></label>
<label><input type="submit" value="Try this code ;)"/></label>
</form:form>
<br>
</div>
</div>
</body>
</html>
customer_order_info
This page will appear when the order will be made. We'll get the order information. When we'll make couple of orders on the same customer name they all will be added in common storage and Order 'id' will increase depending of elements amount in storage. Here the part of that page:
...
<div id="container" style="height:500px;width:500px">
<div id="banner" style="background-color:#66CDAA;height:100px;width:500px;">
<br>
<b style="font-family:arial;color:#FFFFFF;font-size:20px;">Wow! This code works!
</b>
</div>
<div id="page" style="background-color:#F5F5F5;height:400px;width:500px;float:left;">
<h1 style="font-family:arial;color:#66CDAA;font-size:15px;">Here your order information:</h4>
<br>
<p>Order id: <b>${order_id}</b></p>
<p>Product name: <b>${product_name}</b></p>
<p>Customer name: <b>${customer_name}</b></p>
<br>
<a href="http://localhost:8080/SpringJavaConfig-1.0-SNAPSHOT/order_page"><p style="font-family:arial;color:#66CDAA;font-size:15px;">Back to order page</p></a>
</div>
...
This all about building simple application. But I have two unresolved issues. And I hope that you'll help me with those problems.
1. I can't define the session time restriction (In XML config it is easy)
If you now a solution, please, write it in the comments...Thanks!
To try this web-app:
- download it FROM GitHub;
- install Tomcat on your computer;
- copy 'war' file from GitHub archive to Tomcat-server (...\apache-tomcat-(your version )\webapps);
- copy 'main.css' from GitHub archive to a (...\apache-tomcat-(your version )\webapps\css);
- go to the http://localhost:8080/SpringJavaConfig-1.0-SNAPSHOT/order_page in your browser:
No comments:
Post a Comment