Sonntag, 2. Januar 2011

How to Customize the Wicket Feedback Panel

Motivation

The standard FeedbackPanel of Wicket is showing the error and warning messages that occur when validating input fields, which is done by simply showing the text message. There are simple way to customize this standard FeedbackPanel by replacing the used CSS class.

However, sometimes it would be nice to show also the error-level of the message, e.g., by showing a corresponding icon together with the message. This is not possible with the FeedbackPanel given by Wicket. One way of doing that, is to provide a new implementation for the FeedbackPanel.

Realization of a new FeedbackPanel

A good starting point for an own implementation is to copy the source code of the standard FeedbackPanel class. It can be found in the package org.apache.wicket.markup.html.panel of the Wicket source code. Note, it would be much nicer to inherit code instead of copying it, but sometimes this is not possible, as Wicket is (too?) restrictive and much of the code is declared as final.

A new FeedbackPanel must inherit the marker interface IFeedback, as the original class does:

    public class FeedbackPanel extends Panel implements IFeedback

This marker interface is needed to guide the Wicket-Framework when the new FeedbackPanel component has to be rendered. Implementors of IFeedback are rendered after all non-feedback components. This is necessary because non-feedback components must create feedback messages before they can be processed by the feedback panel the FeedbackPanel.

The implementation uses a list view that shows all messages that have been gathered on the current page. For this purposes the FeedbackPanel uses the FeedbackMessagesModel of Wicket. The list view simply iterates through the message items when being rendered and attaches the content of the messages to the corresponding html markups used for the Feedback panel. The following code of the list view, which is used by the FeedbackPanel, provides this functionality:


private final class MessageListView extends ListView {
public final static String IMG_ERROR = "images/error.gif";
public final static String IMG_WARNING = "images/warning.gif";
public final static String IMG_NOTE = "images/note.gif";

private static final long serialVersionUID = 1L;

/**
* @see org.apache.wicket.Component#Component(String)
*/
public MessageListView(final String id, List msgs) {
super(id);
setDefaultModel(newFeedbackMessagesModel());
}

/**
* @see org.apache.wicket.markup.html.list.ListView
* #populateItem(org.apache.wicket.markup.html
* .list.ListItem)
*/
@Override
protected void populateItem(final ListItem listItem) {
final FeedbackMessage message = listItem.getModelObject();
message.markRendered();


WebMarkupContainer container = new WebMarkupContainer("message");
ContextImage image = new ContextImage("messageType", new
Model(getLevelImage(message.getLevel())));
container.add(image);
Component text = newMessageDisplayComponent("text", message);
container.add(text);

listItem.add(container);
}

public String getLevelImage(int level) {
String img = "";
if (level == FeedbackMessage.INFO ||
level == FeedbackMessage.DEBUG || level == FeedbackMessage.UNDEFINED) {
img = IMG_NOTE;
} else if (level == FeedbackMessage.WARNING) {
img = IMG_WARNING;
} else if (level == FeedbackMessage.ERROR ||
level == FeedbackMessage.FATAL) {
img = IMG_ERROR;
}
return img;
}
}


The method populateItem(…) does the main job. It gets the message text as well as the error-level of the message. The latter is got with the help of the method getLevelImage(). This method takes an integer and returns the path to an image which is representing the corresponding error-level of the message.

The html tags of the FeedbackPanel looks as follows and provides simply the tag structure for the list of the message content.


<table border="0" width="800px" cellpadding="0" cellspacing="0">
<tr wicket:id="message">
<td> </td>
<td width="20px">
<img wicket:id="messageType"
src="../../../../../../webapp/images/note.gif">
</td>

<td width="780px">
<span wicket:id="text" >
Message to show.
</span>
</td>
<td> </td>
</tr>
</table>


The rest of the implementation is as provided by the Wicket framework.

The source code for the example can be downloaded here (same sample project as in the previous blog article, for building and execution instructions refer to this article). The Java implementation is given by the file com/blogspot/m3g4h4rd/wicket/FeedbackPanel.java and the html markup can be found in com/blogspot/m3g4h4rd/wicket/FeedbackPanel.html. Note this the source code is published under Apache license 2.0.

Sonntag, 17. Oktober 2010

A Customized Validation Feedback Container for Wicket Form Components

Introduction

