I have experience with Spring MVC with JSPs and am now working on project that uses Freemarker instead, and for the life of me I cannot get errors to display on my web pages via freemarker. I have two problems:
1) My validation errors aren't seen in the freemarker ftl (it shows I have zero errors)
2) Even though my ftl model reports zero errors, if I add spring error support to my ftl the freemarker parser throws an exception if the spring validator added an error.
I'm hoping I'm simply doing something silly that a kind soul can point out to me. Here's the summary followed by code snippets :
- I'm using Spring mvc 3.0.5.RELEASE and Freemarker 2.3.15
- I have a controller and a validator, and my validator correctly adds an error and that error is seen in my controller's POST method's BindingResult. I add the BindingResult's model to my ModelAndView.
- My freemarker ftl binds correctly to my model object, i.e. on the GET it displays the correct values from the model, and on the POST any values I've entered are present in controller's POST method's model object.
- When I put a breakpoint in my controller's POST method just before it returns the ModelAndView, my ModelAndView contains an org.springframework.validation.BeanPropertyBinding Result object with key "org.springframework.validation.BindingResult.paym entInfo" (my command object is called "paymentInfo"). Here's the full object toString fwiw:
controller snippet:Code:org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'paymentInfo' on field 'paymentFields.creditCardNumber': rejected value []; codes [Credit card number must not be blank.paymentInfo.paymentFields.creditCardNumber,Credit card number must not be blank.paymentFields.creditCardNumber,Credit card number must not be blank.creditCardNumber,Credit card number must not be blank.java.lang.String,Credit card number must not be blank]; arguments []; default message [null]
validator snippet:Code:@RequestMapping(value = "/processpayment", method = RequestMethod.POST) public ModelAndView processPayment(@ModelAttribute("paymentInfo") @Valid PaymentInfo paymentInfo, BindingResult result, SessionStatus status, HttpServletRequest request) { final String hapiAccountName = paymentInfo.getAccountName(); String hapiUserName = null; HapiSession session = null; ModelAndView mav = new ModelAndView(); try { if (result.hasErrors()) { ModelAndView mavErr = new ModelAndView(getViewName(paymentInfo), "paymentInfo", paymentInfo); mavErr.addAllObjects(result.getModel()); return mavErr; }
freemarker ftl snippet:Code:@Override public void validate(Object target, Errors errors) { PaymentInfo pi = (PaymentInfo) target; ValidationUtils.rejectIfEmptyOrWhitespace(errors, "paymentFields.creditCardNumber", "Credit card number must not be blank"); }
You'll see I have some debugging code in my ftl. The spring.status.error evaluates to false and spring.status.errorMessages?size evaluates to zero. However addingCode:<@spring.bind "paymentInfo" /> <#if spring.status.error> errors<br> </#if> size=${spring.status.errorMessages?size}<br> <@spring.bind "paymentInfo.paymentFields.creditCardNumber" /> <div class="cart-formcol2"><input id="paymentInfoForm_creditCardNumber" name="paymentFields.creditCardNumber" class="cart-input" type="text" value=""/> </div> <@spring.showErrors "br"/>causes the freemarker parser to fail with this error:Code:<@spring.showErrors "br"/>
I've also tried using the example directly from the spring 3.0 docs:Code:get(errorMessages) failed on instance of org.springframework.web.servlet.support.BindStatus The problematic instruction: ---------- ==> list status.errorMessages as error [on line 330, column 5 in spring.ftl] in user-directive spring.showErrors [on line 98, column 45 in com/homeaway/hapiservice/paymentform/vr/v1.ftl] in user-directive payment.paymentForm [on line 31, column 29 in com/homeaway/hapiservice/paymentform/vr/v1.ftl] ---------- Java backtrace for programmers: ---------- freemarker.template.TemplateModelException: get(errorMessages) failed on instance of org.springframework.web.servlet.support.BindStatus at freemarker.ext.beans.BeanModel.get(BeanModel.java:223) at (etc.)
While that example correctly binds input values to my model object, it throws the same "get(errorMessages) failed..." exception upon parsing.Code:<@spring.bind "paymentInfo.paymentFields.creditCardNumber" /> <input type="text" name="${spring.status.expression}" value="${spring.status.value?default("")}" /><br> <#list spring.status.errorMessages as error> <b>${error}</b> <br> </#list>
Interestingly I don't get a parse exception if the validator doesn't add any errors. This is odd to me because when I have validation errors ${spring.status.errorMessages?size} still evaluates to zero (why doesn't it report the number of errors I have?) while <#list spring.status.errorMessages as error> does throw an error. If ${spring.status.errorMessages?size} then I would think the <#list> would not even evaluate anything. And of course I don't know why ${spring.status.errorMessages?size} would be zero when I can see a BindingResult. And why does one reference to spring.status.errorMessages cause a parse exception while the other doesn't?
I've looked at this for several hours and am stumped. For a jsp in Spring mvc, displaying errors has always been easy for me, but I'm clearly missing something for Spring + Freemarker since no one else on the web seems to report this problem (except for one post in an Asian language I couldn't understand). I'd be most appreciative if anyone has suggestions on where I might look to figure out what I'm doing wrong.
Thanks


Reply With Quote
