Duke’s Forest Case Study Example

This chapter describes Duke’s Forest, a simple e-commerce application that contains several web applications and illustrates the use of multiple Jakarta EE APIs.

Overview of the Duke’s Forest Case Study Example

Duke’s Forest is a simple e-commerce application that contains several web applications and illustrates the use of the following Jakarta EE APIs:

  • Jakarta Faces technology, including Ajax

  • Jakarta Contexts and Dependency Injection (CDI)

  • Jakarta RESTful Web Services

  • Jakarta Persistence

  • Jakarta Bean Validation

  • Jakarta Enterprise Beans technology

  • Jakarta Messaging

The application consists of the following projects.

  • Duke’s Store: A web application that has a product catalog, customer self-registration, and a shopping cart. It also has an administration interface for product, category, and user management. The project name is dukes-store.

  • Duke’s Shipment: A web application that provides an interface for order shipment management. The project name is dukes-shipment.

  • Duke’s Payment: A web service application that has a RESTful web service for order payment. The project name is dukes-payment.

  • Duke’s Resources: A simple Java archive project that contains all resources used by the web projects. It includes messages, CSS style sheets, images, JavaScript files, and Jakarta Faces composite components. The project name is dukes-resources.

  • Entities: A simple Java archive project that contains all Jakarta Persistence entities. This project is shared among other projects that use the entities. The project name is entities.

  • Events: A simple Java archive project that contains a POJO class that is used as a CDI event. The project name is events.

Design and Architecture of Duke’s Forest

Duke’s Forest is a complex application consisting of three main projects and three subprojects. Figure 1, “Architecture of the Duke’s Forest Example Application” shows the architecture of the three main projects that you will deploy: Duke’s Store, Duke’s Shipment, and Duke’s Payment. It also shows how Duke’s Store makes use of the Events and Entities projects.

This figure shows the architecture of the main Duke’s Forest projects and how they use the Events and Entities projects.
Figure 1. Architecture of the Duke’s Forest Example Application

Duke’s Forest uses the following Jakarta EE platform features:

  • Jakarta Persistence entities

    • Bean Validation annotations on the entities for verifying data

    • XML annotations for Jakarta XML binding serialization

  • Web services

    • A Jakarta REST web service for payment, with security constraints

    • A Jakarta REST web service based on Jakarta Enterprise Beans

  • Enterprise beans

    • Local session beans

    • All enterprise beans packaged within the WAR

  • Jakarta Contexts and Dependency Injection (CDI)

    • CDI annotations for Jakarta Faces components

    • A CDI managed bean used as a shopping cart, with conversation scoping

    • Qualifiers

    • Events and event handlers

  • Servlets

    • A servlet for dynamic image presentation

  • Jakarta Faces technology, using Facelets for the web front end

    • Templating

    • Composite components

    • File upload

    • Resources packaged in a JAR file so they can be found in the classpath

  • Security

    • Security constraints on the administrative interface business methods (enterprise beans)

    • Security constraints for customers and administrators (web components)

    • Single Sign-On (SSO) to propagate an authenticated user identity from Duke’s Store to Duke’s Shipment

The Duke’s Forest application has two main user interfaces, both packaged within the Duke’s Store WAR file:

  • The main interface, for customers and guests

  • The administrative interface used to perform back office operations, such as adding new items to the catalog

The Duke’s Shipment application also has a user interface, accessible to administrators.

Figure 2, “Interactions between Duke’s Forest Components” shows how the web applications and the web service interact.

This figure shows the interactions between the Duke’s Store and Duke’s Shipment projects (using REST and HTTP), and between the Duke’s Store and Duke’s Payment projects (using REST and HTTP).
Figure 2. Interactions between Duke’s Forest Components

As illustrated in Figure 2, “Interactions between Duke’s Forest Components”, the customer interacts with the main interface of Duke’s Store, while the administrator interacts with the administration interface. Both interfaces access a façade consisting of managed beans and stateless session beans, which in turn interact with the entities that represent database tables. The façade also interacts with web services APIs that access the Duke’s Payment web service. When the payment for an order is approved, Duke’s Store sends the order to a Jakarta Messaging queue. The administrator also interacts with the interface of Duke’s Shipment, which can be accessed either directly through Duke’s Shipment or from the administration interface of Duke’s Store by means of a web service. When the administrator approves an order for shipping, Duke’s Shipment consumes the order from the Jakarta Messaging queue.

