0

I wish to use Spring's powerful binding tools (errors/validation/tag library/etc.) on a form that really only has one bindable value. Rather than having an object containing a single String property ("name"), I'm trying to use a basic String as the command object, but I'm not sure how (or if) to get this to work with everything at the same top-level. Here's an example using the object (MyObject) with a nested string - this works fine. I'd like to just use a string, but when I change MyObject to String, whatever is entered for this String is not reflected in the next page. What am I doing wrong?

@Controller 
@SessionAttributes("command")
public class TestController {

private static final String[] WIZARD_PAGES = new String[] {
    "enterValue",
    "confirmValue"
};  

@RequestMapping(value = "doStuff.action", method = RequestMethod.GET)
public String formBackingObject(HttpServletRequest request, HttpServletResponse response, final ModelMap modelMap) {
    MyObject entry = new MyObject();
    modelMap.put("command", entry);
    return WIZARD_PAGES[0];
}

@RequestMapping(value = "doStuff.action", method = RequestMethod.POST)
public String onSubmit(HttpServletRequest request, HttpServletResponse response, final ModelMap modelMap,
        final @ModelAttribute("command") MyObject entry,
        final Errors errors, SessionStatus status,
        @RequestParam(value = "_page") Integer currentPage,
        @RequestParam(value = "_finish", required=false) Object finish,
        @RequestParam(value = "_cancel", required=false) Object cancel) {

    // submitting
    if (finish != null) {       
                    // do submit stuff here
        status.setComplete();
        return "redirect:/home.action";
    }

    // cancelling
    if (cancel != null) {
        status.setComplete();
        return "redirect:/home.action";                     
    }       

    // moving to next page
    int targetPage = WebUtils.getTargetPage(request, "_target", currentPage);
    if (targetPage >= currentPage) {    
        // validate current page here
        switch(currentPage) {
        case 0: // TODO: call validation
            if (!errors.hasErrors()) {
               // do some stuff to prepare the next page
            }
            break;                                      
        }
    }

    if (errors.hasErrors())
        return WIZARD_PAGES[currentPage];
    return WIZARD_PAGES[targetPage];
}

And enterValue.jsp:

<form:form commandName="command">
    <form:input path="name"/>
            <input type="submit" name="_target1" value="<spring:message code="COMMON.NEXT"/>" />
    <input type="hidden" name="_page" value="0" />
 </form:form>

And confirmValue.jsp:

<form:form commandName="command">
${name}
    <input type="submit" name="_finish" value="<spring:message code="COMMON.SUBMIT"/>" />
   <input type="hidden" name="_page" value="1" />
</form:form>
Ryan H
  • 349
  • 1
  • 6
  • 20

2 Answers2

0

Strings are immutable. When you use MyObject, what Spring changes is the object's reference to the String, not the String itself.

Devon_C_Miller
  • 16,248
  • 3
  • 45
  • 71
  • I suspected it had something to do with String immutability, but why couldn't the reference to the String be changed by Spring the same way it does for an object property? I guess really the why is unimportant if the conclusion is that it cannot be done. – Ryan H Jan 25 '13 at 22:06
  • See @Hung Tran's answer, that's exactly what is happening. – Devon_C_Miller Jan 28 '13 at 17:17
0

I guess your case possibly caused by two things:

1) String is an immutable object. It means a new reference value will be returned whenever you assign a new String

2) A method parameter is passed by value. Because String is a reference type, then the reference value of a object reference cannot changed.

For example

public static void change(String text) { // (1) pass by value
   text = "Hello Word"; // (2) immutable
}

public static void main(String[] args) {
  String str = "Hello";
  change(str);
  System.out.println(str); // Output: Hello
}

When we wrap a String object reference inside another object, then the object reference that is passed to the change method is myObject, not the String reference anymore. That's why using myObject can change the reference value of the String object reference.

Hung Tran
  • 1,595
  • 2
  • 17
  • 17