1 / 44

Spencer Uresk

Spring MVC, Part 3. Spencer Uresk. Notes. This is a training, NOT a presentation Please ask questions This is being recorded https://tech.lds.org/wiki/Java_Stack_Training Prerequisites Spring MVC 1 and 2. Objectives. Learn the basics of data binding

kane
Download Presentation

Spencer Uresk

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Spring MVC, Part 3 Spencer Uresk

  2. Notes • This is a training, NOT a presentation • Please ask questions • This is being recorded • https://tech.lds.org/wiki/Java_Stack_Training • Prerequisites • Spring MVC 1 and 2

  3. Objectives • Learn the basics of data binding • Be able to write your own conversion service • Save time by using Spring’s form tags • Be able to validate your model objects in an easy, reusable way

  4. Data Binding • Binding is the way in which request parameters get turned into model objects • Properties get set based on their names /echo/person?name=Spencer&age=5 public class Person { private String name; private int age; // Getters and Setters } @RequestMapping("/echo/person") public @ResponseBody String doSomething(Person person) { return person.getName(); }

  5. Properties • name - getName()/setName() • person.name – getPerson().getName()/getPerson().setName() • person[1] – The first person in an array, list, or other ordered collection named person. • people[BOB] – The value of the map entry indexed by the key BOB in the Map people.

  6. Demo DEMO

  7. ConversionService • Since all parameters are Strings, how do they get turned into non-String values? • How do they get turned back into Strings for display on the page? • Spring’s ConversionService • Takes a type S and returns type T • Spring MVC comes with a lot of these pre-configured, but you can add your own

  8. Some pre-configured converters • String to Boolean • String to Number (ie, int, long, etc..) • String to Date • String to Locale • String to Enum • (and vice-versa for all of these) • Doesn’t always have to include a String on one side

  9. Adding new Converters • Figure out what source you want to use (S) • Figure out what the target type should be (T) • Implement the Converter<S, T> interface public class BigIntNumberConverterimplements Converter<String, BigInteger> { public BigInteger convert(String source) { return new BigInteger(source); } }

  10. Custom Converter • Add some configuration to tell Spring MVC to use a custom conversion service • Add some configuration to your Spring MVC config to tell Spring MVC about your converter <mvc:annotation-drivenconversion-service="conversionService"/> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="org.lds.view.BigIntNumberConverter" /> </set> </property> </bean>

  11. Field Formatting • Conversions are useful when just converting from one type of data to another • Field formatting can be useful for when there is actual formatting that needs to occur • Number and Date formatters are built in (Date formatters require Joda time) public class Person { @NumberFormat(style=Style.CURRENCY) private BigDecimal salary; }

  12. What about errors? • What happens if you put ‘asdf’ in a number field? • A conversion error occurs • Which throws an exception • You can tell Spring to add that error to an Errors object to more gracefully deal with conversion errors

  13. Errors • Errors holds a list of errors that apply to a model object • Allows you to deal with binding (and other) errors yourself • Must be positioned immediately after the model object in the parameter list • Also used for Validation errors • BindingResult extends Errors and contains more information about the model object itself

  14. Customizing Error Messages • Default error messages are long and ugly • Customize them by adding properties to your message bundle • By target type: • typeMismatch.java.lang.Long={0} must be a number. • typeMismatch.int=Must be a number. • Note primitives are different than their wrappers • Globally: • typeMismatch=You entered something in wrong.

  15. Displaying Error Messages • Add a <spring:hasBindErrors /> tag for your model object • It makes an errors variable available that has a list of all error messages • You choose how to display the actual messages • <spring:hasBindErrors name="person"> • The following errors were found: • <br /><br /> • <ul> • <c:forEach items="${errors.allErrors}" var="error"> • <li><spring:message message="${error}"/></li> • </c:forEach> • </ul> • </spring:hasBindErrors>

  16. Demo DEMO

  17. Lab 1 • Create a model object that we’ll use for data binding • Populate its values by adding parameters to the query string • Create a simple form to do the same • Customize the conversion error messages

  18. Spring’s form tag library • Binding-aware JSP tags for handling form elements • Integrated with Spring MVC to give the tags access to the model object and reference data • Comes from spring-webmvc.jar • Add the following to make the tags available: <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

  19. The form tag • Renders a form tag and exposes the binding to inner tags • You can specify any HTML attributes that are valid for an HTML form • You can also tell it what the form backing object is (it uses ‘command’ by default).

  20. The form tag - Example @RequestMapping("/person/add") public String addPerson(Model model) { Person person = new Person(); model.addAttribute(person); return "addPerson"; } <form:form method=”get” commandName=”person”> <form:input path=”name” /> </form:form> <form method=”get”> <input type=”text” name=”name” /> </form>

  21. The input tag • Renders an HTML input tag with a type of ‘text’ • You can specify any HTML attributes valid for an HTML input • You bind it to your model object by specifying the path relative to the backing object

  22. The input tag - Example @RequestMapping("/person/add") public String addPerson(Model model) { Person person = new Person(); person.setName(”Spencer”); model.addAttribute(person); return "addPerson"; } <form:form method=”get” commandName=”person”> <form:input path=”name” /> </form:form> <form method=”get”> <input type=”text” name=”name” value=”Spencer” /> </form>

  23. The checkbox tag • Renders an HTML input tag with a type of ‘checkbox’ public class Person { private boolean admin; private String[] languages; } • <form:form commandName=”person”> • <form:checkbox path=”admin” /> • <form:checkbox path=“languages” value=“Java” /> • <form:checkbox path=“languages” value=“Scala” /> • </form:form> • <form> • <input type=”checkbox” name=”admin” value=”true” /> • <input type=”checkbox” name=”languages” value=”Java” /> • <input type=”checkbox” name=”languages” value=”Scala” /> • </form>

  24. The checkboxes tag • Similar to checkbox tag, but creates multiple checkboxes instead of one public class Person { private boolean admin; private String[] favoriteLanguages; private List<String> allLanguages; } • <form:form commandName=”person”> • <form:checkbox path=”admin” /> • <form:checkboxes path=”favoriteLanguages” items=”${allLanguages}” /> • </form:form> • <form> • <input type=”checkbox” name=”admin” value=”true” /> • <input type=”checkbox” name=” favoriteLanguages” value=”Java” /> • <input type=”checkbox” name=” favoriteLanguages” value=”Scala” /> • </form>

  25. The password tag • Renders an HTML input tag with a type of ‘password’ <form:form> <form:input path=”username” /> <form:password path=”password” /> </form:form> <form> <input type=”text” name=”username” /> <input type=”password” name=”password” /> </form>

  26. The select tag • Renders an HTML select tag • It can figure out whether multiple selections should be allowed • You can bind options using this tag, as well as by nesting option and options tags <form:select path=”favoriteLanguage” items=”${allLanguages}” /> <select name=”favoriteLanguage”> <option value=”Java”>Java</option> <option value=”Scala”>Scala</option> </form>

  27. The option/options tags • Renders an HTML option (or multiple options) • Nested within a select tag • Renders ‘selected’ based on the value bound to the select tag <form:select path=”favoriteLanguage”> <form:option value=”3” label=”.NET” /> <form:options items=”${languages}” itemValue=”id” itemLabel=”name” /> </form:select> <select name=”favoriteLanguage”> <option value=”.NET”>.NET</option> <option value=”Java”>Java</option> <option value=”Scala”>Scala</option> </form>

  28. The errors tag • Renders an HTML span tag, containing errors for given fields • You specify which fields to show errors for by specifying a path • path=“name” – Would display errors for name field. • path=“*” – Would display all errors <form:errors path=”*” cssClass=”errorBox” /> <form:errors path=”name” cssClass=”specificErrorBox” /> <span name=”*.errors” class=”errorBox”>Name is required.</span> <span name=“name.errors” class=“specificErrorBox”>Name is required.</span>

  29. Demo DEMO

  30. Lab 2 • Rewrite our form from Lab 1 to use Spring’s taglib • Add in some errors tags to handle conversion errors • Add a favorite language checkbox

  31. Validation • Spring supports a number of different types of validation • Validation shouldn’t be tied to the web tier • Should be easy to localize • Should be easy to plug in any validator • Spring MVC’s validation support provides all of these attributes

  32. Validator interface • org.springframework.validation.Validator • supports – Returns a boolean indicating whether or not the target class can be validated by this validator • validate – In charge of actually performing validation. Validation errors should be reported by adding them to the errors object. public interface Validator { boolean supports(Class<?> clazz); void validate(Object target, Errors errors); }

  33. Validator Example public class PersonValidator implements Validator { /** * This Validator validates just Person instances */ public boolean supports(Class clazz) { return Person.class.equals(clazz); } public void validate(Object obj, Errors e) { ValidationUtils.rejectIfEmpty(e, "name", "name.empty"); Person p = (Person) obj; if (p.getAge() < 0) { e.rejectValue("age", "negativevalue"); } else if (p.getAge() > 110) { e.rejectValue("age", "too. old"); } } }

  34. Invoking our Validator • We can invoke our Validator in our controller code @RequestMapping(value = "/person/add", method = RequestMethod.POST) public String createPerson(Person person, Errors errors) { PersonValidator pv = new PersonValidator(); ValidationUtils.invokeValidator(pv, person, errors); if(errors.hasErrors()) { return "addPerson"; } return "viewPerson"; }

  35. JSR-303 Bean Validator API • We use the Hibernate Validator implementation of this API • Standardizes validation metadata and declaration • To use it, you annotate model properties with validation annotations • A number of useful built-in annotations are available • You can also make your own (outside the scope of this training)

  36. Some Examples • What are we validating here? • Length of ‘name’ is between 3 and 7 chars (inclusive) • Age is between 0 and 120 (inclusive) @Size(min=3, max=7) private String name; @Max(value=120) @Min(0) private Integer age;

  37. Custom error messages • Each validation error has an error message • How do we override it? • 1. Change the global message for that validator • 2. Manually pass in a message • 3. Define and use a specific property javax.validation.constraints.Min.message=Value must be at least {value} @Size(min=3, max=7, message = "Your name must be between 3 and 7 characters.") @Max(value=120, message="{age.too.old}") // Annotation age.too.old=Age must be under 120.// Message bundle property

  38. Demo DEMO

  39. Configuration • How do we tell Spring we want to use JSR-303 validation? • It is already done in the Stack • First, configure a validator in the main applicationContext (remember, this is reusable across tiers!) • Then, tell Spring MVC to use that validator

  40. Configuration • applicationContext.xml (we’re also telling it to use our messageSource bean to find messges) • *-servlet.xml <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <property name="validationMessageSource" ref="messageSource"/> </bean> <mvc:annotation-driven validator="validator" />

  41. Validating Controller Input • In Spring MVC, we can automatically validate controller inputs • Causes person to be validated, will throw validation exceptions • Allows us to gracefully handle validation errors public String createPerson(@Valid Person person) {} public String createPerson(@Valid Person person, Errors errors) { if(errors.hasErrors()) { return "addPerson"; } return "viewPerson"; }

  42. @Valid • In theory, it should also work on parameters annotated with @RequestBody • But it doesn’t • It will, however, work in Spring 3.1

  43. Lab 3 • Validate our person object • Make sure they supply a name that is at least 3 characters • Make sure they supply an age between 0 and 125 • Customize the error messages

  44. Resources • Spring Form taglib documentation • http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/view.html#view-jsp-formtaglib • Spring MVC documentation • http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html

More Related