Spring MVC - The Basics Ilio Catallo - info@iliocatallo.it
Outline • MVC and MVC 2 • Request processing pipeline • Se8ng up Spring MVC • Wri:ng Controllers • References
MVC and MVC 2
Model-View-Controller The Model-View-Controller (MVC) pa5en was invented at Xerox Parc by Trygve Reenskaug in 1979
MVC pa'ern Applica'ons should have three major parts • The part that manages the data • The part that creates screens and reports • The part that handles interac3ons between the user and the other subsystems
MVC pa'ern Applica'ons should have three major parts • Model • View • Controller
MVC pa'ern Applica'ons should have three major parts • Domain model • View • Controller
MVC pa'ern +------------------+ +---------------+ | | | Controller +----------+ | +-------> | | View | +------------------+ | selection | | | | | | | State change | User | | interaction | | | | +---v-------+---+ +-------v--------+ | | | | | View <---Change notification---+ Domain model | | | | | +-------+-------+ +-------^--------+ | | | | +---------------State query---------------+
What is the reason not to use the same MVC pa2ern also for Web applica7ons?
HTTP limita*ons The reason is that the HTTP protocol limits the applicability of the MVC pa7ern
Stateless protocol The MVC pa*ern requires a stateful protocol to keep track of the applica.on state
Applica'on state "If we think of an applica1on as being computerized behavior that achieves a goal, we can describe an applica1on protocol as the set of legal interac1ons necessary to realize that behavior. Applica3on state is a snapshot of an execu1on of such an applica1on protocol." (J. Webber et al.)
Stateless protocol However, HTTP is stateless
Pull protocol The MVC pa*ern requires a push protocol for the views to be no7fied by the model
Pull protocol However, HTTP is a pull protocol: no request implies no response
How can we overcome such limita2ons?
Stateless protocol HTTP is stateless: we can implement the MVC design pa3ern on top of the Java Servlet Pla;orm
Stateless protocol The Java Servlet Pla-orm provides a session context to help track users in the applica8on
Pull protocol HTTP is a pull protocol: we can increase the Controller responsibility
Pull protocol Namely, the Controller will be responsible for: • State changes • State queries • Change no2fica2ons
MVC 2 pa(ern The resul)ng pa.ern is some)mes called MVC 2 or Web MVC +-------------+ +---------------+ +----------------+ | +----------> +---------> | | View | | Controller | | Domain model | | <----------+ <---------+ | +-------------+ +---------------+ +----------------+
MVC 2 pa(ern Any state query or change no0fica0on must pass through the Controller +-------------+ +---------------+ +----------------+ | +----------> +---------> | | View | | Controller | | Domain model | | <----------+ <---------+ | +-------------+ +---------------+ +----------------+
MVC 2 pa(ern The View renders data passed by the Controller rather than data returned directly from the Model +-------------+ +---------------+ +----------------+ | +----------> +---------> | | View | | Controller | | Domain model | | <----------+ <---------+ | +-------------+ +---------------+ +----------------+
MVC 2 pa(ern We refer to such data as the view model +-------------+ +---------------+ +----------------+ | +--------------> +---------> | | View | | Controller | | Domain model | | <--View model--+ <---------+ | +-------------+ +---------------+ +----------------+
Compe&ng architectures Note that MVC 2 proposes a compe&ng architecture to the one we presented during the last lecture ┌──────┐┌────────────────────────────────┐ │ D ││ │ │ o ││ Presentation layer │ │ m ││ │ │ a │└────────────────────────────────┘ │ i │┌────────────────────────────────┐ │ n ││ │ │ ││ Service layer │ │ m ││ │ │ o │└────────────────────────────────┘ │ d │┌────────────────────────────────┐ │ e ││ │ │ l ││ Persistence layer │ │ ││ │ └──────┘└────────────────────────────────┘
Compe&ng architectures We reconcile the two architectures by limi3ng the scope of the MVC 2 pa;ern to the sole presenta(on layer ┌──────┐┌────────────────────────────────┐ │ D ││ │ │ o ││ Presentation layer │ │ m ││ │ │ a │└────────────────────────────────┘ │ i │┌────────────────────────────────┐ │ n ││ │ │ ││ Service layer │ │ m ││ │ │ o │└────────────────────────────────┘ │ d │┌────────────────────────────────┐ │ e ││ │ │ l ││ Persistence layer │ │ ││ │ └──────┘└────────────────────────────────┘
Compe&ng architectures The controller will defer actual computa3on to the service layer +-------------+ +---------------+ +----------------+ | +--------------> +---------> | | View | | Controller | | Service layer | | <--View model--+ <---------+ | +-------------+ +---------------+ +----------------+
What is Spring MVC? Spring MVC is an open source MVC 2 framework for developing Web applica3ons
Spring MVC Spring MVC eases Web applica2on development • It provides a ready-to-use MVC 2 Controller • It promotes Spring’s loosely coupled techniques in the presenta>on layer of an applica>on
Request processing pipeline
DispatcherServlet Spring MVC is designed around a central servlet named DispatcherServlet Presentation layer +---------------------------------+ | | | | | | | +-----------------------+ | | | | | | | DispatcherServlet | | | | | | | +-----------------------+ | | | | | | | | | +---------------------------------+
DispatcherServlet DispatcherServlet acts as a centralized entry point to the Web applica.on Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> DispatcherServlet | | | | | | | | +---------------+ | +-----------------------+ | | | | | | | | | +---------------------------------+
DispatcherServlet That is, every request is handled by DispatcherServlet Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> DispatcherServlet | | | | | | | | +---------------+ | +-----------------------+ | | | | | | | | | +---------------------------------+
DispatcherServlet DispatcherServlet is an expression of the front controller pa.ern Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> Front Controller | | | | | | | | +---------------+ | +-----------------------+ | | | | | | | | | +---------------------------------+
The Front Controller The Front controller’s job is to determine a suitable handler capable of performing the actual processing Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> Front Controller | | | | | | | | +---------------+ | +-----------+-----------+ | | | | | | | | | | | +--------v---------+ | | | | | | | Handler | | | | | | | +------------------+ | | | | | +---------------------------------+
Controllers Handlers are nearly always Spring MVC controllers Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> Front Controller | | | | | | | | +---------------+ | +-----------+-----------+ | | | | | | | | | | | +--------v---------+ | | | | | | | Controller | | | | | | | +------------------+ | | | | | +---------------------------------+
Model The selected Controller interacts with the service layer; the relevant data are collected in a view model Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-------+ | | | | | | | | | | | | +--------v----------+ | | | | | Persistence layer | | | | | +--------+----------+ | | | | | | +---v----------+ | | v | | | | | +--+---+ | | Controller <-----+ | | | | | | | DB | | +--------------+ | | | +--------------------------------------+ +------+
Model The selected Controller interacts with the service layer; the relevant data are collected in a view model Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-----^-+ | | | | | | | | | | | +---+---+ | | +--------v----------+ | | | Model | | | | Persistence layer | | | +---+---+ | | +--------+----------+ | | | | | | | +---v-----+----+ | | v | | | | | +--+---+ | | Controller <-----+ | | | | | | | DB | | +--------------+ | | | +--------------------------------------+ +------+
Model Spring MVC refers to the view model simply as the model. This may lead to confusion with the classic MVC terminology Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-----^-+ | | | | | | | | | | | +---+---+ | | +--------v----------+ | | | Model | | | | Persistence layer | | | +---+---+ | | +--------+----------+ | | | | | | | +---v-----+----+ | | v | | | | | +--+---+ | | Controller <-----+ | | | | | | | DB | | +--------------+ | | | +--------------------------------------+ +------+
Model Regardless the name, remember that the model consists of data the Controller prepares just for the view Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-----^-+ | | | | | | | | | | | +---+---+ | | +--------v----------+ | | | Model | | | | Persistence layer | | | +---+---+ | | +--------+----------+ | | | | | | | +---v-----+----+ | | v | | | | | +--+---+ | | Controller <-----+ | | | | | | | DB | | +--------------+ | | | +--------------------------------------+ +------+
Controllers When the controller has finished processing, the front controller determines which view to render Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-----^-+ | | | | | | | | | | | +---+---+ | | +--------v----------+ | | | Model | | | | Persistence layer | | | +---+---+ | | +--------+----------+ | | | | | | | +-------------+ +---v-----+----+ | | v | | | | | | | +--+---+ | | View | | Controller <-----+ | | | | | | | | | DB | | +-------------+ +--------------+ | | | +--------------------------------------+ +------+
Views When the controller has finished processing, the front controller determines which view to render Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------+-----------+-----^-+ | | | | | | | | | | | +---+---+ | +---+---+ | | +--------v----------+ | | Model | | | Model | | | | Persistence layer | | +---+---+ | +---+---+ | | +--------+----------+ | | | | | | | | +--------v----+ +---v-----+----+ | | v | | | | | | | +--+---+ | | View | | Controller <-----+ | | | | | | | | | DB | | +-------------+ +--------------+ | | | +--------------------------------------+ +------+
Views When the controller has finished processing, the front controller determines which view to render Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-^-----+-----------+-----^-+ | | | | | | | | | | | | | +---+---+ | +---+---+ | | +--------v----------+ | | | Model | | | Model | | | | Persistence layer | | | +---+---+ | +---+---+ | | +--------+----------+ | | | | | | | | | +--+-----v----+ +---v-----+----+ | | v | | | | | | | +--+---+ | | View | | Controller <-----+ | | | | | | | | | DB | | +-------------+ +--------------+ | | | +--------------------------------------+ +------+
Views When the controller has finished processing, the front controller determines which view to render Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | +<-------------+ | | | +--------+----------+ +-------------+ Response| +-^-----+-----------+-----^-+ | | | | | | | | | | | | | +---+---+ | +---+---+ | | +--------v----------+ | | | Model | | | Model | | | | Persistence layer | | | +---+---+ | +---+---+ | | +--------+----------+ | | | | | | | | | +--+-----v----+ +---v-----+----+ | | v | | | | | | | +--+---+ | | View | | Controller <-----+ | | | | | | | | | DB | | +-------------+ +--------------+ | | | +--------------------------------------+ +------+
Se#ng up Spring MVC
Se#ng up Spring MVC Se#ng up Spring MVC is a two-step process 1. Loading DispatcherServlet in the Web container 2. Instan5a5ng a DI container and the related beans
1. Loading DispatcherServlet in the Web container
Loading the front controller We need to tell the Web container to load DispatcherServlet
Loading the front controller To this end, we provide the Web container with a web.xml deployment descriptor file + Web components | (e.g., servlets) | +-------v--------+ | | | Web | web.xml +--------> container | | | +-------+--------+ | | v Web app
Loading the front controller Recall that the web.xml file describes how to deploy the Web components of an applica6on + Web components | (e.g., servlets) | +-------v--------+ | | | Web | web.xml +--------> container | | | +-------+--------+ | | v Web app
Loading the front controller <!-- Load DispatcherServlet --> <servlet> <servlet-name>frontcontroller</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- URL mapping --> <servlet-mapping> <servlet-name>frontcontroller</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
2. Instan)a)ng a DI container and the related beans
Instan&a&ng beans DispatcherServlet instan'ates a Spring DI container +---------------------------------------------------+ | | | | | | | +------------+ +------------+ | | | +------------+ | +------------+ | | | | +-------------+ | | +-------------+ | | | | | | | | | | | | +-+ | Controllers | +-+ | Special | | | +-+ | +-+ beans | | | +-------------+ +-------------+ | | | | | | | +---------------------------------------------------+ Spring DI Container
Instan&a&ng beans Such a container hosts beans belonging to the presenta(on layer • Controllers • Special beans
Controllers Controllers are wri'en by the developer and provide access to the service layer of the applica5on @Controller public class AccountController { ... }
Special beans Special beans are beans that are already part of Spring MVC
Special beans More precisely, special beans are DispatcherServlet's collaborators
Special beans DispatcherServlet relies on them to process requests and render the appropriate views
Special beans Each special bean plays its own small part in the overall processing of the request
Special beans For instance: • HandlerMapping maps HTTP requests to handlers • ViewResolver maps logical name to views • HandlerExceptionResolver maps excep:ons to handlers
Special bean interfaces Each special bean is expressed as an interface public interface ViewResolver { View resolveViewName(String viewName, Locale locale); }
Special bean advantages Thanks to this, the request processing pipeline is highly flexible and configurable
Special bean advantages Indeed, we can tailor each stage of the pipeline just by changing its concrete implementa9on public class VelocityViewResolver implements ViewResolver { ... } public class XmlViewResolver implements ViewResolver { ... } public class InternalResourceViewResolver implements ViewResolver { ... }
Default special beans For each special bean, the DispatcherServlet maintains a list of implementa)ons to be used by default
Default special beans For instance, InternalResourceViewResolver is instan-ated by default public class InternalResourceViewResolver implements ViewResolver { ... }
Default special beans If not stated otherwise, DispatcherServlet will use default implementa4ons throughout the en4re processing pipeline
Web beans Controllers and special beans are the Web beans of our applica3on +---------------------------------------------------+ | | | | | | | +------------+ +------------+ | | | +------------+ | +------------+ | | | | +-------------+ | | +-------------+ | | | | | | | | | | | | +-+ | Controllers | +-+ | Special | | | +-+ | +-+ beans | | | +-------------+ +-------------+ | | | | | | | +---------------------------------------------------+ Spring DI Container
WebApplicationContext The container we obtain is of type WebApplicationContext +---------------------------------------------------+ | | | | | | | +------------+ +------------+ | | | +------------+ | +------------+ | | | | +-------------+ | | +-------------+ | | | | | | | | | | | | +-+ | Controllers | +-+ | Special | | | +-+ | +-+ beans | | | +-------------+ +-------------+ | | | | | | | +---------------------------------------------------+ Spring DI Container
WebApplicationContext WebApplicationContext extends the ApplicationContext interface with some extra features necessary for Web applica7ons public interface WebApplicationContext extends ApplicationContext { ... }
Configura)on metadata As with any DI container, WebApplicationContext has to be provided with some configura)on metadata + Objects | | | | +---------v---------+ | | | Spring | +-------------> Container | | | Configuration +---------+---------+ metadata | (e.g., XML file) | | v Fully configured system
frontcontroller-servlet.xml In par'cular, the container looks in WEB-INF/ for an XML file named frontcontroller-servlet.xml1 1 More generally, the servletName in servletName-servlet.xml must be the same as the <servlet-name> specified in web.xml
frontcontroller-servlet.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=”..."> <!-- CONFIGURE CONTROLLERS AND SPECIAL BEANS HERE --> </beans>
Overriding defaults By altering frontcontroller-servlet.xml, we can customize or replace default beans within the container
Overriding defaults Example: customizing InternalResourceViewResolver <bean class="org.springframework.web. servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
Wri$ng controllers
Controllers Controllers are responsible for responding to the ac#ons the user takes on the user interface • Submi'ng a form • Clicking on a link • Accessing a page
Types of controllers There exist two op-ons for wri-ng controllers • Using the @Controller annota-on • Implemen-ng the Controller interface2 2 Do not use this approach. The only reason why the Controller interface is s5ll available is to preserve compa5bility with legacy code
Annotated controllers To write annotated controllers we need to use the @Controller annota/on @Controller public class GreetingController { ... }
Annotated controllers The @Controller annota)on indicates that a par)cular class serves the role of a controller @Controller public class GreetingController { ... }
Auto-detec)ng controllers A simple addi+on to frontcontroller-servlet.xml allows the container to auto-detect annotated controllers <context:component-scan base-package="it.polimi.awt.springmvc.web"/>
Auto-detec)ng controllers The <context:component-scan> element recursively scans a package, looking for classes to be automa8cally registered as beans <context:component-scan base-package="it.polimi.awt.springmvc.web"/>
@RequestMapping The @RequestMapping annota)on is used to map URLs to handler methods @Controller public class GreetingController { @RequestMapping("/greeting") public String getGreeting() { ... } }
@RequestMapping The /greeting URL is mapped to getGreeting() @RequestMapping("/greeting") public String getGreeting() { ... }
Unique endpoints Think of handler methods as unique endpoints, with mappings derived from the related @RequestMapping annota6ons @RequestMapping("/greeting") public String getGreeting() {...}
Annotated controllers upsides When you open a controller, you can see which URLs the controller is mapped to @RequestMapping("/greeting") public String getGreeting() {...}
Annotated controllers downsides The mapping is sca$ered throughout the codebase, making it harder to see which URL is mapped to which handler method @RequestMapping("/greeting") public String getGreeting() {...}
Mapping URLs to handlers In order to interpret the mappings defined in the controller class, Spring MVC needs a HandlerMapping implementa8on @RequestMapping("/greeting") public String getGreeting() {...}
Determining which handler to call The HandlerMapping interface provides the abstrac2on for mapping requests to handlers3 public interface HandlerMapping { public HandlerExecutionChain getHandler(HttpServletRequest request); } 3 The getHandler method returns a HandlerExecutionChain only because of the need of accoun4ng for possible interceptors. Conceptually, we can s4ll assume the method to return a handler
Determining which handler to call Each HandlerMapping implementa-on is able to inspect the request and come up with an appropriate handler +----------------+ | | | HandlerMapping | | | +---^------+-----+ | | HTTP | | Handler request | | | | +--+------v----+ +----------------+ | | | | | Dispatcher +-------------> Handler | +-------------> Servlet | | (Controller) | | <-------------+ | HTTP +--------------+ +----------------+ request
Determining which handler to call DispatcherServlet consults one or more HandlerMapping implementa.ons to know which handler to call +----------------+ | | | HandlerMapping | | | +---^------+-----+ | | HTTP | | Handler request | | | | +--+------v----+ +----------------+ | | | | | Dispatcher +-------------> Handler | +-------------> Servlet | | (Controller) | | <-------------+ | HTTP +--------------+ +----------------+ request
Determining which handler to call If no handler is found, a 404 HTTP response is sent back to the client +----------------+ | | | HandlerMapping | | | +---^------+-----+ | | HTTP | | Handler request | | | | +--+------v----+ +----------------+ | | | | | Dispatcher +-------------> Handler | +-------------> Servlet | | (Controller) | | <-------------+ | HTTP +--------------+ +----------------+ request
Overriding HandlerMapping DefaultAnnotationHandlerMapping is the default implementa-on of HandlerMapping public class DefaultAnnotationHandlerMapping implements HandlerMapping { ... }
Overriding HandlerMapping As of Spring 3, the suggested implementa.on became RequestMappingHandlerMapping public class DefaultAnnotationHandlerMapping implements HandlerMapping { ... } public class RequestMappingHandlerMapping implements HandlerMapping { ... }
Overriding HandlerMapping RequestMappingHandlerMapping is a HandlerMapping implementa+on that allows performing more advanced opera+ons • Data valida*on • Wri*ng and reading JSON • Date and numbers support
Overriding HandlerMapping To start using RequestMappingHandlerMapping, it is sufficient to alter frontcontroller-servlet.xml so as to add <mvc:annotation-driven/>
Responsibili*es We already know that the Web layer has two responsibili-es 1. Glueing together the service layer and the Web 2. Taking care of the naviga;on logic
Responsibili*es Let us now see how to implement such responsibili2es in prac(ce 1. Glueing together the service layer and the Web 2. Taking care of the naviga;on logic
1. Interac+ng with the service layer
Interac(ng with the service layer A"er being invoked, the controller processes the HTTP request and interacts with the service layer +---------------+ +----------------+ | +---------> | | Controller | | Service layer | | <---------+ | +---------------+ +----------------+
GreetingService For instance, we may assume that in our fic3onal applica3on, the user can request a random gree3ng public interface GreetingService { public String getRandomGreeting(); }
GreetingService implementa*on public class NaiveGreetingService implements GreetingService { private List<String> greetings; public NaiveGreetingService() { this.greetings = Arrays.asList( "Hello sweetie", "Valar morghulis", "Tiger tiger" ); } @Override public String getRandomGreeting() { int index = ThreadLocalRandom.current().nextInt(greetings.size()); return greetings.get(index); } }
Execu&ng the use case Within the handler method, we first execute the related use case @Controller public class GreetingController { private GreetingService service; @RequestMapping("/greeting") public String getGreeting() { // execute the related use case String greeting = service.getRandomGreeting(); ... } }
Execu&ng the use case Such an invoca+on may result in an arbitrarily complex object @Controller public class GreetingController { private GreetingService service; @RequestMapping("/greeting") public String getGreeting() { // execute the related use case String greeting = service.getRandomGreeting(); ... } }
Execu&ng the use case However, in this case we end up with a simple String @Controller public class GreetingController { private GreetingService service; @RequestMapping("/greeting") public String getGreeting() { // execute the related use case String greeting = service.getRandomGreeting(); ... } }
Model Once we collected the use case outcome, the next step is to build a model object +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
Model This model object will contain the frac%on of the outcome that holds some significance for the next view to render +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
Model The view will use the model to build up the dynamic parts of the user interface +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
Model The model is the collec+on of named objects needed by the view in order to render itself +---------------+--------------+ | key1 | value1 | +------------------------------+ | key2 | value2 | +------------------------------+ | key3 | value3 | +---------------+--------------+
Model a(ributes These named objects are usually called model a.ributes +---------------+--------------+ | key1 | value1 | +------------------------------+ | key2 | value2 | +------------------------------+ | key3 | value3 | +---------------+--------------+
Model implementa-ons Several data structures can be used for represen2ng a model • Any implementa-on of java.util.Map • Any implementa-on of the Model interface provided by Spring • A ModelMap object provided by Spring
Model as an input argument Regardless the specific implementa2on, it is common prac2ce to let the framework provide the model directly as an input argument public String getGreeting(Map<String, Object> model) {...} public String getGreeting(Model model) {...} public String getGreeting(ModelMap model) {...}
Model as a Map The only requirement when using java.util.Map to store model a4ributes is that the key has to be of type String @RequestMapping("/greeting") public String getGreeting(Map<String, Object> model) { String greeting = service.getRandomGreeting(); model.put("greeting", greeting); ... }
Model as a Map The value part of the map can be freely decided. Because of its generality, Object is a popular choice @RequestMapping("/greeting") public String getGreeting(Map<String, Object> model) { String greeting = service.getRandomGreeting(); model.put("greeting", greeting); ... }
Model as a Model The downside of using a Map is that we have to decide the name of each model a)ribute we want to store // deciding names... boring (and difficult!) model.put("greeting", greeting);
Model as a Model The Model interface provides convenient methods for popula4ng the Model, such as addAttribute() @RequestMapping("/special-deals") public String getSpecialDeals(Model model) { List<SpecialDeal> specialDeals = service.getSpecialDeals(); model.addAttribute(specialDeals); ... }
Model as a Model addAttribute() is the same as Map’s put(), except that it automa&cally generates the name for the model a5ribute @RequestMapping("/special-deals") public String getSpecialDeals(Model model) { List<SpecialDeal> specialDeals = service.getSpecialDeals(); model.addAttribute(specialDeals); ... }
Naming strategy • Scalar objects take the uncapitalized, unqualified class name • Collec.on objects take the uncapitalized, unqualified class name of the first object in the collec:on, with List appended to the name
Naming strategy Examples: • com.myapp.Product becomes product • List<com.myapp.Product> becomes productList
You can s)ll decide the names If needed, it is s+ll possible to decide the name of each model a4ribute @RequestMapping("/fullname") public String getFullname(Model model) { // as both "Jon" and "Snow" are of type // String, it is better to explicitly name them model.addAttribute("name", "Jon"); model.addAttribute("surname", "Snow"); ... }
Model as ModelMap The ModelMap class is a Map, but it provides some addi4onal conveniences w.r.t. the plain Map interface @RequestMapping("/fullname") public String getFullname(Model model) { // chained calls are handy! model.addAttribute("name", "Jon") .addAttribute("surname", "Snow"); ... }
Model as ModelMap Namely: • It adheres to the same naming conven2on as Model • The addAttribute() method checks if the values are null • It supports chained calls of the addAttribute() method
2. Taking care of the naviga2on logic
Choosing the next view When processing is complete, the controller is responsible for choosing what view the user sees next +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
The View renders the model Views are responsible for rendering the objects in the Model +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
The View interface Spring MVC does not make any assump)on on the specific view technology • JavaServer Pages • JavaServer Faces • Velocity
The View interface To this end, views are modeled according to the View interface public interface View { void render(Map<String,?> model, HttpServletRequest request, HttpServletResponse response) String getContentType(); }
The View interface As with many Spring’s interfaces, the View interface is really simple public interface View { void render(Map<String,?> model, HttpServletRequest request, HttpServletResponse response) String getContentType(); }
The render() method The View will render the output star2ng from • The Model • The Servlet’s request and response objects
The render() method The render() method returns void to denote that it is the arriving point of the en0re request processing pipeline7 void render(Map<String,?> model, HttpServletRequest request, HttpServletResponse response) 7 Here, we are not considering possible calls to HandlerInterceptor.afterCompletion()
The render() method Hence, it is the responsibility of the View not only to render the content, but also to actually return it to the client void render(Map<String,?> model, HttpServletRequest request, HttpServletResponse response)
Wri$ng a View implementa$on Given the interface, we can easily write a View implementa4on public class GreetingView implements View { @Override public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { PrintWriter out = response.getWriter(); out.print(model.get("greeting")); out.flush(); out.close(); } @Override String getContentType() { ... } }
View implementa*ons However, most probably we would prefer to use a specific view technology, rather than implemen9ng our own Views
View technology independence Spring MVC makes a special effort to keep the controller unaware of the adopted view technology @RequestMapping("/greeting") public String getGreeting(Model model) { ... return "greeting"; }
View technology independence Such a decoupling is achieved by referring to views by their logical name @RequestMapping("/greeting") public String getGreeting(Model model) { ... return "greeting"; }
View technology independence In order to enforce decoupling, we let the controller knows nothing of the view but its logical name @RequestMapping("/greeting") public String getGreeting(Model model) { ... return "greeting"; }
ViewResolver The special bean ViewResolver will later resolve the view’s logical name to an actual view instance public interface ViewResolver { View resolveViewName(String viewName, Locale locale); }
ViewResolver Implementa)ons of ViewResolver are able to provide the mapping between logical names and View objects +-----------------+ | | | ViewResolver | | | +---+-----------^-+ | | +---v----+ | | View | | +---+----+ | | | +-----v-----------+---+ +----------------+ | | | | | DispatcherServlet <-------+ Controller | | | | | +---------------------+ +----------------+
getGreeting() @RequestMapping("/greeting") public String getGreeting(Model model) { String greeting = service.getRandomGreeting(); model.addAttribute("greeting", greeting); return "greeting"; }
Controller testability Note that this allows controllers to be easily unit-tested6 public class GreetingControllerTest { @Test public void getGreetingTest() { GreetingController controller = new GreetingController(...); Map<String, Object> model = new HashMap<>(); String viewName = controller.getGreeting(model); assertTrue(viewName.equals("greeting")); assertTrue(model.get("expression") != null); } } 6 Snippet adapted from h0p://stackoverflow.com/a/9363053/1849221
InternalResourceViewResolver The most commonly used ViewResolver when developing with JSP is the InternalResourceViewResolver
InternalResourceViewResolver InternalResourceViewResolver obtains the psychical view loca1on by surrounding the logical name with a prefix and a suffix
InternalResourceViewResolver We need to configure InternalResourceViewResolver in frontcontroller-servlet.xml <bean class="org.springframework.web. servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
Hiding JSP pages It is good prac-ce to place all view pages under the /WEB-INF directory
Hiding JSP pages This protects the pages from being retrieved independently of the Controllers that configure them
References
References • Stackoverflow, Design pa5erns for Web applica:ons • SpringSource, Spring Framework Reference • SpringSource, Java-doc APIs • Stackoverflow, ModelMap usage in Spring
References • S. Ladd, K. Donald, Expert Spring MVC and Web flows, Apress PublicaBons • M. Deinum, K. Serneels, Pro Spring MVC: with Web flows, Apress PublicaBons • Craig Walls, Spring in AcBon (3rd EdiBon), Manning PublicaBons • T. N. Husted et al., Struts 1 In AcBon, Manning PublicaBons
References • Clarence Ho, Rob Harrop, Pro Spring 3, Apress Publica8ons • Rod Johnson et al., Professional Java Development with the Spring Framework, Wiley Publishing

Spring MVC - The Basics

  • 1.
    Spring MVC -The Basics Ilio Catallo - info@iliocatallo.it
  • 2.
    Outline • MVC andMVC 2 • Request processing pipeline • Se8ng up Spring MVC • Wri:ng Controllers • References
  • 3.
  • 4.
    Model-View-Controller The Model-View-Controller (MVC)pa5en was invented at Xerox Parc by Trygve Reenskaug in 1979
  • 5.
    MVC pa'ern Applica'ons shouldhave three major parts • The part that manages the data • The part that creates screens and reports • The part that handles interac3ons between the user and the other subsystems
  • 6.
    MVC pa'ern Applica'ons shouldhave three major parts • Model • View • Controller
  • 7.
    MVC pa'ern Applica'ons shouldhave three major parts • Domain model • View • Controller
  • 8.
    MVC pa'ern +------------------+ +---------------+ | || Controller +----------+ | +-------> | | View | +------------------+ | selection | | | | | | | State change | User | | interaction | | | | +---v-------+---+ +-------v--------+ | | | | | View <---Change notification---+ Domain model | | | | | +-------+-------+ +-------^--------+ | | | | +---------------State query---------------+
  • 9.
    What is thereason not to use the same MVC pa2ern also for Web applica7ons?
  • 10.
    HTTP limita*ons The reasonis that the HTTP protocol limits the applicability of the MVC pa7ern
  • 11.
    Stateless protocol The MVCpa*ern requires a stateful protocol to keep track of the applica.on state
  • 12.
    Applica'on state "If wethink of an applica1on as being computerized behavior that achieves a goal, we can describe an applica1on protocol as the set of legal interac1ons necessary to realize that behavior. Applica3on state is a snapshot of an execu1on of such an applica1on protocol." (J. Webber et al.)
  • 13.
  • 14.
    Pull protocol The MVCpa*ern requires a push protocol for the views to be no7fied by the model
  • 15.
    Pull protocol However, HTTPis a pull protocol: no request implies no response
  • 16.
    How can weovercome such limita2ons?
  • 17.
    Stateless protocol HTTP isstateless: we can implement the MVC design pa3ern on top of the Java Servlet Pla;orm
  • 18.
    Stateless protocol The JavaServlet Pla-orm provides a session context to help track users in the applica8on
  • 19.
    Pull protocol HTTP isa pull protocol: we can increase the Controller responsibility
  • 20.
    Pull protocol Namely, theController will be responsible for: • State changes • State queries • Change no2fica2ons
  • 21.
    MVC 2 pa(ern Theresul)ng pa.ern is some)mes called MVC 2 or Web MVC +-------------+ +---------------+ +----------------+ | +----------> +---------> | | View | | Controller | | Domain model | | <----------+ <---------+ | +-------------+ +---------------+ +----------------+
  • 22.
    MVC 2 pa(ern Anystate query or change no0fica0on must pass through the Controller +-------------+ +---------------+ +----------------+ | +----------> +---------> | | View | | Controller | | Domain model | | <----------+ <---------+ | +-------------+ +---------------+ +----------------+
  • 23.
    MVC 2 pa(ern TheView renders data passed by the Controller rather than data returned directly from the Model +-------------+ +---------------+ +----------------+ | +----------> +---------> | | View | | Controller | | Domain model | | <----------+ <---------+ | +-------------+ +---------------+ +----------------+
  • 24.
    MVC 2 pa(ern Werefer to such data as the view model +-------------+ +---------------+ +----------------+ | +--------------> +---------> | | View | | Controller | | Domain model | | <--View model--+ <---------+ | +-------------+ +---------------+ +----------------+
  • 25.
    Compe&ng architectures Note thatMVC 2 proposes a compe&ng architecture to the one we presented during the last lecture ┌──────┐┌────────────────────────────────┐ │ D ││ │ │ o ││ Presentation layer │ │ m ││ │ │ a │└────────────────────────────────┘ │ i │┌────────────────────────────────┐ │ n ││ │ │ ││ Service layer │ │ m ││ │ │ o │└────────────────────────────────┘ │ d │┌────────────────────────────────┐ │ e ││ │ │ l ││ Persistence layer │ │ ││ │ └──────┘└────────────────────────────────┘
  • 26.
    Compe&ng architectures We reconcilethe two architectures by limi3ng the scope of the MVC 2 pa;ern to the sole presenta(on layer ┌──────┐┌────────────────────────────────┐ │ D ││ │ │ o ││ Presentation layer │ │ m ││ │ │ a │└────────────────────────────────┘ │ i │┌────────────────────────────────┐ │ n ││ │ │ ││ Service layer │ │ m ││ │ │ o │└────────────────────────────────┘ │ d │┌────────────────────────────────┐ │ e ││ │ │ l ││ Persistence layer │ │ ││ │ └──────┘└────────────────────────────────┘
  • 27.
    Compe&ng architectures The controllerwill defer actual computa3on to the service layer +-------------+ +---------------+ +----------------+ | +--------------> +---------> | | View | | Controller | | Service layer | | <--View model--+ <---------+ | +-------------+ +---------------+ +----------------+
  • 28.
    What is SpringMVC? Spring MVC is an open source MVC 2 framework for developing Web applica3ons
  • 29.
    Spring MVC Spring MVCeases Web applica2on development • It provides a ready-to-use MVC 2 Controller • It promotes Spring’s loosely coupled techniques in the presenta>on layer of an applica>on
  • 30.
  • 31.
    DispatcherServlet Spring MVC isdesigned around a central servlet named DispatcherServlet Presentation layer +---------------------------------+ | | | | | | | +-----------------------+ | | | | | | | DispatcherServlet | | | | | | | +-----------------------+ | | | | | | | | | +---------------------------------+
  • 32.
    DispatcherServlet DispatcherServlet acts asa centralized entry point to the Web applica.on Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> DispatcherServlet | | | | | | | | +---------------+ | +-----------------------+ | | | | | | | | | +---------------------------------+
  • 33.
    DispatcherServlet That is, everyrequest is handled by DispatcherServlet Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> DispatcherServlet | | | | | | | | +---------------+ | +-----------------------+ | | | | | | | | | +---------------------------------+
  • 34.
    DispatcherServlet DispatcherServlet is anexpression of the front controller pa.ern Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> Front Controller | | | | | | | | +---------------+ | +-----------------------+ | | | | | | | | | +---------------------------------+
  • 35.
    The Front Controller TheFront controller’s job is to determine a suitable handler capable of performing the actual processing Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> Front Controller | | | | | | | | +---------------+ | +-----------+-----------+ | | | | | | | | | | | +--------v---------+ | | | | | | | Handler | | | | | | | +------------------+ | | | | | +---------------------------------+
  • 36.
    Controllers Handlers are nearlyalways Spring MVC controllers Presentation layer +---------------------------------+ | | | | | | +---------------+ | +-----------------------+ | | | Request | | | | | Browser +--------------> Front Controller | | | | | | | | +---------------+ | +-----------+-----------+ | | | | | | | | | | | +--------v---------+ | | | | | | | Controller | | | | | | | +------------------+ | | | | | +---------------------------------+
  • 37.
    Model The selected Controllerinteracts with the service layer; the relevant data are collected in a view model Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-------+ | | | | | | | | | | | | +--------v----------+ | | | | | Persistence layer | | | | | +--------+----------+ | | | | | | +---v----------+ | | v | | | | | +--+---+ | | Controller <-----+ | | | | | | | DB | | +--------------+ | | | +--------------------------------------+ +------+
  • 38.
    Model The selected Controllerinteracts with the service layer; the relevant data are collected in a view model Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-----^-+ | | | | | | | | | | | +---+---+ | | +--------v----------+ | | | Model | | | | Persistence layer | | | +---+---+ | | +--------+----------+ | | | | | | | +---v-----+----+ | | v | | | | | +--+---+ | | Controller <-----+ | | | | | | | DB | | +--------------+ | | | +--------------------------------------+ +------+
  • 39.
    Model Spring MVC refersto the view model simply as the model. This may lead to confusion with the classic MVC terminology Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-----^-+ | | | | | | | | | | | +---+---+ | | +--------v----------+ | | | Model | | | | Persistence layer | | | +---+---+ | | +--------+----------+ | | | | | | | +---v-----+----+ | | v | | | | | +--+---+ | | Controller <-----+ | | | | | | | DB | | +--------------+ | | | +--------------------------------------+ +------+
  • 40.
    Model Regardless the name,remember that the model consists of data the Controller prepares just for the view Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-----^-+ | | | | | | | | | | | +---+---+ | | +--------v----------+ | | | Model | | | | Persistence layer | | | +---+---+ | | +--------+----------+ | | | | | | | +---v-----+----+ | | v | | | | | +--+---+ | | Controller <-----+ | | | | | | | DB | | +--------------+ | | | +--------------------------------------+ +------+
  • 41.
    Controllers When the controllerhas finished processing, the front controller determines which view to render Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------------------+-----^-+ | | | | | | | | | | | +---+---+ | | +--------v----------+ | | | Model | | | | Persistence layer | | | +---+---+ | | +--------+----------+ | | | | | | | +-------------+ +---v-----+----+ | | v | | | | | | | +--+---+ | | View | | Controller <-----+ | | | | | | | | | DB | | +-------------+ +--------------+ | | | +--------------------------------------+ +------+
  • 42.
    Views When the controllerhas finished processing, the front controller determines which view to render Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-------+-----------+-----^-+ | | | | | | | | | | | +---+---+ | +---+---+ | | +--------v----------+ | | Model | | | Model | | | | Persistence layer | | +---+---+ | +---+---+ | | +--------+----------+ | | | | | | | | +--------v----+ +---v-----+----+ | | v | | | | | | | +--+---+ | | View | | Controller <-----+ | | | | | | | | | DB | | +-------------+ +--------------+ | | | +--------------------------------------+ +------+
  • 43.
    Views When the controllerhas finished processing, the front controller determines which view to render Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | | | | | | | +--------+----------+ +-------------+ | +-^-----+-----------+-----^-+ | | | | | | | | | | | | | +---+---+ | +---+---+ | | +--------v----------+ | | | Model | | | Model | | | | Persistence layer | | | +---+---+ | +---+---+ | | +--------+----------+ | | | | | | | | | +--+-----v----+ +---v-----+----+ | | v | | | | | | | +--+---+ | | View | | Controller <-----+ | | | | | | | | | DB | | +-------------+ +--------------+ | | | +--------------------------------------+ +------+
  • 44.
    Views When the controllerhas finished processing, the front controller determines which view to render Presentation layer +--------------------------------------+ | | +-------------+ Request | +---------------------------+ | | +--------------> | | +-------------------+ | Browser | | | Front controller | | +-> Service layer | | +<-------------+ | | | +--------+----------+ +-------------+ Response| +-^-----+-----------+-----^-+ | | | | | | | | | | | | | +---+---+ | +---+---+ | | +--------v----------+ | | | Model | | | Model | | | | Persistence layer | | | +---+---+ | +---+---+ | | +--------+----------+ | | | | | | | | | +--+-----v----+ +---v-----+----+ | | v | | | | | | | +--+---+ | | View | | Controller <-----+ | | | | | | | | | DB | | +-------------+ +--------------+ | | | +--------------------------------------+ +------+
  • 45.
  • 46.
    Se#ng up SpringMVC Se#ng up Spring MVC is a two-step process 1. Loading DispatcherServlet in the Web container 2. Instan5a5ng a DI container and the related beans
  • 47.
    1. Loading DispatcherServletin the Web container
  • 48.
    Loading the frontcontroller We need to tell the Web container to load DispatcherServlet
  • 49.
    Loading the frontcontroller To this end, we provide the Web container with a web.xml deployment descriptor file + Web components | (e.g., servlets) | +-------v--------+ | | | Web | web.xml +--------> container | | | +-------+--------+ | | v Web app
  • 50.
    Loading the frontcontroller Recall that the web.xml file describes how to deploy the Web components of an applica6on + Web components | (e.g., servlets) | +-------v--------+ | | | Web | web.xml +--------> container | | | +-------+--------+ | | v Web app
  • 51.
    Loading the frontcontroller <!-- Load DispatcherServlet --> <servlet> <servlet-name>frontcontroller</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- URL mapping --> <servlet-mapping> <servlet-name>frontcontroller</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
  • 52.
    2. Instan)a)ng aDI container and the related beans
  • 53.
    Instan&a&ng beans DispatcherServlet instan'atesa Spring DI container +---------------------------------------------------+ | | | | | | | +------------+ +------------+ | | | +------------+ | +------------+ | | | | +-------------+ | | +-------------+ | | | | | | | | | | | | +-+ | Controllers | +-+ | Special | | | +-+ | +-+ beans | | | +-------------+ +-------------+ | | | | | | | +---------------------------------------------------+ Spring DI Container
  • 54.
    Instan&a&ng beans Such acontainer hosts beans belonging to the presenta(on layer • Controllers • Special beans
  • 55.
    Controllers Controllers are wri'enby the developer and provide access to the service layer of the applica5on @Controller public class AccountController { ... }
  • 56.
    Special beans Special beansare beans that are already part of Spring MVC
  • 57.
    Special beans More precisely,special beans are DispatcherServlet's collaborators
  • 58.
    Special beans DispatcherServlet relieson them to process requests and render the appropriate views
  • 59.
    Special beans Each specialbean plays its own small part in the overall processing of the request
  • 60.
    Special beans For instance: •HandlerMapping maps HTTP requests to handlers • ViewResolver maps logical name to views • HandlerExceptionResolver maps excep:ons to handlers
  • 61.
    Special bean interfaces Eachspecial bean is expressed as an interface public interface ViewResolver { View resolveViewName(String viewName, Locale locale); }
  • 62.
    Special bean advantages Thanksto this, the request processing pipeline is highly flexible and configurable
  • 63.
    Special bean advantages Indeed,we can tailor each stage of the pipeline just by changing its concrete implementa9on public class VelocityViewResolver implements ViewResolver { ... } public class XmlViewResolver implements ViewResolver { ... } public class InternalResourceViewResolver implements ViewResolver { ... }
  • 64.
    Default special beans Foreach special bean, the DispatcherServlet maintains a list of implementa)ons to be used by default
  • 65.
    Default special beans Forinstance, InternalResourceViewResolver is instan-ated by default public class InternalResourceViewResolver implements ViewResolver { ... }
  • 66.
    Default special beans Ifnot stated otherwise, DispatcherServlet will use default implementa4ons throughout the en4re processing pipeline
  • 67.
    Web beans Controllers andspecial beans are the Web beans of our applica3on +---------------------------------------------------+ | | | | | | | +------------+ +------------+ | | | +------------+ | +------------+ | | | | +-------------+ | | +-------------+ | | | | | | | | | | | | +-+ | Controllers | +-+ | Special | | | +-+ | +-+ beans | | | +-------------+ +-------------+ | | | | | | | +---------------------------------------------------+ Spring DI Container
  • 68.
    WebApplicationContext The container weobtain is of type WebApplicationContext +---------------------------------------------------+ | | | | | | | +------------+ +------------+ | | | +------------+ | +------------+ | | | | +-------------+ | | +-------------+ | | | | | | | | | | | | +-+ | Controllers | +-+ | Special | | | +-+ | +-+ beans | | | +-------------+ +-------------+ | | | | | | | +---------------------------------------------------+ Spring DI Container
  • 69.
    WebApplicationContext WebApplicationContext extends theApplicationContext interface with some extra features necessary for Web applica7ons public interface WebApplicationContext extends ApplicationContext { ... }
  • 70.
    Configura)on metadata As withany DI container, WebApplicationContext has to be provided with some configura)on metadata + Objects | | | | +---------v---------+ | | | Spring | +-------------> Container | | | Configuration +---------+---------+ metadata | (e.g., XML file) | | v Fully configured system
  • 71.
    frontcontroller-servlet.xml In par'cular, thecontainer looks in WEB-INF/ for an XML file named frontcontroller-servlet.xml1 1 More generally, the servletName in servletName-servlet.xml must be the same as the <servlet-name> specified in web.xml
  • 72.
    frontcontroller-servlet.xml <?xml version="1.0" encoding="UTF-8"?> <beansxmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=”..."> <!-- CONFIGURE CONTROLLERS AND SPECIAL BEANS HERE --> </beans>
  • 73.
    Overriding defaults By alteringfrontcontroller-servlet.xml, we can customize or replace default beans within the container
  • 74.
    Overriding defaults Example: customizingInternalResourceViewResolver <bean class="org.springframework.web. servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
  • 75.
  • 76.
    Controllers Controllers are responsiblefor responding to the ac#ons the user takes on the user interface • Submi'ng a form • Clicking on a link • Accessing a page
  • 77.
    Types of controllers Thereexist two op-ons for wri-ng controllers • Using the @Controller annota-on • Implemen-ng the Controller interface2 2 Do not use this approach. The only reason why the Controller interface is s5ll available is to preserve compa5bility with legacy code
  • 78.
    Annotated controllers To writeannotated controllers we need to use the @Controller annota/on @Controller public class GreetingController { ... }
  • 79.
    Annotated controllers The @Controllerannota)on indicates that a par)cular class serves the role of a controller @Controller public class GreetingController { ... }
  • 80.
    Auto-detec)ng controllers A simpleaddi+on to frontcontroller-servlet.xml allows the container to auto-detect annotated controllers <context:component-scan base-package="it.polimi.awt.springmvc.web"/>
  • 81.
    Auto-detec)ng controllers The <context:component-scan>element recursively scans a package, looking for classes to be automa8cally registered as beans <context:component-scan base-package="it.polimi.awt.springmvc.web"/>
  • 82.
    @RequestMapping The @RequestMapping annota)onis used to map URLs to handler methods @Controller public class GreetingController { @RequestMapping("/greeting") public String getGreeting() { ... } }
  • 83.
    @RequestMapping The /greeting URLis mapped to getGreeting() @RequestMapping("/greeting") public String getGreeting() { ... }
  • 84.
    Unique endpoints Think ofhandler methods as unique endpoints, with mappings derived from the related @RequestMapping annota6ons @RequestMapping("/greeting") public String getGreeting() {...}
  • 85.
    Annotated controllers upsides Whenyou open a controller, you can see which URLs the controller is mapped to @RequestMapping("/greeting") public String getGreeting() {...}
  • 86.
    Annotated controllers downsides Themapping is sca$ered throughout the codebase, making it harder to see which URL is mapped to which handler method @RequestMapping("/greeting") public String getGreeting() {...}
  • 87.
    Mapping URLs tohandlers In order to interpret the mappings defined in the controller class, Spring MVC needs a HandlerMapping implementa8on @RequestMapping("/greeting") public String getGreeting() {...}
  • 88.
    Determining which handlerto call The HandlerMapping interface provides the abstrac2on for mapping requests to handlers3 public interface HandlerMapping { public HandlerExecutionChain getHandler(HttpServletRequest request); } 3 The getHandler method returns a HandlerExecutionChain only because of the need of accoun4ng for possible interceptors. Conceptually, we can s4ll assume the method to return a handler
  • 89.
    Determining which handlerto call Each HandlerMapping implementa-on is able to inspect the request and come up with an appropriate handler +----------------+ | | | HandlerMapping | | | +---^------+-----+ | | HTTP | | Handler request | | | | +--+------v----+ +----------------+ | | | | | Dispatcher +-------------> Handler | +-------------> Servlet | | (Controller) | | <-------------+ | HTTP +--------------+ +----------------+ request
  • 90.
    Determining which handlerto call DispatcherServlet consults one or more HandlerMapping implementa.ons to know which handler to call +----------------+ | | | HandlerMapping | | | +---^------+-----+ | | HTTP | | Handler request | | | | +--+------v----+ +----------------+ | | | | | Dispatcher +-------------> Handler | +-------------> Servlet | | (Controller) | | <-------------+ | HTTP +--------------+ +----------------+ request
  • 91.
    Determining which handlerto call If no handler is found, a 404 HTTP response is sent back to the client +----------------+ | | | HandlerMapping | | | +---^------+-----+ | | HTTP | | Handler request | | | | +--+------v----+ +----------------+ | | | | | Dispatcher +-------------> Handler | +-------------> Servlet | | (Controller) | | <-------------+ | HTTP +--------------+ +----------------+ request
  • 92.
    Overriding HandlerMapping DefaultAnnotationHandlerMapping isthe default implementa-on of HandlerMapping public class DefaultAnnotationHandlerMapping implements HandlerMapping { ... }
  • 93.
    Overriding HandlerMapping As ofSpring 3, the suggested implementa.on became RequestMappingHandlerMapping public class DefaultAnnotationHandlerMapping implements HandlerMapping { ... } public class RequestMappingHandlerMapping implements HandlerMapping { ... }
  • 94.
    Overriding HandlerMapping RequestMappingHandlerMapping isa HandlerMapping implementa+on that allows performing more advanced opera+ons • Data valida*on • Wri*ng and reading JSON • Date and numbers support
  • 95.
    Overriding HandlerMapping To startusing RequestMappingHandlerMapping, it is sufficient to alter frontcontroller-servlet.xml so as to add <mvc:annotation-driven/>
  • 96.
    Responsibili*es We already knowthat the Web layer has two responsibili-es 1. Glueing together the service layer and the Web 2. Taking care of the naviga;on logic
  • 97.
    Responsibili*es Let us nowsee how to implement such responsibili2es in prac(ce 1. Glueing together the service layer and the Web 2. Taking care of the naviga;on logic
  • 98.
    1. Interac+ng withthe service layer
  • 99.
    Interac(ng with theservice layer A"er being invoked, the controller processes the HTTP request and interacts with the service layer +---------------+ +----------------+ | +---------> | | Controller | | Service layer | | <---------+ | +---------------+ +----------------+
  • 100.
    GreetingService For instance, wemay assume that in our fic3onal applica3on, the user can request a random gree3ng public interface GreetingService { public String getRandomGreeting(); }
  • 101.
    GreetingService implementa*on public classNaiveGreetingService implements GreetingService { private List<String> greetings; public NaiveGreetingService() { this.greetings = Arrays.asList( "Hello sweetie", "Valar morghulis", "Tiger tiger" ); } @Override public String getRandomGreeting() { int index = ThreadLocalRandom.current().nextInt(greetings.size()); return greetings.get(index); } }
  • 102.
    Execu&ng the usecase Within the handler method, we first execute the related use case @Controller public class GreetingController { private GreetingService service; @RequestMapping("/greeting") public String getGreeting() { // execute the related use case String greeting = service.getRandomGreeting(); ... } }
  • 103.
    Execu&ng the usecase Such an invoca+on may result in an arbitrarily complex object @Controller public class GreetingController { private GreetingService service; @RequestMapping("/greeting") public String getGreeting() { // execute the related use case String greeting = service.getRandomGreeting(); ... } }
  • 104.
    Execu&ng the usecase However, in this case we end up with a simple String @Controller public class GreetingController { private GreetingService service; @RequestMapping("/greeting") public String getGreeting() { // execute the related use case String greeting = service.getRandomGreeting(); ... } }
  • 105.
    Model Once we collectedthe use case outcome, the next step is to build a model object +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
  • 106.
    Model This model objectwill contain the frac%on of the outcome that holds some significance for the next view to render +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
  • 107.
    Model The view willuse the model to build up the dynamic parts of the user interface +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
  • 108.
    Model The model isthe collec+on of named objects needed by the view in order to render itself +---------------+--------------+ | key1 | value1 | +------------------------------+ | key2 | value2 | +------------------------------+ | key3 | value3 | +---------------+--------------+
  • 109.
    Model a(ributes These namedobjects are usually called model a.ributes +---------------+--------------+ | key1 | value1 | +------------------------------+ | key2 | value2 | +------------------------------+ | key3 | value3 | +---------------+--------------+
  • 110.
    Model implementa-ons Several datastructures can be used for represen2ng a model • Any implementa-on of java.util.Map • Any implementa-on of the Model interface provided by Spring • A ModelMap object provided by Spring
  • 111.
    Model as aninput argument Regardless the specific implementa2on, it is common prac2ce to let the framework provide the model directly as an input argument public String getGreeting(Map<String, Object> model) {...} public String getGreeting(Model model) {...} public String getGreeting(ModelMap model) {...}
  • 112.
    Model as aMap The only requirement when using java.util.Map to store model a4ributes is that the key has to be of type String @RequestMapping("/greeting") public String getGreeting(Map<String, Object> model) { String greeting = service.getRandomGreeting(); model.put("greeting", greeting); ... }
  • 113.
    Model as aMap The value part of the map can be freely decided. Because of its generality, Object is a popular choice @RequestMapping("/greeting") public String getGreeting(Map<String, Object> model) { String greeting = service.getRandomGreeting(); model.put("greeting", greeting); ... }
  • 114.
    Model as aModel The downside of using a Map is that we have to decide the name of each model a)ribute we want to store // deciding names... boring (and difficult!) model.put("greeting", greeting);
  • 115.
    Model as aModel The Model interface provides convenient methods for popula4ng the Model, such as addAttribute() @RequestMapping("/special-deals") public String getSpecialDeals(Model model) { List<SpecialDeal> specialDeals = service.getSpecialDeals(); model.addAttribute(specialDeals); ... }
  • 116.
    Model as aModel addAttribute() is the same as Map’s put(), except that it automa&cally generates the name for the model a5ribute @RequestMapping("/special-deals") public String getSpecialDeals(Model model) { List<SpecialDeal> specialDeals = service.getSpecialDeals(); model.addAttribute(specialDeals); ... }
  • 117.
    Naming strategy • Scalarobjects take the uncapitalized, unqualified class name • Collec.on objects take the uncapitalized, unqualified class name of the first object in the collec:on, with List appended to the name
  • 118.
    Naming strategy Examples: • com.myapp.Productbecomes product • List<com.myapp.Product> becomes productList
  • 119.
    You can s)lldecide the names If needed, it is s+ll possible to decide the name of each model a4ribute @RequestMapping("/fullname") public String getFullname(Model model) { // as both "Jon" and "Snow" are of type // String, it is better to explicitly name them model.addAttribute("name", "Jon"); model.addAttribute("surname", "Snow"); ... }
  • 120.
    Model as ModelMap TheModelMap class is a Map, but it provides some addi4onal conveniences w.r.t. the plain Map interface @RequestMapping("/fullname") public String getFullname(Model model) { // chained calls are handy! model.addAttribute("name", "Jon") .addAttribute("surname", "Snow"); ... }
  • 121.
    Model as ModelMap Namely: •It adheres to the same naming conven2on as Model • The addAttribute() method checks if the values are null • It supports chained calls of the addAttribute() method
  • 122.
    2. Taking careof the naviga2on logic
  • 123.
    Choosing the nextview When processing is complete, the controller is responsible for choosing what view the user sees next +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
  • 124.
    The View rendersthe model Views are responsible for rendering the objects in the Model +--------------+ +--------------------+ +----------------+ | | +----------+ | | +----------+ | | | View <--+ Model +--+ Front Controller <--+ Model +--+ Controller | | | +----------+ | | +----------+ | | +--------------+ +--------------------+ +----------------+
  • 125.
    The View interface SpringMVC does not make any assump)on on the specific view technology • JavaServer Pages • JavaServer Faces • Velocity
  • 126.
    The View interface Tothis end, views are modeled according to the View interface public interface View { void render(Map<String,?> model, HttpServletRequest request, HttpServletResponse response) String getContentType(); }
  • 127.
    The View interface Aswith many Spring’s interfaces, the View interface is really simple public interface View { void render(Map<String,?> model, HttpServletRequest request, HttpServletResponse response) String getContentType(); }
  • 128.
    The render() method TheView will render the output star2ng from • The Model • The Servlet’s request and response objects
  • 129.
    The render() method Therender() method returns void to denote that it is the arriving point of the en0re request processing pipeline7 void render(Map<String,?> model, HttpServletRequest request, HttpServletResponse response) 7 Here, we are not considering possible calls to HandlerInterceptor.afterCompletion()
  • 130.
    The render() method Hence,it is the responsibility of the View not only to render the content, but also to actually return it to the client void render(Map<String,?> model, HttpServletRequest request, HttpServletResponse response)
  • 131.
    Wri$ng a Viewimplementa$on Given the interface, we can easily write a View implementa4on public class GreetingView implements View { @Override public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception { PrintWriter out = response.getWriter(); out.print(model.get("greeting")); out.flush(); out.close(); } @Override String getContentType() { ... } }
  • 132.
    View implementa*ons However, mostprobably we would prefer to use a specific view technology, rather than implemen9ng our own Views
  • 133.
    View technology independence SpringMVC makes a special effort to keep the controller unaware of the adopted view technology @RequestMapping("/greeting") public String getGreeting(Model model) { ... return "greeting"; }
  • 134.
    View technology independence Sucha decoupling is achieved by referring to views by their logical name @RequestMapping("/greeting") public String getGreeting(Model model) { ... return "greeting"; }
  • 135.
    View technology independence Inorder to enforce decoupling, we let the controller knows nothing of the view but its logical name @RequestMapping("/greeting") public String getGreeting(Model model) { ... return "greeting"; }
  • 136.
    ViewResolver The special beanViewResolver will later resolve the view’s logical name to an actual view instance public interface ViewResolver { View resolveViewName(String viewName, Locale locale); }
  • 137.
    ViewResolver Implementa)ons of ViewResolverare able to provide the mapping between logical names and View objects +-----------------+ | | | ViewResolver | | | +---+-----------^-+ | | +---v----+ | | View | | +---+----+ | | | +-----v-----------+---+ +----------------+ | | | | | DispatcherServlet <-------+ Controller | | | | | +---------------------+ +----------------+
  • 138.
    getGreeting() @RequestMapping("/greeting") public String getGreeting(Modelmodel) { String greeting = service.getRandomGreeting(); model.addAttribute("greeting", greeting); return "greeting"; }
  • 139.
    Controller testability Note thatthis allows controllers to be easily unit-tested6 public class GreetingControllerTest { @Test public void getGreetingTest() { GreetingController controller = new GreetingController(...); Map<String, Object> model = new HashMap<>(); String viewName = controller.getGreeting(model); assertTrue(viewName.equals("greeting")); assertTrue(model.get("expression") != null); } } 6 Snippet adapted from h0p://stackoverflow.com/a/9363053/1849221
  • 140.
    InternalResourceViewResolver The most commonlyused ViewResolver when developing with JSP is the InternalResourceViewResolver
  • 141.
    InternalResourceViewResolver InternalResourceViewResolver obtains thepsychical view loca1on by surrounding the logical name with a prefix and a suffix
  • 142.
    InternalResourceViewResolver We need toconfigure InternalResourceViewResolver in frontcontroller-servlet.xml <bean class="org.springframework.web. servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
  • 143.
    Hiding JSP pages Itis good prac-ce to place all view pages under the /WEB-INF directory
  • 144.
    Hiding JSP pages Thisprotects the pages from being retrieved independently of the Controllers that configure them
  • 145.
  • 146.
    References • Stackoverflow, Designpa5erns for Web applica:ons • SpringSource, Spring Framework Reference • SpringSource, Java-doc APIs • Stackoverflow, ModelMap usage in Spring
  • 147.
    References • S. Ladd,K. Donald, Expert Spring MVC and Web flows, Apress PublicaBons • M. Deinum, K. Serneels, Pro Spring MVC: with Web flows, Apress PublicaBons • Craig Walls, Spring in AcBon (3rd EdiBon), Manning PublicaBons • T. N. Husted et al., Struts 1 In AcBon, Manning PublicaBons
  • 148.
    References • Clarence Ho,Rob Harrop, Pro Spring 3, Apress Publica8ons • Rod Johnson et al., Professional Java Development with the Spring Framework, Wiley Publishing