🎭 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:
- You type in the text box
- Only the greeting updates
- 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
- Version Control - Resources can have versions
- Caching - Browser remembers them
- 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:
- Enter → Get seated
- Order food
- Eat
- Pay bill
- 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 fieldnone- 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!
- Ajax = Update parts, not whole page
- PPR = Render only what changed
- Resources = Organized file management
- Flow = Multi-step wizard
- i18n = Speak every language
- 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! 🎉
