Dead simple (and pretty) form creation, client and server side validation, and request parameter to object mapping. No configuration required.
Here's how it works:
Create your model classes
Create your model using the javax.validation validation Annotations (JSR 303).
public class AccountForm {
@NotBlank(groups = RequiredChecks.class)
@Size(min = 2, max = 25)
private String name;
...
}
(See below for actual classes)
Create a form
Use the jails taglib to present your form, make sure input names match your model fields names.
<%@ taglib uri="http://org.jails.org/form/taglib" prefix="s" %>
<s:form name="accountForm" action="/jails-demo/jails" label="Your Account Details" style="side">
<s:text name="name" label="Name" size="25" />
<s:text name="accountName" label="Account Name" size="15" />
<s:password name="password" label="Password" size="25" />
<s:password name="confirmPassword" label="Confirm Password" size="25" />
<s:text name="creditCardNumber" label="Credit Card" size="20" />
<s:text name="address.street" label="Street" size="50" />
<s:text name="address.city" label="City" size="25" />
<s:state_select name="address.state" label="Street" />
<s:text name="address.zip" label="Zip" size="25" />
<s:country_select name="address.country" label="Country" />
<s:text name="balance" label="Limit" size="25" />
<s:text name="age" label="Age" size="5" />
<s:date_select name="birthday" label="Birthday" format="@MM-dd-yyyy"/>
<s:submit label="Submit" />
</s:form>
Now validate it!
public class SimpleFormServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
SimpleValidator validator = new SimpleValidator();
if ("Submit".equals(request.getParameter("submit"))) {
Map<String, List<String>> errors = validator.validate(AccountForm.class, request.getParameterMap());
if (errors != null) {
AccountForm account = validator.getMapper().toObject(AccountForm.class, request.getParameterMap());
//do something with valid account
} else {
SimpleForm.validateAs(AccountForm.class).inRequest(request).setErrors(errors);
//handle error
}
} else {
SimpleForm.validateAs(AccountForm.class).inRequest(request);
//forward to formPage
}
}
}


For more detailed documentation, check out the using jails page or read the javadocs.
Below are the model classes.
@FieldMatch(field = "password", matchField = "confirmPassword", message = "Passwords must match.")
@AcceptsNestedAttributes
public class AccountForm {
@NotBlank(groups = RequiredChecks.class)
@Size(min = 2, max = 25)
private String name;
@NotBlank(groups = RequiredChecks.class)
@Pattern(regexp = "[0-9a-zA-Z]*", message = "may only contain letters and numbers.")
private String accountName;
@NotBlank(groups = RequiredChecks.class)
@StrongPassword
private String password;
@NotBlank(groups = RequiredChecks.class)
@StrongPassword
private String confirmPassword;
@NotNull
@Valid
private AddressForm address;
@NotBlank(groups = RequiredChecks.class)
@CreditCardNumber
private String creditCardNumber;
@NotNull(groups = RequiredChecks.class)
@DecimalMin(value = "1000.00")
@DecimalMax(value = "7000.00")
private Double balance;
@Max(value = 123)
@Min(value = 18)
private Integer age;
@Past
private Date birthday;
public AccountForm() {}
public AccountForm(String name, String accountName, String password,
String creditCardNumber, Double balance, Integer age, Date birthday) {
this.name = name;
this.accountName = accountName;
this.password = password;
this.creditCardNumber = creditCardNumber;
this.balance = balance;
this.age = age;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getConfirmPassword() {
return confirmPassword;
}
public void setConfirmPassword(String confirmPassword) {
this.confirmPassword = confirmPassword;
}
public AddressForm getAddress() {
return address;
}
public void setAddress(AddressForm address) {
this.address = address;
}
public String getCreditCardNumber() {
return creditCardNumber;
}
public void setCreditCardNumber(String creditCardNumber) {
this.creditCardNumber = creditCardNumber;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
public class AddressForm {
@NotBlank(groups = RequiredChecks.class)
@Size(min = 2, max = 125)
private String street;
private String apt;
@NotBlank(groups = RequiredChecks.class)
@Size(min = 2, max = 75)
private String city;
@NotBlank(groups = RequiredChecks.class)
@Size(min = 2, max = 2)
private String state;
@NotBlank(groups = RequiredChecks.class)
@Size(min = 5, max = 15)
private String zip;
@NotBlank(groups = RequiredChecks.class)
@Size(min = 2, max = 2)
private String country;
public AddressForm() {}
public AddressForm(String street, String city, String state, String zip, String country) {
this.street = street;
this.city = city;
this.state = state;
this.zip = zip;
this.country = country;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getApt() {
return apt;
}
public void setApt(String apt) {
this.apt = apt;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}