Archive for the ‘Web’ Category

JSF, Iterating with tomahawk radio buttons, t:datalist, a4j:repeat

The standard JSF radio buttons h:selectOneRadio render a load of old school html (i.e. they use table tags to do layout, (all a bit 1996)).

e.g. JSF h:selectOneRadio tag

<h:selectOneRadio id="aRadio">
	<f:selectItems value="#{radioOptions.items}" />
</h:selectOneRadio>

Code for #{radioOptions}

import java.util.ArrayList;
import java.util.List;

import javax.faces.model.SelectItem;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

@Name("radioOptions")
@Scope(ScopeType.APPLICATION)
public class RadioOptions
{
	public List<SelectItem> items = new ArrayList<SelectItem>();

	public RadioOptions()
	{
		items.add(new SelectItem("1", "label 1"));
		items.add(new SelectItem("2", "label 2"));
		items.add(new SelectItem("3", "label 3"));
	}

	public List<SelectItem> getItems()
	{
		return items;
	}

	public void setItems(List<SelectItem> items)
	{
		this.items = items;
	}
}

Note: I’m using jboss seam in the example above, but you could easily remove the seam annotations and define the bean in using jsf managed beans or faces config etc. Also the examples here are a bit mickey mouse and could be better.

Under JSF 1.2 will be rendered as

<table id="myForm:aRadio">
	<tr>
		<td>
			<input type="radio" name="myForm:aRadio" id="myForm:aRadio:0" value="1" />
			<label for="myForm:aRadio:0">Label 1</label>
		</td>
		<td>
			<input type="radio" name="myForm:aRadio" id="myForm:aRadio:1" value="2" />
			<label for="myForm:aRadio:1">Label 2</label>
		</td>
		<td>
			<input type="radio" name="myForm:aRadio" id="myForm:aRadio:2" value="3" />
			<label for="myForm:aRadio:2">Label 3</label>
		</td>
	</tr>
</table>

Anyway this limitation is well known and as a result we’ve been using the apache tomahawk t:selectOneRadio (using the layout=”spread” attribute) and t:radio tags to provide more flexible layouts which can be styled by css.

Iterating through a list of select items

There are times when I want to render the radio buttons in a flexible fashion (offered by t:radio) using a loop tag such as t:dataList or a4j:repeat e.g.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:c="http://java.sun.com/jstl/core" xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:a4j="https://ajax4jsf.dev.java.net/ajax">
<f:view>
<h:form id="myForm">
	<!-- radio button, layout spread  -->
	<t:selectOneRadio id="myRadio" forceId="true" layout="spread">
		<f:selectItems value="#{radioOptions.items}" />
	</t:selectOneRadio>

	<!-- data list, loops through all the radio button options -->
	<t:dataList var="helper" value="#{radioOptions.items}" rowIndexVar="idx">
		<!-- example html, not constrained to table layout -->
		<h1>Heading</h1>
		<t:radio for="myRadio" index="#{idx}"/>
		<h1>Another Heading</h1>
	</t:dataList>
</h:form>
</f:view>
</html>

Unfortunately this doesn’t work and throws:

java.lang.IllegalStateException: Could not find component 'myRadio' (calling findComponent on component 'myForm:j_id3:0:j_id5')

The Fix:

I almost always forget this which is why im blogging about it,

<t:radio for="myRadio" index="#{idx}"/>

needs to be replaced with

<t:radio for=":myForm:myRadio" index="#{idx}"/>

The tomahawk t:radio component must have the fully qualified component name of the t:selectOneRadio name otherwise it cannot find it.

Since the form is defined as:

<h:form id="myForm">

:myForm needs to be prefixed to the for attribute of the t:radio giving :myForm:myRadio

I take absolutely no credit for this because its explained here and on the Myfaces wiki this article is merely a note to self.

Btw, the above works with a4j:repeat as well as t:datalist

Currently tomahawk isn’t working in JSF 2.0 which is a shame as we are looking to upgrade very soon. Hopefully a decent radio button will become part of JSF 2 at some point.

The tomahawk component library now works with JSF 2.0

Update: Fully Qualified JSF Name

A bit of searching around on the web took me to Lincoln Baxter’s blog where he mentions rendering components outside of the form and explains that the first “:” tells JSF to start looking from the very top of the JSF View Root. Thanks for that!

3D Secure and the PaReq field in Google Chrome & Safari Browsers

I recently had to implement the 3D Secure payment system.

In order to do this 3 fields must be sent to the 3D Secure ACS (Access Control Server)

  • MD
  • Term Url
  • PaReq (Payer authentication request)

Initally everything went well until we tested our pages in Google Chrome and Safari. Under both browsers the 3D Secure inline frame displayed the following message

“Error decoding PAREQ message”

A support page mentions that a PaReq contains newlines and that if any of these are missing the PaReq decoding will fail. The page also mentions that there are issues with Chrome and Safari but provides no solution.

So what is the problem?

The problem is indeed the newline.

In our markup we use and EL (Expression Language) to output the PaReq e.g.

<input type="hidden" name="PaReq" value="#{paReq}" />

If the PaReq returned a string such as

"I am
The PaReq
"

Note the quotes above mark the begining and end of the string. The string itself is terminated by a newline, in code it would be:

String paReq = "I am\nThe PaReq\n";

The browser should generate the following markup

<input type="hidden" name="PaReq" value="I am
The PaReq
" />

However Chrome and Safari generate the following markup (as both browsers do this I assume its a Webkit thing)

<input type="hidden" name="PaReq" value="I am
The PaReq" />

Note, the traililng newline has disappeared and herein lies the problem, the server fails to recoginse the PaReq as the trailing newline has gone (currently Chrome 4.0.429.89 contains the above bug).

The fix? Dont use Chrome or Safari, Only kidding

The way we overcame this was to use a “hidden” textarea

<textarea name="PaReq" style="display:none">#{paReq}</textarea>

Which renders

<textarea name="PaReq" style="display:none">I am
The PaReq
</textarea>

In all browsers and preserves the trailing newline. The style=”display:none” hides the textarea. Although this is crude it does provide a fix for Chrome and Safari.