Views
mvc-overview.notes

Spring Web MVC Overview


my-bean.json
{
   "bean":{
      "children":[
         {
            "children":[
               {
                  "children":[

                  ],
                  "stringValue":"ddd",
                  "intValue":400,
                  "booleanValue":false
               }
            ],
            "stringValue":"bbb",
            "intValue":200,
            "booleanValue":false
         },
         {
            "children":[

            ],
            "stringValue":"ccc",
            "intValue":300,
            "booleanValue":true
         }
      ],
      "stringValue":"aaa",
      "intValue":100,
      "booleanValue":true
   }
}
my-bean.xml
<myBean>
  <intValue>100</intValue>
  <stringValue>aaa</stringValue>
  <booleanValue>true</booleanValue>
  <children>
    <myBean>
      <intValue>200</intValue>
      <stringValue>bbb</stringValue>
      <booleanValue>false</booleanValue>
      <children>
        <myBean>
          <intValue>400</intValue>
          <stringValue>ddd</stringValue>
          <booleanValue>false</booleanValue>
          <children/>
        </myBean>
      </children>
    </myBean>
    <myBean>
      <intValue>300</intValue>
      <stringValue>ccc</stringValue>
      <booleanValue>true</booleanValue>
      <children/>
    </myBean>
  </children>
</myBean>
using-lishys-notes.notes

Guide


The guide pane on the right contains information organized into sections.

Use the and buttons to move through the sections, or click an accordion tab (shown below) to go directly to a particular topic.



Code Reference


Each paragraph in the guide is usually associated with a particular piece of code. An orange arrow indicates that the code displayed in the middle pane is relevant to the guide text.



If the arrow is gray, simply click anywhere on the paragraph and the relevant code will be displayed.



Code Highlighter


The highlight feature identifies areas of the code which relate to a word or term in the guide. Hover the mouse over any underlined word and the relevant code will be highlighted.



You can disable the highlighting feature at any time by clicking on the button.

Don't forget to make the appropriate code page visible by clicking on any paragraph with a gray arrow.
ExcelPageView.java
package lishy.views.web;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.write.Formula;
import jxl.write.Label;
import jxl.write.Number;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

import org.springframework.web.servlet.view.document.AbstractJExcelView;

public class ExcelPageView extends AbstractJExcelView {

    @Override
    protected void buildExcelDocument(Map<String, Object> model,
                                      WritableWorkbook wb, 
                                      HttpServletRequest request,
                                      HttpServletResponse response) 
                                                throws Exception {
    
        int[] numbers = (int[]) model.get("numbers");
        int size = numbers.length;
        
        WritableSheet sheet = wb.createSheet("random numbers", 0);        
        sheet.addCell(new Label(0, 0, "Numbers"));       
        for (int i=0; i < size; i++) {
            sheet.addCell(new Number(0, i+1, numbers[i]));
        }
        sheet.addCell(new Formula(0, size+1, "SUM(A1:A" + (size+1) + ")"));
        
    }

}

PdfPageView.java
package lishy.views.web;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.view.document.AbstractPdfView;

import com.lowagie.text.Document;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;


public class PdfPageView extends AbstractPdfView {

    @Override
    protected void buildPdfDocument(Map<String, Object> model,
                                    Document doc,
                                    PdfWriter writer,
                                    HttpServletRequest request,
                                    HttpServletResponse response)
                                        throws Exception {
        
        doc.add( new Paragraph((String) model.get("message")));
    
    }
}

ViewController.java
package lishy.views.web;

import java.io.StringReader;

import lishy.views.MyBean;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ViewController {
 
    @RequestMapping("/message/{view}")
    public ModelAndView messageData(@PathVariable("view") String view) {       
        return new ModelAndView(view, "message", "A message from the model");
    }
    
    @RequestMapping("/xml/{view}")
    public ModelAndView xmlData(@PathVariable("view") String view) {
        final StringReader xmlReader = new StringReader(
                "<?xml version='1.0' encoding='ISO-8859-1'?>" +
                "<message>This is added to the model in the XML</message>");
        return new ModelAndView(view, "xmlSource", xmlReader);
    }
    
    @RequestMapping("/numbers/{view}")
    public ModelAndView excelData(@PathVariable("view") String view) {
        return new ModelAndView(view, "numbers", new int[]{10,30,60,5,90,12});
    }    
    
    @RequestMapping("/bean/{view}")
    public ModelAndView beanData(@PathVariable("view") String view) {
        return new ModelAndView(view, "bean", populateBean());
    } 
    
    private MyBean populateBean() {
        MyBean parent       = new MyBean(100, "aaa", true);
        MyBean firstChild   = new MyBean(200, "bbb", false);
        MyBean secondChild  = new MyBean(300, "ccc", true);
        MyBean grandChild   = new MyBean(400, "ddd", false);
        firstChild.addChild(grandChild);
        parent.addChild(firstChild);
        parent.addChild(secondChild);
        return parent;
    }
}