Wicket provides a set of mechanisms for validating entered data and displaying error messages caused by malformed user input. There are the following two feedback components (see Wicket 1.4.9) which help to show any validation errors.
The existing feedback component FormComponentFeedbackBorder org.apache.wicket.markup.html.form.validation.FormComponentFeedbackBorder helps to mark components that caused a validation error. It wraps another form component, e.g., a text field. In the case a text field causes a validation error, an asterisk (*) trailing the component indicates the validation error is shown, whereas the corresponding error message may be shown in a feedback panel (org.apache.wicket.markup.html.panel.FeedbackPanel), somewhere else on the same page. This article presents an improved feedback mechanism for validation errors replacing the FormComponentFeedbackBorder component and allowing one to handle more than component that cause together a validation error. This is often the case when having a form-based validation (see IFormValidator and Custom Form Validator). Furthermore, the presented component uses CSS classes to show validation errors.

The code for the Wicket component described in the following can be downloaded.

Motivation

Recently, I had to implement a system with a complex validation procedure for the entered data using Wicket. The customer had the following requirements:
  • The mandatory fields were denoted by an asterisk (*) which resulted in a confusion with the asterisk shown by a FormComponentFeedbackBorder component. The customer wanted rather to indicate a validation error occurred at a component using a different way than showing an asterisk, e.g., by showing components causing a validation error in a different background color.
  • Some of the validation steps included form-based validation. This means that several values together form a validation unit. The customer wanted that all fields involved in a form-based validation should visualize the validation error.
However, the requirements stated above could not be realized with the existing validation feedback components. Therefore, I was intensively looking for a Wicket component fulfilling these requirements. To the best of my knowledge, I did not find one that solved exactly this problem.

Extending the Feedback Mechanism

Consequently, I implemented a new Wicket component that solves the above issues and uses org.apache.wicket.markup.html.form.validation.FormComponentFeedbackBorder as a basis. The implementation provides a container which contains one or more form components that may cause validation errors. Any error is displayed by adding a CSS class visualizing the form element in the container that is responsible for showing the error. The default behavior is that if one or more component contained in the container causes a validation error, all components in the container display the error.

There are four properties that allow one to change this default behavior. The first two allow the user of the feedback component to define which set of components in the feedback container show a validation error:
  1. It is possible to define a set of components in the container which will show the errors occurring in the container. If this set is defined, any component that is not in this set will not show the error.
  2. There is a set of elements that explicitly define the components that will show an error, i.e., this is the opposite of 1. Note that either the first way of defining the visualizing components should be used or the second, but not both.
The second two properties allow the user of the feedback component to define which set of components in the feedback container is checked as source of a validation error:
  1. It is possible to define a set of components contained in the feedback container that will be ignored as a source of validation errors.
  2. As an opposite way, it is possible to define a set of components that is are observed as a source of validation errors. Note that either the first way of defining the components that are a source of validation errors should be used or the second way, but not both.
The components of the sets described above are referred to by their Wicket ids.

Example

The following example is based on a form that queries a user for his/her name and account information. There may be two different types of accounts: first, postal accounts which just ask for an account number and an account holder, and second, bank accounts which ask also for the address of the bank. The following Figure 1 shows a screen shot of the corresponding web form.

Figure 1: A sample application showing a simple web form for entering bank or postal account information.

The application should provide a validation mechanism which checks the following:
  1. Either the bank account radio button or the postal account radio button must be selected.
  2. If the bank account is checked, the corresponding fields (account number, address of bank, account holder) are mandatory.
  3. If the postal account is ticked, the corresponding fields (account number, account holder) are mandatory.
If one of these validation errors occur, the involved fields must be emphasized. With the conventional FormComponentFeedbackBorder container provided by the Wicket framework, this behavior showing the error feedback is not possible because the feedback border can just be applied to exactly one component.

The presented validation feedback container solves the problem. It provides a possibility to nest feedback containers and to use a CSS class to mark all or just a part of the components that caused the validation feedback errors. Figure 2 shows how the provided account information is nested by using this new component.

Figure 2: The Web GUI showing the nested validation feedback containers.

The outer feedback container is responsible for showing any validation errors occurring for the radio button group containing the choice “Bank Account” and “Postal Account”. It is visualized in the figure by the red box with the number 1. Apart from this feedback container there are five feedback containers for any validation errors occurring in the text fields designated by the red boxes with the numbers 2, 3, 4, 5, and 6.

In the case neither “Bank Account” nor “Postal Account” is chosen and submit is pressed, both labels will be marked with a validation error (see Fig. 3).

In the case “Bank Account” is checked, the fields 2, 3, and 4 are enabled and checked for the correctness when submitting the data. In the case one of these fields cause a validation error when pressing submit, the corresponding fields are marked (Fig. 4).

The equivalent validation feedback behavior is given for “Postal Account” and the corresponding fields (Fig. 5).

Figure 3: Showing a validation error for the outer validation feedback container.

Figure 4: Showing validation errors for the bank detail fields.

