We will have one view controller, ViewController.java defined in the com.nilangpatel.worldgdp.controller.view. The view controller will be responsible for populating the data required for the view templates and also mapping URLs to corresponding view templates.
We will be using Thymeleaf (www.thymeleaf.org) as the server-side template engine and Mustache.js (https://github.com/janl/mustache.js) as our client-side template engine. The advantage of using a client-side template engine is that any data loaded asynchronously in the form of JSON can easily be added to the DOM by generating HTML using the client-side templates. We will explore more about Thymeleaf and Mustache.js in Chapter 3, Blogpress – A simple blog management system.
There are much better ways to do this by using frameworks such as Vue.js, React.js, Angular.js, and so on. We will look at the view template in the next section. Let's continue our discussion about the view controller. The view controller should map the right view template and the data for the following scenarios:
- Listing of countries
- Viewing country detail
- Editing country detail
Let's look at the following skeletal structural definition of the ViewController class:
@Controller
@RequestMapping("/")
public class ViewController {
@Autowired CountryDAO countryDao;
@Autowired LookupDAO lookupDao;
@Autowired CityDAO cityDao;
@GetMapping({"/countries", "/"})
public String countries(Model model,
@RequestParam Map<String, Object> params
) {
//logic to fetch country list
return "countries";
}
@GetMapping("/countries/{code}")
public String countryDetail(@PathVariable String code, Model model) {
//Logic to Populate the country detail in model
return "country";
}
@GetMapping("/countries/{code}/form")
public String editCountry(@PathVariable String code,
Model model) {
//Logic to call CountryDAO to update the country
return "country-form";
}
}
The following are a few important things from the previous code:
- @Controller: This annotation is used to declare a controller that can return view template names to be able to render the view, as well as returning JSON/XML data in the response body.
- @ResponseBody: This annotation when present on the method of the controller indicates that the method is going to return the data in the response body, and hence, Spring will not use the view resolver to resolve the view to be rendered. The @RestController annotation by default adds this annotation to all its methods.
- Model: This instance is used to pass on the data required for building the view.
In case of the listing of countries, the complete HTML is rendered at the server using the Thymeleaf template engine, so we need to obtain the request parameters, if any are present in the URL, and obtain a filtered and paginated list of the countries. We also need to populate the lookups that is the data for the <select> controls, which will be used for filtering the data. Let's look at its implementation as follows:
@GetMapping({"/countries", "/"})
public String countries(Model model,
@RequestParam Map<String, Object> params
) {
model.addAttribute("continents", lookupDao.getContinents());
model.addAttribute("regions", lookupDao.getRegions());
model.addAttribute("countries", countryDao.getCountries(params));
model.addAttribute("count", countryDao.getCountriesCount(params));
return "countries";
}
The previous code is pretty straightforward. We are making use of the DAO classes to populate the required data into the Model instance and then returning the view name, which in this case is countries. Similarly, the rest of the method implementation can be found in the ViewController controller class.