MyBean.java
package lishy.views;

import java.util.ArrayList;
import java.util.List;

public class MyBean {
 
    private int intValue;
    private String stringValue;
    private boolean booleanValue;
    private List<MyBean> children = new ArrayList<MyBean>();
    
    public MyBean(){};
    
    public MyBean(int intValue, String stringValue, boolean booleanValue) {
        this.intValue = intValue;
        this.stringValue = stringValue;
        this.booleanValue = booleanValue;
    }
    
    public int getIntValue() {
        return intValue;
    }
    public void setIntValue(int intValue) {
        this.intValue = intValue;
    }
    public String getStringValue() {
        return stringValue;
    }
    public void setStringValue(String stringValue) {
        this.stringValue = stringValue;
    }
    public boolean isBooleanValue() {
        return booleanValue;
    }
    public void setBooleanValue(boolean booleanValue) {
        this.booleanValue = booleanValue;
    }
    public List<MyBean> getChildren() {
        return children;
    }
    public void addChild(MyBean child) {
        this.children.add(child);
    }
    
    public String toString() {
        return toString("  ");
    }
    public String toString(String indent) {
        StringBuffer result = new StringBuffer();
        result.append(getIntValue() + ", " +  
                      getStringValue() + ", " +
                      isBooleanValue());
        for (MyBean child : getChildren()) {
            result.append("\n" + indent + child.toString(indent + " "));
        }
        return result.toString();
    }

}
jsp-view.jsp
<html>
  <body>
  
    <h1>JSP View</h1>
    
    <p style="color:green">${message}</p>
    
    <p>
      <a href="../../index.html">back</a>
    </p>
    
  </body>
</html>
xslt-view.xslt
<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="html" omit-xml-declaration="yes"/>

<xsl:template match="/">
<html>
  <body>
  
    <h1>XSLT View</h1>
    
    <p style="color:green"><xsl:value-of select="."/>
    and rendered using XSLT
    </p>
    
    <p>
      <a href="../../index.html">back</a>
    </p>
    
  </body>
</html>
</xsl:template>
</xsl:stylesheet>
views-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"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

  <context:component-scan base-package="lishy.views.web"/>

  <bean class="org.springframework.web.servlet.view.XmlViewResolver"/>

