JavaServer Faces

Toggle view

A simple ViewController for JSF

Very early Apache Shale came up with the idea of providing a view controller that allowed to execute dedicated methods (annotated, etc.) during various JSF life-cycle (phase) events for doing initialization work upfront for example. As Shale was hibernated, Apache Orchestra stepped in and added many more useful features.
Both frameworks are based on the idea of having a dedicated page bean (a JSF managed bean per view) that would control important processing steps for the entire view (page).
It requires following naming conventions in order to associate a page bean to a view, optionally a view controller mapper provided the ability of explicitely associating page beans and views.

Read more

The dreading timezone issue with JSF and how it hits you again with daylights saving

JSF is converting all date/datetime types into GMT base for rendering. This can cause a date offset of n-hours to be shown depending on the timezone you are in. You have 2 choices to deal with it:
Either you implement an application wide (global) date converter as described here or you add the timezone attribute to each of the convertDateTime tags.

Read more

Extending the FacesContext (and using a Faces Factory)

JavaServer Faces has always been sold as a piece of flexible and extensible code. It really is. Through its factory facilities you can bend and twist that web framework until it fits. Today I tried to resolve something that has bothered me a long time. For a showcase I have implemented a few supporting lines of code that come handy in lots of places. When prototyping something, that code often ends up in some abstract base class from which managed bean are subclassed or it even ends up in some “helper” class with static methods. In the end you don’t feel that it is at the right place.

Read more

Close a PrimeFaces dialog when no validation messages are available

I’m posting this to memorize a PrimeFaces pattern for reuse. The visibility of PrimeFaces dialog panel can be controlled using the visible attribute. JavaScript widget.open() or widget.hide() modify the visibility state as well.

<p:dialog widgetVar="widget" id="dialog"
	visible="#{not empty facesContext.maximumSeverity}">
	<f:facet name="header">
		<h:outputText value="Form" />
	</f:facet>
	<h:form>
		<h:panelGrid columns="3">
			<h:outputLabel for="input" value="Input" />
			<h:inputText id="input" label="Input" required="true" value="VALUE" />
			<h:message for="input" />
		</h:panelGrid>

		<h:panelGroup>
			<!-- update the form for the case we get validation errors -->
			<p:commandButton value="Update" update="dialog"/>
		</h:panelGroup>
	</h:form>
</p:dialog>

Change appearance of UI elements based on validation results

In my previous post I showed how simple it is to control rendering of UI elements based on validation results.

Today I want to put this idea a little bit further and add another convenicent facelets tag that will allow to assign a style class to any UI element based on validation results. In order to create an appealing form that clearly indicates the position where validation fails very often you see that input elements change their visual appearance based on the validation state. For example any invalid input element is shown with red background. With no component you end up with tedious (or complex) EL expressions that are assigned to the styleClass attribute.

To make that concept reusable and simple to apply I show how to create a facelets tag setStyleClassIfMessages that evaluates the faces messages available for a specific component, looks for the message with highest severity and uses the severity to apply a CSS style class to any component.



	
	

The tag implementation is quite straightforward, I have stripped some obvious details from the code.

public class SetStyleClassIfMessagesTagHandler extends MessagesTagHandler {

	protected final TagAttribute[] classAttributes = new TagAttribute[5];

	public SetStyleClassIfMessagesTagHandler(TagConfig config) {
		super(config);
		classAttributes[0] = getAttribute("passedClass");
		classAttributes[FacesMessage.SEVERITY_INFO.getOrdinal() + 1] = getAttribute("infoClass");
		classAttributes[FacesMessage.SEVERITY_WARN.getOrdinal() + 1] = getAttribute("warnClass");
		classAttributes[FacesMessage.SEVERITY_ERROR.getOrdinal() + 1] = getAttribute("errorClass");
		classAttributes[FacesMessage.SEVERITY_FATAL.getOrdinal() + 1] = getAttribute("fatalClass");
	}

	public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
			ELException {
		if (forAttribute != null) {
			UIComponent forComponent = getForComponent(ctx.getFacesContext(), forAttribute.getValue(ctx), parent);
			if (forComponent != null) {
				setMaximumSeverityStyleClass(ctx, forComponent);
			} else {
				LOGGER.warn("No component {} found.", forAttribute.getValue(ctx));
			}
		} else if (parent != null) {
			setMaximumSeverityStyleClass(ctx, parent);
		}
	}