Figure 5: Showing validation errors for the postal detail fields.

Implementing the Example Above

The presented validation feedback container is implemented by the class com.blogspot.m3g4h4rd.wicket.CSSComponentFeedbackContainer and can be found in the archive file (.zip) provided by the link at the end of this article.

The following Wicket-HTML and Java source of the above Web-UI shows how the feedback container is used.

<html>
<body>
<wicket:panel>
<!-- Container showing validation errors -->
<wicket:container wicket:id="accountsFeedbackContainer">
<!-- Container for the account radio group -->
<wicket:container wicket:id="accountRadioGroup">
<br/>
<b>
<span wicket:id="accountInformationLabel">
Account Information
</span>
</b>
<table border="0">
<tr>
<td><input type="radio" wicket:id="bankAccount">
<span wicket:id="bankAccountLabel">Bank Account</span>
</td>
<td>
<table border="0">
<tr>
<td>
<span wicket:id="bankAccountNumberLabel">
Bank Account Number:
</span>
</td>
<td>
<wicket:container wicket:id="bankAccountNumberFeedback">
<input wicket:id="bankAccountNumber"/>
</wicket:container>
</td>
</tr>
<tr>
<td>
<span wicket:id="bankAddressLabel">
Address of Bank:
</span>
</td>
<td>
<wicket:container wicket:id="bankAddressFeedback">
<input wicket:id="bankAddress"/>
</wicket:container>
</td>
</tr>
<tr>
<td>
<span wicket:id="bankAccountHolderLabel">
Bank AccountHolder:
</span>
</td>
<td>
<wicket:container wicket:id="bankAccountHolderFeedback">
<input wicket:id="bankAccountHolder"/>
</wicket:container>
</td>
</tr>
</table>
</td>
</tr>
<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr>
<td>
<input type="radio" wicket:id="postalAccount">
<span wicket:id="postalAccountLabel">
Postal Account
</span>
</td>
<td>
<table border="0">
<tr>
<td>
<span wicket:id="postalAccountNumberLabel">
Postal Account Number:
</span>
</td>
<td>
<wicket:container wicket:id="postalAccountNumberFeedback">
<input wicket:id="postalAccountNumber"/>
</wicket:container>
</td>
</tr>
<tr>
<td>
<span wicket:id="postalAccountHolderLabel">
Postal Account Holder:
</span>
</td>
<td>
<wicket:container wicket:id="postalAccountHolderFeedback">
<input wicket:id="postalAccountHolder"/>
</wicket:container>
</td>
</tr>
</table>
</td>
</tr>
</table>
</wicket:container>
</wicket:container>
</wicket:panel>
</body>
</html>
The above Wicket-HTML code contains several >wicket:container< tags that are used to bind the feedback container. The outer container (1) is referred as accountsFeedbackContainer, whereas bankAccountNumberFeedback, bankAddressFeedback, bankAccountHolderFeedback, postalAccountNumberFeedback, and postalAccountHolderFeedback are the (inner) containers 2 – 6 in Fig. 2.

The CSS class which is used to visualize components that caused a validation errors is defined as

