Announcement Announcement Module
Collapse
No announcement yet.
Spring MVC 2.5.6 - Form Select Tag not working as expected Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring MVC 2.5.6 - Form Select Tag not working as expected

    Hi everyone,

    I am doing a new web project, and still using the old property editor in spring 2.5. Recently I met a strange problem: a form Select tag has multiple values selected while it is not supposed to, and the same similar tags work fine in other places.

    Please see my code snippets below:
    Code:
    public class MyBindingInitializer implements WebBindingInitializer {
    
    	@Autowired
    	private MiscService miscService;
    
    	public void initBinder(WebDataBinder binder, WebRequest request) {
    		binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
    		SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    		dateFormat.setLenient(false);
    		binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    		binder.registerCustomEditor(BigDecimal.class, new BigDecimalEditor());
    		binder.registerCustomEditor(String.class, new StringEditor());
    		binder.registerCustomEditor(Category.class, new CategoryPropertyEditor(miscService));
    		binder.registerCustomEditor(Supplier.class, new SupplierPropertyEditor(miscService));
    		binder.registerCustomEditor(Color.class, new ColorPropertyEditor(miscService));
    		binder.registerCustomEditor(Size.class, new SizePropertyEditor(miscService));
    	}
    
    }
    Code:
    @Entity
    @Table(name="size_def", uniqueConstraints=@UniqueConstraint(columnNames={"name"}))
    public class Size extends BaseObject {
    
    	private static final long serialVersionUID = 1L;
    
    	private Long id;
    
    	private String name = "";
    
    	private String systemCode = "";
    
    	private Integer seqNo;
    
    	private Integer version;
    	
    	
    	@Id 
    	@GeneratedValue(strategy = GenerationType.AUTO)
    	public Long getId() {
    		return id;
    	}
    	
    	public void setId(Long id) {
    		this.id = id;
    	}
    	
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	@Column(name="sys_code")
    	public String getSystemCode() {
    		return systemCode;
    	}
    
    	public void setSystemCode(String systemCode) {
    		this.systemCode = systemCode;
    	}
    
    	@Column(name="seqno")
    	public Integer getSeqNo() {
    		return seqNo;
    	}
    
    	public void setSeqNo(Integer seqNo) {
    		this.seqNo = seqNo;
    	}
    
    	@Version
    	public Integer getVersion() {
    		return version;
    	}
    	
    	public void setVersion(Integer version) {
    		this.version = version;
    	}
    	
    	@Override
    	public boolean equals(Object o) {
    		boolean equals = false;
    		if (o!= null && Size.class.isAssignableFrom(o.getClass()) ) {
    			Size c = (Size) o;
    			equals = (new EqualsBuilder()
    				.append(getName(), c.getName()))
    				.isEquals( );
    		}
    		return equals;
    
    	}
    	
    	@Override
    	public int hashCode() {
    		return (getName() != null ? getName().hashCode() : 0);
    	}
    	
    	@Override
    	public String toString() {
    		return new ToStringBuilder(this, ToStringStyle.SIMPLE_STYLE).append(getName()).toString();
    	}
    }
    Code:
    public class SizePropertyEditor extends PropertyEditorSupport {
    
    	private MiscService miscService;
    
        public SizePropertyEditor(MiscService miscService) {
            this.miscService = miscService;
        }
    
        public void setAsText(String text) throws IllegalArgumentException {
        	if(StringUtils.isBlank(text)){
        		setValue(null);
        	}
        	else{
    	        Long id = Long.parseLong(text);
    	        Size s = (Size)miscService.get(Size.class, id);
    	    	setValue(s);
        	}
        }
    
        public String getAsText() {
        	Object value = getValue();
        	if(value==null) return "";
        	
        	Size s = (Size)value;
        	return ""+s.getId();
        }
    
    }

    Code:
    @Controller
    @SessionAttributes("productVariant")
    public class ProductVariantFormController extends BaseController {
    
    	@RequestMapping(method=RequestMethod.GET, params="method=edit")
    	public void edit(@RequestParam("id") Long id, ModelMap model){
    		ProductVariant productVariant = (ProductVariant) miscService.get(ProductVariant.class, id);
    		model.addAttribute(productVariant);
    	}
    	
    	@RequestMapping(method=RequestMethod.GET, params="method=add")
    	public void add(@RequestParam("prodId") Long prodId, ModelMap model){
    		ProductEntity pe = (ProductEntity)miscService.get(ProductEntity.class, prodId);
    		ProductVariant productVariant = new ProductVariant();
    		productVariant.setProductEntity(pe);
    		model.addAttribute(productVariant);
    	}
    
    	@RequestMapping(method=RequestMethod.POST)
    	public String processSubmit(HttpServletRequest request,
    			@ModelAttribute("productVariant") ProductVariant productVariant, 
    			BindingResult result, SessionStatus status){
    		
    		ProductVariantValidator productVariantValidator = new ProductVariantValidator(miscService);
    		productVariantValidator.validate(productVariant, result);
    		if(result.hasErrors()){
    			translateErrors(result, request);
    			return "/catalog/productVariantForm";
    		}
    		
    		productVariant = (ProductVariant) miscService.save(productVariant);
    		saveFormMessage(request, messageSource.getMessage("changes.saved", null, request.getLocale()));
    		
    		status.setComplete();
    		
    		return "redirect:/catalog/productVariantForm.html?method=edit&id=" + productVariant.getId();
    	}
    	
    	@SuppressWarnings("unchecked")
    	@ModelAttribute("colorList")
    	public List<Color> getAllColors(){
    		List<Color> colorList = miscService.getAll(Color.class);
    		Collections.sort(colorList, new GenericComparator("name"));
    		return colorList;
    	}
    
    	@SuppressWarnings("unchecked")
    	@ModelAttribute("sizeList")
    	public List<Size> getAllSizes(){
    		List<Size> sizeList = miscService.getAll(Size.class);
    		Collections.sort(sizeList, new GenericComparator("seqNo"));
    		return sizeList;
    	}
    	
    }
    Code:
    <form:form modelAttribute="productVariant" cssStyle="width: 100%;">
    
    <%@ include file="/common/formMessages.jsp" %>
    
    <table class="borderless">
    	<tr>
    		<td>
    			Product
    		</td>
    		<td>
    			${productVariant.productEntity.name}
    		</td>
    	</tr>
    	<tr>
    		<td>
    			SKU<span class="required">*</span>
    		</td>
    		<td>
    			<form:input path="sku" size="80" maxlength="128"></form:input>
    		</td>
    	</tr>
    	<tr>
    		<td>
    			Color
    		</td>
    		<td>
    			<form:select path="color">
    				<form:option value="" label="Select"/>
    	            <form:options items="${colorList}" itemValue="id" itemLabel="name"/>
    			</form:select>
    		</td>
    	</tr>
    	<tr>
    		<td>
    			Size
    		</td>
    		<td>
    			<form:select path="size">
    				<form:option value="" label="Select"/>
    	            <form:options items="${sizeList}" itemValue="id" itemLabel="name"/>
    			</form:select>
    		</td>
    	</tr>
    ...
    
    	<tr>
    		<td></td>
    		<td>			
    			<form:hidden path="version" />
    			<a class="button" href="#" onclick="$('#productVariant').submit(); return false;">
    				<span><fmt:message key="button.save"/></span>
    			</a>
    			&nbsp;
    			<a class="button" href="<c:url value='/catalog/productEntityForm.html'/>?method=edit&id=${productVariant.productEntity.id}">
    				<span><fmt:message key="button.cancel"/></span>
    			</a>
    		</td>
    	</tr>
    </table>
    
    </form:form>
    The strange thing is, the color select tag works totally fine with similar setting (background list and property editor), while the size select tag has got two values selected (id=1 or id=5), while only the first one is correct. I've also checked the size object fields, and it's correct.

    Could anyone have a hint of what might be wrong?

    By the way, after I replace the form:option tags with old fashioned codes below, it works fine:

    Code:
    			<form:select path="size">
    		        <c:choose>
    		            <c:when test="${productVariant.size==null}">
    		                <option selected="true" value="">Select</option>
    		            </c:when>
    		            <c:otherwise>
    		                <option value="">Select</option>
    		            </c:otherwise>
    		        </c:choose> 
    				<c:forEach var="s" items="${sizeList}">
    			        <c:choose>
    			            <c:when test="${productVariant.size.id eq s.id}">
    			                <option selected="true" value="${s.id}">${s.name}</option>
    			            </c:when>
    			            <c:otherwise>
    			                 <option value="${s.id}">${s.name}</option>
    			            </c:otherwise>
    			        </c:choose> 
    			    </c:forEach>
    			</form:select>
    But I am not happy with it, as this is verbose, and it's supposed to be done by the form:options tags.

    Thanks for help in advance.

    Mark
Working...
X