/mojarra

Eclipse Mojarra implements Jakarta Faces

Primary LanguageJavaOtherNOASSERTION

Mojarra 4.0 WIP

Eclipse's implementation of the Jakarta Faces specification

Minimum Requirements

  • Java 1.8
  • Jakarta Servlet 5.0
  • Jakarta Expression Language 4.0
  • CDI 3.0
  • Jakarta Standard Tag Library 2.0
  • Jakarta JSON Processing 2.0 (optional, only when <f:websocket> is used)
  • Jakarta Validation 3.0 (optional, only when <f:validateBean> or <f:validateWholeBean> is used; 2.0 recommended)

CDI is explicitly required because since Jakarta Faces 2.3 the javax.faces.bean.* annotations such as @ManagedBean are deprecated, and in 4.0 these have been removed. Several implicit Jakarta Expression Language objects are produced via CDI producers, and <f:websocket> manages the Jakarta WebSocket sessions and events via CDI.

Installation

Depending on the server used, Jakarta Faces may already be built-in (full fledged Jakarta EE containers such as WildFly, JBoss EAP, TomEE, Payara, GlassFish, Liberty, etc.), or not (barebones Jakarta Server Pages/Jakarta Servlet containers such as Tomcat, Jetty, etc.). If the server doesn't ship with Jakarta Faces built-in, then you need to manually install Jakarta Faces 3.0 along with CDI 3.0+, Jakarta JSON Processing 2.0+ and Jakarta Standard Tag Library 2.0+ as those Jakarta Servlet containers usually also don't even ship with those Jakarta Faces dependencies.

Non-Maven

In case you're manually carrying around JARs:

Maven

In case you're using Maven, you can find below the necessary coordinates:

  • Java EE containers (WildFly, JBoss EAP, TomEE, Payara, GlassFish, Liberty, etc)

    <dependency>
       <groupId>jakarta.platform</groupId>
       <artifactId>jakarta.jakartaee-api</artifactId>
       <version>9.0.0</version>
       <scope>provided</scope>
    </dependency>

In case of WildFly/JBoss EAP, you need to manually package jsf-api.jar and jsf-impl.jar based on jakarta.faces.jar first. In case of TomEE, just swap the myfaces*.jar files with jakarta.faces.jar in the server's /lib folder. In case of Payara/GlassFish, just swap the jakarta.faces.jar file in the server's /glassfish/modules folder.

  • Servletcontainers (Tomcat, Jetty, etc)

    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>jakarta.faces</artifactId>
        <version><!-- Use latest 3.0.x version. --></version>
    </dependency>
    <dependency>
        <groupId>org.jboss.weld.servlet</groupId>
        <artifactId>weld-servlet-shaded</artifactId>
        <version>4.0.0.Final</version>
    </dependency>
    <dependency>
        <groupId>jakarta.servlet.jsp.jstl</groupId>
        <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency> <!-- Optional, only when <f:websocket> is used. -->
        <groupId>org.glassfish</groupId>
        <artifactId>jakarta.json</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency> <!-- Optional, only when <f:validateBean> or <f:validateWholeBean> is used. -->
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>7.0.0.Final</version>
    </dependency>

    You can check org.glassfish:jakarta.faces repository to find the latest Mojarra 3.0.x version.

Hello World Example

We assume that you already know how to create an empty Maven WAR Project or Dynamic Web Project in your favourite IDE with a CDI 3.0+ compatible /WEB-INF/beans.xml deployment descriptor file (which can be kept fully empty). Don't forget to add JARs or configure pom.xml if necessary, as instructed in previous chapter.

Controller

Optionally, register the FacesServlet in a Servlet 5.0+ compatible deployment descriptor file /WEB-INF/web.xml as below:

<?xml version="1.0" encoding="UTF-8"?>
<web-app
    xmlns="https://jakarta.ee/xml/ns/jakartaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
    version="5.0"
>
    <servlet>
        <servlet-name>facesServlet</servlet-name>
        <servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>facesServlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
</web-app>