.errorFeedback { background-color: #FA8895; }

If this CSS class is referred to by an HTML element, it causes the element to be shown with a red background. This CSS class is used by the presented example for showing validation errors by the feedback container. The following code snippets show how. It creates the feedback container for the feedback panel (1) in Figure 2.

// initializes the feedback container
accountsFeedbackContainer = new CSSFeedbackContainer("accountsFeedbackContainer",
"errorFeedback");
this.add(accountsFeedbackContainer);

The first argument of the constructor CSSFeedbackContainer is the id of the markup container to which the feedback panel will be bound. The second argument is the name of the CSS class that is used to visualize a feedback error.

// Set the components that will show a validation error feedback
accountsFeedbackContainer.addErrorFeedbackComponetIds(
new String[]{"bankAccountLabel", "postalAccountLabel"});

The above code adds the ids of the two labels bankAccountLabel and postalAccountLabel as components that will show validation error feedback if any of the components that are observed as source of validation error return an error.

// Set the components whose validation errors will be ignored by this component
accountsFeedbackContainer.addIgnoredComponentIds(
new String[]{"bankAddress",
"bankAccountNumber",
"bankAccountHolder",
"postalAccountNumber",
"postalAccountHolder"});

The code above excludes any validations errors caused by the components with the id bankAddress, bankAccountNumber, bankAccountHolder, postalAccountNumber, and postalAccountHolder. This is necessary, as those components are each handled by an own feedback container that is, in turn, contained in the outer feedback container.

accountsFeedbackContainer.add(accountRadioGroup);

The above code adds the radio group, which contains the radio button for the selection of either a bank or a postal account, to the feedback container. All elements of the bank account and postal account will be in turn added directly or indirectly added to the accountRadioGroup container or one of its sub-container, respectively.

The input fields of the bank account and postal account are enclosed by an own feedback container handling all validation errors that occur on their own. The following code describes how the inner feedback container for the bank account number is created.
// bank account number text field and label
bankAccountNumberLabel = new Label("bankAccountNumberLabel",
new Model("Account Number:"));
bankAccountNumber = new TextField("bankAccountNumber");

// feedback for validation errors of the bank account number
CSSFeedbackContainer bankAccountNumberFeedback =
new CSSFeedbackContainer("bankAccountNumberFeedback",
"errorFeedback");

accountRadioGroup.add(bankAccountNumberFeedback);

bankAccountNumberFeedback.add(bankAccountNumber);
bankAccountNumber.setRequired(true);
accountRadioGroup.add(bankAccountNumberLabel);

The above code simply binds the bank account number label and the corresponding bank account number text field to the corresponding elements in the Wicket-HTML. Thereafter, a new feedback container (bankAccountNumberFeedback) is created which is then added to the accountRadioGroup. The account number label and the account number text field are added to the feedback container. The code of the other parts in the Wicket UI are similar to the above code.

Hands-On
If you like to test and see in detail how it works, download the source code for the above example, including the feedback component, from here. Unzip it. Then run it with Maven 2 by entering
mvn clean jetty:run

After startup, the demo web application is reachable under

http://localhost/WicketCSSFeedback/

Conclusions
This article presented a feedback container component which allows one to
  • show validation feedback for multiple components involved in an error of a form-validation.
  • use a CSS class to show the feedback of a validation error.

Sonntag, 22. August 2010

Wicket

Wicket is a very attractive Web framework for Java. In contrast to other Web frameworks, such as JSP or Asp.NET, Wicket strictly separates the visual design in HTML from the executed code behind the scenes and does make use of very little extra non-HTML tags in the visual representation. This feature enables the use of visual prototypes at an early stage of a software project which can be developed towards the actual piece of software.

Even though Wicket framework is very mature, I was missing some features when I was using it in the last projects. The following few blog articles will present a few useful extensions to the framework, namely:

  • A validation error container for nested wicket containers/components that allows to use CSS to show validation errors in components and that enables the feedback on the component level resulting from a validation errors of a form validation.
  • Show the way how to customize/rewrite the FeedbackPanel component in order to adapt the look of the feedback panel to own needs.
  • An extension for Radio buttons which allows one to cope with Boolean values and to retrieve the selected radio button.
  • Showing how to introduce a component which sets the focus on a particular component.

Samstag, 24. Juli 2010

Swiss Social Security Number Checker/Validator in Java

Keywords: Social Security Number, Switzerland, Swiss, Validation, Number Checker, Java Implementation

Recently, I had to realize a validator for the Swiss Social Security Number, called SV No. (previously AHV No.), in Java. I was searching the WWW for an appropriate implementation but couldn't find any implementation. So, I implemented the thing myself and decided to share the code, perhaps saving some minutes of time in the busy life of another engineer.

The SV no. is a number that consists of four number blocks which are separated by dots. The first block must consist of three, the next two of four, and the last block of two digits. The last digit is a check sum which is calculated according to the EAN13 algorithm. A detailed description of the number format is given on this page (in German).

Using the present implementation of the Social Security No. Checker is quite easy. Just call

SSNNumberChecker.checkSSN(String number, String countryCode)

The first argument number is the SV No. The second argument is the countryCode that must match. If left blank or null, the country code is not checked. If the country code is given, it must match the first block of three digits.

The checking procedure consists of three steps:
  1. The number of blocks and their length are checked.
  2. There is a check, whether the blocks consist of digits, or whether they contain non-digits.
  3. The checksum is computed and checked against the last digit.
The method returns an integer number with one of the following results:
  • SSNNumberChecker.ERR_NO: no problem was found within the SV No.
  • SSNNumberChecker.ERR_LENGTH: either number blocks are missing, a wrong separator character was used, or one or more blocks do not match the required length.
  • SSNNumberChecker.ERR_CONTAINS_NON_DIGITS: there are non-digits in the blocks.
  • SSNNumberChecker.ERR_CHECKSUM: the checksum is incorrect, which may indicate a typo in the number.
  • SSNNumberChecker.ERR_WRONG_COUNTRY: indicates that the number does not start with the expected country code. This error can only occur when the argument countryCode is given.

The implementation can be found here.