Showing posts with label ajax. Show all posts
Showing posts with label ajax. Show all posts

Friday, March 19, 2010

Shopping Cart Web Application - Bean Validation

Introduction
In my previous blog entry I wrote about adding security to the shopping cart web application. Part of the change I made to the application was adding a form to register users and a form to add and update items. It made sense to add validation to the fields so that we could maintain the integrity of our data.

I currently maintain two different versions of the application:
  • ShoppingCartSecurity.zip – A standard web application that runs off Tomcat 6 and is built with Hibernate, Spring, JPA and RichFaces. This is an Eclipse archive file that contains two Eclipse projects. 
  • ShoppingCartGF.zip – A JEE application that runs off GlassFish vs 3 and is built with EJB 3.0, JPA and RichFaces.

There are a number of different approaches one can take when doing validation. A common approach is using client side form validation which uses JavaScript to validate the form fields. There is no round trip to the server so the validation is nice and fast. The jQuery Javascript library has a nice plugin to use if you are interested in this approach. Even though client side validation is nice it isn't essential however server side validation is not an option and should be implemented to ensure data integrity. For the shopping cart application I decided to only use server side validation so that I was using a common validation implementation. In order to get the same user experience as client side validation I chose to use the Ajax JSF RichFaces library.

The validation  framework I have chosen to use is the standard validation framework (JSR 303: Bean Validation) implemented in Java EE 6. As of version 4.x Hibernate Validator is based on a new code base which is the reference implementation for JSR 303.

"JSR 303 defines a metadata model and API for JavaBean validation. The default metadata source is annotations, with the ability to override and extend the meta-data through the use of XML validation descriptors. The API is not tied to a specific application tier or programming model. It is specifically not tied to either the web tier or the persistence tier, and is available for both server-side application programming, as well as rich client Swing application developers."

What we will cover
  • Defining constraints
  • Custom validation
  • Spring injection into custom validators
  • Validating constraints
  • RichFaces Ajax validation for JSF inputs


Constraints
Constraints in Bean Validation are expressed via Java annotations. There are three different types of constraint annotations, namely: field, property, and class-level annotations. An example of property annotations can be seen in the User class:

@Column(name="username", nullable=false, unique=true)
@NotEmpty
@Length(min=4, max=12)
@Pattern(regexp="^[a-zA-Z\\d_]{4,12}$", message="{validator.username.invalid}")
@Username(message="{validator.username}")
public String getUsername() {
 return username;
}

The getter method for the username property specifies the following validation annotations:
  • @NotEmpty – The username cannot be null or empty.
  • @Length(min=4, max=12) – The length of the username must be at least 4 characters long and no more than 12 characters long.
  • @Pattern(regexp="^[a-zA-Z\\d_]{4,12}$", message="{validator.username.invalid}") – Match a regular expression. The username must contain alphanumeric characters. The default message is overridden with a key mapped to a message in the validation resource file. 
  • @Username(message="{validator.username}") – Custom validator to compares the usernames already stored in the database to check for duplicates.

An example of where I have used class-level annotation validation can be found in the Register.java JSF backing bean class:

@FieldMatch.List({
 @FieldMatch(first="password", second="confirmedPassword",
   message="{validator.fieldmatch.password}")
  })
public class Register extends BasePage {
 private Validator validator;
 private String password;
 private String confirmedPassword;

 @NotEmpty
 @Length(min=6, max=12)
 @Pattern(regexp = "(?=.*\\d)(?=.*[a-zA-Z]).{6,12}", message = "{validator.password.insecure}")
 public String getPassword() {
  return password;
 }

 public void validateUsername() {
  Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(getUser(), "username");
  if (constraintViolations.size() > 0) {
   String msg = constraintViolations.iterator().next().getMessage();
   addError(getUiUsername().getClientId(getFacesContext()), msg);
  }
 }
 
 public void validatePassword() {
  Set<ConstraintViolation<Register>> constraintViolations = validator.validateProperty(this, "password");
  if (constraintViolations.size() > 0) {
   String msg = constraintViolations.iterator().next().getMessage();
   addError(getUiPassword().getClientId(getFacesContext()), msg);
  }
 }
 
 public void validateConfirmedPassword() {
  Set<ConstraintViolation<Register>> constraintViolations = validator.validate(this);
  if (constraintViolations.size() > 0) {
   ConstraintViolation<Register> cv = constraintViolations.iterator().next();
   if (cv.getMessageTemplate().equals("{validator.fieldmatch.password}")) {
    addError(getUiConfirmedPassword().getClientId(getFacesContext()), cv.getMessage());    
   }
  }
 }
 
