You're trying to do validation in a binder. That's not the binder's purpose. A binder is supposed to bind request parameters to your backing object, nothing more.
A property editor converts Strings to objects and vice versa - it is not designed to do anything else.
You're trying to do validation in a binder. That's not the binder's purpose. A binder is supposed to bind request parameters to your backing object, nothing more.
A property editor converts Strings to objects and vice versa - it is not designed to do anything else. In other words, you need to consider separation of concerns - you're trying to shoehorn functionality into an object that was never meant to do anything more than convert a string into an object and vice versa. You might consider breaking up your SSN object into multiple, validateable fields that are easily bound (String objects, basic objects like Dates, etc).
This way you can use a validator after binding to verify that the SSN is correct, or you can set an error directly. With a property editor, you throw an IllegalArgumentException, Spring converts it to a type mismatch error because that's what it is - the string doesn't match the type that is expected. That's all that it is.
A validator, on the other hand, can do this. You can use the spring bind tag to bind to nested fields, as long as the SSN instance is populated - it must be initialized with new() first. For instance: ... If you truly want to persist on this path, however, have your property editor keep a list of errors - if it is to throw an IllegalArgumentException, add it to the list and then throw the IllegalArgumentException (catch and rethrow if needed).
Because you can construct your property editor in the same thread as the binding, it will be threadsafe if you simply override the property editor default behavior - you need to find the hook it uses to do binding, and override it - do the same property editor registration you're doing now (except in the same method, so that you can keep the reference to your editor) and then at the end of the binding, you can register errors by retrieving the list from your editor if you provide a public accessor. Once the list is retrieved you can process it and add your errors accordingly.
I was afraid of this and I'm a bit disappointed with Spring's form handling. From what I'm hearing the "correct" Spring approach is to perform validation before the binding. So this means creating a form command with string fields.
– Steve Kuo Apr 9 '09 at 17:50 Continued from prev comment: The validator validates these fields. The controller's onSubmit would then convert the string fields to their correct type and set the value on the backing model. This is a pain because now I have to re-create each editable field as a string in the form's command.
– Steve Kuo Apr 9 '09 at 17:51 No, you validate after you bind - binding is not supposed to validate anything - if you do want this, another alternate approach is to create some sort of errors list in your specific object and store the errors in it when you bind, and have the validator check this list... – MetroidFan2002 Apr 10 '09 at 15:57 Your problem is that you are trying to validate specific fields inside binding an object, which is why the fields should be separate on your form object to begin with - this way, Spring can bind each field, and you can manually post process this in doBind to make it your object if needed. – MetroidFan2002 Apr 10 '09 at 15:58 +1 with Metroid. BaseCommandController binds data from incoming request to your command object, and then calls yours Validator.
Take a look @Javadoc for BaseCommandController for details (Im' brief cause I don't want to post a new fully detail reply as this one is perfectly OK :) – Olivier Apr 10 '09 at 22:02.
What I want is the specific error message generated by the PropertyEditor to surface to the error message on the Spring form Behind the scenes, Spring MVC uses a BindingErrorProcessor strategy for processing missing field errors, and for translating a PropertyAccessException to a FieldError. So if you want to override default Spring MVC BindingErrorProcessor strategy, you must provide a BindingErrorProcessor strategy according to: public class CustomBindingErrorProcessor implements DefaultBindingErrorProcessor { public void processMissingFieldError(String missingField, BindException errors) { super. ProcessMissingFieldError(missingField, errors); } public void processPropertyAccessException(PropertyAccessException accessException, BindException errors) { if(accessException.getCause() instanceof IllegalArgumentException) errors.
RejectValue(accessException. GetPropertyChangeEvent().getPropertyName(), "", accessException.getCause().getMessage()); else defaultSpringBindingErrorProcessor. ProcessPropertyAccessException(accessException, errors); } } In order to test, Let's do the following protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) { binder.
RegisterCustomEditor(SSN. Class, new PropertyEditorSupport() { public String getAsText() { if(getValue() == null) return null; return ((SSN) getValue()).toString(); } public void setAsText(String value) throws IllegalArgumentException { if(StringUtils. IsBlank(value)) return; boolean somethingGoesWrong = true; if(somethingGoesWrong) throw new IllegalArgumentException("Something goes wrong!"); } }); } Now our Test class public class PersonControllerTest { private PersonController personController; private MockHttpServletRequest request; @BeforeMethod public void setUp() { personController = new PersonController(); personController.
SetCommandName("command"); personController. SetCommandClass(Person. Class); personController.
SetBindingErrorProcessor(new CustomBindingErrorProcessor()); request = new MockHttpServletRequest(); request. SetMethod("POST"); request. AddParameter("ssn", "somethingGoesWrong"); } @Test public void done() { ModelAndView mav = personController.
HandleRequest(request, new MockHttpServletResponse()); BindingResult bindingResult = (BindingResult) mav.getModel(). Get(BindingResult. MODEL_KEY_PREFIX + "command"); FieldError fieldError = bindingResult.
GetFieldError("ssn"); Assert. AssertEquals(fieldError.getMessage(), "Something goes wrong!"); } } regards.
This sounds similar to an issue I had with NumberFormatExceptions when the value for an integer property could not be bound if, say, a String was entered in the form. The error message on the form was a generic message for that exception. The solution was to add my own message resource bundle to my application context and add my own error message for type mismatches on that property.
Perhaps you can do something similar for IllegalArgumentExceptions on a specific field.
I believe you could just try to put this in your message source: typeMismatch.person. Ssn=Wrong SSN format.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.