Announcement Announcement Module
Collapse
No announcement yet.
Binding errors vs Validation errors Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Binding errors vs Validation errors

    Hi,

    I'm having a small difficulty maintaining my error messages. Let's say I have the following scenario:

    On my form, I have a field where I can enter a Date in a specific format. When entering no date or a non date value, an exception is thrown by Spring which will then be mapped by an error in my error.properties file (so that I don't see the verbose error message from spring in my page)
    On the other hand, I have validator specified to check if the date field is not empty.

    In my JSP, I loop over my errors and display each of them on top of the screen. When the date field was left empty, I will then see 2 messages for that date field. I could for example drop the validation of the date field in my validator. But the thing is, when I am having 2 date fields to enter, I want to specifiy in my error message which one was not valid. The binding error will display 2 times that there was an error on binding a Date.

    If someone could help me out, I would really appreciate that

  • #2
    can you post some code snippet?

    Comment


    • #3
      Here is some code:

      Code:
      Init binder for the date values in the form
      
      @Override
      	protected void initBinder(HttpServletRequest request,
      			ServletRequestDataBinder binder) throws Exception {
      		//Create a custom binder that will convert a String with pattern dd/MM/yyyy to an appropriate Date object.
      		SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
      		binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
      	}
      Code:
      Code for validating dates:
      
      private void validatePage1(Object target, Errors errors) {
      		CampaignWizardData data = (CampaignWizardData) target;
      		//If the wizard is in update mode, don't do the validation there because the controller will redirect you to that page in case
      		//of errors, this is due to the fact that a check is done on the existence of a campaign with the filled in name.
      		if (!data.isUpdate() && !data.isCopy()) {
      		    ValidationUtils.rejectIfEmptyOrWhitespace(errors, "startDate", "errors.startDate","Please fill in a valid start date");
      		    ValidationUtils.rejectIfEmptyOrWhitespace(errors, "endDate", "errors.endDate","Please fill in a valid end date");
      		    if (data.getEndDate() != null && data.getStartDate() != null && data.getEndDate().before(data.getStartDate())) {
      	            errors.reject("errors.endDateBeforeStartDate", "The end date should come after the start date");
      	        }else if (data.getEndDate() != null && data.getStartDate() != null && data.getStartDate().before(DateUtils.addDays(DateUtils.truncate(new Date(), Calendar.DATE), 1))) {
      	            errors.reject("errors.startDateBeforeToday", "The start date should be at least one day after today");
      	        }
      	        if (pmgmFacade.checkExistingCampaignName(data.getName())) {
      	            errors.reject("errors.campaignName", "A campaign with this name already exists");
      	        }
      		}
      		
      }
      Code:
      Displayal of errors in the jsp page:
      
      ...
      <spring:bind path="campaignData.*">
      	<c:if test="${not empty status.errorMessages}">
      		<c:forEach items="${status.errorMessages}" var="error">
      			<c:out value="${error}" escapeXml="false"/> <br />
      	    </c:forEach>
      	</c:if>
      </spring:bind>
      
      ....

      Comment


      • #4
        your can have the following in your error.properties file..

        typeMismatch.startDate = Invalid Start Date
        typeMismatch.endDate = Invalid End Date

        cusstermize the messages for each property as you want...
        then drop the validation for empty string in your validator class for both properties.

        so when the user leave a date field empty or keys in a invalid input the relevent error message will be displayed..

        Comment


        • #5
          Thank you rukshan, that really did the trick

          I thought you could only map the errors on their type like 'typeMismatch.java.util.date'

          Comment


          • #6
            actually there are some more available variables to map:

            inspecting the error object:

            Field error in object 'order' on field 'dateStart': rejected value [];
            codes [typeMismatch.order.dateStart,typeMismatch.dateStar t,typeMismatch.java.util.Date,typeMismatch];
            arguments [org.springframework.context.support.DefaultMessage SourceResolvable: codes [order.dateStart,dateStart];
            arguments [];
            default message [dateStart]];
            default message [Failed to convert property value of type [java.lang.String] to required type [java.util.Date] for property 'dateStart';
            nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: ""]

            the codes section is what you're looking for, overriding any of the following codes in ur properties file will lead to custom messages:

            typeMismatch
            typeMismatch.java.util.Date
            typeMismatch.dateStart
            typeMismatch.order.dateStart

            where "order" is actually the name of the command you used on your form <spring:form commandName="order" ...>
            <spring:input path="dateStart">
            .. etc.

            dont forget to inject the commandname to your controller as well (or set it through the controllers constructor).

            Comment


            • #7
              you are welcome...

              If I'm not wrong the following mapping should work as well

              typeMismatch.campaignData.startDate = Invalid Start Date
              typeMismatch.campaignData.endDate = Invalid End Date

              generally its like typeMismatch.commandName.propertyName

              Comment


              • #8
                That's even a better solution. In that way, I could create different error messages even if the field names are the same for the command objects

                Comment


                • #9
                  It's even gonna be better. Check the error object again.

                  there's a line saying this:
                  arguments [org.springframework.context.support.DefaultMessage SourceResolvable: codes [order.dateStart,dateStart];

                  if you gonna override one of those codes in you're properties file you can do something like this:

                  order.dateStart=Order startdate
                  typeMismatch.java.util.Date={0} is an invalid date

                  the message will be resolved as:
                  "Order startdate is an invalid date"

                  Mixing a very generic date parsing error with a specific fieldname. One thing to consider is that you'd have to override the resolvable fieldname for each date field you use or the system will use the default name.

                  Comment


                  • #10
                    Very nice. You did a great job finding this out I think it would be great if such examples would be in the reference manual (if it isn't already included of course)

                    Comment


                    • #11
                      Last but not least. If you use the commons validator. You can create those error objects yourself as well. Basically thats what the property binder is doing as well: rejecting values because they cannot be bound.

                      errors.rejectValue("order.dateStart", "error.field.invalid.mustSelect",
                      new Object[] { new DefaultMessageSourceResolvable(
                      new String[]{ "order.dateStart" })}, null);

                      error.field.invalid.mustSelect= {0} must be selected
                      order.dateStart=Order startdate

                      acumulates to: "Order startdate must be selected"

                      it looks perhaps a bit complicated. Basically what ur doing is passing a list of objects (new Object[]) as parameters for the supplied message code (so yes you can give more the one {} parameter in a message code). The DefaultMessageSourceResolvable resolves the list of given parameters (new String[]) to Strings from your message.properties file (or whatever you named it). Im not sure wether the list given to the DefaultMessageSourceResolvable is a priority list (seems to be the case looking at the error object).

                      Comment


                      • #12
                        Originally posted by Krycek_A View Post
                        Very nice. You did a great job finding this out I think it would be great if such examples would be in the reference manual (if it isn't already included of course)
                        I cant take full credit, Bbut i think its important enough to repeat and enhance.

                        Comment


                        • #13
                          That's true, but at least you saved me a lot of time

                          Comment


                          • #14
                            http://static.springframework.org/sp...sResolver.html

                            Comment


                            • #15
                              Thanks, it seems that it is already documented but I was looking at the wrong place

                              Comment

                              Working...
                              X