 ...
 
}

  • @FieldMatch – Custom cross field validation class-level annotation used to compare the values of two fields, namely password and confirmed password. 
  • @NotEmpty – The password cannot be null or empty.
  • @Length(min=6, max=12) – The length of the password must be at least 6 characters long and no more than 12 characters long.
  • @Pattern(regexp = "(?=.*\\d)(?=.*[a-zA-Z]).{6,12}", message="{validator.password.insecure}") – Match a regular expression. The password must contain alphanumeric characters. The default message is overridden with a key mapped to a message in the validation resource file. 

Custom Validators
As mentioned above I have two custom validators, namely Username and FieldMatch. Creating a custom validator is actually very simple and requires the following three steps:

  • Create a constraint annotation
  • Implement a validator
  • Define a default error message

I won’t go over this in too much detail as the Hibernate Validator documentation is pretty good and covers this nicely.

Username constraint annotation (Username.java)

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy=UsernameValidator.class)
public @interface Username {
 String message() default "Username already exists";
 Class<?>[] groups() default {};
 Class<? extends Payload>[] payload() default {};
}

Username validator (UsernameValidator.java)

public class UsernameValidator implements ConstraintValidator<Username, Object> {
 @Autowired
 private UserDao userDao;

 public void setUserDao(UserDao userDao) {
  this.userDao = userDao;
 }

 public void initialize(Username parameters) {
 }

