Skip to content
CMO & CTO
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

  • Digital Experience
    • Experience Strategy
    • Experience-Driven Commerce
    • Multi-Channel Experience
    • Personalization & Targeting
    • SEO & Performance
    • User Journey & Behavior
  • Marketing Technologies
    • Analytics & Measurement
    • Content Management Systems
    • Customer Data Platforms
    • Digital Asset Management
    • Marketing Automation
    • MarTech Stack & Strategy
    • Technology Buying & ROI
  • Software Engineering
    • Software Engineering
    • Software Architecture
    • General Software
    • Development Practices
    • Productivity & Workflow
    • Code
    • Engineering Management
    • Business of Software
    • Code
    • Digital Transformation
    • Systems Thinking
    • Technical Implementation
  • About
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

JSF for real-world teams: Component Power with Caveats

Posted on July 12, 2008October 17, 2025 By Luis Fernandez
\n\n\n\n\n

�JSF is like a power drill. It makes holes fast, but it will also make a hole in your desk if you let it.�

\n\n\n\n

Why teams keep picking JSF

\n\n\n\n

When folks ask me why JavaServer Faces keeps showing up on enterprise project plans, the answer is simple. Components. Managers like the promise of drag and drop screens. Developers like the idea of reusable widgets with validators, converters, and navigation built in. UI devs get Facelets templates and tag files. Ops teams get to run everything on Tomcat or GlassFish with out of the box support from the Java EE stack. It checks many boxes after a short demo.

\n\n\n\n

That demo is not a lie. With JSF 1.2 and Facelets, you can crank out forms, reuse layouts, and wire Ajax with RichFaces or ICEfaces. The moment you add real traffic, shared dev branches, and three releases running side by side, you discover the other side of the story. JSF is powerful, and power always comes with knobs. If no one owns the knobs, the app starts to feel sticky.

\n\n\n\n

A week in the life of a JSF crew

\n\n\n\n

Day one you sketch a flow in faces-config.xml, set up a couple of backing beans, and drop in Facelets templates. Day three you bring in Ajax4jsf and start partial updates. By Friday your signup flow works, validations fire, and QA is happy. Then the next sprint hits. Marketing wants a dashboard that refreshes parts of the page, ops wants lower memory on each node, and the team needs clean URLs for campaigns. The same framework that felt smooth now requires decisions about state saving, scope, and partial rendering.

\n\n\n\n

This is where teams either lean into the strengths of JSF or start fighting it. The trick is to know which levers matter and set a few ground rules that keep screens predictable.

\n\n\n\n

Deep dive 1: State saving without surprises

\n\n\n\n

JSF keeps a component tree for each view. That tree can live on the server or ride along the client. Default server side mode is safe, but it eats memory as your user count grows. Client side lowers memory but grows the page size and makes diffs noisy. Pick one and document why. If you go client side, turn on compression, and watch payloads.

\n\n\n\n
<!-- web.xml -->\n<context-param>\n  <param-name>javax.faces.STATE_SAVING_METHOD</param-name>\n  <param-value>server</param-value>  <!-- or client -->\n</context-param>\n\n<context-param>\n  <param-name>com.sun.facelets.SKIP_COMMENTS</param-name>\n  <param-value>true</param-value>\n</context-param>
\n\n\n\n

Memory also depends on scope. A bean in session feels convenient until you have thousands of users. Keep most beans in request or view scope. For view scope with JSF 1.2 and Facelets, many teams use a simple pattern with component bindings or a map inside the view root. If you are on Seam, you get a clean view scope but that is another topic.

\n\n\n\n
<managed-bean>\n  <managed-bean-name>signupBean</managed-bean-name>\n  <managed-bean-class>com.example.SignupBean</managed-bean-class>\n  <managed-bean-scope>request</managed-bean-scope>\n</managed-bean>
\n\n\n\n

Tip: Profile memory with a real load. One user on a dev box will hide server side state problems. Open two browsers, fill a few forms, hit back, and watch session size.

\n\n\n\n

Deep dive 2: Ajax with RichFaces and ICEfaces

\n\n\n\n

Plain JSF does full page postbacks. That is fine for admin screens, not so great for dashboards. RichFaces gives you partial page rendering with a small tag set. ICEfaces pushes incremental updates with a slightly different model. Both work, but they shape how you code and test.

\n\n\n\n
<!-- Facelets page using RichFaces -->\n<ui:composition xmlns="http://www.w3.org/1999/xhtml"\n  xmlns:f="http://java.sun.com/jsf/core"\n  xmlns:h="http://java.sun.com/jsf/html"\n  xmlns:ui="http://java.sun.com/jsf/facelets"\n  xmlns:a4j="http://richfaces.org/a4j"\n  xmlns:rich="http://richfaces.org/rich">\n\n  <h:form id="form">\n    <h:panelGroup id="pricePanel">\n      <h:outputText value="#{cartBean.total}"/>\n    </h:panelGroup>\n\n    <h:inputText value="#{cartBean.coupon}"/>\n    <a4j:commandButton value="Apply"\n        action="#{cartBean.applyCoupon}"\n        reRender="pricePanel"\n        oncomplete="console.log('updated')"/>\n  </h:form>\n</ui:composition>
\n\n\n\n

Keep partial updates tight. Re render the smallest area you can. Avoid nesting many forms. Watch for duplicate component ids when you include fragments. If tests start failing only on Fridays, look for Ajax areas that rerender a parent component. That can reset child state and confuse users.

\n\n\n\n

Pick one Ajax library for the app. Mixing RichFaces and ICEfaces in the same page gets messy. Both touch the request and response in special ways. Your future self will thank you for a single approach.

\n\n\n\n

Deep dive 3: Validation, conversion, and messages that help

