SlideShare a Scribd company logo
1 of 36
Download to read offline
Spring MVC
Introduction / Gore
Ted Pennings
NHJUG Co-Founder
16 November 2010
Who’s Ted
✦ Developer with Fortune 100 financial services firm
since July 2008.
✦ Working with Java since late 2008.
✦ Web developer as freelance/hobby since 2001
(LAMP)
✦ Lots of freelancing and web hosting during college
✦ http://ted.pennin.gs / @thesleepyvegan / ted@pennin.gs
What is MVC?
✦ MVC spits code into three areas
✦ Model – data/persistence
layer
✦ View – presentation layer, UI
and client-side scripts
✦ Controller – business logic
that controls data and
execution
✦ Strong design pattern that
emphasizes separation.
MVC Cleanliness
✦ Application logic goes in the controllers.
✦ Data persistence goes in the model.
✦ UI presentation and JavaScript varnish goes in the
views.
✦ Do not try to fight MVC code separation. If you
feel the need to break convention, refactor.
MVC Done Badly – Views
✦Doing actual work in JSPs
<%
try {
String url="jdbc:mysql://localhost/companies?user=larry_ellison&password=yachts";
con=DriverManager.getConnection(url);
stmt=con.createStatement();
} catch(Exception e){ System.err.println(“Unable to acquire companies!”);
e.printStackTrace(); }
if (request.getParameter("action") != null){
String bookname = request.getParameter("company_name");
String author = request.getParameter("price");
stmt.executeUpdate("insert into acquisitions(company_name,price) values
('"+company_name+"','"+price+"')");
rst=stmt.executeQuery("select * from acquisitions");
%>
<html> <body> <center>
<h2>Victim List</h2>
<table border="1" cellspacing="0" cellpadding="0">
Adapted from http://www.roseindia.net/jsp/Accessingdatabase-fromJSP.shtml
MVC Done Badly – Controllers
✦HTML in the controllers
@RequestMapping(“/acquisitions/new”)
public void createAcquisition(Model model) {
Acquisition v = new Acquisition();
model.addAttribute(“newVictim”, v);
model.addAttribute(“newVictimForm”, collectVictimVitalStats(v));
}
private String renderVictimInfoForm(Acquisition v) {
StringBuilder sb = new StringBuilder()
.append("<form action='").append(SERVLET_PATH)
.append("' method='post'><h1>Please enter your information</h1>");
sb.append("<p><label for='name'>Victim Name</label>")
.append("<input type='text' name='name' value='")
.append(v.getName()).append("'/>").append("</p>");
[...]
return sb.toString();
}
Speaking of Bad Things
Oracle CEO Larry Ellison
MVC Done Badly – Models
✦Business logic in the model
public class Victim {
private String name;
private short numberOfYachts;
[. . . ]
public Victim(String name, short numberOfYachts) {
if (numberOfYachts < 4) {
throw new VictimUnworthyException(“Too few yachts. Larry Ellison will not be sated.”);
}
}
[. . . ]
}
✦HTML in methods
public String toString() {
return “<h3 class=‘name’>Why Hello ” + this.name + “!</h3><br/>I admire your”
+ “<strong><font color=“pink”>” + this.numberOfYachts + “</font></strong> yachts”;
}
Spring MVC is Still Spring
✦ Full Dependency Injection and Inversion of Control
✦ XML- and Annotation-based configuration
✦ Heavy use of annotation-based configuration
✦ Application context files are still available, but mostly
unnecessary
✦ <mvc:annotation-driven> and <content:component-scan>
✦ Maven dependencies and archetypes
✦ Convention over configuration
✦ Very few interfaces to implement
“Spring Goodness”
The Basic Annotations
✦ Spring MVC is mostly annotation driven, so here is your
vernacular:
✦ Standard Spring annotations:
✦ @Component, @Service, @Repository,
✦ @Autowired, @Value, @Configuration
✦ @Transactional, @Aspect and JSR 284 + 330
✦ @Controller – an MVC Controller
✦ @RequestMapping
✦ @ModelAttribute
✦ @RequestParam and @PathVariable
✦ @SessionAttributes
How does Spring do MVC?
✦ All requests are sent to Spring’s DispatcherServlet
✦ DispatcherServlet sends requests to @Controllers
✦ THERE ARE NO DEVELOPER-WRITTEN SERVLETS
Diagram from Spring docs on their website
The Simplicity of Controllers
✦ @Controller makes a class a controller “bean”
✦ Specialization of @Component
✦ @RequestMapping defines the URL paths handled by a
controller or method.
✦ It is possible to nest paths, as in example.
✦ Many different RequestMethods can be serviced.
✦ {} define @PathVariable/@ReqParam
✦ Value of Inheritance
✦ Annotation caveat
Controller Example
@Controller
@RequestMapping({ "/yachts", "/mah-boats" })
public class YachtController extends BaseController {
@RequestMapping(value = "/{yachtKey}", method = GET)
public String displayYacht( @PathVariable(“yachtKey”) String
yachtKey, Model model) {
LOG.debug("Displaying Yacht " + yachtKey);
Yacht yacht = service.findYachtByKey(yachtKey);
model.addAttribute("yacht", yacht);
return YACHT_PAGE_VIEW;
}
}
Reading User Input
✦ Typically happens through method parameter annotations
✦ @PathVariable(“var”) / @RequestParam(“var”)
✦ Corresponds to a {var} value in a @RequestMapping
✦ Best practice to be explicit
✦ @ModelAttribute
✦ @RequestBody
✦ Any type can be used.
✦ Be wary of type conversion issues
✦ See PropertyEditorSupport and Spring’s Converter SPI
✦ Use @InitBinder in a controller superclass
✦ JSON payloads can often be unmarshalled on the fly.
Populating The Model
✦ In MVC, dynamic data only appears in views through the model.
✦ Spring MVC enforces this pattern constraint.
✦ Each request receives a fresh new Model (or equivalent).
✦ Two basic approaches
✦ In @Controller method, receive a Model or ModelAndView object
✦ Add directly to it.
✦ No need to return Model/MV object received. (More on that later.)
✦ In @Controller class, annotate methods with @ModelAttribute(“name”)
✦ Used in a @Controller superclass, can be used for template data
✦ User privileges
✦ Pseudo-security hack until full security is implemented
Creating Forms (1/2)
✦ Creating a new object submission form requires manually instantiating your
target object
✦ if you want to create a com.oracle.acquisition.timekeeper.model.TimeEntry(),
in your controller method you must
✦ model.addAttribute(“timeEntry”, new
com.oracle.acquisition.timekeeper.model.TimeEntry());
Assuming:
package com.oracle.acquisition.timekeeper.model;
public class TimeEntry {
private String victimName;
private String projectCode;
private double hours;
private Date timestamp;
[…getters, setters, etc…]
}
✦ This exact object will be used by your JSP (or similar) in the
next step… getter/setter round-tripping on POST
Creating Forms (2/2)
Most new object views can function as an edit view. Conserve code.
<form:form method="post" modelAttribute=“timeEntry"
cssClass="form">
<form:label path=“projectCode">
Project Code <form:errors path=“projectCode"
cssClass="error" />
</form:label>
<form:select items="${userProjectCodes}"
path=“projectCode“ itemLabel=“projectName"/>
<form:label path=“hours">
Hours <form:errors path=“hours" cssClass="error" />
</form:label>
<form:input path=“hours“ />
<button type="submit">Submit</button>
</form:form>
Demo
✦ Working forms
✦ Bean validation
✦ Error messages appear in browser automagically
Bean Validation (JSR-303)
✦ Constraints are defined by
annotations on the actual data
entities
✦ Validation is executed
automagically by framework
✦ User-friendly errors appear
automagically on the view.
✦ Object graphs can be traversed
and nested objects are validated
(or not, if you wish).
@Entity
public class Yacht {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Size(min = 4, max = 35, message = "Key must be
between {min} and {max} characters long.")
@NotEmpty(message = "Key is required.")
@Pattern(regexp = "[A-Za-z0-9_-]*", message = "Only
letters, numbers, underscores and hyphens may be used.")
private String key;
@Size(min = 4, max = 35, message = "Name must be
between {min} and {max} characters long.")
@NotEmpty(message = "Name is required.")
private String name;
@ValidDate
private Date acquisitionDate;
}
Setting Up And Using Bean
Validation
✦ As simple as @Valid
✦ Can be applied inside domain to validate child/2nd degree
objects
✦ BindingResult for errors
✦ MUST be argument after @Valid argument (quirk)
✦ RuntimeException if not
✦ toString() is your friend.
✦ Validating a large object graph is risky.
✦ Complicates future changes
✦ On the other hand, very hard to merge BindingResults
Updated Controller
@Controller
public class YachtController {
@RequestMapping(method = POST)
public ModelAndView saveYacht(@Valid Yacht yacht, BindingResult result,
ModelAndView mv) {
LOG.debug("Attempting to save Yacht: " + yacht.getKey());
if (result.hasErrors()) {
LOG.debug("Submission has errors " + result);
mv.setViewName(MODIFY_YACHT_VIEW);
return mv;
}
service.store(yacht);
FlashMap.setSuccessMessage("Successfully saved Yacht");
return createRedirect(yacht);
}
}
Handling Validation Errors
✦ Ensure that you have a BindingResult.hasErrors() check in @Controller
✦ When returning edit view, ensure all needed model attributes are
present
✦ This includes the object being validated if you construct a new Model/
MV
✦ You may need a call to the root-level form:errors in order to capture object-
level errors (not field-level).
✦ <form:errors path=“” />
✦ Be sure you interrupt flow so you don’t persist invalid objects
✦ VALIDATION ERRORS ARE NOT EXCEPTIONS
✦ There is a Hibernate option to validate pre-persist, but this is nuanced
✦ Legacy objects
✦ May be incompatible with Spring-managed dependencies
Writing Your Own Constraints
✦ Constraints can be combined and composed
✦ For example, @NotEmpty actually means @NotNull, @Size(min=1) &
@ReportAsSingleViolation
✦ Write an annotation class
✦ @Target(ElementType.FIELD)
✦ @Retention(RetentionPolicy.RUNTIME)
✦ @Documented (or not)
✦ @Constraint(validatedBy = YourCustomValidator.class)
✦ Be sure to add a default message
✦ These can be Java properties read from a file (Internationalization/
i18n)
✦ Write a validator
✦ Implement ConstraintValidator<AnnotationType, TargetClass>
✦ Return boolean for isValid(TargetClass object, …)
✦ Statefulness (via initialize() method)
✦ Dependency Injection, Constructors, and Hibernate ORM issue
Writing Unit Tests For Validation
Magic
✦ A lot of JSR-303 is wizardry and magic beans.
✦ Write unit tests so you ensure code execution is predictable.
✦ Easiest to write using Spring’s JUnit Test Runner
✦ Point to an application context field that contains
✦ <bean id="validator“
class="org.springframework.validation.beanvalidation.LocalVa
lidatorFactoryBean" />
✦ Ensure a JSR-303-compliant validator is on your test
classpath
✦ Eg, Hibernate Validator
Example Unit Test
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:your-persistence.xml",
"classpath:your-persistence-test.xml" })
public class YachtValidationTest {
@Autowired
private javax.validation.Validator validator;
private Yacht emptyYacht;
@Before
public void setUpEmptyYacht() {
emptyYacht = new Yacht();
}
@Test
public void theKeyFieldIsRequired() {
Set<ConstraintViolation<Yacht>> constraintViolations = validator
.validate(emptyYacht);
boolean containsYachtKeyViolation = false;
for (ConstraintViolation<Yacht> violation : constraintViolations) {
if ("key".equals(violation.getPropertyPath().toString())
&& violation.getMessageTemplate().contains("required")) {
containsYachtKeyViolation = true;
}
}
assertTrue(containsYachtKeyViolation);
}
}
The Guts of Spring MVC
✦ Method Return Types
✦ View Resolvers
✦ Exception Handling
✦ File Uploads
✦ Servlet-level code (if you have to)
✦ URL Rewriting
Controller Method Return Types
✦ @Controller methods can return many different types. Often:
✦ Model
✦ ModelAndView (use Model.setView(View) or Model.setViewName
(String))
✦ Distinction between View and View Name
✦ String for the view name to display
✦ Can return void if you’ve drank plenty of convention over configuration
koolaid.
✦ Dangerous if you refactor a lot (or the next person does).
✦ Methods can also be annotated with @RequestBody
✦ Used to return a value without going through MVC apparatus
✦ Generally bad form, but good for testing or mock apps.
✦ @ModelAttribute has the same two distinct meanings as
@ModelAttribute
View Resolvers
✦ What is a ViewResolver and how does this differ from a View Name?
✦ Apache Tiles and TilesViewResolver
✦ InternalResourceViewResolver (default)
✦ ContentNegotiatingViewResolver
✦ JSON
✦ XML (if needed)
✦ RSS/Atom
✦ And many, many others… ViewResolver overload….
View options and Apache Tiles
✦ Spring MVC is does not attempt to implement its own view layer
✦ JSTL and JSP/JSPX
✦ Apache Tiles is commonly used for page modularization and
templating
✦ org.springframework.web.servlet.view.tiles2.TilesViewResolver
✦ org.springframework.web.servlet.view.tiles2.TilesConfigurer
✦ Similar options are available for Freemarker, Velocity and others
✦ JSON can be rendered easily via MappingJacksonJsonView
✦ Don’t forget ContentNegotiatingViewResolver and ignoreAcceptHeaders
(true)
✦ Straight JSPs are possible too
✦ Convention over configuration, but often creates complexity/duplication
Handling Exceptions
✦ Implement a HandlerExceptionResolver for application-wide errors
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex);
}
✦ @ExceptionHandler can annotate a method for @Controller-specific
exceptions, such as an IOException in a particular method. This only
applies to the controller in which it is declared.
✦ Consider adding web.xml <error-page> handlers too (if your exception
handler throws an exception, or if you think everything may break.)
✦ A separate error @Controller is a good idea, with minimal
dependencies
File Uploads
✦ Uses Commons File Upload
✦ org.springframework.web.multipart.commons.CommonsMultipartResolver
✦ Three easy steps (plus background Spring magic)
✦ Instantiate CommonsMultipartResolver in app context or @Config
✦ Add enctype=“multipart/form-data” to your <form> tag in your view
✦ Add a MultipartFile to your POST @Controller method argument
✦ Use @ModelAttribute for form submission specificity
✦ MultipartFile is your friend
✦ getBytes()*
✦ getContentType() – don’t forget about mime types!
✦ getOriginalFilename()
✦ transferTo(File dest)*
(* but IOException is not)
Burrowing Down To The
Servlets
✦ Sometimes it is necessary to write output
directly to servlets.
✦ Extend AbstractView
✦ In your controller, specify your custom
view
✦ ModelAndView.setViewName(String
name)
✦ ModelAndView.setView(View view)
✦ This is useful for user data in binary form,
such as images.
✦ In general, avoid this approach
@Component
public class ByteArrayView extends AbstractView {
public ByteArrayView() { }
@Override
protected final void renderMergedOutputModel(Map
model,
HttpServletRequest request, HttpServletResponse
response)
throws Exception {
byte[] bytes = (byte[]) model.get("data");
String contentType = (String) model.get
("contentType");
response.setContentType(contentType);
response.setContentLength(bytes.length);
ServletOutputStream out =
response.getOutputStream();
FileCopyUtils.copy(bytes, out);
}
}
URL Rewriting
✦ URL rewriting implemented as a servlet-level filter (web.xml):
✦ org.tuckey.web.filters.urlrewrite.UrlRewriteFilter
✦ Uses a urlrewrite.xml file, typically in the WEB-INF:
<rule>
<from>/sun/*</from>
<to>/oracle/$1</to>
</rule>
✦ Rules are standard regular expressions (java.util.regex.Pattern).
✦ Used extensively to separate dynamic content requests from static content
requests (eg, css, images, javascript).
✦ Can be used to route multiple different request paths to the same
DispatcherServlet instance (thereby conserving memory).
Demo
✦ Creating a new project from the Maven
archetype/template in STS IDE
✦ maven-tomcat-plugin, maven-jetty-plugin
✦ Live coding!
References
✦ Spring Docs (3.0.x)
Manual: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/
JavaDocs: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/
✦ Maven Jetty Plugin (mvn jetty:run)
http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin
✦ Miscellaneous
✦ Spring Roo Keynote
http://www.youtube.com/watch?v=GQHlhIIxCIc
Questions? Comments?

More Related Content

What's hot

Introduction to Spring MVC
Introduction to Spring MVCIntroduction to Spring MVC
Introduction to Spring MVCRichard Paul
 
Introduction to ASP.NET MVC
Introduction to ASP.NET MVCIntroduction to ASP.NET MVC
Introduction to ASP.NET MVCLearnNowOnline
 
AngularJS Project Setup step-by- step guide - RapidValue Solutions
AngularJS Project Setup step-by- step guide - RapidValue SolutionsAngularJS Project Setup step-by- step guide - RapidValue Solutions
AngularJS Project Setup step-by- step guide - RapidValue SolutionsRapidValue
 
AngularJs presentation
AngularJs presentation AngularJs presentation
AngularJs presentation Phan Tuan
 
Vaadin and Spring at Devoxx UK 2015
Vaadin and Spring at Devoxx UK 2015Vaadin and Spring at Devoxx UK 2015
Vaadin and Spring at Devoxx UK 2015Sami Ekblad
 
Top 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular AppTop 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular AppKaty Slemon
 
Testdrive AngularJS with Spring 4
Testdrive AngularJS with Spring 4Testdrive AngularJS with Spring 4
Testdrive AngularJS with Spring 4Oliver Wahlen
 
AngularJS - Services
AngularJS - ServicesAngularJS - Services
AngularJS - ServicesNir Kaufman
 
Angular Mini-Challenges
Angular Mini-ChallengesAngular Mini-Challenges
Angular Mini-ChallengesJose Mendez
 
Gdg dev fest hybrid apps your own mini-cordova
Gdg dev fest hybrid apps  your own mini-cordovaGdg dev fest hybrid apps  your own mini-cordova
Gdg dev fest hybrid apps your own mini-cordovaAyman Mahfouz
 
Seven Versions of One Web Application
Seven Versions of One Web ApplicationSeven Versions of One Web Application
Seven Versions of One Web ApplicationYakov Fain
 
Vaadin Components @ Angular U
Vaadin Components @ Angular UVaadin Components @ Angular U
Vaadin Components @ Angular UJoonas Lehtinen
 
Angular App Presentation
Angular App PresentationAngular App Presentation
Angular App PresentationElizabeth Long
 
Introduction to Google Guice
Introduction to Google GuiceIntroduction to Google Guice
Introduction to Google GuiceKnoldus Inc.
 
Introduction to angular js for .net developers
Introduction to angular js  for .net developersIntroduction to angular js  for .net developers
Introduction to angular js for .net developersMohd Manzoor Ahmed
 
Comparing Angular and React JS for SPAs
Comparing Angular and React JS for SPAsComparing Angular and React JS for SPAs
Comparing Angular and React JS for SPAsJennifer Estrada
 

What's hot (20)

Introduction to Spring MVC
Introduction to Spring MVCIntroduction to Spring MVC
Introduction to Spring MVC
 
Angular 5
Angular 5Angular 5
Angular 5
 
Vaadin & Web Components
Vaadin & Web ComponentsVaadin & Web Components
Vaadin & Web Components
 
Introduction to ASP.NET MVC
Introduction to ASP.NET MVCIntroduction to ASP.NET MVC
Introduction to ASP.NET MVC
 
AngularJS Project Setup step-by- step guide - RapidValue Solutions
AngularJS Project Setup step-by- step guide - RapidValue SolutionsAngularJS Project Setup step-by- step guide - RapidValue Solutions
AngularJS Project Setup step-by- step guide - RapidValue Solutions
 
AngularJs presentation
AngularJs presentation AngularJs presentation
AngularJs presentation
 
Vaadin and Spring at Devoxx UK 2015
Vaadin and Spring at Devoxx UK 2015Vaadin and Spring at Devoxx UK 2015
Vaadin and Spring at Devoxx UK 2015
 
Angular js
Angular jsAngular js
Angular js
 
Top 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular AppTop 7 Angular Best Practices to Organize Your Angular App
Top 7 Angular Best Practices to Organize Your Angular App
 
Testdrive AngularJS with Spring 4
Testdrive AngularJS with Spring 4Testdrive AngularJS with Spring 4
Testdrive AngularJS with Spring 4
 
AngularJS - Services
AngularJS - ServicesAngularJS - Services
AngularJS - Services
 
Angular Mini-Challenges
Angular Mini-ChallengesAngular Mini-Challenges
Angular Mini-Challenges
 
Gdg dev fest hybrid apps your own mini-cordova
Gdg dev fest hybrid apps  your own mini-cordovaGdg dev fest hybrid apps  your own mini-cordova
Gdg dev fest hybrid apps your own mini-cordova
 
Seven Versions of One Web Application
Seven Versions of One Web ApplicationSeven Versions of One Web Application
Seven Versions of One Web Application
 
Asp.Net MVC Intro
Asp.Net MVC IntroAsp.Net MVC Intro
Asp.Net MVC Intro
 
Vaadin Components @ Angular U
Vaadin Components @ Angular UVaadin Components @ Angular U
Vaadin Components @ Angular U
 
Angular App Presentation
Angular App PresentationAngular App Presentation
Angular App Presentation
 
Introduction to Google Guice
Introduction to Google GuiceIntroduction to Google Guice
Introduction to Google Guice
 
Introduction to angular js for .net developers
Introduction to angular js  for .net developersIntroduction to angular js  for .net developers
Introduction to angular js for .net developers
 
Comparing Angular and React JS for SPAs
Comparing Angular and React JS for SPAsComparing Angular and React JS for SPAs
Comparing Angular and React JS for SPAs
 

Similar to Spring MVC Intro / Gore - Nov NHJUG

JavaScript Framework Smackdown
JavaScript Framework SmackdownJavaScript Framework Smackdown
JavaScript Framework Smackdownmeghantaylor
 
Unit 38 - Spring MVC Introduction.pptx
Unit 38 - Spring MVC Introduction.pptxUnit 38 - Spring MVC Introduction.pptx
Unit 38 - Spring MVC Introduction.pptxAbhijayKulshrestha1
 
MVC 1.0 als alternative Webtechnologie
MVC 1.0 als alternative WebtechnologieMVC 1.0 als alternative Webtechnologie
MVC 1.0 als alternative WebtechnologieOPEN KNOWLEDGE GmbH
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with SpringJoshua Long
 
Top 10 Mistakes AngularJS Developers Make
Top 10 Mistakes AngularJS Developers MakeTop 10 Mistakes AngularJS Developers Make
Top 10 Mistakes AngularJS Developers MakeMark Meyer
 
Apache Wicket Web Framework
Apache Wicket Web FrameworkApache Wicket Web Framework
Apache Wicket Web FrameworkLuther Baker
 
ASP.NET MVC, AngularJS CRUD for Azerbaijan Technical University
ASP.NET MVC, AngularJS CRUD for Azerbaijan Technical UniversityASP.NET MVC, AngularJS CRUD for Azerbaijan Technical University
ASP.NET MVC, AngularJS CRUD for Azerbaijan Technical UniversitySyed Shanu
 
ASP.NET MVC Presentation
ASP.NET MVC PresentationASP.NET MVC Presentation
ASP.NET MVC Presentationivpol
 
Planbox Backbone MVC
Planbox Backbone MVCPlanbox Backbone MVC
Planbox Backbone MVCAcquisio
 
Build your website with angularjs and web apis
Build your website with angularjs and web apisBuild your website with angularjs and web apis
Build your website with angularjs and web apisChalermpon Areepong
 
Asp.net mvc training
Asp.net mvc trainingAsp.net mvc training
Asp.net mvc trainingicubesystem
 
Java Spring MVC Framework with AngularJS by Google and HTML5
Java Spring MVC Framework with AngularJS by Google and HTML5Java Spring MVC Framework with AngularJS by Google and HTML5
Java Spring MVC Framework with AngularJS by Google and HTML5Tuna Tore
 
springmvc-150923124312-lva1-app6892
springmvc-150923124312-lva1-app6892springmvc-150923124312-lva1-app6892
springmvc-150923124312-lva1-app6892Tuna Tore
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Patterngoodfriday
 
Patterns Are Good For Managers
Patterns Are Good For ManagersPatterns Are Good For Managers
Patterns Are Good For ManagersAgileThought
 
MeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analystsMeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analystsSimo Ahava
 
Getting start Java EE Action-Based MVC with Thymeleaf
Getting start Java EE Action-Based MVC with ThymeleafGetting start Java EE Action-Based MVC with Thymeleaf
Getting start Java EE Action-Based MVC with ThymeleafMasatoshi Tada
 
Asp.Net Mvc
Asp.Net MvcAsp.Net Mvc
Asp.Net Mvcmicham
 

Similar to Spring MVC Intro / Gore - Nov NHJUG (20)

JavaScript Framework Smackdown
JavaScript Framework SmackdownJavaScript Framework Smackdown
JavaScript Framework Smackdown
 
Unit 38 - Spring MVC Introduction.pptx
Unit 38 - Spring MVC Introduction.pptxUnit 38 - Spring MVC Introduction.pptx
Unit 38 - Spring MVC Introduction.pptx
 
MVC 1.0 als alternative Webtechnologie
MVC 1.0 als alternative WebtechnologieMVC 1.0 als alternative Webtechnologie
MVC 1.0 als alternative Webtechnologie
 
Multi Client Development with Spring
Multi Client Development with SpringMulti Client Development with Spring
Multi Client Development with Spring
 
Top 10 Mistakes AngularJS Developers Make
Top 10 Mistakes AngularJS Developers MakeTop 10 Mistakes AngularJS Developers Make
Top 10 Mistakes AngularJS Developers Make
 
Apache Wicket Web Framework
Apache Wicket Web FrameworkApache Wicket Web Framework
Apache Wicket Web Framework
 
ASP.NET MVC, AngularJS CRUD for Azerbaijan Technical University
ASP.NET MVC, AngularJS CRUD for Azerbaijan Technical UniversityASP.NET MVC, AngularJS CRUD for Azerbaijan Technical University
ASP.NET MVC, AngularJS CRUD for Azerbaijan Technical University
 
ASP.NET MVC Presentation
ASP.NET MVC PresentationASP.NET MVC Presentation
ASP.NET MVC Presentation
 
Valentine with AngularJS
Valentine with AngularJSValentine with AngularJS
Valentine with AngularJS
 
Planbox Backbone MVC
Planbox Backbone MVCPlanbox Backbone MVC
Planbox Backbone MVC
 
Build your website with angularjs and web apis
Build your website with angularjs and web apisBuild your website with angularjs and web apis
Build your website with angularjs and web apis
 
Asp.net mvc training
Asp.net mvc trainingAsp.net mvc training
Asp.net mvc training
 
Java Spring MVC Framework with AngularJS by Google and HTML5
Java Spring MVC Framework with AngularJS by Google and HTML5Java Spring MVC Framework with AngularJS by Google and HTML5
Java Spring MVC Framework with AngularJS by Google and HTML5
 
springmvc-150923124312-lva1-app6892
springmvc-150923124312-lva1-app6892springmvc-150923124312-lva1-app6892
springmvc-150923124312-lva1-app6892
 
Asp.NET MVC
Asp.NET MVCAsp.NET MVC
Asp.NET MVC
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Pattern
 
Patterns Are Good For Managers
Patterns Are Good For ManagersPatterns Are Good For Managers
Patterns Are Good For Managers
 
MeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analystsMeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
MeasureCamp IX (London) - 10 JavaScript Concepts for web analysts
 
Getting start Java EE Action-Based MVC with Thymeleaf
Getting start Java EE Action-Based MVC with ThymeleafGetting start Java EE Action-Based MVC with Thymeleaf
Getting start Java EE Action-Based MVC with Thymeleaf
 
Asp.Net Mvc
Asp.Net MvcAsp.Net Mvc
Asp.Net Mvc
 

Recently uploaded

Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...Aggregage
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationIES VE
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostMatt Ray
 
Building AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxBuilding AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxUdaiappa Ramachandran
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024D Cloud Solutions
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemAsko Soukka
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxMatsuo Lab
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1DianaGray10
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Websitedgelyza
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1DianaGray10
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesMd Hossain Ali
 

Recently uploaded (20)

Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
 
Building AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxBuilding AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptx
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystem
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptx
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Website
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
 

Spring MVC Intro / Gore - Nov NHJUG

  • 1. Spring MVC Introduction / Gore Ted Pennings NHJUG Co-Founder 16 November 2010
  • 2. Who’s Ted ✦ Developer with Fortune 100 financial services firm since July 2008. ✦ Working with Java since late 2008. ✦ Web developer as freelance/hobby since 2001 (LAMP) ✦ Lots of freelancing and web hosting during college ✦ http://ted.pennin.gs / @thesleepyvegan / ted@pennin.gs
  • 3. What is MVC? ✦ MVC spits code into three areas ✦ Model – data/persistence layer ✦ View – presentation layer, UI and client-side scripts ✦ Controller – business logic that controls data and execution ✦ Strong design pattern that emphasizes separation.
  • 4. MVC Cleanliness ✦ Application logic goes in the controllers. ✦ Data persistence goes in the model. ✦ UI presentation and JavaScript varnish goes in the views. ✦ Do not try to fight MVC code separation. If you feel the need to break convention, refactor.
  • 5. MVC Done Badly – Views ✦Doing actual work in JSPs <% try { String url="jdbc:mysql://localhost/companies?user=larry_ellison&password=yachts"; con=DriverManager.getConnection(url); stmt=con.createStatement(); } catch(Exception e){ System.err.println(“Unable to acquire companies!”); e.printStackTrace(); } if (request.getParameter("action") != null){ String bookname = request.getParameter("company_name"); String author = request.getParameter("price"); stmt.executeUpdate("insert into acquisitions(company_name,price) values ('"+company_name+"','"+price+"')"); rst=stmt.executeQuery("select * from acquisitions"); %> <html> <body> <center> <h2>Victim List</h2> <table border="1" cellspacing="0" cellpadding="0"> Adapted from http://www.roseindia.net/jsp/Accessingdatabase-fromJSP.shtml
  • 6. MVC Done Badly – Controllers ✦HTML in the controllers @RequestMapping(“/acquisitions/new”) public void createAcquisition(Model model) { Acquisition v = new Acquisition(); model.addAttribute(“newVictim”, v); model.addAttribute(“newVictimForm”, collectVictimVitalStats(v)); } private String renderVictimInfoForm(Acquisition v) { StringBuilder sb = new StringBuilder() .append("<form action='").append(SERVLET_PATH) .append("' method='post'><h1>Please enter your information</h1>"); sb.append("<p><label for='name'>Victim Name</label>") .append("<input type='text' name='name' value='") .append(v.getName()).append("'/>").append("</p>"); [...] return sb.toString(); }
  • 7. Speaking of Bad Things Oracle CEO Larry Ellison
  • 8. MVC Done Badly – Models ✦Business logic in the model public class Victim { private String name; private short numberOfYachts; [. . . ] public Victim(String name, short numberOfYachts) { if (numberOfYachts < 4) { throw new VictimUnworthyException(“Too few yachts. Larry Ellison will not be sated.”); } } [. . . ] } ✦HTML in methods public String toString() { return “<h3 class=‘name’>Why Hello ” + this.name + “!</h3><br/>I admire your” + “<strong><font color=“pink”>” + this.numberOfYachts + “</font></strong> yachts”; }
  • 9. Spring MVC is Still Spring ✦ Full Dependency Injection and Inversion of Control ✦ XML- and Annotation-based configuration ✦ Heavy use of annotation-based configuration ✦ Application context files are still available, but mostly unnecessary ✦ <mvc:annotation-driven> and <content:component-scan> ✦ Maven dependencies and archetypes ✦ Convention over configuration ✦ Very few interfaces to implement “Spring Goodness”
  • 10. The Basic Annotations ✦ Spring MVC is mostly annotation driven, so here is your vernacular: ✦ Standard Spring annotations: ✦ @Component, @Service, @Repository, ✦ @Autowired, @Value, @Configuration ✦ @Transactional, @Aspect and JSR 284 + 330 ✦ @Controller – an MVC Controller ✦ @RequestMapping ✦ @ModelAttribute ✦ @RequestParam and @PathVariable ✦ @SessionAttributes
  • 11. How does Spring do MVC? ✦ All requests are sent to Spring’s DispatcherServlet ✦ DispatcherServlet sends requests to @Controllers ✦ THERE ARE NO DEVELOPER-WRITTEN SERVLETS Diagram from Spring docs on their website
  • 12. The Simplicity of Controllers ✦ @Controller makes a class a controller “bean” ✦ Specialization of @Component ✦ @RequestMapping defines the URL paths handled by a controller or method. ✦ It is possible to nest paths, as in example. ✦ Many different RequestMethods can be serviced. ✦ {} define @PathVariable/@ReqParam ✦ Value of Inheritance ✦ Annotation caveat
  • 13. Controller Example @Controller @RequestMapping({ "/yachts", "/mah-boats" }) public class YachtController extends BaseController { @RequestMapping(value = "/{yachtKey}", method = GET) public String displayYacht( @PathVariable(“yachtKey”) String yachtKey, Model model) { LOG.debug("Displaying Yacht " + yachtKey); Yacht yacht = service.findYachtByKey(yachtKey); model.addAttribute("yacht", yacht); return YACHT_PAGE_VIEW; } }
  • 14. Reading User Input ✦ Typically happens through method parameter annotations ✦ @PathVariable(“var”) / @RequestParam(“var”) ✦ Corresponds to a {var} value in a @RequestMapping ✦ Best practice to be explicit ✦ @ModelAttribute ✦ @RequestBody ✦ Any type can be used. ✦ Be wary of type conversion issues ✦ See PropertyEditorSupport and Spring’s Converter SPI ✦ Use @InitBinder in a controller superclass ✦ JSON payloads can often be unmarshalled on the fly.
  • 15. Populating The Model ✦ In MVC, dynamic data only appears in views through the model. ✦ Spring MVC enforces this pattern constraint. ✦ Each request receives a fresh new Model (or equivalent). ✦ Two basic approaches ✦ In @Controller method, receive a Model or ModelAndView object ✦ Add directly to it. ✦ No need to return Model/MV object received. (More on that later.) ✦ In @Controller class, annotate methods with @ModelAttribute(“name”) ✦ Used in a @Controller superclass, can be used for template data ✦ User privileges ✦ Pseudo-security hack until full security is implemented
  • 16. Creating Forms (1/2) ✦ Creating a new object submission form requires manually instantiating your target object ✦ if you want to create a com.oracle.acquisition.timekeeper.model.TimeEntry(), in your controller method you must ✦ model.addAttribute(“timeEntry”, new com.oracle.acquisition.timekeeper.model.TimeEntry()); Assuming: package com.oracle.acquisition.timekeeper.model; public class TimeEntry { private String victimName; private String projectCode; private double hours; private Date timestamp; […getters, setters, etc…] } ✦ This exact object will be used by your JSP (or similar) in the next step… getter/setter round-tripping on POST
  • 17. Creating Forms (2/2) Most new object views can function as an edit view. Conserve code. <form:form method="post" modelAttribute=“timeEntry" cssClass="form"> <form:label path=“projectCode"> Project Code <form:errors path=“projectCode" cssClass="error" /> </form:label> <form:select items="${userProjectCodes}" path=“projectCode“ itemLabel=“projectName"/> <form:label path=“hours"> Hours <form:errors path=“hours" cssClass="error" /> </form:label> <form:input path=“hours“ /> <button type="submit">Submit</button> </form:form>
  • 18. Demo ✦ Working forms ✦ Bean validation ✦ Error messages appear in browser automagically
  • 19. Bean Validation (JSR-303) ✦ Constraints are defined by annotations on the actual data entities ✦ Validation is executed automagically by framework ✦ User-friendly errors appear automagically on the view. ✦ Object graphs can be traversed and nested objects are validated (or not, if you wish). @Entity public class Yacht { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Size(min = 4, max = 35, message = "Key must be between {min} and {max} characters long.") @NotEmpty(message = "Key is required.") @Pattern(regexp = "[A-Za-z0-9_-]*", message = "Only letters, numbers, underscores and hyphens may be used.") private String key; @Size(min = 4, max = 35, message = "Name must be between {min} and {max} characters long.") @NotEmpty(message = "Name is required.") private String name; @ValidDate private Date acquisitionDate; }
  • 20. Setting Up And Using Bean Validation ✦ As simple as @Valid ✦ Can be applied inside domain to validate child/2nd degree objects ✦ BindingResult for errors ✦ MUST be argument after @Valid argument (quirk) ✦ RuntimeException if not ✦ toString() is your friend. ✦ Validating a large object graph is risky. ✦ Complicates future changes ✦ On the other hand, very hard to merge BindingResults
  • 21. Updated Controller @Controller public class YachtController { @RequestMapping(method = POST) public ModelAndView saveYacht(@Valid Yacht yacht, BindingResult result, ModelAndView mv) { LOG.debug("Attempting to save Yacht: " + yacht.getKey()); if (result.hasErrors()) { LOG.debug("Submission has errors " + result); mv.setViewName(MODIFY_YACHT_VIEW); return mv; } service.store(yacht); FlashMap.setSuccessMessage("Successfully saved Yacht"); return createRedirect(yacht); } }
  • 22. Handling Validation Errors ✦ Ensure that you have a BindingResult.hasErrors() check in @Controller ✦ When returning edit view, ensure all needed model attributes are present ✦ This includes the object being validated if you construct a new Model/ MV ✦ You may need a call to the root-level form:errors in order to capture object- level errors (not field-level). ✦ <form:errors path=“” /> ✦ Be sure you interrupt flow so you don’t persist invalid objects ✦ VALIDATION ERRORS ARE NOT EXCEPTIONS ✦ There is a Hibernate option to validate pre-persist, but this is nuanced ✦ Legacy objects ✦ May be incompatible with Spring-managed dependencies
  • 23. Writing Your Own Constraints ✦ Constraints can be combined and composed ✦ For example, @NotEmpty actually means @NotNull, @Size(min=1) & @ReportAsSingleViolation ✦ Write an annotation class ✦ @Target(ElementType.FIELD) ✦ @Retention(RetentionPolicy.RUNTIME) ✦ @Documented (or not) ✦ @Constraint(validatedBy = YourCustomValidator.class) ✦ Be sure to add a default message ✦ These can be Java properties read from a file (Internationalization/ i18n) ✦ Write a validator ✦ Implement ConstraintValidator<AnnotationType, TargetClass> ✦ Return boolean for isValid(TargetClass object, …) ✦ Statefulness (via initialize() method) ✦ Dependency Injection, Constructors, and Hibernate ORM issue
  • 24. Writing Unit Tests For Validation Magic ✦ A lot of JSR-303 is wizardry and magic beans. ✦ Write unit tests so you ensure code execution is predictable. ✦ Easiest to write using Spring’s JUnit Test Runner ✦ Point to an application context field that contains ✦ <bean id="validator“ class="org.springframework.validation.beanvalidation.LocalVa lidatorFactoryBean" /> ✦ Ensure a JSR-303-compliant validator is on your test classpath ✦ Eg, Hibernate Validator
  • 25. Example Unit Test @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({ "classpath:your-persistence.xml", "classpath:your-persistence-test.xml" }) public class YachtValidationTest { @Autowired private javax.validation.Validator validator; private Yacht emptyYacht; @Before public void setUpEmptyYacht() { emptyYacht = new Yacht(); } @Test public void theKeyFieldIsRequired() { Set<ConstraintViolation<Yacht>> constraintViolations = validator .validate(emptyYacht); boolean containsYachtKeyViolation = false; for (ConstraintViolation<Yacht> violation : constraintViolations) { if ("key".equals(violation.getPropertyPath().toString()) && violation.getMessageTemplate().contains("required")) { containsYachtKeyViolation = true; } } assertTrue(containsYachtKeyViolation); } }
  • 26. The Guts of Spring MVC ✦ Method Return Types ✦ View Resolvers ✦ Exception Handling ✦ File Uploads ✦ Servlet-level code (if you have to) ✦ URL Rewriting
  • 27. Controller Method Return Types ✦ @Controller methods can return many different types. Often: ✦ Model ✦ ModelAndView (use Model.setView(View) or Model.setViewName (String)) ✦ Distinction between View and View Name ✦ String for the view name to display ✦ Can return void if you’ve drank plenty of convention over configuration koolaid. ✦ Dangerous if you refactor a lot (or the next person does). ✦ Methods can also be annotated with @RequestBody ✦ Used to return a value without going through MVC apparatus ✦ Generally bad form, but good for testing or mock apps. ✦ @ModelAttribute has the same two distinct meanings as @ModelAttribute
  • 28. View Resolvers ✦ What is a ViewResolver and how does this differ from a View Name? ✦ Apache Tiles and TilesViewResolver ✦ InternalResourceViewResolver (default) ✦ ContentNegotiatingViewResolver ✦ JSON ✦ XML (if needed) ✦ RSS/Atom ✦ And many, many others… ViewResolver overload….
  • 29. View options and Apache Tiles ✦ Spring MVC is does not attempt to implement its own view layer ✦ JSTL and JSP/JSPX ✦ Apache Tiles is commonly used for page modularization and templating ✦ org.springframework.web.servlet.view.tiles2.TilesViewResolver ✦ org.springframework.web.servlet.view.tiles2.TilesConfigurer ✦ Similar options are available for Freemarker, Velocity and others ✦ JSON can be rendered easily via MappingJacksonJsonView ✦ Don’t forget ContentNegotiatingViewResolver and ignoreAcceptHeaders (true) ✦ Straight JSPs are possible too ✦ Convention over configuration, but often creates complexity/duplication
  • 30. Handling Exceptions ✦ Implement a HandlerExceptionResolver for application-wide errors public interface HandlerExceptionResolver { ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex); } ✦ @ExceptionHandler can annotate a method for @Controller-specific exceptions, such as an IOException in a particular method. This only applies to the controller in which it is declared. ✦ Consider adding web.xml <error-page> handlers too (if your exception handler throws an exception, or if you think everything may break.) ✦ A separate error @Controller is a good idea, with minimal dependencies
  • 31. File Uploads ✦ Uses Commons File Upload ✦ org.springframework.web.multipart.commons.CommonsMultipartResolver ✦ Three easy steps (plus background Spring magic) ✦ Instantiate CommonsMultipartResolver in app context or @Config ✦ Add enctype=“multipart/form-data” to your <form> tag in your view ✦ Add a MultipartFile to your POST @Controller method argument ✦ Use @ModelAttribute for form submission specificity ✦ MultipartFile is your friend ✦ getBytes()* ✦ getContentType() – don’t forget about mime types! ✦ getOriginalFilename() ✦ transferTo(File dest)* (* but IOException is not)
  • 32. Burrowing Down To The Servlets ✦ Sometimes it is necessary to write output directly to servlets. ✦ Extend AbstractView ✦ In your controller, specify your custom view ✦ ModelAndView.setViewName(String name) ✦ ModelAndView.setView(View view) ✦ This is useful for user data in binary form, such as images. ✦ In general, avoid this approach @Component public class ByteArrayView extends AbstractView { public ByteArrayView() { } @Override protected final void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { byte[] bytes = (byte[]) model.get("data"); String contentType = (String) model.get ("contentType"); response.setContentType(contentType); response.setContentLength(bytes.length); ServletOutputStream out = response.getOutputStream(); FileCopyUtils.copy(bytes, out); } }
  • 33. URL Rewriting ✦ URL rewriting implemented as a servlet-level filter (web.xml): ✦ org.tuckey.web.filters.urlrewrite.UrlRewriteFilter ✦ Uses a urlrewrite.xml file, typically in the WEB-INF: <rule> <from>/sun/*</from> <to>/oracle/$1</to> </rule> ✦ Rules are standard regular expressions (java.util.regex.Pattern). ✦ Used extensively to separate dynamic content requests from static content requests (eg, css, images, javascript). ✦ Can be used to route multiple different request paths to the same DispatcherServlet instance (thereby conserving memory).
  • 34. Demo ✦ Creating a new project from the Maven archetype/template in STS IDE ✦ maven-tomcat-plugin, maven-jetty-plugin ✦ Live coding!
  • 35. References ✦ Spring Docs (3.0.x) Manual: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/ JavaDocs: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/ ✦ Maven Jetty Plugin (mvn jetty:run) http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin ✦ Miscellaneous ✦ Spring Roo Keynote http://www.youtube.com/watch?v=GQHlhIIxCIc