</beans>
views.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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

  <bean id="jsp-view"
        class="org.springframework.web.servlet.view.JstlView"
        p:url="/WEB-INF/jsp/jsp-view.jsp"/> 
    
  <bean id="xslt-view"
        class="org.springframework.web.servlet.view.xslt.XsltView"
        p:url="/WEB-INF/xslt/xslt-view.xslt"
        p:cacheTemplates="false"/>
          
  <bean id="pdf-view" class="lishy.views.web.PdfPageView"/>  
        
  <bean id="excel-view" class="lishy.views.web.ExcelPageView"/>      
  
  <bean id="json-view"
        class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>     
  
  <bean id="marshaller-view"
        class="org.springframework.web.servlet.view.xml.MarshallingView"
        p:marshaller-ref="marshaller"
        p:modelKey="bean"/>
        
  <bean id="marshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
    <property name="aliases">
        <props>
            <prop key="myBean">lishy.views.MyBean</prop>
        </props>
    </property>
  </bean>
    
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID"
         version="2.5">

  <display-name>Views</display-name>
  
  <servlet>
    <servlet-name>views</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>views</servlet-name>
    <url-pattern>/app/*</url-pattern>
  </servlet-mapping>
  
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
</web-app>
index.html
<html>
  <body>
  
    <h1>Views</h1>
   
    <p>
      <a href="app/message/jsp-view">JSP</a>
    </p>
    
    <p>
      <a href="app/xml/xslt-view">XSLT</a>
    </p>
        
    <p>
      <a href="app/message/pdf-view">PDF</a>
    </p>
    
    <p>
      <a href="app/numbers/excel-view">Excel</a>
    </p>
        
    <p>
      <a href="app/bean/json-view">JSON</a>
    </p> 
    
    <p>
      <a href="app/bean/marshaller-view">XML Marshaller</a>
    </p>    

  </body>
</html> 

Overview

A view uses data from the model to render content as JSP, XSLT, PDF, Excel etc.

A view resolver provides a mapping between view names (from the controller) and actual views.

Because we are combining different view technologies in the same application, we use XmlViewResolver to specify the mappings in an XML file.
Here we use the default filename of /WEB-INF/views.xml to map logical view names-view" to implementations of a View.
The following examples show how several of the view technologies can be configured.

JSP & JSTL

A requestjsp-view is made which will result in a JSP page being displayed.

A controller receives this request/message/, populates the model with a messagefrom the model, and specifies the view nameview:eq(5) which was passed in as part of the URL{view}:eq(0) (in this case 'jsp-view').

XmlViewResolver maps the logical view name, jsp-viewjsp-view", to a physical JSP pagejsp-view.jsp, which is then rendered using JstlView.

The JSP page is displayed and the message displayed from the model.

XSLT

A requestxslt-view is made which will result in an XML document being transformed into HTML, using XSLT.

Our controller receives the request/xml/, and adds a StringReaderStringReader:gt(0), containing the source XML, to the xmlSource attribute of the model.

The view{view}:eq(1) variable is extracted from the URI template and used as the view nameview:eq(9).
If we take another look at index.html we can see that xslt-view occupies this part of the URL.

xslt-viewxslt-view" is mapped to the XsltView class, which applies the specified style sheet/xslt/ to the XML produced by our controller.

The location of the source XML in the model (in our case xmlSource) can be specified explicitly using the sourceKey property of XsltView.

Alternatively, if this value is not supplied, Spring will attempt to locate an object of a supported type in the model (currently Source, Document, Node, Reader, InputStream and Resource).

The style sheet extracts the message from the root""/"" of the document and displaysvalue-of it on the page.

PDF

A requestpdf-view is made which will produce a PDF document containing a simple message.

As with the JSP & JSTL example, the controller receives this request/message/, populates the model with a messagefrom the model, and specifies the view nameview:eq(5) which was passed in as part of the URL{view}:eq(0) (in this case 'pdf-view').

This shows that the same information can be rendered using different technologies, just by changing the name of the view.

To produce the PDF document we map pdf-viewpdf-view" to the PdfPageView class.
This varies from the previous examples in that we must produce a custom implementation of AbstractPdfViewAbstractPdfView:eq(1) in order to create the document content.

This implementation relies on the iText package to build a document using data from the model.

Excel

A requestexcel-view is made which will produce an Excel spreadsheet containing a list of numbers and a total.

The controller receives the request/numbers/, populates the model with an array of numbers""numbers"", and specifies the view nameview:eq(13) which was passed in as part of the URL{view}:eq(2) (in this case 'excel-view').

To produce the Excel spreadsheet we map excel-viewexcel-view" to the ExcelPageView class.
ExcelPageView is a custom implementation of AbstractJExcelViewAbstractJExcelView:eq(1), which relies on JExcelAPI to produce a spreadsheet using data from the model.

JSON

A requestjson-view is made which will encode the contents of the model data returned by our controller, as JSON.

The controller receives the request/bean/, populates the model with an arbitrary JavaBeanpopulateBean, and specifies the view nameview:eq(17) which was passed in as part of the URL{view}:eq(3) (in this case 'json-view').

XmlViewResolver maps the logical view name json-view to a the MappingJacksonJsonView class which encodes the data in the model as JSON.

By default, the entire contents of the model map (with the exception of framework-specific classes) will be encoded. Use the renderedAttributes property of MappingJacksonJsonView to specify a set of model attributes to be used instead.

The JSON representation of our JavaBean looks like this.

XML Marshalling

A requestmarshaller-view is made which will use XStream object serialization to output our data as XML.

Like the previous example, the controller receives the request/bean/, populates the model with an arbitrary JavaBeanpopulateBean, and specifies the view nameview:eq(17) which was passed in as part of the URL{view}:eq(3) (in this case 'marshaller-view').

The logical view name, marshaller-view, is mapped to the MarshallingView class, which accepts two properties; marshaller-ref and modelKey.

marshaller-ref references XStreamMarshaller which is used to convert our beanMyBean to XML.

modelKey specifies the name of the model key that represents the object to be marshalled. In other words, the model attribute that contains our JavaBean.

The XML representation of our JavaBean looks like this.
Home  |  Getting Started  |  Controllers  |  Views  |  Forms  |  REST  |  Testing  |  Configuration  |  MVC Walkthrough  |   lishblog  |  Email Lishy