PDA

View Full Version : Problems resolving error messages for arrays of objects


jonfurse
Oct 11th, 2005, 07:40 AM
I'm having problems getting error messages resolved for arrays of objects

I have a view which displays multiple dates. These dates are bound to a date array on the command object associated with a SimpleFormController subclass.
I've registered a custom property editor for the dates and using velocity's dateTool, I convert them to dd/mm/yyyy format in my template.

The binding works correctly and the dates are displayed in dd/mm/yyyy format. However, if I put a set of characters into a date field that the date formatter cannot parse, a get a nasty null pointer exception on submit, rather than the typeMismatch error I was expecting.

Here is the exception and a simplified version of the code:

Exception:
org.apache.velocity.exception.MethodInvocationExce ption: Invocation of method 'getMessage' in class org.springframework.web.servlet.support.RequestCon text threw exception class java.lang.NullPointerException : null
at org.apache.velocity.runtime.parser.node.ASTMethod. execute(Ljava.lang.Object;Lorg.apache.velocity.con text.InternalContextAdapter;)Ljava.lang.Object;(AS TMethod.java:246)
at org.apache.velocity.runtime.parser.node.ASTReferen ce.execute(Ljava.lang.Object;Lorg.apache.velocity. context.InternalContextAdapter;)Ljava.lang.Object; (ASTReference.java:175)
...


Controller:
public class TestController extends SimpleFormController{

protected SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

protected Object formBackingObject(HttpServletRequest request) throws ServletException {

TestCommandObject obj = new TestCommandObject();
obj.setMydates(new Date[]{
new Date(System.currentTimeMillis()),
new Date(System.currentTimeMillis()),
new Date(System.currentTimeMillis())
});
return obj;
}

protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) {
dateFormat.setLenient(true);
binder.registerCustomEditor(Date.class, null, new CustomDateEditor(dateFormat, true));
}
}

Command Object:
public class TestCommandObject {

private Date[] mydates;

public Date[] getMydates() {
return mydates;
}

public void setMydates(Date[] mydates) {
this.mydates = mydates;
}
}

message properties file fragment:
typeMismatch.command.mydates[0]=Top Code matched
typeMismatch.java.util.Date=Object Type matched
typeMismatch=General type mismatch

Velocity template fragment:
<tr>
#foreach ( $mydate in $command.mydates )

<td>
<input type="text" name="mydates[$velocityCount]" value="$!dateTool.format("dd/MM/yyyy", $!mydate)" />
</td>

</tr>
<tr>
<td>
#if( $errors )
#if( $errors.getFieldErrors( $field ) )
#foreach( $err in $errors.getFieldErrors( $field ) )
<span class="error">$rc.getMessage($err)</span>
#end
#end
#end
</td>
</tr>
#end

debugging the resulting BindException if I submit "NOTADATE" into the second date input field:
errors = {org.springframework.validation.BindException@8625 }
errors: java.util.List = {java.util.LinkedList@8626} size = 1
[0] = {org.springframework.validation.FieldError@863 6}
field: java.lang.String = "mydates[1]"
rejectedValue: java.lang.Object = "NOTADATE"
bindingFailure: boolean = true
objectName: java.lang.String = "command"
codes: java.lang.String[] = {java.lang.String[6]@8639}
[0] = "typeMismatch.command.mydates[1]"
[1] = "typeMismatch.command.mydates"
[2] = "typeMismatch.mydates[1]"
[3] = "typeMismatch.mydates"
[4] = "typeMismatch.java.util.Date"
[5] = "typeMismatch"
arguments: java.lang.Object[] = {java.lang.Object[1]@8640}
[0] = {org.springframework.context.support.DefaultMessag eSourceResolvable@8648}
codes: java.lang.String[] = {java.lang.String[2]@8649}
[0] = "command.mydates[1]"
[1] = "mydates[1]"
arguments: java.lang.Object[] = null
defaultMessage: java.lang.String = "mydates[1]"
defaultMessage: java.lang.String = "Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property 'mydates[1]'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: \"NOTADATE\""

Note that because I've added the message property command.mydates[0], the first failure does print a helpful message ("Top code matched"), but the other fields cause the exception to be thrown, which indicates that the message code resolution order detailed in DefaultMessageCodesResolver JavaDocs (and replicated in the debugging above) doesn't seem to be working.

What am I doing wrong? Is this linked to the registered property editor in any way? I would be very grateful for any help...

Jon