The most fundamental building blocks of the application are the Events and Entities projects, which are bundled into Duke’s Store and Duke’s Shipment along with the Duke’s Resources project.

The events Project

Events are one of the core components of Duke’s Forest. The events project, included in all three of the main projects, is the most simple project of the application. It has only one class, OrderEvent, but this class is responsible for most of the messages between objects in the application.

The application can send messages based on events to different components and react to them based on the qualification of the event. The application supports the following qualifiers:

  • @LoggedIn: For authenticated users

  • @New: When a new order is created by the shopping cart

  • @Paid: When an order is paid for and ready for shipment

The following code snippet from the PaymentHandler class of Duke’s Store shows how the @Paid event is handled:

@Inject @Paid Event<OrderEvent> eventManager;

...
public void onNewOrder(@Observes @New OrderEvent event) {

    if (processPayment(event)) {
        orderBean.setOrderStatus(event.getOrderID(),
                String.valueOf(OrderBean.Status.PENDING_PAYMENT.getStatus()));
        logger.info("Payment Approved");
        eventManager.fire(event);
    } else {
        orderBean.setOrderStatus(event.getOrderID(),
                String.valueOf(OrderBean.Status.CANCELLED_PAYMENT.getStatus()));
        logger.info("Payment Denied");
    }
}

To enable users to add more events to the project easily or update an event class with more fields for a new client, this component is a separate project within the application.

The entities Project

The entities project is a Jakarta Persistence project used by both Duke’s Store and Duke’s Shipment. It is generated from the database schema shown in Figure 3, “Duke’s Forest Database Tables and Their Relationships” and is also used as a base for the entities consumed and produced by the web services through Jakarta XML Binding. Each entity has validation rules based on business requirements, specified using Jakarta Bean Validation.

This figure shows the database tables in Duke’s Forest and their relationships.
Figure 3. Duke’s Forest Database Tables and Their Relationships

The database schema contains eight tables:

  • PERSON, which has a one-to-many relationship with PERSON_GROUPS and CUSTOMER_ORDER

  • GROUPS, which has a one-to-many relationship with PERSON_GROUPS

  • PERSON_GROUPS, which has a many-to-one relationship with PERSON and GROUPS (it is the join table between those two tables)

  • PRODUCT, which has a many-to-one relationship with CATEGORY and a one-to-many relationship with ORDER_DETAIL

  • CATEGORY, which has a one-to-many relationship with PRODUCT

  • CUSTOMER_ORDER, which has a one-to-many relationship with ORDER_DETAIL and a many-to-one relationship with PERSON and ORDER_STATUS

  • ORDER_DETAIL, which has a many-to-one relationship with PRODUCT and CUSTOMER_ORDER (it is the join table between those two tables)

  • ORDER_STATUS, which has a one-to-many relationship with CUSTOMER_ORDER

The entity classes that correspond to these tables are as follows.

  • Person, which defines attributes common to customers and administrators. These attributes are the person’s name and contact information, including street and email addresses. The email address has a Bean Validation annotation to ensure that the submitted data is well-formed. The generated table for the Person entity also has a DTYPE field that represents the discriminator column. Its value identifies the subclass (Customer or Administrator) to which the person belongs.

  • Customer, a specialization of Person with a specific field for CustomerOrder objects.

  • Administrator, a specialization of Person with fields for administration privileges.

  • Groups, which represents the group (USERS or ADMINS) to which the user belongs.

  • Product, which defines attributes for products. These attributes include name, price, description, associated image, and category.

  • Category, which defines attributes for product categories. These attributes include a name and a set of tags.

  • CustomerOrder, which defines attributes for orders placed by customers. These attributes include an amount and a date, along with id values for the customer and the order detail.

  • OrderDetail, which defines attributes for the order detail. These attributes include a quantity and id values for the product and the customer.

  • OrderStatus, which defines a status attribute for each order.

