Advanced Faces

Back

Loading concept...

🎭 Jakarta EE Advanced Faces: The Smart Restaurant Kitchen

Imagine your web app is a busy restaurant. The kitchen (server) and dining area (browser) need to work together perfectly. Advanced Faces is like having a super-smart system that makes everything run smoothly!


🍳 Our Restaurant Story

Think of a restaurant where:

  • The Kitchen = Your Server (where data lives)
  • The Dining Area = Your Browser (what users see)
  • Waiters = AJAX Requests (carrying info back and forth)
  • The Menu = Resources (images, styles, scripts)
  • Customer Journey = Faces Flow (ordering → eating → paying)

Let’s explore each part of this smart restaurant!


1. ⚡ Ajax in Faces: The Speed Waiter

What’s the Problem?

Imagine ordering a drink and the ENTIRE restaurant closes, rebuilds itself, then reopens just to bring you water. Crazy, right? That’s what happens without Ajax - the whole page refreshes!

The Magic Solution

Ajax in Faces is like having a speed waiter. You ask for water, and ONLY the water arrives. Everything else stays exactly the same!

How It Works

<h:commandButton value="Get Water">
  <f:ajax execute="@this"
          render="drinkArea"/>
</h:commandButton>

<h:panelGroup id="drinkArea">
  Your drink appears here!
</h:panelGroup>

The Two Magic Words

Word What It Does
execute What to SEND to kitchen
render What to UPDATE on table

Quick Examples

<!-- Update just one thing -->
<f:ajax render="myOutput"/>

<!-- Update multiple things -->
<f:ajax render="area1 area2"/>

<!-- Update everything in a form -->
<f:ajax render="@form"/>

🎯 Special Keywords

  • @this → Just this button/input
  • @form → The whole form
  • @all → Everything on page
  • @none → Nothing at all

2. 🧩 Partial Page Rendering: The Smart Update

The Restaurant Analogy

Instead of replacing your ENTIRE table setting when you spill sauce, you only replace the dirty napkin. Smart, right?

How PPR Works

graph TD A["User Clicks Button"] --> B["Only Selected Parts Sent"] B --> C["Server Processes"] C --> D["Only Changed Parts Return"] D --> E["Page Updates Smoothly"]

Real Example

<h:form>
  <h:inputText id="name"
               value="#{bean.name}">
    <f:ajax event="keyup"
            render="greeting"/>
  </h:inputText>

  <h:outputText id="greeting"
    value="Hello, #{bean.name}!"/>
</h:form>

What happens:

  1. You type in the text box
  2. Only the greeting updates
  3. Rest of page stays put!

Events You Can Listen To

Event When It Fires
click User clicks
keyup Key released
change Value changes
blur Focus leaves

3. 📦 Faces Resource Handling: The Supply Room

The Problem

Your restaurant needs plates, napkins, decorations. Where do you keep them? How do you find them?

The Solution

Faces has a special supply room at:

resources/
├── images/
│   └── logo.png
├── css/
│   └── styles.css
└── js/
    └── app.js

How to Use Resources

<!-- Load an image -->
<h:graphicImage library="images"
                name="logo.png"/>

<!-- Load CSS -->
<h:outputStylesheet library="css"
                    name="styles.css"/>

<!-- Load JavaScript -->
<h:outputScript library="js"
                name="app.js"/>

Why This Is Awesome

  1. Version Control - Resources can have versions
  2. Caching - Browser remembers them
  3. Organization - Everything in one place

Resource URL Pattern

/javax.faces.resource/logo.png?ln=images

The browser can cache this! Fast loading!


4. 🚂 Faces Flow: The Customer Journey

The Restaurant Journey

When you visit a restaurant:

  1. Enter → Get seated
  2. Order food
  3. Eat
  4. Pay bill
  5. Leave

Each step follows the previous. You can’t pay before ordering!

What is Faces Flow?

It’s a way to create multi-step wizards or processes that guide users through a journey.

Flow Structure

graph TD A["Start: Enter Info"] --> B["Step 2: Confirm"] B --> C["Step 3: Payment"] C --> D["End: Thank You"] B -.-> A C -.-> B

Creating a Flow

Step 1: Define the flow (checkout-flow.xml)

<faces-flow>
  <flow-definition id="checkout">
    <start-node>cart</start-node>

    <view id="cart">
      <vdl-document>/checkout/cart.xhtml</vdl-document>
    </view>

    <view id="shipping">
      <vdl-document>/checkout/shipping.xhtml</vdl-document>
    </view>

    <view id="payment">
      <vdl-document>/checkout/payment.xhtml</vdl-document>
    </view>

    <return id="complete">
      <from-outcome>/thankyou</from-outcome>
    </return>
  </flow-definition>
