Rendering BindingResult error messages in a JSP

38 views
Skip to first unread message

Neil Griffin

unread,
Jan 25, 2019, 5:39:19 PM1/25/19
to MVC 1.0 Users Mailing List
One very common use-case that I have not seen in any MVC samples/demos is rendering BindingResult error messages in a JSP.

For example, I think that something like a "binding" EL keyword would be helpful:

<label for="firstName">
<fmt:message bundle="${i18n}" key="first-name" />
</label>
<input id="firstName" class="form-control" name="firstName" type="text" value="${applicant.firstName}"/>
<c:if test="${binding.hasErrors('applicant.firstName')}">
<div class="alert alert-primary" role="alert">${binding.error('applicant.firstName')}</div>
</c:if>

Thoughts?

Thanks,

-- Neil

Christian Kaltepoth

unread,
Jan 26, 2019, 1:03:40 AM1/26/19
to MVC 1.0 Users
Hey Neil,

good point. IIRC the BindingResult interface was created to be accessed from the controller only. Typically, a controller reads the BindingResult and then prepares some special model for parameter errors (and maybe other messages) which allows the view to access all the details. So you could implement a view model that can be used like shown in your example like this:

  public class BindingModel {

    private Set<ParamError> errors;

    public BindingModel( BindingResult bindingResult ) {
      this.errors = bindingResult.getAllErrors();
    }

    public boolean hasErrors(String paramName) {
      return errors.stream()
                   .anyMatch( p -> p.getParamName().equals(paramName) );
    }

    public String error(String paramName) {
      return errors.stream()
                   .filter( p -> p.getParamName().equals(paramName) )
                   .map(ParamError::getMessage)
                   .findFirst().orElse(null);
    }

    ...

  }

And in your controller:

  if( bindingResult.isFailed() ) {
    models.put("binding", new BindingModel(bindingResult));
    return "view.jsp";
  }

You can also use CDI models to make it a bit simpler. See this code in one of my example apps:
I'm not really sure about how to address this. Back then I proposed a "Messages" class which can be used to store arbitrary messages that need to be rendered (similar to the Messages class from my example), but the former spec leads voted against this. Such a messages class could also carry success messages which are also very common in web apps. So maybe this is somehow related.

There is also support for "messages" in the MVC Toolbox project, which contains some utilities for MVC apps. See:
To sum up. I'm not really sure if we found the optimal solution for this yet. And as we are close to the final release of the *first* spec version, I would prefer to target such an improvement for the next spec version. Especially because users can implement a solution which fits their needs best very easily them self.

Other thoughts?

Christian





--
You received this message because you are subscribed to the Google Groups "MVC 1.0 Users Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jsr371-users...@googlegroups.com.
To post to this group, send email to jsr371...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jsr371-users/c146a907-25fb-41cb-9446-0c1f7d5f0655%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--

Florian Hirsch

unread,
Jan 26, 2019, 6:32:31 AM1/26/19
to jsr371...@googlegroups.com
Hi Neil,

thanks for your feedback here. I also think this needs improvement  but it's nothing really missing. We're working on this spec for a long time now and it's time to deliver a 1.0. So we should focus on fixing bugs and unclear things.
After that I would add features like this in the RI or extensions and adapt the accepted ones in the next spec version.

best
Flo

Neil Griffin

unread,
Feb 1, 2019, 7:07:33 PM2/1/19
to MVC 1.0 Users Mailing List
Hi Christian, Flo,

Thanks for your replies. I also wanted to point out a related use-case of conversion. For example, given the following POJO/DTO:

public class Applicant {
    private java.util.Date dateOfBirth;
    public java.util.Date getDateOfBirth() {
        return dateOfBirth;
    }
    public void setDateOfBirth(java.util.Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }
}

And given the following markup in a JSPX view:

<input id="dateOfBirth" name="dateOfBirth" type="text" value="${applicant.dateOfBirth}"/>

Without conversion, this would render a value like "Fri Feb 01 23:53:00 GMT 2019"

Similar to the "binding" keyword, the developer would have to something like the following:

<input id="dateOfBirth" name="dateOfBirth" type="text" value="${converter.convert('applicant.dateOfBirth')}"/>

And then write a utility called Converter.java that finds the appropriate javax.ws.rs.ext.ParamConverter (by following the Spec rules, asking the BeanManager for all the ParamConverterProviders, etc..)

Is there an existing feature in MVC 1.0 that makes this easy for the developer? I didn't see it in any demos so I wrote the code to handle it in my application.

Christian Kaltepoth

unread,
Feb 3, 2019, 7:44:05 AM2/3/19
to MVC 1.0 Users
Hi Neil,

No, there is currently nothing in MVC to support  "object to string" conversion. IMO a "view model" would be responsible for preparing the data for rending in the view if required. Something like:

  public class Applicant {
      private java.util.Date dateOfBirth;
      public java.util.Date getDateOfBirthAsIsoDate() {
          return new SimpleDateFormat("yyyy-MM-dd").format(dateOfBirth);
      }
  }

But I agree that dates are usually the most problematic types. Especially if dates get submitted from HTML input elements. Currently MVC doesn't specify any binding rules for dates. We may add some explicit support in a later spec version after we get some more feedback about how developers expect something like this to work.

And it highly depends on the view engine you are using if you need a view model at all. In case of Freemarker for example you could simply do it like this:

  ${applicant.dateOfBirth?string["yyyy-MM-dd"]}

BTW: You mentioned that developers may need to look up ParamConverterProviders them self. Please note that even JAX-RS doesn't provide full support for "object to string" conversion. There is ParamConverter.toString(Object), but the API docs state:

    This method is reserved for future use. Proprietary JAX-RS extensions may leverage the method. Users should be aware that any such support for the method comes at the expense of producing non-portable code.

Christian



For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages