Get to Know JSF: An Easy and Straightforward a Jakarta Framework
Join the DZone community and get the full member experience.
Join For FreeDeveloping web systems is a reality in the current market, and the Jakarta Server Faces framework is a standard Jakarta EE option to solve this type of problem. One of the characteristics of JSF is to work in a way oriented towards screen components and their events (for example, clicks). In this way, we can associate these components with different aspects of our system, such as the execution of business operations, value conversions, field validations, etc. In this article, we'll talk about this JSF and how to move this application to the cloud with Platform.sh.
To celebrate the new year, let's create a small wish list in Java with Jakarta EE technologies. In the front end, we'll use Java Server Faces (JSF), a Java-based web application framework that simplifies the development and integration of web-based user interfaces with several already-made components. To store the list, let's use MongoDB.
Jakarta Server Faces defines an MVC framework for building user interfaces for web applications, including UI components, state management, event handling, input validation, page navigation, and support for internationalization and accessibility. It is MVC easy.
As with any Maven project, the first step is to define the dependencies that the application requires. On this JSF and MongoDB application on the Jakarta EE stack, we'll use JSF, Jakarta NoSQL, and Primefaces. Primefaces is an open-source user interface (UI) component library for JSF-based applications.
xxxxxxxxxx
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sh.platform.template</groupId>
<artifactId>microprofile-thorntail</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<version.thorntail>2.6.0.Final</version.thorntail>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<platform.sh.version>2.2.3</platform.sh.version>
<jakarta.nosql.version>1.0.0-b1</jakarta.nosql.version>
<junit.version>5.5.2</junit.version>
<maven.surefire.plugin.version>2.22.2</maven.surefire.plugin.version>
<test.containers.version>1.12.0</test.containers.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>bom-all</artifactId>
<version>${version.thorntail}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>jsf</artifactId>
</dependency>
<dependency>
<groupId>io.thorntail</groupId>
<artifactId>cdi</artifactId>
</dependency>
<dependency>
<groupId>sh.platform</groupId>
<artifactId>config</artifactId>
<version>${platform.sh.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jnosql.artemis</groupId>
<artifactId>artemis-document</artifactId>
<version>${jakarta.nosql.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jnosql.diana</groupId>
<artifactId>mongodb-driver</artifactId>
<version>${jakarta.nosql.version}</version>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>7.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${test.containers.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>wish</finalName>
<plugins>
<plugin>
<groupId>io.thorntail</groupId>
<artifactId>thorntail-maven-plugin</artifactId>
<version>${version.thorntail}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.plugin.version}</version>
</plugin>
</plugins>
</build>
</project>
The next step is the MongoDB integration; we won't go further because we have two articles about the introduction to Jakarta NoSQL one about the API and second what's Jakarta NoSQL and the introduction with cloud native.
xxxxxxxxxx
import jakarta.nosql.mapping.Column;
import jakarta.nosql.mapping.Convert;
import jakarta.nosql.mapping.Entity;
import jakarta.nosql.mapping.Id;
import java.util.Objects;
public class Wish {
ObjectIdConverter.class) (
private String id;
private String dream;
//getter and setter
}
public interface WishRepository extends Repository<Wish, String> {
List<Wish> findAll();
}
The entity and the database integration both are done. The next step is the controller. JSF has a Managed Bean that is a regular Java Bean class registered with JSF. In other words, the Managed Bean is a Java bean managed by the JSF framework. Managed Bean contains the getter and setter methods, business logic, or even a backing bean (a bean contains all the HTML form value).
xxxxxxxxxx
import javax.enterprise.inject.Model;
import javax.inject.Inject;
import java.util.List;
public class WishBean {
private WishRepository repository;
private String wish = "";
public String getWish() {
return wish;
}
public void setWish(String wish) {
this.wish = wish;
}
public void add() {
repository.save(Wish.of(wish));
this.wish = "";
}
public List<Wish> getWishes() {
return repository.findAll();
}
public void remove(String id) {
repository.deleteById(id);
}
}
The bean has the @Model
annotation to map this map to be ready to use on the JSF page and has the request scope. This will enable us to use this class as wishBean
. JSF has several scopes in its managed beans such as:
@RequestScoped: Bean lives as long as the HTTP request-response lives. It gets created upon an HTTP request and gets destroyed when the HTTP response associated with the HTTP request is finished.
@ViewScoped: Bean lives as long as the user is interacting with the same JSF view in the browser window/tab. It gets created upon an HTTP request and gets destroyed once the user postbacks to a different view.
- @SessionScoped: Bean lives as long as the HTTP session lives. It gets created upon the first HTTP request involving this bean in the session and gets destroyed when the HTTP session is invalidated.
- @ApplicationScoped: Bean lives as long as the web application lives. It gets created upon the first HTTP request involving this bean in the application (or when the web application starts up and the eager=true attribute is set in @ManagedBean) and gets destroyed when the web application shuts down.
xxxxxxxxxx
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Wish List to the new year</title>
</h:head>
<h:body>
<h:form id="form">
<p:panel header="Put your dreams to the next year">
<p:panelGrid columns="2" layout="grid" cellpadding="4">
<p:inputText id="dream" value="${wishBean.wish}" label="Wish" placeholder="Wish"></p:inputText>
<p:commandButton id="btn" action="#{wishBean.add}" update="form" icon="ui-icon-disk"></p:commandButton>
</p:panelGrid>
</p:panel>
<p:dataTable id="table" var="wish" value="#{wishBean.wishes}">
<p:column headerText="Wish">
<h:outputText value="#{wish.dream}"></h:outputText>
</p:column>
<p:column>
<p:commandButton action="#{wishBean.remove(wish.id)}" icon="ui-icon-trash" update="form"></p:commandButton>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
The XHML page shows how easy it is to integrate action with Ajax using Java classes mapped by JSF/CDI annotations. On the JSF, we have Ajax natively, so we can use the update attribute without a strong effort on the frontend (e.g., to list elements, there are the #{wishBean.wishes}
where it calls the method getWishes
in the class WishBean
.
Platform.sh Structure
The Java application is ready to go! The next step is to set the Platform.sh files required to manage and deploy the application. In our first Java post, we took a deep dive into each detail of these three files:
One router (.platform/routes.yaml). Platform.sh allows you to define the routes.
Zero or more service containers (.platform/services.yaml). Platform.sh allows you to completely define and configure the topology and services you want to use on your project.
One or more application containers (.platform.app.yaml). You control your application and the way it will be built and deployed on Platform.sh via a single configuration file.
We'll change the services.yaml to add MongoDB.
xxxxxxxxxx
mongodb
type mongodb3.6
disk512
We'll set the application file.
xxxxxxxxxx
# This file describes an application. You can have multiple applications
# in the same project.
#
# See https://docs.platform.sh/user_guide/reference/platform-app-yaml.html
# The name of this app. Must be unique within a project.
name app
# The runtime the application uses.
type"java:11"
disk1024
# The hooks executed at various points in the lifecycle of the application.
hooks
build mvn -DskipTests clean package thorntail package
# The relationships of the application with services or other applications.
#
# The left-hand side is the name of the relationship as it will be exposed
# to the application in the PLATFORM_RELATIONSHIPS variable. The right-hand
# side is in the form `<service name>:<endpoint name>`.
relationships
mongodb'mongodb:mongodb'
# The configuration of app when it is exposed to the web.
web
commands
start java -jar -Xmx2048m -Dswarm.http.port=$PORT -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Addresses=true target/wish-thorntail.jar
Move the Project to a Github Repository
We’ll create a Git repository and Platform.sh account in three easy steps:
This integration allows us to once we push the code to the master branch on the Github repository, Platform.sh will generate the application automatically to us.
In this article, we discussed JSF and how it is easy to integrate Java applications on Jakarta EE. Software that has CI/CD has a great guarantee of quality, is best practice, and makes and Platform.sh a perfect fit for your next cloud project.
Source: https://github.com/soujava/wishlist.
Opinions expressed by DZone contributors are their own.
Comments