Upgrading Faces to Jakarta
Liferay DXP 2025.Q3+
Liferay Faces now uses the jakarta.* namespace to align with Jakarta EE 9 APIs. Migrating an existing Liferay Faces (JSF) portlet from the legacy javax.* namespace requires updating dependency coordinates, XML namespaces, and Java imports.
Because the migration uses a transformed build of JSF 2.3, the underlying JSF semantics are unchanged. Behavioral changes to your application are minimal.
Before changing Faces dependencies, bring your Liferay Workspace and target platform up to a Jakarta-based release. See Update Workspace in the general Jakarta upgrade guide — set the Workspace Gradle plugin to 14.0.0 or later and liferay.workspace.target.platform.version=2025.q3.0 or later.
Step 1: Install the Jakarta Runtime (Thin WAR Only)
If your project uses a Thin WAR packaging model (where runtime dependencies are provided by the Liferay server rather than bundled in the WAR), you must deploy the new Jakarta-namespaced runtime JARs to your Liferay instance before deploying your migrated portlets.
Copy the following JARs into the ${liferay.home}/osgi/modules/ folder. Wait for all bundles to reach the STARTED state in the server log before proceeding.
| Role | Required JAR |
|---|---|
| Portlet Bridge API | com.liferay.faces.bridge.api-7.0.0.jar |
| Portlet Bridge Impl | com.liferay.faces.bridge.impl-7.0.0.jar |
| Bridge Extensions | com.liferay.faces.bridge.ext-9.0.0.jar |
| Shared Utilities | com.liferay.faces.util-5.0.0.jar |
| Liferay Portal Tags | com.liferay.faces.portal-7.0.0.jar |
| Alloy Tags (if used) | com.liferay.faces.alloy-5.0.0.jar |
| JSF 2.3 Impl | jakarta.faces-2.3.21.LIFERAY-PATCHED-4.JAKARTA-LIFERAY-PATCHED-1.jar |
| PrimeFaces (if used) | org.primefaces-15.0.6.LIFERAY-PATCHED-3.JAKARTA-LIFERAY-PATCHED-1.jar |
If you deploy a Thin WAR before these bundles are active, the WAR fails to start and throws ClassNotFoundException: jakarta.faces.webapp.FacesServlet.
Step 2: Update Project Dependencies
Update your project’s build file (e.g., pom.xml or build.gradle) to use the new Jakarta-namespaced dependency versions.
If you are using a Thin WAR, set the scope of these dependencies to provided. If you are using a Thick WAR (bundling the runtime), set the scope to compile or runtime, with the exception of jakarta.portlet-api and jakarta.servlet-api, which must always remain provided.
Key dependency coordinates:
| Dependency | Version |
|---|---|
com.liferay.faces:com.liferay.faces.bridge.api | 7.0.0 |
com.liferay.faces:com.liferay.faces.bridge.impl | 7.0.0 |
com.liferay.faces:com.liferay.faces.bridge.ext | 9.0.0 |
com.liferay.faces:com.liferay.faces.util | 5.0.0 |
com.liferay.faces:com.liferay.faces.portal | 7.0.0 |
com.liferay.faces:com.liferay.faces.alloy | 5.0.0 |
com.liferay:jakarta.faces | 2.3.21.LIFERAY-PATCHED-4.JAKARTA-LIFERAY-PATCHED-1 |
com.liferay:org.primefaces | 15.0.6.LIFERAY-PATCHED-3.JAKARTA-LIFERAY-PATCHED-1 |
com.liferay.jakarta.portlet:com.liferay.jakarta.portlet-api | 4.0.0 |
jakarta.servlet:jakarta.servlet-api | 5.0.0 |
Step 3: Automate the Namespace Migration
Do not manually edit your Java imports and XML files. Use a batch migration tool such as the Jakarta Upgrade Tool (blade gw upgradeJakarta), Eclipse Transformer, or OpenRewrite.
The Jakarta Upgrade Tool rewrites javax.* references — including javax.faces.*, javax.portlet.*, javax.inject.*, and javax.enterprise.* — to jakarta.* across Java sources, JSPs, XML descriptors, bnd.bnd, and build.gradle files. It also remaps the Liferay Faces, jakarta.faces, and PrimeFaces Gradle/BND coordinates to their Jakarta-namespaced replacements.
Facelet .xhtml templates are not in the Jakarta Upgrade Tool’s per-extension handler list as of Liferay DXP 2026.Q1. Inspect each.xhtmlforxmlnsattributes that still referencehttp://java.sun.com/jsforhttp://xmlns.jcp.org/jsfand EL expressions that referencejavax.*; update them manually, or run a complementary tool (such as Eclipse Transformer) over your view templates.
Standard Java SE packages (such as javax.sql.* and javax.crypto.*) are not part of Jakarta EE and must not be renamed. The Jakarta Upgrade Tool excludes these by design. If you use a different tool, confirm it excludes them or revert manually.
Step 4: Update XML Descriptors
Confirm each descriptor in your WEB-INF folder is correct:
-
In
web.xml, the namespace must behttps://jakarta.ee/xml/ns/jakartaee(version 5.0+) and the<servlet-class>must point to the JakartaFacesServlet:<servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> -
In
portlet.xml, the namespace must use the Jakarta Portlet 4.0 schema and the<portlet-class>must point to the Jakarta package:<portlet-class>jakarta.portlet.faces.GenericFacesPortlet</portlet-class> <init-param> <name>jakarta.portlet.faces.defaultViewId.view</name> <value>/WEB-INF/views/view.xhtml</value> </init-param> -
In
liferay-plugin-package.properties, confirm the-cdiannotations:instruction is present:-cdiannotations:This prevents Liferay’s WAB Generator from scanning CDI annotations, which lets the bundled CDI implementation (Weld) discover beans for the JSF portlet.
Step 5: Deploy and Validate
Compile and deploy your updated WAR to your Liferay instance, then validate the migration:
-
Check the Liferay logs to confirm the WAR starts without bundle-wiring errors.
-
Navigate to the portlet and test view rendering, file uploads, and inter-portlet events.
-
Execute an Ajax interaction and confirm it routes correctly without returning a
403error. -
If you bundle PrimeFaces, test the components you use to confirm compatibility with the
LIFERAY-PATCHEDJakarta build.
For more on Liferay Faces artifact versioning, see Liferay Faces Version Scheme.
Troubleshooting
- Injected dependencies fail to wire: Ensure
beans.xmlis present in yourWEB-INFfolder,-cdiannotations:is present inliferay-plugin-package.properties, and that no scope annotations still reference the oldjavax.*packages. - Bundle-wiring errors in staging or production: Verify that the Thin WAR runtime JARs in your remote
osgi/modulesfolder exactly match the versions your WAR expects. Align the server runtime before deploying the migrated WAR.