 public boolean isValid(final Object value, ConstraintValidatorContext context) {
  try {
   User user = userDao.findByUsername((String) value);
   if (user == null) {
    return true;
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
  return false;
 }
}

Spring injection
You will notice I am injecting the UserDao class into this validator using Springs @Autowired annotation. This is made possible thanks to Spring’s LocalValidatorFactoryBean class.

"By default, the LocalValidatorFactoryBean configures a SpringConstraintValidatorFactory that uses Spring to create ConstraintValidator instances. This allows your custom ConstraintValidators to benefit from dependency injection like any other Spring bean."

I only needed to add the following line of code to the shoppingcart-database.xml Spring bean configuration file in order to use the SpringConstraintValidatorFactory:

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

The Register.java JSF backing bean mentioned earlier gets a reference to the Spring created Validator by declaring the managed property in the faces-config.xml:

<managed-bean>
 <managed-bean-name>pc_Register</managed-bean-name>
 <managed-bean-class>com.mydomain.shoppingcart.view.Register</managed-bean-class>
 <managed-bean-scope>request</managed-bean-scope>
 <managed-property>
  <property-name>shoppingViewHelper</property-name>
  <value>#{shoppingViewHelper}</value>
 </managed-property>
 <managed-property>
  <property-name>validator</property-name>
  <value>#{validator}</value>
 </managed-property>
</managed-bean>

ValidationMessages.properties
I created a ValidationMessages.properties file and saved it in my src folder of my project. Hibernate Validator uses this file to retrieve the messages used by the validators.

Tying it together with the user interface
The login-form.jspx page includes a form for registering users. Instead of explaining each input field I am only going to step through one of them (username) and explain the validation process for it:

<h:inputText id="usrnameInTxt" binding="#{pc_Register.uiUsername}" value="#{pc_Register.user.username}" label="usrnameOutTxt" tabindex="1">
 <a4j:support id="usrnameSpt" event="onblur" reRender="usrnameMsg" limitToList="true" action="#{pc_Register.validateUsername}" />
</h:inputText>
<rich:message id="usrnameMsg" for="usrnameInTxt" errorClass="error" />

The a4j:support tag is a RichFaces tag that provides Ajax support to JSF input fields. Here it defines that the validateUsername method in the Register backing bean will be invoked when the onblur event of the input text field is triggered.

public void validateUsername() {
 Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(getUser(), "username");
 if (constraintViolations.size() > 0) {
  String msg = constraintViolations.iterator().next().getMessage();
  addError(getUiUsername().getClientId(getFacesContext()), msg);
 }
}

As you can see from the above code the validator class in the validateUsername method invokes the validateProperty method. The single property username is validated and if any constraint violations are raised an error message is added to the FacesContext.

The RichFaces rich:message tag behaves the same way as the standard JSF h:message tag except it will auto re-render itself after an Ajax request.

RichFaces Ajax Validator
RichFaces also has an Ajax validator tag that ties nicely into Hibernate Validator. I use this tag in the Items Admin modal panel of the items.jspx page.

<h:inputText id="nameInTxt" 
 value="#{pc_Items.selectedItem.name}"
 label="nameOutTxt" tabindex="1">
 <rich:ajaxValidator event="onblur" />
</h:inputText>
<rich:message id="nameMsg" for="nameInTxt" errorClass="error" />

As you can see there are no a4j:support tags or validation methods that get called. RichFaces will create its own Validator instance and call the validate property methods automatically for you. This works pretty nicely in the above example however for the registration form we are not using this tag because the validator is created for us by the Spring LocalValidatorFactoryBean class.


Registration screen shot



Wednesday, August 5, 2009

Shopping Cart Web Application - Part 10 - AJAX

Introduction
Asynchronous JavaScript and XML (AJAX) is a group of interrelated web development techniques used for creating interactive web applications or rich Internet applications. With Ajax, web applications can retrieve data from the server asynchronously in the background without interfering with the display and behavior of the existing page. Data is retrieved using the XMLHttpRequest object or through the use of Remote Scripting in browsers that do not support it. Despite the name, the use of JavaScript and XML is not required, and they do not have to be used asynchronously

What you need before we get started

What we will cover
  • Advantages of AJAX
  • RichFaces
  • Limitations and rules
  • Shopping cart

Level
  • Beginner

Advantages of AJAX
  • Nice user experience - AJAX gives the user a way to interact with a website without having to wait for lengthy refreshes on a website. Sections of pages can be reloaded individually without having to reload the whole page
  • Less bandwidth used - instead of the full contents of the HTML page being sent to and from the server only the required information is transmitted. The network utilization is minimized and quicker operations occur
  • Limited processing on the server — Users may perceive the application to be faster or more responsive because only the necessary data is sent to the server, the server is not required to process all form elements. By sending only the necessary data, there is limited processing on the server. There is no need to process all form elements, process the viewstate, send images back to the client, and no need to send a full page back to the client

RichFaces 
RichFaces is an open source framework that adds Ajax capability into existing JSF applications without resorting to JavaScript. RichFaces leverages JavaServer Faces framework including lifecycle, validation, conversion facilities and management of static and dynamic resources. RichFaces UI library contains components for adding rich user interface features to JSF applications. Create a modern rich user interface look-and-feel with skins-based technology. RichFaces UI components come ready to use out-of-the-box, so developers save their time and immediately gain the advantage of the mentioned above features in Web applications creation. As a result, usage experience can be faster and easily obtained.

RichFaces allows to define (by means of JSF tags) different parts of a JSF page you wish to update with an Ajax request and provide a few options to send Ajax requests to the server. JSF page doesn't change from a "regular" JSF page and you don't need to write any JavaScript or XMLHTTPRequest objects by hands, everything is done automatically.

  • Ajax Filter - RichFaces uses a filter for a correction of code received on an Ajax request. In case of a "regular" JSF request a browser makes correction independently. In case of Ajax request in order to prevent layout destruction it's needed to use a filter, because a received code could differ from a code validated by a browser and a browser doesn't make any corrections
  • Ajax Action Components - There are Ajax Action Components: <a4j:commandButton>, <a4j:commandLink>, <a4j:poll>, <a4j:support>, etc. You can use them to send Ajax requests from the client side
  • Ajax Containers - AjaxContainer is an interface that describes an area on your JSF page that should be decoded during an Ajax request. AjaxViewRoot and AjaxRegion are implementations of this interface
  • JavaScript Engine - RichFaces JavaScript Engine runs on the client-side. It knows how to update different areas on your JSF page based on the information from the Ajax response. Do not use this JavaScript code directly, as it is available automatically

Limitations and Rules
  • Any Ajax framework should not append or delete, but only replace elements on the page. For successful updates, an element with the same ID as in the response must exist on the page. If you'd like to append any code to a page, put in a placeholder for it (any empty element). For the same reason, it's recommended to place messages in the "AjaxOutput" component (as no messages is also a message)
  • Don't use <f:verbatim> for self-rendered containers, since this component is transient and not saved in the tree
  • Ajax requests are made by XMLHTTPRequest functions in XML format, but this XML bypasses most validations and the corrections that might be made in a browser. Thus, create only a strict standards-compliant code for HTML and XHTML, without skipping any required elements or attributes. Any necessary XML corrections are automatically made by the XML filter on the server, but lot's of unexpected effects can be produced by an incorrect HTML code
  • The RichFaces ViewHandler puts itself in front of the Facelets ViewHandlers chain
  • RichFaces components uses their own renderers. On the Render Response Phase RichFaces framework makes a traversal of the component tree, calls its own renderer and puts the result into the Faces Response

Shopping Cart Application

1. RichFaces Filter
I added the RichFaces filter to the web deployment descriptor:

<filter>
 <display-name>RichFaces Filter</display-name>
 <filter-name>richfaces</filter-name>
 <filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
 <filter-name>richfaces</filter-name>
 <servlet-name>Faces Servlet</servlet-name>
 <dispatcher>REQUEST</dispatcher>
 <dispatcher>FORWARD</dispatcher>
 <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

2. RichFaces components
I will only be adding AJAX components to the items.jspx page. The other pages can stay as they are as there isn’t a need to add any AJAX components to them. The first thing I did was add the RichFaces tag library xml namespaces to the items.jspx page. Below is the completed items.jspx page. I you compare it to the previous version you would realize that there is very little change, I just replaced most of the standard JSF components with RichFaces components.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" 
    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:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"
    version="2.0">
<ui:composition template="/template.jspx">
 <ui:define name="body">
  <h:outputText id="headingOutTxt" value="#{msg.items_txt_heading}"
   styleClass="headingOutputText" />
  <a4j:form id="itemListFrm">
   <rich:dataTable id="itemsTbl" var="items" value="#{pc_Items.items}"
    binding="#{pc_Items.itemsTable}" styleClass="dataTable"
    columnClasses="dataTableCol1" rowClasses="dataTableRow1"
    headerClass="dataTableHeader">
    <rich:column id="nameCol">
     <f:facet name="header">
      <h:outputText id="nameHeaderOutTxt"
       value="#{msg.items_txt_name_col_header}" />
     </f:facet>
     <h:outputText id="nameOutTxt" value="#{items.name}" />
    </rich:column>
    <rich:column id="descriptionCol">
     <f:facet name="header">
      <h:outputText id="descriptionHeaderOutTxt"
       value="#{msg.items_txt_description_col_header}" />
     </f:facet>
     <h:outputText id="descriptionOutTxt" value="#{items.description}" />
    </rich:column>
    <rich:column id="priceCol">
     <f:facet name="header">
      <h:outputText id="priceHeaderOutTxt"
       value="#{msg.items_txt_price_col_header}" />
     </f:facet>
     <h:outputText id="priceOutTxt" value="#{items.price}">
      <f:convertNumber pattern="#{msg.currency_pattern}" />
     </h:outputText>
    </rich:column>
    <rich:column id="addActionCol">
     <a4j:commandLink id="buyLnk" value="#{msg.items_lnk_buy}"
      action="#{pc_Items.addItemToBasket}" reRender="basketTbl" />
    </rich:column>
   </rich:dataTable>
   <p />
   <h:outputText id="basketOutTxt" value="#{msg.items_txt_basket}" />
   <p />
   <rich:dataTable id="basketTbl" var="basketItem" styleClass="dataTable"
    columnClasses="dataTableCol1" rowClasses="dataTableRow1"
    value="#{shoppingViewHelper.basket.basketItems}"
    binding="#{pc_Items.basketTable}">
    <rich:column id="basketItemCol">
     <f:facet name="header">
      <h:outputText id="basketTblHeaderOutTxt"
       value="#{msg.items_txt_basket_item_col_header}" />
     </f:facet>
     <h:outputText id="basketItemOutTxt" value="#{basketItem.item.name}" />
    </rich:column>
    <rich:column id="basketItemQuantityCol">
     <f:facet name="header">
      <h:outputText id="basketTblQuantityOutTxt"
       value="#{msg.items_txt_basket_quantity_col_header}" />
     </f:facet>
     <h:outputText id="basketItemQuantityOutTxt" value="#{basketItem.quantity}" />
    </rich:column>
    <rich:column id="basketItemPriceCol">
     <f:facet name="header">
      <h:outputText id="basketTblPriceOutTxt"
       value="#{msg.items_txt_basket_price_col_header}" />
     </f:facet>
     <h:outputText id="basketItemPriceOutTxt" value="#{basketItem.price}" />
    </rich:column>
    <rich:column id="removeActionCol">
     <a4j:commandLink id="removeLnk" value="#{msg.items_lnk_remove}"
      action="#{pc_Items.removeItemFromBasket}" reRender="basketTbl" />
   </rich:column>
   </rich:dataTable>
   <p />
   <h:commandButton id="checkoutBtn" value="#{msg.btn_checkout}"
    action="#{pc_Items.checkout}" />
   <rich:messages errorClass="errorText" /> 
  </a4j:form>
 </ui:define>
</ui:composition>
</jsp:root>

3. Items backing bean
There are two very small changes we need to make to the Items backing bean (Items.java). Our itemsTbl datatable and our basketTbl datatable are bound to javax.faces.component.html.HtmlDataTable objects within our Items.java backing bean. Because our datatables are no longer standard JSF datatables but RichFaces datatables we need to change this binding from a javax.faces.component.html.HtmlDataTable to a org.richfaces.component.UIDataTable.

The end result:



As you can see it was actually pretty simple to get up and running. Please visit the RichFaces demo site to see the full range of RichFaces components in action. You may have to register on their website to view the demo but it is well worth it. Also please read through the RichFaces developers guide . It is very useful reference manual that contains a comprehensive guide to all of the RichFaces components.