This Confluence has been LDAP enabled, if you are an ASF Committer, please use your LDAP Credentials to login. Any problems file an INFRA jira ticket please.

Page tree
Skip to end of metadata
Go to start of metadata

This page contains supplemental information to the Developing a Spring Framework MVC application step-by-step article by Thomas Risberg, showing the changes needed to use Velocity instead of JSP.

Part 1 - Basic Application and Environment Setup

Step 2 - index.jsp

Of course, we will be using Velocity, so let's name this file index.vm.

Step 4 - Test the application

Naturally, the URL is http://localhost:8080/springapp/index.vm

Step 6 - Modify web.xml in WEB-INF directory

web.xml : Change the welcome-file to...

  <welcome-file-list>
    <welcome-file>
      index.vm
    </welcome-file>
  </welcome-file-list>

Step 12 - Create a View

Again, this file will be hello.vm.

SpringappController.java : return the template.

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        logger.info("SpringappController - returning hello view");

        return new ModelAndView("hello.vm");
    }

Part 2 - Developing and Configuring the Application

Step 13 - Improve index.jsp

We won't be needing an include.vm, but let's make the springapp/war/WEB-INF/velocity directory anyways.

Add Velocity jar to springapp/war/WEB-INF/lib

web.xml : Change welcome file to hello.htm and add a servlet mapping to it

  <servlet-mapping>
    <servlet-name>springapp</servlet-name>
    <url-pattern>*.htm</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>springapp</servlet-name>
    <url-pattern>/hello.htm</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>
      hello.htm
    </welcome-file>
  </welcome-file-list>

Now, we won't even need an index.vm. Thanks to Marcelo Bello for the post in bugzilla, and Maarten Bosteels for finding this. (smile)

Step 14 - Improve the view and the controller

Move the view hello.vm to the WEB-INF/velocity directory.

springapp/war/WEB-INF/velocity/hello.vm : Use VTL instead of JSTL

<p>Greetings, it is now ${now}

springapp/src/SpringappController.java : Change the view to WEB-INF/velocity/hello.vm.

        return new ModelAndView("WEB-INF/velocity/hello.vm", "now", now);

Those of the impatient ones should now be wondering, "How come the ${now} doesn't get replaced by the time?". That is because Spring does not know of Velocity yet. So, we'll need to go ahead and add Velocity settings to the springapp-servlet.xml.

springapp/war/WEB-INF/springapp-servlet.xml : Add Velocity settings

    <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <property name="resourceLoaderPath">
            <value>/</value>
        </property>
    </bean>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
    </bean>

Now, you should be able to see the same screen.

Step 15 - Decouple the view and the controller

From this step, the Controller class is the same for JSP and Velocity. Isn't that wonderful?

springapp/war/WEB-INF/springapp-servlet.xml

    <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
        <property name="prefix"><value>/WEB-INF/velocity/</value></property>
        <property name="suffix"><value>.vm</value></property>
    </bean>

Step 17 - Modify the view to display business data and add support for message bundle

springapp/war/WEB-INF/velocity/hello.vm : VTL instead of JSTL

<html>
<head><title>#springMessage("title")</title></head>
<body>
<h1>#springMessage("heading")</h1>
<p>#springMessage("greeting") ${model.now}
</p>
<h3>Products</h3>
#foreach ($prod in ${model.products})
  ${prod.description} <i>${prod.price}</i><br><br>
#end
</body>
</html>

In order to enable the Spring Velocimacros, we need to set the "exposeSpringMacroHelpers" property to "true" for org.springframework.web.servlet.view.velocity.VelocityViewResolver.

springapp/war/WEB-INF/springapp-servlet.xml

    <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
        <property name="prefix"><value>/WEB-INF/velocity/</value></property>
        <property name="suffix"><value>.vm</value></property>
        <property name="exposeSpringMacroHelpers"><value>true</value></property>
    </bean>

Part 3 - Adding Unit Tests and a Form to the Application

Step 22 - Adding a form

As we are using Velocity, we won't need to add the taglib entry to web.xml.

springapp/war/WEB-INF/jsp/priceincrease.vm : Use VTL

<html>
<head><title>#springMessage("title")</title></head>
<body>
<h1>#springMessage("priceincrease.heading")</h1>
<form method="post">
  <table width="95%" bgcolor="f8f8ff" border="0" cellspacing="0" cellpadding="5">
    <tr>
      <td alignment="right" width="20%">Increase (%):</td>
      #springBind("priceIncrease.percentage")
        <td width="20%">
          <input type="text" name="percentage" value="${status.value}">
        </td>
        <td width="60%">
          <font color="red">${status.errorMessage}</font>
        </td>
    </tr>
  </table>
  <br>
  #springBind("priceIncrease.*")
  #if(${status.error})
    <b>Please fix all errors!</b>
  #end
  <br><br>
  <input type="submit" alignment="center" value="Execute">
</form>
<a href="#springUrl("/hello.htm")">Home</a>
</body>
</html>

springapp/war/WEB-INF/jsp/hello.vm : Use VTL

<br>
<a href="#springUrl("/priceincrease.htm")">Increase Prices</a>
<br>

A few things to note about the Spring Velocimacro.

  • #springBind is not a block, hence there is no #end and the $status reference stays in the Context. See a JIRA issue about this.
  • #hasBindErrors does not exist, so you need to use an alternative.
  • #springUrl will not add a leading / to the URL, so you need to add it by yourself.

Part 4 - Implementing Database Persistence

Nothing to change. (smile)

  • No labels