开发者

How can I validate a complex model object in Spring 3 using @Valid annotations?

开发者 https://www.devze.com 2023-03-08 03:51 出处:网络
I have a model object modelling a purchase order. The purchase order has a few fields (such as ID and date) and a list of line-items as ArrayList. I can validate the parent purchase order ok, but it c

I have a model object modelling a purchase order. The purchase order has a few fields (such as ID and date) and a list of line-items as ArrayList. I can validate the parent purchase order ok, but it chokes when validating the line-items.

Can anyone help me with validation of complex objects? If I cannot validate complex objects auto-magically, how can I write a custom validator that relies upon the constraint ann开发者_Python百科otations in the parent and then iterates over the child line-items? This Validator instance needs to be able to call something.validate(purchaseOrder) and (for each line-item) something.validate(lineItem). Where do I get "something" from?

I have specified <mvc:annotation-driven /> in dispatcher-servlet. I am not using @InitBinder. And I am using @Valid annotation for validation in controller's method like

    @RequestMapping(params="confirmPurchaseOrder")
    public String confirm(
            @ModelAttribute("purchaseOrder") @Valid PurchaseOrder purchaseOrder,
            BindingResult result,
            @RequestParam("account") String accountString,
            @RequestParam("division") String divisionString,
            Model model)
    {
        if (result.hasErrors()) {
            return PURCHASE_ORDER_CREATE_VIEW;
        }

The domain classes look like this: -

public class PurchaseOrder implements Comparable<PurchaseOrder> {
    /** Based on GUID */
    private String id;

    /** SOP */
    @NotNull
    private Integer SOP;

    /** Reference from client */
    @NotBlank
    private String purchaseOrderReference;

    /** PO date */
    @DateTimeFormat(style="S-")
    @NotNull
    private Date date;

    @Valid
    private final Collection<LineItem> lineItems = new ArrayList<LineItem>();

And

public class LineItem {
    ...Elided

    /** Generated from GUID */
    private String id;

    @NotNull
    @DateTimeFormat(style="S-")
    @Future
    private Date expiry;

    private String softwareVersion;

    @NotNull
    @NumberFormat(style = Style.NUMBER)
    @Min(1)
    private Integer licenceCount;

When committing a Purchase Order with an empty expiry date, I get the following exception:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property 'lineItems[]' of bean class [com.nit.ols.domain.PurchaseOrder]: Invalid index in property path 'lineItems[]'; nested exception is java.lang.NumberFormatException: For input string: ""
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:730)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:634)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)


In your PurchaseOrder class, try changing your lineItems collection to a List. It looks like you are having the same problem addressed in this question.


It's like David said, declaring lineItems of type List should do the trick. In Hibernate Validator 4.2.0 CR1 (not yet released atm, you could use the latest snapshot build if you are interested) also Collection should work, see HV-468 for more details.

0

精彩评论

暂无评论...
验证码 换一张
取 消