I am working on an application where a user can enter multiple addresses. I am using Struts2 XML validation and for those fields [Address (Country, City, Street)], I have used visitor validator but it is not working. The validation is working fine on remaining fields.
Can anyone suggest what might be the problem ?
EmployeeForm.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//Dtd HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Add Employee</title>
<script language="javascript">
function addRow(tableID) {
var table = document.getElementById(tableID);
var rowCount = table.rows.length;
var row = table.insertRow(rowCount);
var counts=rowCount-1;
var cell1 = row.insertCell(0);
var street = document.createElement("input");
street.type = "text";
street.name="employeeModel.addresses["+counts+"].street";
cell1.appendChild(houseNum);
var cell2 = row.insertCell(1);
var city = document.createElement("input");
city.type = "text";
city.name="employeeModel.addresses["+counts+"].city";
cell2.appendChild(city);
var cell3 = row.insertCell(2);
var country = document.createElement("input");
country.type = "text";
country.name="employeeModel.addresses["+counts+"].country";
cell3.appendChild(country);
}
</script>
</head>
<body>
<s:form action="addEmployee.action" method="post" >
<s:textfield label="Name" name="employeeModel.employeeName" size="20" />
<table id="addressesTable" width="350px" border="1">
<tr>
<td>Street</td>
<td>City</td>
<td>Country</td>
</tr>
<tr>
<td><input type="text" name="employeeModel.addresses[0].street" /></td>
<td><input type="text" name="employeeModel.addresses[0].city" /></td>
<td><input type="text" name="employeeModel.addresses[0].country" /></td>
</tr>
</table>
<input type="button" value="Add More" onclick="addRow('addressesTable')" />
<s:submit />
</s:form>
</body>
</html>
EmployeeAction-Validation.xml
<validators>
<field name="employeeModel.employeeName">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>Name is required.</message>
</field-validator>
</field>
<field name="employeeModel.addresses" >
<field-validator type="visitor">
<message></message>
</field-validator>
</field>
</validators>
EmployeeModel-Validation.xml
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="employeeModel.addresses" >
<field-validator type="visitor">
<message></message>
</field-validator>
</field>
</validators>
EmployeeAction.java
package com.action;
import com.model.EmployeeModel;
import com.opensymphony.xwork2.ActionSupport;
public class EmployeeAction extends ActionSupport{
private static final long serialVersionUID = 1L;
private EmployeeModel employeeModel;
public String execute() {
return SUCCESS;
}
public EmployeeModel getEmployeeModel() {
return employeeModel;
}
public void setEmployeeModel(EmployeeModel employeeModel) {
this.employeeModel = employeeModel;
}
}
EmployeeModel.java
package com.model;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class EmployeeModel implements Serializable{
private static final long serialVersionUID = -484846216250373240L;
private String employeeName;
private List<AddressModel> addresses;
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public List<AddressModel> getAddresses() {
return addresses;
}
public void setAddresses(List<AddressModel> addresses) {
this.addresses = addresses;
}
}
AddressModel.java
package com.model;
import java.io.Serializable;
public class AddressModel implements Serializable{
private static final long serialVersionUID = 6965346469594926268L;
private String country;
private String city;
private String street;
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" extends="struts-default">
<action name="addEmployee" class="com.action.EmployeeAction" >
<result name="success">/Result.jsp</result>
<result name="input">/EmployeeForm.jsp</result>
</action>
</package>
</struts>
You have one EmployeeModel
object, that has multiple AddressModel
objects.
This means that in the Action validation file, you need to use simple validation for EmployeeModel
properties, and visitor validation for AddressModel
object.
You are correctly saying that AddressModel
must be validated through visitor validation here:
<field name="employeeModel.addresses" >
<field-validator type="visitor">
but then, instead of the validation file for AddressModel
, you are trying to use a validation file for EmployeeModel
!
Instead of
EmployeeModel-Validation.xml
you need to use
AddressModel-Validation.xml
and inside it, you need to validate the simple properties, without any employeeModel
in front of them (because this validation could be visitor-used by many different validation files, with different actions and models containing AddressModel
, that doesn't care about its parent objects):
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="country">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>Country is required.</message>
</field-validator>
</field>
</validators>
You've also forgot to name the attributes of your AddressModel
object; add them:
<td><input type="text" name="employeeModel.addresses[0].street" /></td>
<td><input type="text" name="employeeModel.addresses[0].city" /></td>
<td><input type="text" name="employeeModel.addresses[0].country" /></td>
and do the same in your javascript code.