Note
|
This repository contains the guide documentation source. To view the guide in published form, view it on the Open Liberty website. |
Learn how to build a dynamic web application using Jakarta Faces, Jakarta Contexts and Dependency Injection, and Jakarta Expression Language.
You’ll learn how to build a dynamic web application using Jakarta Faces for the user interface (UI), Jakarta Contexts and Dependency Injection (CDI) for managing backend logic, and Jakarta Expression Language (EL) for data binding.
Jakarta Faces is a powerful framework for building web applications with reusable UI components. It provides an API for managing component state, handling events, server-side validation, page navigation, and supports internationalization. The framework also offers tag libraries for adding components and binding them to server-side objects, simplifying UI development. Jakarta Contexts and Dependency Injection provides a flexible way to manage the lifecycle of backend beans, allowing managed beans to be automatically created and injected when needed. Jakarta Expression Language allows data binding between the UI and the backend, enabling componenets to display dynamic data and respond to user actions.
The application you will build in this guide is a dynamic web application that displays system load data on demand. Using Jakarta Faces for the UI, you’ll create a table to show the system’s cpu load and heap memory usage. You’ll also learn how to use CDI to provide the system load data from a managed bean, and to use Jakarta Expression Language to bind this data to the UI components.
The finish
directory in the root of this guide contains the finished application. Give it a try before you proceed.
To try out the application, first go to the finish
directory and run Maven with the liberty:run
goal to build the application and deploy it to Open Liberty:
cd finish
mvn liberty:run
After you see the following message, your Liberty instance is ready.
The defaultServer server is ready to run a smarter planet.
Check out the web application at http://localhost:9080/index.xhtml. Click the refresh button, located next to the table title, to update and display the latest system load data in the table.
After you are finished checking out the application, stop the Liberty instance by pressing CTRL+C
in the command-line session where you ran Liberty. Alternatively, you can run the liberty:stop
goal from the finish
directory in another shell session:
mvn liberty:stop
Start by creating a static Jakarta Faces page that displays an empty table for system load data, which serves as the starting point for your application.
Navigate to the start
directory to begin.
When you run Open Liberty in dev mode, dev mode listens for file changes and automatically recompiles and deploys your updates whenever you save a new change. Run the following goal to start Open Liberty in dev mode:
mvn liberty:dev
After you see the following message, your Liberty instance is ready in dev mode:
**************************************************
* Liberty is running in dev mode.
Dev mode holds your command-line session to listen for file changes. Open another command-line session to continue, or open the project in your editor.
Create the index.xhtml file.
src/main/webapp/index.xhtml
index.xhtml
link:staging/index.xhtml[role=include]
footer.xhtml
link:finish/src/main/webapp/WEB-INF/includes/footer.xhtml[role=include]
In the index.xhtml
file, the xmlns
attributes define the XML namespaces for various Jakarta Faces tag libraries. These namespaces allow the page to use Jakarta Faces tags for templating, creating UI components, and enabling core functionality like form submissions and data binding. For more information on the various tag libraries and their roles in Jakarta Faces, refer to the Jakarta Faces Tag Libraries Documentation.
The index.xhtml
file combines standard HTML elements with Jakarta Faces components, enabling both static layout and dynamic functionality. Jakarta Faces tags, like <h:outputStylesheet>
and <ui:include>
, manage UI components, resource inclusion, and data binding, offering additional features beyond standard HTML; while standard elements like <div>
and <section>
structure the page’s layout. The <h:outputStylesheet>
includes a CSS file to style the page. The <ui:include>
tag incorporates reusable components, such as the provided footer.xhtml
file, to streamline maintenance and reuse across multiple pages.
At this point, the page defines a table that has no data entries. We’ll add dynamic content in the following steps.
Before you can access the Jakarta Faces page, you need to configure the Faces Servlet in your application. This servlet handles all requests for .xhtml
pages and processes them using Jakarta Faces.
Create the web.xml file.
src/main/webapp/WEB-INF/web.xml
web.xml
link:finish/src/main/webapp/WEB-INF/web.xml[role=include]
The <servlet>
element defines the Faces Servlet that is responsible for processing requests for Jakarta Faces pages. The <load-on-startup>
element with a value of 1 specifies that the servlet should be loaded and initialized when the application starts.
The <servlet-mapping>
element specifies which URL patterns are routed to the Faces Servlet. In this case, all URLs ending with .xhtml
are mapped to be processed by Jakarta Faces. This ensures that any request for a .xhtml
page is handled by the Faces Servlet, which manages the lifecycle of Jakarta Faces components, processes the page, and renders the output.
By configuring both the servlet and the servlet mapping, you’re ensuring that Jakarta Faces pages are properly processed and delivered in response to user requests.
The jakarta.faces.PROJECT_STAGE
context parameter determines the current stage of the application in its development lifecycle. Because it is currently set to Development
, you will see additional debugging information, including developer-friendly warning messages such as WARNING: Apache MyFaces Core is running in DEVELOPMENT mode.
For more information about valid values and how to set the PROJECT_STAGE
parameter, you can refer to the official Jakarta Faces ProjectStage documentation.
Because you are running Open Liberty in dev mode and have configured the Faces Servlet, all the changes are automatically picked up.
Check out the web application that you created at the http://localhost:9080/index.xhtml URL. You should see the static page with the system loads table displaying only the headers and no data.
To provide system load data to your web application, you’ll create a CDI-managed bean that retrieves information about the system’s CPU load and memory usage. This bean will be accessible from the Jakarta Faces page and will supply the data to be displayed.
Create the SystemLoadBean class.
src/main/java/io/openliberty/guides/application/SystemLoadBean.java
SystemLoadBean.java
link:finish/src/main/java/io/openliberty/guides/application/SystemLoadBean.java[role=include]
Annotate the SystemLoadBean
class with a @Named
annotation to make it accessible in the Jakarta Faces pages under the name systemLoadBean
. Because the SystemLoadBean
bean is a CDI managed bean, a scope is necessary. An application scope is used in this example. To learn more about CDI, see the Injecting dependencies into microservices guide.
The @PostConstruct
annotation ensures the init()
method runs after the SystemLoadBean
is initialized and dependencies are injected. The init()
method sets up any required resources for the bean’s lifecyccle.
The fetchSystemLoad()
method retrieves the current system load and memory usage, then updates the list of system load data.
The getSystemLoads()
method is a getter method for accessing the list of system load data from the Jakarta Faces page.
Now that you have the backend logic implemented with CDI, you’ll update the Jakarta Faces page to display the dynamic system load data by binding the UI components to the backend data using Jakarta Expression Language.
Update the index.xhtml file.
src/main/webapp/index.xhtml
index.xhtml
link:finish/src/main/webapp/index.xhtml[role=include]
SystemLoadBean.java
link:finish/src/main/java/io/openliberty/guides/application/SystemLoadBean.java[role=include]
The index.html
uses a <h:commandButton>
tag to create the refresh button, where the action #{systemLoadBean.fetchSystemLoad}
invokes the fetchSystemLoad()
method using Jakarta Expression Language when the button is clicked. This EL expression references the systemLoadBean
managed bean, triggering the method to update the system load data. The <f:ajax>
tag ensures that the systemLoadForm
component is re-rendered without a full page reload.
The systemLoadsTable
is populated using the <ui:repeat>
tag, which iterates over the list of system load data provided by the systemLoadBean
. The EL expression #{systemLoadBean.systemLoads}
calls the getSystemLoads()
method from the managed bean, binding the data to the UI components. If the systemLoadBean
hasn’t been created yet, it is automatically initialized at this point. For each entry, the time
, cpuLoad
, and memoryUsage
fields are displayed using <h:outputText>
, while <f:convertNumber>
formats numeric values to two decimal places.
server.xml
link:finish/src/main/liberty/config/server.xml[role=include]
The required faces
, expressionLanguage
, and cdi
features have been enabled for you in the Liberty server.xml
configuration file.
Because you started the Open Liberty in dev mode at the beginning of the guide, so all the changes were automatically picked up.
Navigate to the http://localhost:9080/index.xhtml to view your web application. Click on the refresh button to trigger an update on the system loads table.
While you can manually verify the web application by visiting http://localhost:9080/index.xhtml, automated tests are a much better approach because they are more reliable and trigger a failure if a breaking change is introduced. You can write unit tests for your CDI bean to ensure that the basic operations you implemented function correctly.
Create the SystemLoadBeanTest class.
src/test/java/io/openliberty/guides/application/SystemLoadBeanTest.java
SystemLoadBeanTest.java
link:finish/src/test/java/io/openliberty/guides/application/SystemLoadBeanTest.java[role=include]
The setUp()
method is annotated with the @BeforeEach
annotation, indicating that it is run before each test case to ensure a clean state for each test execution. In this case, it creates a new instance of SystemLoadBean
and manually calls the init()
method to initialize the list of system load data before each test.
The testInitMethod()
test case verifies that after initializing SystemLoadBean
, the list of system load data is not null and contains at least one entry.
The testFetchSystemLoad()
test case verifies that after calling the fetchSystemLoad()
method, the size of the list of system load data increases by one.
The testDataIntegrity()
test case verifies that each SystemLoadData
entry in the list of system load data contains valid values for time
, cpuLoad
, and memoryUsage
.
Because you started Open Liberty in dev mode, you can run the tests by pressing the enter/return
key from the command-line session where you started dev mode.
You see the following output:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running io.openliberty.guides.application.SystemLoadBeanTest
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.037 s -- in io.openliberty.guides.application.SystemLoadBeanTest
Results:
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
When you are done checking out the service, exit dev mode by pressing CTRL+C
in the command-line session where you ran Liberty.
You just built a dynamic web application on Open Liberty by using Jakarta Faces for the user interface, CDI for managing beans, and Jakarta Expression Language for binding and handling data.