PDA

View Full Version : concatenation if spring:bind is used with property "pat


chmeier
Oct 5th, 2005, 04:47 AM
Hi folks,

I have an odd behaviour in my Spring MVC app (SimpleFormController): I have a bean with an attribute "pattern" (with String getPattern() / setPattern(String) accessors).
The value that is returned to the bean gets concatenated with the old value of the bean.

Example (user enters "newvalue" in the pattern input box):
pattern (before): "oldvalue"
pattern (after): "oldvalue,newvalue"

However, if I rename the "pattern" property to "pattern1" it works fine! That leads me to my question: are there any reserved names, therefore names that may not be used to name properties.

Thanks a lot for your help!

Chris

Colin Yates
Oct 5th, 2005, 07:27 AM
I would be suprised ;)

Can you post your controller, and your jsp please :)

chmeier
Oct 5th, 2005, 07:50 AM
Here it is.

As I mentioned in my initial post: Once I change the name of "pattern" to something else, e.g. "patternString" in the getter/setter methods and in the JSP file the problem is gone.

editVirtualAlias.jsp:

<%@ include file="include.jsp" %>
<%@ taglib prefix="spring" uri="/spring" %>

<html>
<head>
<title><fmt:message key="title"/></title>
</head>

<body>
<c:import url="inc/title.jsp"/>

<h2>Edit Virtual Alias</h2>

<form method="post">
<spring:bind path="virtualAlias.*">
<c:forEach items="${status.errorMessages}" var="error">
Error code: <c:out value="${error}"/><br>
</c:forEach>
</spring:bind>

<p>
Pattern:
<spring:bind path="virtualAlias.pattern">
<input type="text"
name="<c:out value='${status.expression}'/>"
value="<c:out value='${status.value}'/>"/>
</spring:bind>
</p>
<input type="submit" value="OK"/>
</form>

</body>



EditVirtualAliasFormController.java:

package web;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormCont roller;
import org.springframework.web.servlet.view.RedirectView;

import bus.VirtualAlias;
import bus.VirtualAliasManager;
import bus.impl.VirtualAliasImpl;

public class EditVirtualAliasFormController extends SimpleFormController {

private VirtualAliasManager virtualAliasManager;

public ModelAndView onSubmit(Object command) throws ServletException {
VirtualAlias va = (VirtualAlias)command;
virtualAliasManager.updateVirtualAlias(va);

ModelAndView mav = new ModelAndView(new RedirectView(getSuccessView()));

return mav;
}

protected Object formBackingObject(HttpServletRequest request) throws ServletException {
String pattern = request.getParameter("pattern");

VirtualAlias va = virtualAliasManager.getVirtualAliasByPattern(patte rn);

if (va==null) { // create a new virtual alias mapping
logger.info("create new virtual alias");
va = new VirtualAliasImpl();
}

return va;
}


public void setVirtualAliasManager(VirtualAliasManager virtualAliasManager) {
this.virtualAliasManager = virtualAliasManager;
}


public VirtualAliasManager getVirtualAliasManager() {
return virtualAliasManager;
}

}


Bean config from Application Context:

<bean id="editVirtualAliasValidator" class="bus.EditVirtualAliasValidator"/>
<bean id="editVirtualAliasForm" class="web.EditVirtualAliasFormController">
<property name="sessionForm"><value>true</value></property>
<property name="commandName"><value>virtualAlias</value></property>
<property name="commandClass"><value>bus.impl.VirtualAliasImpl</value></property>
<property name="validator"><ref bean="editVirtualAliasValidator"/></property>
<property name="formView"><value>editVirtualAlias</value></property>
<property name="successView"><value>listVirtualAliases.htm</value></property>
<property name="virtualAliasManager">
<ref bean="virtualAliasManager"/>
</property>
</bean>


command class (VirtualAliasImpl.java):

package bus.impl;

import bus.VirtualAlias;
import java.util.LinkedList;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class VirtualAliasImpl implements VirtualAlias {

protected final Log logger = LogFactory.getLog(getClass());

private String pattern;
private LinkedList<String> addresses = new LinkedList<String>();
private String originalPattern;


public String getPattern() {
return pattern;
}

public void setPattern(String newpattern) {
if (this.originalPattern == null) { // initial load
this.originalPattern = newpattern;
}
this.pattern = newpattern;
}

public String[] getAddresses() {
return addresses.toArray(new String[addresses.size()]);
}

public void setAddresses(String[] addresses) {
if (addresses != null) {
this.addresses.clear();

for (int i=0; i<addresses.length; i++) {
this.addresses.add(addresses[i]);
}
}
}

public void addAddress(String address) {
this.addresses.add(address);
}

public void removeAddress(String address) {
this.addresses.remove(address);
}

public boolean equals(Object o) {
return o != null &&
o instanceof VirtualAlias &&
this.pattern.equals(((VirtualAlias)o).getPatternSt ring()) &&
this.addresses.equals(((VirtualAlias)o).getAddress es());
}

public String getOriginalPattern() {
return originalPattern;
}

public String toString() {
return pattern + " " + addresses;
}

}

fjanon
Mar 2nd, 2006, 02:03 AM
I have a form with an input field called "title". I use the same form to create a new course (title, content, fee) and to edit one. I use the title as the id of the course object. It seems that the problem comes from the mapping of the HTML fields and URL encoding: "title" in the command object is set to "Tennis, Soccer".

I seems to me that if the URL has a "title" param and also contains an input field of the same name, then the mapper will concatenate the two with a comma and a space in between. I think the issue is around BeanWrapperImpl.java

Here are the request headers:

http://localhost:8080/training/editCourse.htm?title=Tennis

POST /training/editCourse.htm?title=Tennis HTTP/1.1
Referer: http://localhost:8080/training/editCourse.htm?title=Tennis
Cookie: JSESSIONID=DA00D486589D4D8060993F9E9B9DA82D
Content-Type: application/x-www-form-urlencoded
Content-Length: 57
title=Soccer&content=Beginner%27s+Level+6+weeks&fee=110