The dukes-payment Project

The dukes-payment project is a web project that holds a simple Payment web service. Since this is an example application, it does not obtain any real credit information or even customer status to validate the payment. For now, the only rule imposed by the payment system is to deny all orders above $1,000. This application illustrates a common scenario where a third-party payment service is used to validate credit cards or bank payments.

The project uses HTTP Basic Authentication and JAAS (Java Authentication and Authorization Service) to authenticate a customer to a Jakarta REST web service. The implementation itself exposes a simple method, processPayment, which receives an OrderEvent to evaluate and approve or deny the order payment. The method is called from the checkout process of Duke’s Store.

The dukes-resources Project

The dukes-resources project contains a number of files used by both Duke’s Store and Duke’s Shipment, bundled into a JAR file placed in the classpath. The resources are in the src/main/resources directory:

  • META-INF/resources/css: Two style sheets, default.css and jsfcrud.css

  • META-INF/resources/img: Images used by the projects

  • META-INF/resources/js: A JavaScript file, util.js

  • META-INF/resources/util: Composite components used by the projects

  • bundles/Bundle.properties: Application messages in English

  • bundles/Bundle_es.properties: Application messages in Spanish

  • ValidationMessages.properties: Bean Validation messages in English

  • ValidationMessages_es.properties: Bean Validation messages in Spanish

The Duke’s Store Project

Duke’s Store, a web application, is the core application of Duke’s Forest. It is responsible for the main store interface for customers as well as the administration interface.

The main interface of Duke’s Store allows the user to perform the following tasks:

  • Browsing the product catalog

  • Signing up as a new customer

  • Adding products to the shopping cart

  • Checking out

  • Viewing order status

The administration interface of Duke’s Store allows administrators to perform the following tasks:

  • Product maintenance (create, edit, update, delete)

  • Category maintenance (create, edit, update, delete)

  • Customer maintenance (create, edit, update, delete)

  • Group maintenance (create, edit, update, delete)

The project also uses stateless session beans as façades for interactions with the Jakarta Persistence entities described in The entities Project, and CDI managed beans as controllers for interactions with Facelets pages. The project thus follows the MVC (Model-View-Controller) pattern and applies the same pattern to all entities and pages, as in the following example.

  • AbstractFacade is an abstract class that receives a Type<T> and implements the common operations (CRUD) for this type, where <T> is a Persistence entity.

  • ProductBean is a stateless session bean that extends AbstractFacade, applying Product as Type<T>, and injects the PersistenceContext for the EntityManager. This bean implements any custom methods needed to interact with the Product entity or to call a custom query.

  • ProductController is a CDI managed bean that interacts with the necessary enterprise beans and Facelets pages to control the way the data will be displayed.

ProductBean begins as follows:

@Stateless
public class ProductBean extends AbstractFacade<Product> {
    private static final Logger logger =
        Logger.getLogger(ProductBean.class.getCanonicalName());

    @PersistenceContext(unitName="forestPU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }
    ...
}

Enterprise Beans Used in Duke’s Store

The enterprise beans used in Duke’s Store provide the business logic for the application and are located in the com.forest.ejb package. All are stateless session beans.

AbstractFacade is not an enterprise bean but an abstract class that implements common operations for Type<T>, where <T> is a Persistence entity.

Most of the other beans extend AbstractFacade, inject the PersistenceContext, and implement any needed custom methods:

  • AdministratorBean

  • CategoryBean

  • EventDispatcherBean

  • GroupsBean

  • OrderBean

  • OrderDetailBean

  • OrderJMSManager

  • OrderStatusBean

  • ProductBean

  • ShoppingCart

  • UserBean

The ShoppingCart class, although it is in the ejb package, is a CDI managed bean with conversation scope, which means that the request information will persist across multiple requests. Also, ShoppingCart is responsible for starting the event chain for customer orders, which invokes the RESTful web service in dukes-payment and publishes an order to the Jakarta Messaging queue for shipping approval if the payment is successful.

Facelets Files Used in the Main Interface of Duke’s Store

Like the other case study examples, Duke’s Store uses Facelets to display the user interface. The main interface uses a large number of Facelets pages to display different areas. The pages are grouped into directories based on which module they handle.