	private void setMaximumSeverityStyleClass(FaceletContext ctx, UIComponent forComponent) {
		FacesMessage message = findMostSevereMessage(ctx.getFacesContext(), forComponent);
		if (PropertyUtils.isWriteable(forComponent, STYLE_CLASS_PROPERTY_NAME)) {
			TagAttribute messageStyleClass = message == null ? classAttributes[0] : classAttributes[message
					.getSeverity().getOrdinal() + 1];
			try {
				StringBuilder newStyleClass = new StringBuilder(messageStyleClass == null ? "" : messageStyleClass
						.getValue(ctx));
				// read style and remove style class from previous post-back,
				// then set new style class
				String oldStyleClass = (String) PropertyUtils
						.getSimpleProperty(forComponent, STYLE_CLASS_PROPERTY_NAME);

				Set<String> classNames = new HashSet<String>();
				for (TagAttribute classAttribute : classAttributes) {
					if (classAttribute != null) {
						classNames.add(classAttribute.getValue());
					}
				}
				StringTokenizer tokenizer = new StringTokenizer(oldStyleClass == null ? "" : oldStyleClass, " ");
				while (tokenizer.hasMoreElements()) {
					String styleClass = tokenizer.nextToken();
					if (classNames.contains(styleClass)) {
						continue;
					}
					newStyleClass.append(' ').append(styleClass);
				}
				PropertyUtils.setSimpleProperty(forComponent, STYLE_CLASS_PROPERTY_NAME, newStyleClass.toString());
			} catch (Exception e) {
				throw new FaceletException(e);
			}
		}
	}
}

Control rendering of UI elements based on validation results

In this post I describe how I tackled a problem that I faced quite often in the past. I need control over rendering a part of the UI based on validation results. E.g. when there is a validation message available for a certain input component then render a tooltip (containing a validation message) for the component.

JSF components offer a boolean rendered attribute that allows controling the rendering process. For complex decisions that means that a method on a managed bean would calculate the resulting state.

Exactly that was the solution that I was starting with for the problem described above.

public Map<String, Boolean> getHasMessages() {
	HashMap<String, Boolean> flags = new HashMap<String, Boolean>(1);
	Iterator<String> messages = FacesContext.getCurrentInstance().getClientIdsWithMessages();
	while (messages.hasNext()) {
		flags.put(messages.next(), Boolean.TRUE);
	}
	return flags;
}
<h:inputText label="Amount" id="amount" >
	<p:tooltip for="amount" showEvent="focus" hideEvent="blur" rendered="#{mbean.hasMessages['amount']}">
		<h:message for="amount" />
	</p:tooltip>
</h:inputText>

So I had a simple solution working fairly quickly. But let’s face it: It’s a clumsy solution that is hard to reuse and breaks when the id of the ui container around the input is changed.

To improve that, I decided that this requires a component that would be simple to reuse. As I’m using Facelets for the view I updated my knowledge of their support for custom components.

public class IfMessagesTagHandler extends TagHandler {
	private static final Logger LOGGER = LoggerFactory.getLogger(IfMessagesTagHandler.class);
	private static final String FOR_ATTRIBUTE_NAME = "for";
	private final TagAttribute forAttribute;

	public IfMessagesTagHandler(TagConfig config) {
		super(config);
		forAttribute = getAttribute(FOR_ATTRIBUTE_NAME);
	}

	public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
			ELException {
		if (forAttribute != null) {
			UIComponent forComponent = getForComponent(ctx.getFacesContext(), forAttribute.getValue(ctx), parent);
			if (forComponent != null) {
				if (ctx.getFacesContext().getMessages(forComponent.getClientId(ctx.getFacesContext())).hasNext()) {
					this.nextHandler.apply(ctx, parent);
				}
			} else {
				LOGGER.warn("No component {} found.", forAttribute.getValue(ctx));
			}
		} else if (parent != null) {
			if (ctx.getFacesContext().getMessages(parent.getClientId(ctx.getFacesContext())).hasNext()) {
				this.nextHandler.apply(ctx, parent);
			}
		}
	}
}

The above implementation accepts the optional attribute for that refers to a component id for which it tests if messages are available. In case the for attribute was not passed the tag would assume that the component to test for messages is the enclosing parent tag.

To register the tag handler a facelets tag library descriptor in META-INF is required.

<?xml version="1.0"?>

<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">

<facelet-taglib>
	<namespace>http://martinahrer.at/jsf/facelets/blueprint</namespace>
	<tag>
		<tag-name>ifMessages</tag-name>
		<handler-class>at...view.facelets.IfMessagesTagHandler</handler-class>
	</tag>
