EQUIP2 WebApp Simple Request Handling

Chris Greenhalgh, 2007-01-29

Contents:

Introduction

"I just want to get a web page...".

No EQUIP2 required - just J2EE and Spring.

See also EQUIP2_WebApp_Dynamic_Pages_with_JSP.html.

Without Spring

Files outside the web application's WEB-INF/ directory will be served directly by Tomcat (assuming that the underlying file permissions allow it).

For example, a request for the top-level index.html file from the web application:

A J2EE servlet container such as Tomcat also has built-in support for Java Server Pages, so a request for (e.g.) index2.jsp will also look for a file webapp/index2.jsp, and if it is present try to process it as a JSP and return the result.

Images, stylesheet files, applet files and other static content should normally be placed in the webapp directory (or subdirectories), outside of the WEB-INF/ subdirectory.

With Spring

This is also overviewed in the first few sections of EQUIP2_WebApp_Structure_Overview.html.

Request Mapping

For a request to be handled by Spring:

    <bean id="urlMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
               <prop key="/index.html">filenameViewController</prop>
            </props>
        </property>
    </bean>

What happens next depends completely on the Spring Controller that is called.

Note that mapping can contain wildcards, e.g. key="/view/*.html".

Standard Controllers

Spring has a number of standard reusable (configurable) controllers, as well as an hierarchy of abstract Controllers that can be specifialised - see the Spring documentation.

Static pages can often be handled using the simple UrlFilenameViewController, e.g. (as configured in simplerequest-servlet.xml):

	<bean id="filenameViewController"
class="org.springframework.web.servlet.mvc.UrlFilenameViewController">
<property name="prefix" value="simplerequest/" />
</bean>

This Controller extracts the last filename (without extension) from the request URL and returns this as the name of the Spring 'View' that should be rendered as the response. This view name (here, 'index' from the URL '.../index.html') is optionally modified by the Controller's configuration options, here a prefix string 'simplerequest/', which is applied to every view name which it returns.

This is a standard strategy that we have used - to map the servlet name (from the request) right through to the view name (and JSP file page - see below). This makes it relatively easy to identify which directories are relevant to which pieces of an application, e.g. JSPs in WEB-INF/jsp/simplerequest/.

Named View Resolution

A Spring View is a Java object which knows how to render itself. Spring support various view technologies (see Spring's documentation), but so far we have exclusively used Java Server Pages. A Controller can return an actual View object, however it can also - as in this example - return just the name of a view. The Spring dispatcher servlet then refers to its 'view resolution' configuration to get an actual view object to render.

The following generic configuration tells the Spring dispatcher that a named view should be a reference to a similarly named Java Server Page:

	<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>

For the case of the index page, above, the view name 'simplerequest/index' is therefore mapped othe resource path '/WEB-INF/jsp/simplerequest/index.jsp' (this path is within the scope of the web application); the corresponding JSP, WEB-INF/jsp/simplerequest/index.jsp is processed to get the result.

Note that Spring (and J2EE) also allows data to be passed from the Controller to the view, via the usual J2EE mechanisms, i.e.:

Spring normally uses the request scope to pass 'Model' information to the view.

Simple Custom Controller

The Controller interface required by the Spring Dispatcher servlet is org.springframework.web.servlet.mvc.Controller, which has the single method:
ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws Exception

 There are various abstract implementations base classes of this which implement the handleRequest() method itself, but provide various other override/extension points in their own processing. For example org.springframework.web.servlet.mvc.AbstractController has configuration options to specify the supported HTTP method(s) (GET, POST) and session and cacheing information, and requires implementations to override:

protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response)
throws Exception;

For example, the simplerequest-servlet.xml configures the URL http://.../simplerequest/abstract_controller.html to be handled by the bean 'myAbstractController' which it turn is an instance of class equip2.webapptutorial.simplerequest.MyAbstractController. This has configuration properties 'viewPrefix' and 'viewName', which are specified in this case as 'simplerequest/' and 'abstract_controller_ok', respectively. Consequently, the request is finally handled by rendering the JSP WEB-INF/jsp/simplerequest/abstract_controller_ok.jsp.

This controller also passes the string "Magic!" to the view as model attribute "model_info":

	ModelAndView mav = new ModelAndView();
mav.setViewName(getViewPrefix()+getViewName());

Map model = mav.getModel();
model.put("model_info", "Magic!");
return mav;

This is displayed by the view JSP:

	<%= requestScope.getAttribute("model_info") %>

Alternatively, a Controller can use the J2EE response object directly to provide a complete response; it should then return null from the handleRequest method, e.g.

	// return a HTTP Bad Request error
response.sendError(response.SC_BAD_REQUEST);
return null;

Changes

2007-01-29
2007-01-30