</faces-flow>

Step 2: Navigate between steps

<!-- Go to next step -->
<h:commandButton value="Next"
                 action="shipping"/>

<!-- Go back -->
<h:commandButton value="Back"
                 action="cart"/>

Flow Scope

Variables live ONLY during the flow:

@Named
@FlowScoped
public class CheckoutBean {
    private String shippingAddress;
    // Lives only during checkout flow!
}

5. 🌍 Internationalization (i18n): Speaking Every Language

The Restaurant Speaks Many Languages!

Imagine customers from Japan, France, Brazil all visiting. The menu should show in their language!

Setting Up Languages

Step 1: Create message files

messages_en.properties  (English)
messages_es.properties  (Spanish)
messages_ja.properties  (Japanese)

Step 2: Add translations

# messages_en.properties
greeting=Hello
goodbye=Goodbye
order.button=Place Order

# messages_es.properties
greeting=Hola
goodbye=Adiós
order.button=Hacer Pedido

Step 3: Configure in faces-config.xml

<application>
  <locale-config>
    <default-locale>en</default-locale>
    <supported-locale>es</supported-locale>
    <supported-locale>ja</supported-locale>
  </locale-config>
  <resource-bundle>
    <base-name>messages</base-name>
    <var>msg</var>
  </resource-bundle>
</application>

Step 4: Use in pages

<h:outputText value="#{msg.greeting}"/>
<h:commandButton value="#{msg['order.button']}"/>

Changing Language Dynamically

@Named
public class LanguageBean {
    public void changeToSpanish() {
        FacesContext.getCurrentInstance()
            .getViewRoot()
            .setLocale(new Locale("es"));
    }
}
<h:commandLink action="#{languageBean.changeToSpanish}">
  Español
</h:commandLink>

6. 🪟 Client Window Scope: Multiple Tabs, No Confusion!

The Problem

Imagine you’re at a restaurant with two menus open (two browser tabs). You order pizza on Menu 1 and pasta on Menu 2. But both orders go to the same kitchen!

Without Client Window Scope, the kitchen (server) gets confused. Which order is which?

The Solution

Each browser tab gets its own “table number” (window ID). The kitchen knows exactly which order belongs to which table!

How It Works

graph TD A["Tab 1: Window ID = abc123"] --> S["Server"] B["Tab 2: Window ID = xyz789"] --> S S --> C["Separate Data for Each"]

Enabling Client Window

In web.xml:

<context-param>
  <param-name>
    jakarta.faces.CLIENT_WINDOW_MODE
  </param-name>
  <param-value>url</param-value>
</context-param>

Modes Available:

  • url - Window ID in URL (recommended)
  • client - Window ID in hidden field
  • none - Disabled

Using Window Scoped Beans

@Named
@WindowScoped  // One instance per tab!
public class ShoppingCart {
    private List<Item> items;
    // Each tab has its own cart!
}

How URL Looks

/myapp/page.xhtml?jfwid=abc123

The jfwid parameter identifies the window!


🎯 Quick Comparison Table

Feature What It Does Restaurant Analogy
Ajax in Faces Partial updates Speed waiter
Partial Page Rendering Update only what changed Replace dirty napkin only
Resource Handling Manage images/CSS/JS Organized supply room
Faces Flow Multi-step processes Customer journey
Internationalization Multiple languages Menu in every language
Client Window Scope Tab isolation Separate table numbers

🚀 Putting It All Together

Here’s a mini checkout flow using ALL concepts:

<!-- checkout.xhtml -->
<h:form>
  <!-- i18n: Multi-language -->
  <h:outputText value="#{msg.checkout.title}"/>

  <!-- Resource: Logo -->
  <h:graphicImage library="images"
                  name="logo.png"/>

  <!-- Ajax: Real-time total -->
  <h:inputText id="quantity"
               value="#{cart.quantity}">
    <f:ajax render="total"/>
  </h:inputText>

  <!-- Partial Render: Just the total -->
  <h:outputText id="total"
    value="#{cart.total}"/>

  <!-- Flow: Move to payment -->
  <h:commandButton value="#{msg.next}"
                   action="payment"/>
</h:form>

🧠 Remember This!

  1. Ajax = Update parts, not whole page
  2. PPR = Render only what changed
  3. Resources = Organized file management
  4. Flow = Multi-step wizard
  5. i18n = Speak every language
  6. Client Window = Tab isolation

You’re now a Faces expert! Each piece makes your web app faster, smarter, and more user-friendly. Like a perfectly run restaurant where everything just works! 🎉

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.