</facelet-taglib>

A client would use that tag as:

<h:inputText label="Amount" id="amount" value="#{expenseSlipFormController.entity.amount}" required="true">
	<b:ifMessages >
		<p:tooltip for="amount" showEvent="focus" hideEvent="blur" style="myStyle">
			<h:message for="amount" />
		</p:tooltip>
	</b:ifMessages>
</h:inputText>

PhaseListener rendering a binary document (PDF)

Inspired by Cagatay Civici’s idea of having a phase listener rendering images I decided to replace my PDF rendering servlets from a product that I’m currently working on.

At the end of the RESTORE_VIEW phase the listener would decode the request URL and extract a managed property reference expression, create an EL expression and get the byte array for the binary document.

	public void afterPhase(PhaseEvent event) {
		String viewId = event.getFacesContext().getViewRoot().getViewId();
		if (viewId.startsWith(PDF_STREAM_VIEW_ID_PREFIX)) {
			String streamExpression = StringUtils.substringAfter(viewId, PDF_STREAM_VIEW_ID_PREFIX);
			ELContext elContext = event.getFacesContext().getELContext();

			byte[] bytes = (byte[]) event.getFacesContext().getApplication().getExpressionFactory()
					.createValueExpression(elContext, "#{" + streamExpression + "}", byte[].class).getValue(elContext);
			if (bytes != null) {
				HttpServletResponse response = (HttpServletResponse) event.getFacesContext().getExternalContext()
						.getResponse();
				response.setContentType("application/pdf");
				response.setContentLength(bytes.length);

				try {
					response.getOutputStream().write(bytes);
				} catch (Exception exception) {
					LOG.error(exception.getMessage());
				}
			}
			event.getFacesContext().responseComplete();
		}
	}

To display the binary document a matching URL needs to be generated. Here the <object> tag is used for displaying a PDF document. The URL part after “/pdf/stream/” is used as a part of a value expression for referencing the actual PDF binary document (here it is managedBeanName.propertyName).


	<object
		data="#{facesContext.externalContext.requestContextPath}/#{facesContext.externalContext.requestServletPath}/pdf/stream/managedBeanName.propertyName"
			type="application/pdf" />

JSF Challenge

I have started to work on a new internal project that eventually sometime might turn into a product. It’s relies in JavaServer Faces for the web UI layer. For deepening my knowledge of the JSF technology (after I haven’t worked with JSF for almost a year) I have decided to start my JSF Challenge that would accompany my project development.
My JSF Challenge means that whatever the problem is that has to be solved I would tackle it directly using no workarounds but would rather try to utilize the most efficient features of JSF.
Also that would mean that for many of these solutions I would strive to create solutions that are re-usable for other projects in future as well. So this would for example also involve creating custom JSF components and using more of the JSF APIs than I did in the past.

WebSphere 6.1 and JSF 1.2

The last week I was asked to migrate a JSF 1.2 / Seam 2.x based web app to a WebSphere 6.1 application server. I hadn’t worked with WebSphere in a while, though I knew what I had to expect.

IBM still hasn’t released a JavaEE 5 compliant product, so the 6.1 version is still on J2SE 1.4 with JSP 2.0 and Java Servlet 2.4. Also it has a built-in JSF 1.1.

The application to be migrated luckly is using facelets as its view technology otherwise I would have been screwed anyway. JSF 1.2 itself doesn’t rely on the servlet spec 2.4 so a good chance to get it done.

To run JSF 1.2 the following is required:

  1. Make sure that you WebSphere installation is at least running with fixpack 13!
  2. Create a shared library containing JSF RI 1.2 jars (jsf-api.jar, jsf-impl.jar, el-api-1.0.jar, el-impl-1.0.jar)
  3. Create a classloader with application classes loaded first and bind it to the shared library above
  4. Set the classloading policy as application classes loaded first and assign the classloader

Implementing Logon Forms with JSF

Implementing a logon form with JSF has been alwys a bit troublesome. This requires form input elements with input names j_username and j_password. With the JSF RI this is hard to accomplish. So you typically end up with including the Apache MyFaces Tomahawk components which offer a forceId attribute.





If you are using other popular JSF component libraries, things might get a bit more handy (you can avoid including tomahawk just for fully controlling the input ids!).

With Myfaces Trinidad (Oracle ADF Faces) it is pretty easy, ids are accepted as they are:





With JBoss Rich-Faces use the a4j:form tag:


	
	
	
	

green red blue grey