Hello, I'm using the spring MVC + Velocity + Hibernate combo. I recently changed over the new way of making forms using the BindStatus object. I am generating my selection lists with this macro:
The first time I enter the editing form, I construct the model object like this:Code:#macro( selectEntity $path $entities ) #springBind($path) <!-- status.value is $status.value.class $status.value --> <select name="${status.expression}"> #foreach($entity in $entities) #if($status.value && $status.value == $entity) #set( $sel = 'selected="true"' ) #else #set( $sel = "" ) #end <option value="${entity.id}" $sel>${entity.name}</option> #end </select> #end
When the user submits the form, I update the Object in question and create the model using:Code:public Map getModel(Object command) { return new BindException(command, "this").getModel(); }
The GameslaveBindInitializer adds a bunch of custom property editors which looks up object Ids in the database for each type I store in the database. (side note: I wonder if this could be automated based on hibernate metadata?)Code:protected Map bindAndValidate(ServletRequest request, Object command) throws ServletException { ServletRequestDataBinder binder = new ServletRequestDataBinder(command, "this"); new GameslaveBindInitializer(getStorage()).initBinder(request, binder); binder.bind(request); return binder.getErrors().getModel(); }
Now for the problem: the first time I construct the object and render the template (using getModel()), $status.value is correctly set to a gameslave.dnd35.db.* instance. However, in a subsequent edit (using bindAndValidate()), $status.value is a string, thus screwing up the form logic.
Taking a look at BindException we easily find a culprit:
Note how BindException will always return a String instance for fields with a custom editor; fields without custom editors, however, will be returned as an object. I can guess at the reasoning behind this but it is inconvenient for me.Code:public Object getFieldValue(String field) { FieldError fe = getFieldError(field); String fixedField = fixedField(field); // use rejected value in case of error, current bean property value else Object value = (fe != null) ? fe.getRejectedValue() : getBeanWrapper().getPropertyValue(fixedField); // apply custom editor, but not on binding failures like type mismatches if (fe == null || !fe.isBindingFailure()) { PropertyEditor customEditor = getCustomEditor(fixedField); if (customEditor != null) { customEditor.setValue(value); return customEditor.getAsText(); } } return value; }
I think BindStatus should have an accessor that returns the original object instead of a translated string even when there is a property editor.
As a workaround, I can check whether $status.editor is not null, and if so use $status.editor.value instead of $status.value (I think - I'll try once I'm done this post).


Reply With Quote