  • template.xhtml: Template file, used for both main and administration interfaces. It first performs a browser check to verify that the user’s browser supports HTML 5, which is required for Duke’s Forest. It divides the screen into several areas and specifies the client page for each area.

  • topbar.xhtml: Page for the login area at the top of the screen.

  • top.xhtml: Page for the title area.

  • left.xhtml: Page for the left sidebar.

  • index.xhtml: Page for the main screen content.

  • login.xhtml: Login page specified in web.xml. The main login interface is provided in topbar.xhtml, but this page appears if there is a login error.

  • admin directory: Pages related to the administration interface, described in Facelets Files Used in the Administration Interface of Duke’s Store.

  • customer directory: Pages related to customers (Create.xhtml, Edit.xhtml, List.xhtml, Profile.xhtml, View.xhtml).

  • order directory: Pages related to orders (Create.xhtml, List.xhtml, MyOrders.xhtml, View.xhtml).

  • orderDetail directory: Popup page allowing users to view details of an order (View_popup.xhtml).

  • product directory: Pages related to products (List.xhtml, ListCategory.xhtml, View.xhtml).

Facelets Files Used in the Administration Interface of Duke’s Store

The Facelets pages for the administration interface of Duke’s Store are found in the web/admin directory:

  • administrator directory: Pages related to administrator management (Create.xhtml, Edit.xhtml, List.xhtml, View.xhtml)

  • category directory: Pages related to product category management (Create.xhtml, Edit.xhtml, List.xhtml, View.xhtml)

  • customer directory: Pages related to customer management (Create.xhtml, Edit.xhtml, List.xhtml, Profile.xhtml, View.xhtml)

  • groups directory: Pages related to group management (Create.xhtml, Edit.xhtml, List.xhtml, View.xhtml)

  • order directory: Pages related to order management (Create.xhtml, Edit.xhtml, List.xhtml, View.xhtml)

  • orderDetail directory: Popup page allowing the administrator to view details of an order (View_popup.xhtml)

  • product directory: Pages related to product management (Confirm.xhtml, Create.xhtml, Edit.xhtml, List.xhtml, View.xhtml)

Managed Beans Used in Duke’s Store

Duke’s Store uses the following CDI managed beans, which correspond to the enterprise beans. The beans are in the com.forest.web package:

  • AdministratorController

  • CategoryController

  • CustomerController

  • CustomerOrderController

  • GroupsController

  • OrderDetailController

  • OrderStatusController

  • ProductController

  • UserController

Helper Classes Used in Duke’s Store

The CDI managed beans in the main interface of Duke’s Store use the following helper classes, found in the com.forest.web.util package:

  • AbstractPaginationHelper: An abstract class with methods used by the managed beans

  • ImageServlet: A servlet class that retrieves the image content from the database and displays it

  • JsfUtil: Class used for Jakarta Faces operations, such as queuing messages on a FacesContext instance

  • MD5Util: Class used by the CustomerController managed bean to generate an encrypted password for a user

Qualifiers Used in Duke’s Store

Duke’s Store defines the following qualifiers in the com.forest.qualifiers package:

  • @LoggedIn: Qualifies a user as having logged in

  • @New: Qualifies an order as new

  • @Paid: Qualifies an order as paid

Event Handlers Used in Duke’s Store

Duke’s Store defines event handlers related to the OrderEvent class packaged in the events project (see The events Project). The event handlers are in the com.forest.handlers package.

  • IOrderHandler: The IOrderHandler interface defines a method, onNewOrder, implemented by the two handler classes.

  • PaymentHandler: The ShoppingCart bean fires an OrderEvent qualified as @New. The onNewOrder method of PaymentHandler observes these events and, when it intercepts them, processes the payment using the Duke’s Payment web service. After a successful response from the web service, PaymentHandler fires the OrderEvent again, this time qualified as @Paid.

