开发者

Spring MVC 3.0 Model Attribute Inheritance

开发者 https://www.devze.com 2023-04-09 04:15 出处:网络
I\'m not sure if this is possible in Spring MVC 3.0, but I\'m trying to create an annotated Controller that extends another Controller and whose model attributes depend on a model attribute set by the

I'm not sure if this is possible in Spring MVC 3.0, but I'm trying to create an annotated Controller that extends another Controller and whose model attributes depend on a model attribute set by the parent. For example:

@Controller
public abstract class ParentModel {

    @ModelAttribute("numbers")
    protected List<Integer> getNumbers() {
        return Arrays.asList(new Integer(1));
    }

}

@Controll开发者_开发技巧er
public abstract class ChildModel extends ParentModel {

    @ModelAttribute("number")
    protected Integer getNumber(@ModelAttribute("numbers") List<Integer> numbers) {
        return numbers.get(0);
    }

}

@Controller
public class RequestHandler extends ChildModel {

    @RequestMapping("/number")
    public String items(@ModelAttribute("number") Integer number) {
        return "number"; // number.jsp
    }

}

So far, I've been unable to get this to work - it throws the following exception:

Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [java.util.List]: Specified class is an interface] with root cause org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [java.util.List]: Specified class is an interface at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:101) at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveModelAttribute(HandlerMethodInvoker.java:762) ... etc ...

When the dependency on the attribute set by the parent is removed from ChildModel.getNumber() (by removing the @ModelAttribute("numbers") List<Integer> numbers parameter), both model attribute methods are called. However, ParentModel.getNumbers() is always called before ChildModel.getNumber().

Please let me know if I'm missing something to get this fully working or that this is just not possible.

Thanks in advance!

EDIT:

After some more experimentation, it seems that having model attributes depend on other model attributes is probably not supported. I put both model attribute methods into the ParentModel and it works sporadically at best... The sporadic behavior is likely due to the order in which the methods are returned by reflection. When ParentModel.getNumbers() is called before ChildModel.getNumber() (the desirable order), it works properly. Having discovered this, my follow-up question is: Is there a way to specify the order in which model attribute methods are called?


Spring is complaing becuase it cannot instantiate a List, which is an interface, try declaring it as ArrayList( or LinkedList) which are both implentations of the interface List.


I am probably using Spring model attributes incorrectly. One way to add an attribute to the model AND reuse it is to have the second (dependent) method add both of them to the model, e.g.:

public abstract class ParentModel {

    // no longer annotated as model attribute
    // adds the attribute to the model if it does not exist
    protected List<Integer> getNumbers(Model model) {
        List<Integer> numbers = (List<Integer>) model.asMap().get("numbers");
        if (numbers == null) {
            numbers = Arrays.asList(new Integer(1));
            model.addAttribute("numbers", numbers);
        }
        return numbers;
    }

}

@Controller
public abstract class ChildModel extends ParentModel {

    @ModelAttribute("number")
    protected Integer getNumber(Model model) {
        return getNumbers(model).get(0);
    }

}

I'm not sure if this is a good way to design Spring MVC inheriting model-populating controllers either, but for now this works.

0

精彩评论

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