Noted should be that Jakarta Faces 3.0+ is already "implicitly" registered and mapped on *.jsf, *.faces and /faces/* when running on a Jakarta Servlet 5.0+ container. This will be overridden altogether when explicitly registering as above. The *.xhtml URL pattern is preferred over above for security and clarity reasons. Jakarta Faces 2.3+ adds *.xhtml to set of default patterns, hence the FacesServlet registration being optional. But when you don't explicitly map it on *.xhtml, then people can still access JSF pages using *.jsf, *.faces or /faces/* URL patterns. This is not nice for SEO as JSF by design doesn't 301-redirect them to a single mapping.

The Faces deployment descriptor file /WEB-INF/faces-config.xml is fully optional, but if any it must be Jakarta Faces 3.0 compatible, otherwise Jakarta Faces 3.0 will run in a fallback modus matching the exact version as declared in <faces-config> root element.

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="https://jakarta.ee/xml/ns/jakartaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-facesconfig_3_0.xsd"
    version="3.0"
>
    <!-- Put any faces config here. -->
</faces-config>

Model

Then create a backing bean class as below:

package com.example;

import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;

@Named
@RequestScoped
public class Hello {

    private String name;
    private String message;

    public void createMessage() {
        message = "Hello, " + name + "!";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMessage() {
        return message;
    }

}

Noted should be that in reality in the average Jakarta EE application the above "model" is further breakdown into a Jakarta Persistence entity, a Jakarta Enterprise Beans service and a smaller backing bean. The Jakarta Persistence entity and Jakarta Enterprise Beans service then basically act as a true "model" and the backing bean becomes a "controller" for that model. This may in first place be confusing to starters, but it all depends on the point of view. See also What components are MVC in JSF MVC framework? and JSF Controller, Service and DAO.

View

Finally create a Facelets file /hello.xhtml as below:

<!DOCTYPE html>
<html lang="en"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Hello, World!</title>
    </h:head>
    <h:body>
        <h:form>
            <h:outputLabel for="name" value="Enter your name" required="true" />
            <h:inputText id="name" value="#{hello.name}" />
            <h:message for="name" />
            <br />
            <h:commandButton value="Say hello" action="#{hello.createMessage}">
                <f:ajax execute="@form" render="@form" />
            </h:commandButton>
            <br />
            #{hello.message}
        </h:form>
    </h:body>
</html>

Start the server and open it by http://localhost:8080/contextname/hello.xhtml.

Activating CDI in Jakarta Faces 3.0

By default, Jakarta Faces 3.0 will run in Jakarta Faces 2.2 modus as to CDI support. Even when you use a Jakarta Faces 2.3 or 3.0 compatible faces-config.xml. In other words, the Jakarta Faces 2.3+ feature of injection and EL resolving of Jakarta Faces artifacts (spec issue 1316) won't work until you explicitly activate this. In other words, @Inject FacesContext doesn't work by default. This was necessary in order for Jakarta Faces 2.3 to stay compatible with 2.2, and this carried over to 3.0.

There is currently only one way to activate CDI in Jakarta Faces 2.3 and 3.0 and herewith make Jakarta Faces 2.3 and 3.0 to run in full Jakarta Faces 2.3/3.0 modus. Put the @FacesConfig annotation on an arbitrary CDI managed bean. For example, a general startup/configuration bean.

@FacesConfig
@ApplicationScoped
public class YourApplicationConfig {
    // ...
}

Building

In case you want to checkout this repository and manually build from source yourself (if necessary after editing source code), here are the instructions:

Jakarta Faces 4.0

  1. Make sure that you have JDK 1.8, Ant and Maven installed.

  2. Checkout branch master.

  3. Run the following commands from the root directory of the project:

    # under the root dir of project
    mvn clean install
  4. The binary is now available as impl/target/jakarta.faces-4.0.x-SNAPSHOT.jar.

Jakarta Faces 3.0

  1. Make sure that you have JDK 1.8, Ant and Maven installed.

  2. Checkout branch 3.0.

  3. Run the following commands from the root directory of the project:

    # under the root dir of project
    mvn clean install
  4. The binary is now available as impl/target/jakarta.faces-3.0.x-SNAPSHOT.jar.

Jakarta Faces 2.3

  1. Make sure that you have JDK 1.8, Ant and Maven installed.

  2. Checkout branch 2.3.

  3. Run the following commands from the root directory of the project:

    # under the root dir of project
    mvn clean install
  4. The binary is now available as impl/target/jakarta.faces-2.3.x-SNAPSHOT.jar.

Jakarta Faces 2.2

Jakarta Faces 2.2 and lower are not supported by Eclipse. If such support is needed, consult your Jakara EE vendor of choice.

Editing source code with IDE

In case you want to checkout to edit the source code of Mojarra with full IDE support, here are the instructions. Note that this only allows you to edit the code. Actually building the Mojarra artefacts still has to be done using the instructions provided above.

Eclipse

Jakarta Faces 3.0

  1. Checkout branch 3.0 using File -> import -> Git
  2. Right click the Mojarra project after checkout, choose Configure -> Convert to Maven Project

Jakarta Faces 2.3

  1. Checkout branch master using File -> import -> Git
  2. Switch to 2.3 rolling branch using Team -> Switch to -> Other -> Remote Tracking -> origin/2.3 -> New Branch
  3. Go to the commandline and cd into the directory where Mojarra was checked-out.
  4. Follow the instructions for build JSF 2.2 from the build instructions above from step 3 (copy/edit properties, run ant)
  5. Go back to Eclipse and refresh the Eclipse project

Pull Requests

Pull requests are accepted on following branches:

Note that it's okay to send a PR to the master branch, but this one is for JSF.next and not the current 2.3.x or 3.0.x version.

Resources