  • DeliveryHandler: The onNewOrder method of DeliveryHandler observes OrderEvent objects qualified as @Paid (orders paid and ready for delivery) and modifies the order status to PENDING_SHIPMENT. When an administrator accesses Duke’s Shipment, it will call the Order Service, a RESTful web service, and ask for all orders in the database that are ready for delivery.

Deployment Descriptors Used in Duke’s Store

Duke’s Store uses the following deployment descriptors, located in the web/WEB-INF directory:

  • faces-config.xml: The Jakarta Faces configuration file

  • glassfish-web.xml: The configuration file specific to GlassFish Server

  • web.xml: The web application configuration file

The Duke’s Shipment Project

Duke’s Shipment is a web application with a login page, a main Facelets page, and some other objects. This application, which is accessible only to administrators, consumes orders from a Jakarta Messaging queue and calls the RESTful web service exposed by Duke’s Store to update the order status. The main page of Duke’s Shipment shows a list of orders pending shipping approval and a list of shipped orders. The administrator can approve or deny orders for shipping. If approved, the order is shipped, and it appears under the Shipped heading. If denied, the order disappears from the page, and on the customer’s Orders list it appears as cancelled.

There is also a gear icon on the Pending list that makes an Ajax call to the Order Service to refresh the list without refreshing the page. The code looks like this:

<h:commandLink>
    <h:graphicImage library="img" title="Check for new orders"
                    style="border:0px" name="refresh.png"/>
    <f:ajax execute="@form" render="@form" />
</h:commandLink>

Enterprise Beans Used in Duke’s Shipment

The UserBean stateless session bean used in Duke’s Shipment provides the business logic for the application and is located in the com.forest.shipment.session package.

Like Duke’s Store, Duke’s Shipment uses the AbstractFacade class. This class is not an enterprise bean but an abstract class that implements common operations for Type<T>, where <T> is a Jakarta Persistence entity.

The OrderBrowser stateless session bean, located in the com.forest.shipment.ejb package, has one method that browses the Jakarta Messaging order queue and another that consumes an order message after the administrator approves or denies the order for shipment.

Facelets Files Used in Duke’s Shipment

Duke’s Shipment has only one page, so it has many fewer Facelets files than Duke’s Store.

  • template.xhtml: The template file, like the one in Duke’s Store, first performs a browser check to verify that the user’s browser supports HTML 5, which is required for Duke’s Forest. It divides the screen into areas and specifies the client page for each area.

  • topbar.xhtml: Page for the login area at the top of the screen.

  • top.xhtml: Page for the title area.

  • index.xhtml: Page for the initial main screen content.

  • login.xhtml: Login page specified in web.xml. The main login interface is provided in topbar.xhtml, but this page appears if there is a login error.

  • admin/index.xhtml: Page for the main screen content after authentication.

Managed Beans Used in Duke’s Shipment

Duke’s Shipment uses the following CDI managed beans, in the com.forest.shipment package:

  • web.ShippingBean: Managed bean that acts as a client to the Order Service

  • web.UserController: Managed bean that corresponds to the UserBean session bean

Helper Class Used in Duke’s Shipment

The Duke’s Shipment managed beans use only one helper class, found in the com.forest.shipment.web.util package:

  • JsfUtil: Class used for Jakarta Faces operations, such as queuing messages on a FacesContext instance

Qualifier Used in Duke’s Shipment

Duke’s Shipment includes the @LoggedIn qualifier described in Qualifiers Used in Duke’s Store.

Deployment Descriptors Used in Duke’s Shipment

Duke’s Shipment uses the following deployment descriptors:

  • faces-config.xml: The Jakarta Faces configuration file

  • glassfish-web.xml: The configuration file specific to GlassFish Server

  • web.xml: The web application configuration file

Building and Deploying the Duke’s Forest Case Study Application

You can use NetBeans IDE or Maven to build and deploy Duke’s Forest.

To Build and Deploy the Duke’s Forest Application Using NetBeans IDE

