• Settings
    • Locale
    • Change the locale of the datepicker, schedule and client side validation messages.

      Language
      English
      English
      English
      French
      German
      German
      German
      Italian
      Korean
      Spanish
      Catalan
      Dutch
      Portuguese
      Portuguese
      Arabic
      Arabic
      Bulgarian
      Bangla
      Bosnian
      Czech
      Greek
      Estonian
      Persian
      Finnish
      Danish
      Hindi
      Indonesian
      Icelandic
      Croatian
      Japanese
      Hungarian
      Hebrew
      Georgian
      Central Kurdish
      Khmer
      Kyrgyz
      Kazakh
      Lithuanian
      Latvian
      Malay
      Norwegian
      Polish
      Romanian
      Russian
      Slovak
      Slovenian
      Serbian
      Serbian
      Swedish
      Thai
      Turkish
      Ukrainian
      Uzbek
      Vietnamese
      Chinese
      Chinese
  • Resources
[email protected]

UI Suite for  .p-component Jakarta Faces

Build complete business UIs in Java. 153 components for Jakarta EE, Quarkus and Spring Boot – no npm, no REST layer, no second stack.

Built for Java teams shipping business apps

Your Java developers build the whole app, from the database to the UI. No separate frontend team, no second stack to build, secure and keep up to date.

153 components

DataTable, Schedule, TreeTable, FileUpload, Charts and more, with lazy loading, filtering and export built in.

No npm, no bundler

One Maven dependency. No node_modules, no lockfile churn, no second toolchain to keep patched.

No API layer for your own UI

Components bind straight to CDI beans. No REST endpoints, JSON mapping or CORS rules just to talk to yourself.

Logic stays on the server

Validation and business rules run in the JVM, next to your data and security. The browser gets rendered HTML, not your domain model.

Security built in

Strict nonce-based CSP with one context parameter. Faces itself brings CSRF protection and output escaping.

Tests in Java, too

JUnit 5 and Selenium with ready-made page objects for PrimeFaces components. No second test stack in JavaScript.

Design tokens

Aura, Lara, Nora, Metal and Glass, each in light and dark. Change any token at runtime, no build step.

Accessible by default

Keyboard navigation, screen reader support, ARIA roles and focus management built into the components.

Runs on your stack

Jakarta EE servers, Quarkus and Spring Boot, on Mojarra or MyFaces. Your existing runtime, no extra service.

One view, one bean.

Add PrimeFaces to Jakarta EE, Quarkus or Spring Boot and bind components straight to your beans. A sortable, filterable, paginated table is a Facelets view and a CDI bean, nothing else: field alone gives every column sorting and its own filter.

PrimeFaces Angular + component library
Files for this table 2 6
Toolchains to build and patch Maven Maven, Node, npm, Angular CLI
Languages Java, XHTML Java, TypeScript, HTML
API layer for the UI None REST endpoints, DTOs

Angular files shown next to the code, here with Angular Material as component library. Generated tsconfig.json and index.html, auth token handling and CORS not counted. pom.xml not counted on either side: both projects have one, PrimeFaces adds a single dependency.

Read the Docs
PrimeFaces
customers.xhtml CustomerView.java
<h:form>
    <p:dataTable var="c" value="#{customerView.customers}"
                 paginator="true" rows="10" sortMode="multiple">
        <p:column field="name" headerText="Name"/>
        <p:column field="country" headerText="Country"/>
        <p:column field="status" headerText="Status">
            <p:tag value="#{c.status}"/>
        </p:column>
    </p:dataTable>
</h:form>
The same table with Angular + component library
customers.component.ts CustomerResource.java CustomerDto.java main.ts package.json angular.json
import { AfterViewInit, Component, inject, viewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
import { MatInputModule } from '@angular/material/input';
import { MatChipsModule } from '@angular/material/chips';

export interface Customer {
    name: string;
    country: string;
    status: string;
}

@Component({
    selector: 'app-customers',
    imports: [MatTableModule, MatSortModule, MatPaginatorModule, MatInputModule, MatChipsModule],
    template: `
        <mat-form-field>
            <input matInput placeholder="Search" (keyup)="filter($event)">
        </mat-form-field>
        <table mat-table [dataSource]="customers" matSort>
            <ng-container matColumnDef="name">
                <th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
                <td mat-cell *matCellDef="let c">{{ c.name }}</td>
            </ng-container>
            <ng-container matColumnDef="country">
                <th mat-header-cell *matHeaderCellDef mat-sort-header>Country</th>
                <td mat-cell *matCellDef="let c">{{ c.country }}</td>
            </ng-container>
            <ng-container matColumnDef="status">
                <th mat-header-cell *matHeaderCellDef mat-sort-header>Status</th>
                <td mat-cell *matCellDef="let c"><mat-chip>{{ c.status }}</mat-chip></td>
            </ng-container>
            <tr mat-header-row *matHeaderRowDef="columns"></tr>
            <tr mat-row *matRowDef="let row; columns: columns"></tr>
        </table>
        <mat-paginator [pageSize]="10"></mat-paginator>
    `
})
export class CustomersComponent implements AfterViewInit {

    private http = inject(HttpClient);
    private sort = viewChild.required(MatSort);
    private paginator = viewChild.required(MatPaginator);

    columns = ['name', 'country', 'status'];
    customers = new MatTableDataSource<Customer>();

    ngAfterViewInit() {
        this.customers.sort = this.sort();
        this.customers.paginator = this.paginator();
        this.http.get<Customer[]>('/api/customers')
            .subscribe(data => this.customers.data = data);
    }

    filter(event: Event) {
        this.customers.filter = (event.target as HTMLInputElement).value.trim().toLowerCase();
    }
}

Ready to build something amazing?

Join thousands of developers who trust PrimeFaces for their Jakarta Faces applications.