\n\n\n\n

JSF validators and converters are a sweet spot. They live with the component, they run before your action method, and they keep the code honest. The miss is usually in the messages. Users do not enjoy stack traces in a growl panel.

\n\n\n\n
<h:form>\n  <h:messages errorClass="err" infoClass="ok"/>\n\n  <h:inputText id="email" value="#{userBean.email}">\n    <f:validator validatorId="emailValidator"/>\n  </h:inputText>\n\n  <h:commandButton value="Create" action="#{userBean.create}"/>\n</h:form>
\n\n\n\n
// EmailValidator.java\n@FacesValidator("emailValidator")\npublic class EmailValidator implements Validator {\n  public void validate(FacesContext ctx, UIComponent c, Object value) throws ValidatorException {\n    String s = value == null ? "" : value.toString();\n    if (!s.matches(".+@.+\\\\..+")) {\n      FacesMessage m = new FacesMessage("Please enter a valid email");\n      m.setSeverity(FacesMessage.SEVERITY_ERROR);\n      throw new ValidatorException(m);\n    }\n  }\n}
\n\n\n\n

Keep messages in a bundle and reference it in faces config so your UI team can tune the tone without touching code.

\n\n\n\n
<!-- faces-config.xml -->\n<application>\n  <message-bundle>com.example.messages</message-bundle>\n</application>
\n\n\n\n

Bonus: Wrap common patterns into small composite tags with Facelets tag files. A field with label input help and message can be one tag. That removes copy paste bugs across forms.

\n\n\n\n

Practical setup that keeps teams happy

\n\n\n\n

Use Facelets for everything. JSP works but template reuse is nicer with Facelets. Pair JSF with Spring for services and data access and wire beans through EL resolvers. Keep navigation simple. Most screens can use postback to the same view and outcome based buttons for branching.

\n\n\n\n
<!-- faces-config.xml navigation -->\n<navigation-rule>\n  <from-view-id>/signup.xhtml</from-view-id>\n  <navigation-case>\n    <from-outcome>success</from-outcome>\n    <to-view-id>/welcome.xhtml</to-view-id>\n    <redirect />\n  </navigation-case>\n</navigation-rule>
\n\n\n\n

On the tool side, NetBeans 6.1 and Eclipse Ganymede both offer decent JSF support. The Facelets plugin is worth the install if you live in Eclipse. For servers, GlassFish v2 has smooth JSF and Facelets support, and Tomcat 6 is fine for lighter stacks.

\n\n\n\n

Do not skip filters. Add a character encoding filter and set everything to UTF 8. Broken accents in user names can ruin a launch day.

\n\n\n\n
<filter>\n  <filter-name>encodingFilter</filter-name>\n  <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>\n  <init-param>\n    <param-name>charset</param-name>\n    <param-value>UTF-8</param-value>\n  </init-param>\n</filter>\n<filter-mapping>\n  <filter-name>encodingFilter</filter-name>\n  <url-pattern>/*</url-pattern>\n</filter-mapping>
\n\n\n\n

What JSF teaches you even if you move on later

\n\n\n\n

JSF is opinionated about state, events, and components. That mental model sticks with you. You start to think in trees, scopes, and clean boundaries between view and action. You learn to respect page size, and you learn that a nice component can hide a heavy cost. These are lessons that apply whether next month you touch Flex, GWT, or something lighter.

\n\n\n\n

So is JSF right for every team right now. Not really. If you need a tiny public site, keep it simple. If you are building form heavy apps with lots of reuse and a team that will share components, JSF with Facelets is a strong pick. Go in with eyes open, set your knobs early, and write down the rules. The power is real. The caveats are too.

\n\n\n\n

Created on 2008 07 12

\n
Engineering Management Software Architecture Software Engineering

Post navigation

Previous post
Next post
  • Digital Experience (94)
    • Experience Strategy (19)
    • Experience-Driven Commerce (5)
    • Multi-Channel Experience (9)
    • Personalization & Targeting (21)
    • SEO & Performance (10)
  • Marketing Technologies (92)
    • Analytics & Measurement (14)
    • Content Management Systems (45)
    • Customer Data Platforms (4)
    • Digital Asset Management (8)
    • Marketing Automation (6)
    • MarTech Stack & Strategy (10)
    • Technology Buying & ROI (3)
  • Software Engineering (310)
    • Business of Software (20)
    • Code (30)
    • Development Practices (52)
    • Digital Transformation (21)
    • Engineering Management (25)
    • General Software (82)
    • Productivity & Workflow (30)
    • Software Architecture (85)
    • Technical Implementation (23)
  • 2025 (12)
  • 2024 (8)
  • 2023 (18)
  • 2022 (13)
  • 2021 (3)
  • 2020 (8)
  • 2019 (8)
  • 2018 (23)
  • 2017 (17)
  • 2016 (40)
  • 2015 (37)
  • 2014 (25)
  • 2013 (28)
  • 2012 (24)
  • 2011 (30)
  • 2010 (42)
  • 2009 (25)
  • 2008 (13)
  • 2007 (33)
  • 2006 (26)

Ab Testing Adobe Adobe Analytics Adobe Target AEM agile-methodologies Analytics architecture-patterns CDP CMS coding-practices content-marketing Content Supply Chain Conversion Optimization Core Web Vitals customer-education Customer Data Platform Customer Experience Customer Journey DAM Data Layer Data Unification documentation DXP Individualization java Martech metrics mobile-development Mobile First Multichannel Omnichannel Personalization product-strategy project-management Responsive Design Search Engine Optimization Segmentation seo spring Targeting Tracking user-experience User Journey web-development

©2025 CMO & CTO | WordPress Theme by SuperbThemes