  1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server), as well as the database server (see Starting and Stopping Apache Derby).

  2. From the File menu, choose Open Project.

  3. In the Open Project dialog box, navigate to:

    jakartaee-examples/tutorial/case-studies
  4. Select the dukes-forest folder.

  5. Select the Open Required Projects check box and click Open Project.

  6. Right-click the dukes-forest folder and select Build.

    This task configures the server, creates and populates the database, builds all the subprojects, assembles them into JAR and WAR files, and deploys the dukes-payment, dukes-store, and dukes-shipment applications.

    To configure the server, this task creates a JDBC security realm named jdbcRealm, enables default principal-to-role mapping, and enables single sign-on (SSO) for the HTTP Service.

To Build and Deploy the Duke’s Forest Application Using Maven

  1. Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server), as well as the database server (see Starting and Stopping Apache Derby).

  2. In a terminal window, go to:

    jakartaee-examples/tutorial/case-studies/dukes-forest/
  3. Enter the following command to configure the server, create and populate the database, build all the subprojects, assemble them into JAR and WAR files, and deploy the dukes-payment, dukes-store, and dukes-shipment applications:

    mvn install

    To configure the server, this task creates a JDBC security realm named jdbcRealm, enables default principal-to-role mapping, and enables single sign-on (SSO) for the HTTP Service.

Running the Duke’s Forest Application

Running the Duke’s Forest application involves several tasks:

  • Registering as a customer of Duke’s Store

  • As a customer, purchasing products

  • As an administrator, approving or denying shipment of a product

  • As an administrator, creating a new product, customer, group, or category

To Register as a Duke’s Store Customer

  1. In a web browser, enter the following URL:

    http://localhost:8080/dukes-store

    The Duke’s Forest - Store page opens.

  2. Click Sign Up at the top of the page.

  3. Fill in the form fields, then click Save.

    All fields are required, and the Password value must be at least 7 characters in length.

To Purchase Products

  1. To log in as the user you created, or as one of two users already in the database, enter the user name and password and click Log In.

    The preexisting users have the user names jack@example.com and robert@example.com, and they both have the same password, 1234.

  2. Click Products in the left sidebar.

  3. On the page that appears, click one of the categories (Plants, Food, Services, or Tools).

  4. Choose a product and click Add to Cart.

    You can order only one of any one product, but you can order multiple different products in multiple categories. The products and a running total appear in the Shopping Cart in the left sidebar.

  5. When you have finished choosing products, click Checkout.

    A message appears: "Your order is being processed. Check the Orders page to see the status of your order."

  6. Click Orders in the left sidebar to verify your order.

    If the total of the order exceeds $1,000, the status of the order is "Order cancelled," because the Payment web service denies orders over that limit. Otherwise, the status is "Ready to ship."

  7. When you have finished placing orders, click Logout at the top of the page.

To Approve Shipment of a Product

  1. Log in to Duke’s Store as an administrator.

    Your user name is admin@example.com, and your password is 1234.

    The main administration page allows you to view categories, customers, administrators, groups, products, and orders, and to create new objects of all types except orders.

  2. At the bottom of the page, click Approve Shipment.

    This action takes you to Duke’s Shipment, retaining your administrator login.

  3. On the Pending list, click Approve to approve an order and move it to the Shipped area of the page.

    If you click Deny, the order disappears from the page. If you log in to Duke’s Store again as the customer, it will appear in the Orders list as "Order cancelled."

To return to Duke’s Store from Duke’s Shipment, click Return to Duke’s Store.

To Create a New Product

You can create other kinds of objects as well as products. Creating products is more complex than the other creation processes, so it is described here.

  1. Log in to Duke’s Store as an administrator.

  2. On the main administration page, click Create New Product.

  3. Enter values in the Name, Price, and Description fields.

  4. Select a category, then click Next.

  5. On the Upload the Product Image page, click Browse to locate an image on your file system using a file chooser.

  6. Click Next.

  7. On the next page, view the product fields, then click Done.

  8. Click Products in the left sidebar, then click the category to verify that the product has been added.

  9. Click Administration at the top of the page to return to the main administration page, or click Logout to log out.