Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: strange binding result

  1. #1
    Join Date
    Sep 2006
    Location
    UK
    Posts
    39

    Default strange binding result

    Hi,

    I'm binding attributes of a command object within a form in my jsp in the following way (I'm using Spring 1.2.8):
    Code:
    <spring:bind path="user.username">
        <input type="text"
            name="<c:out value="${status.expression}"/>"
            value="<c:out value="${status.value}"/> "/>
    </spring:bind>
    In the associated form controller (which extends SimpleFormController) I populate the command object's username property with a value from formBackingObject(). All works fine so far, with the value showing up as expected in the input field.

    Now the problem is that when the form is submitted, the username attribute of the user command object contains both the original value (set by formBackingObject()) followed by a comma and then followed by the new user entered value!

    Can anyone tell me what's happening here please? It smells like a property editor issue, but I'm not sure. I can see that returning both the original value and the new value might have it's uses, but in most cases I would have thought that the new property value is all that is required.

    Any help would be much appreciated.

    Thanks,

    Peeper.

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,629

    Default

    Can you post also the code of the relevant controller and the applicationcontext of that controller? Might give some more insights.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Sep 2006
    Location
    UK
    Posts
    39

    Default

    Here's the relavant part of the DispatcherServlet configuration file:
    Code:
    <beans>
    	...
    	<bean id="userEditValidator" class="bus.UserEditValidator"/>
    	<bean id="userEditForm" class="web.UserEditFormController">
    		<property name="sessionForm">
    			<value>true</value>
    		</property>
    		<property name="commandName">
    			<value>user</value>
    		</property>
    		<property name="commandClass">
    			<value>bus.User</value>
    		</property>
    		<property name="validator">
    			<ref bean="userEditValidator"/>
    		</property>
    		<property name="formView">
    			<value>user-edit</value>
    		</property>
    		<property name="successView">
    			<value>user-management</value>
    		</property>
    		<property name="userManager">
    			<ref bean="userManager"/>
    		</property>
    	</bean>
    	...
    </beans>
    Here's the code for the Controller (fairly bare until I resolve this problem):
    Code:
    public class UserEditFormController extends SimpleFormController
    {
    	private UserManager userManager;
    
    	protected ModelAndView onSubmit(Object command) throws Exception
    	{
    		User user = (User)command;
    		
    		return new ModelAndView(getSuccessView());
    	}
    
    	protected Object formBackingObject(HttpServletRequest request)
    		throws Exception
    	{
    		String	username;
    		User	user;
    		
    		username = request.getParameter("username");
    		if (username != null)
    		{
    			user = userManager.getUser(username);
    			if (user == null)
    			{
    				// username not found so create a new user with the given name
    				user = new User();
    				user.setUsername(username);
    			}
    			return user;
    		}
    
    		// no username parameter found so just create an empty, default user
    		return new User();
    	}
    
    	public UserManager getUserManager()
    	{
    		return userManager;
    	}
    
    	public void setUserManager(UserManager userManager)
    	{
    		this.userManager = userManager;
    	}
    }
    And the validator:
    Code:
    public class UserEditValidator implements Validator
    {
    	public boolean supports(Class clazz)
    	{
    		return clazz.equals(User.class);
    	}
    
    	public void validate(Object obj, Errors errors)
    	{
    		ValidationUtils.rejectIfEmptyOrWhitespace(errors, 
    				"username",
                    "user-edit-error.username-required",
                    "Username required");
    	}
    }
    Thanks,

    Peeper.

  4. #4
    Join Date
    Apr 2005
    Location
    Finland
    Posts
    314

    Default

    Quote Originally Posted by peeper
    Hi,

    I'm binding attributes of a command object within a form in my jsp in the following way (I'm using Spring 1.2.8):
    Code:
    <spring:bind path="user.username">
        <input type="text"
            name="<c:out value="${status.expression}"/>"
            value="<c:out value="${status.value}"/> "/>
    </spring:bind>
    In the associated form controller (which extends SimpleFormController) I populate the command object's username property with a value from formBackingObject(). All works fine so far, with the value showing up as expected in the input field.

    Now the problem is that when the form is submitted, the username attribute of the user command object contains both the original value (set by formBackingObject()) followed by a comma and then followed by the new user entered value!

    Can anyone tell me what's happening here please? It smells like a property editor issue, but I'm not sure. I can see that returning both the original value and the new value might have it's uses, but in most cases I would have thought that the new property value is all that is required.

    Any help would be much appreciated.

    Thanks,

    Peeper.
    I got same kind of "errors" and the problem was that there was the used the same field binding twice in the same form.

  5. #5
    Join Date
    Sep 2006
    Location
    UK
    Posts
    39

    Default

    Quote Originally Posted by noon
    I got same kind of "errors" and the problem was that there was the used the same field binding twice in the same form.
    I don't think that is the case in my situation. Here is the whole of the jsp file, which only contains the one field:
    Code:
    <%@ include file="/WEB-INF/jsp/include.jsp"%>
    <%@ taglib prefix="spring" uri="/spring"%>
    
    <html>
    <head>
    <title><fmt:message key="app.title"/></title>
    </head>
    <body>
    
    <h1><fmt:message key="user-edit.heading"/></h1>
    
    <form method="post">
    	<spring:bind path="user.username">
    		<input type="text"
    			name="<c:out value="${status.expression}"/>"
    			value="<c:out value="${status.value}"/>" />
    	</spring:bind>
    	<p>
    	<input type="submit" alignment="center" value="Submit">
    </form>
    
    </body>
    </html>
    As you can see there's only one field so there can't be any duplication!

    Any other ideas gratefully received!

    Thanks,

    Peeper.

  6. #6

    Default

    I'm a bit confused in what you are doing. Try the following......

    I don't think you need sessionForm = true (set to false)

    Your formBackingObject should simply return a new User() object

    The onSubmit method which gets called after the post will populate the User() object for you which you have done but don't do anything with.

    Basically the logic should be in the onSubmit method, something like:

    Code:
    protected ModelAndView onSubmit(Object command) throws Exception
    {
      User user = (User)command;		
      User matchedUser = userManager.getUser(user.getUsername());
      if (matchedUser != null)
      {
        // probably set matchedUser in session as an attribute (up to you!!)
        return new ModelAndView(getSuccessView());
      }
      else
      {
        errors.reject("incorrectLogin","Incorrect user please try again");
        return showForm(request, response, errors);
      }
    }
    errors.reject will create a global error for the user command object. You can use errors.rejectValue if you want a field specific error.

    Hope this helps.

  7. #7
    Join Date
    Apr 2005
    Location
    Finland
    Posts
    314

    Default

    I think you should not set the value in formBackingObject. Just create the new object and Spring will bind the value with the model setters.

    This is how I have done in my Spring projects. If model was 'new', I just created a new model (POJO). Otherwise I fetch the real model e.g. from database by its id or something.

    I hope you solve this problem.

  8. #8
    Join Date
    Sep 2006
    Location
    UK
    Posts
    39

    Default

    Thanks for you suggestions guys. Let me explain the rationale behind what I'm doing and ask a couple of questions that may finally help me resolve this...

    The form is used to edit user details, so the fields must be populated when it is first shown (i.e. upon GET). So I create the User command object in formBackingObject() and then set its properties so that the form fields can be taken from this. Is this the correct way to do this? From paulf's and noon's comments I'm beginning to suspect that formBackingObject() is not the right place to populate User properties when first showing the form.

    As paulf says, onSubmit() isn't doing a great deal at the moment, but my intention is to update the user's details from the command object - that is, upon POST. Is this the right thing to do?

    Thanks,

    Peeper.

  9. #9

    Default

    the formBackingObject() is the right place to create your User object so that it is displayed in your form on the first subsequent GET.

    It depends on your requirements. You may want to create a different object when it is GET or POST. To be more precise you should call isFormSubmission() which will tell you if it is a form submission. By default a POST is treated as a form submission and a GET as simply displaying the form. (It's best to call this method in case you overide the method later and decide on an alternative stratedgy on what is a form submission and what is not)

    For some reason you know the username before the form is displayed and is passed in the URL as a parameter. So yes you could do what you are doing to obtain the relevant User object to be displayed in the initial form. So in formBakingObject check isFormSubmission == false and then return your user object based on the username parameter.

    If isFormSubmission == true then again it is up to you what object you want auto binded by Spring on the form submission. You may simply return a new User() object to be populated so you can compare this object with the USre object returned from your userManager. It depends on what you are trying to do so I can only speculate.

    I found reading the workflow section in the javadoc of AbstractFormController very useful. It is all explained there.

    Anyway you seem to have the idea so best of luck!!!

  10. #10
    Join Date
    Sep 2006
    Location
    UK
    Posts
    39

    Default

    Many thanks for the suggestions.

    I finally discovered that the original problem was the result of a simple mistake/ommision in the <form> element of my jsp. I'd neglected to provide the 'action' attribute in the opening form tag. So rather than using something like:
    Code:
    <form action="<c:url value="user-edit.html"/>" method="post">
    I was using the incorrect code:
    Code:
    <form method="post">
    Now to try to understand why a missing 'action' attribute results in weird field values...

    Peeper.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •