Implementing a Web UI Adapter in Spring’s Classical Three-Layered Architecture

In this practical session, you will implement a Web UI Adapter on top of RentIT’s domain model. You will follow the Spring classical three-layered architecture (Web layer, services layer, repository layer) seen in the lecture. This means that the Controller(s) should interact with the SalesService using DTOs, and the SalesService (together with other application services) will interact with the repository layer using domain (entity) objects.

You are required to implement the scenario given in the sequence diagram below. We will assume that all interactions are automated (i.e. the plant reservation is handled by the information system without the intervention of Rentit’s clerk). If the reservation succeeds, the purchase order must be updated with a reference to the reservation. The total cost of the purchase order is updated only if the reservation is successful. If no physical equipment for requested plant (entry) is available, we have to set the purchase order as rejected and notify the customer of this situation. The following diagram sketches the sequence of steps that your project must implement.

Sequence

This practical session is largely a refactoring/re-implementation of the application developed in the previous practical session (session #3). You can start with the codebase of the previous practical session and refactor it as needed.

We are going to use the UUID-based approach to generate identifiers. We will avoid the use of custom ID classes (e.g. PlantInventoryEntryID) and will rather use strings. I propose you use one identifier factory class per bounded context. Moreover, I propose to put the class under the package infrastructure. For instance, if we take the case of the sales bounded context, we will need to add the class SalesIdentifierFactory (provided below) within the package com.example.sales.infrastructure.

SalesIdentifierFactory.java
@Service
public class SalesIdentifierFactory {
    public String nextPurchaseOrderID() {
      return UUID.randomUUID().toString();
    }
}

Please note that we are returning a String and not a wrapper class (e.g. PurchaseOrderID) as described in the lecture. You will need to replace the PurchaseOrderID) as described in the lecture. You will need to replace the current definition of the identifiers used in entity classes (they will not longer be Long and @AutoGenerated). Beware that this change will have an impact in your test code and repositories. The decision of not using wrapper classes is just because the changes will be even more dramatic.

If it helps, you will find a pair of html files that you can use in your application by selecting the following links: query-form.html and query-result.html (since the files are html, you would need to ask the browser to show the source code and grab it from there). Copy the files into the folder templates/dashboard/catalog and templates/dashboard/catalog in the source folder containing your project’s resources.

clipboard checklist pencil icon display Your to do list
  • Reorganize your current project according to the Module Pattern. I propose you to consider the names common (for shared value object classes), sales (for purchase orders), inventory or reservations, and maintenance

  • Refactor all the Entity classes to use the UUID-based identifiers (note that will also require to update the repositories)

  • Apply the Factory Method Pattern to your domain model (follow the example given in the lecture for class PurchaseOrder)

  • Implement the Web adapter as described in the lecture. We assume that customer interactions happen in a dashboard. This assumption is explicit in the URLs used within the HTML documents.

    • Create the DTOs that are required as Presentation Model. For conversion of DTOs from/to Domain objects use the Assembler Pattern presented in the lecture (See page 30 on lecture’s slides)

  • Implement the Application Services to mediate the interaction of the Web adaptor with the domain model

  • Implement a validator using the Spring Validation framework, which will check that the rental period in the PO is valid. A period is valid if start < end date, the period is in the future, and both dates are different from null.