Spring Velocity Integration by flurdy
| More

How I integrate Velocity template engine into the Spring Framework.

Spring Framework & Apache Velocity

I use Velocity a lot in my projects as I dont need over-engineered JSPs in my simple templates.
I use the View Layout tools to simplefy even further.

And by editing a couple of xml files, spring uses its full potential.

These libraries need to be included:

  • spring-1.2.3.jar
  • velocity-1.4.jar
  • velocity-tools-1.1.jar
  • velocity-tools-generic-1.1.jar
  • velocity-tools-view-1.1.jar

and their dependencies e.g.

  • velocity-dep-1.4.jar

And my own

but more about that later.

First here is sections of my web.xml. Some bits are just standard spring mvc setup.

<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/applicationContext.xml</param-value> </context-param> <listener> <description>ServletContextListener</description> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/spring-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- These two mappings is a fudge due to silly web-app specs. It avoids having jsp forward to html files --> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/index.html</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/contact/index.html</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <!-- My own error pages, not a requirement --> <error-page> <error-code>404</error-code> <location>/missing.html</location> </error-page> <error-page> <error-code>403</error-code> <location>/access.html</location> </error-page> <error-page> <error-code>500</error-code> <location>/error.html</location> </error-page>

And here is my spring-servlet.xml

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"> <property name="resourceLoaderPath" value="/"/> <property name="configLocation" value="/WEB-INF/velocity/velocity.properties"/> </bean> <bean id="viewResolvers" class="com.flurdy.grid.mvc.view.VelocityLayoutViewResolver"> <property name="layoutUrl" value="WEB-INF/templates/layout/grid.vm"/> <property name="toolboxConfigLocation" value="/WEB-INF/velocity/toolbox.xml"/> <property name="prefix" value="/WEB-INF/templates/"/> <property name="suffix" value=".vm"/> <property name="exposeSpringMacroHelpers" value="true"/> </bean> <bean id="internalResolver" class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver"> <property name="suffix" value="Handler"/> </bean> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>text</value> </list> </property> </bean> <bean id="handler" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/**/*.html">viewController</prop> <prop key="/**/*.do">viewController</prop> </props> </property> </bean> <bean id="viewController" class="org.springframework.web.servlet.mvc.multiaction.MultiActionController"> <property name="methodNameResolver" ref="internalResolver"/> <property name="delegate" ref="viewDelegate"/> </bean> <bean id="viewDelegate" class="some.package.ViewDelegate"> <!-- <property name="someinjection" ref="someotherbean"/> --> </bean> </beans>

As you see the viewResolvers bean uses my own VelocityLayoutViewResolver. This is due to my set up uses the VelocityLayoutView tools. And spring does not include a resolver for it in its 1.x version. It is however included in the lastest versions. More details here.

Next thing is to create a grid.vm layout template referenced in the viewResolvers bean. I tend to use a specific css based layout, but that will be detailed in another doc sometime.

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title> #springMessage("title") </title> <link rel="shortcut icon" href="$request.contextPath/favicon.ico" /> <link type="text/css" rev="StyleSheet" rel="StyleSheet" href="http://flurdy.com/style/grid.css" /> <link type="text/css" rev="StyleSheet" rel="StyleSheet" href="http://flurdy.com/style/ship.css" /> <link type="text/css" rev="StyleSheet" rel="StyleSheet" href="http://flurdy.com/style/cargo.css" /> </head> <body> <div id="ship"> <div id="stern" class="grid head"> <span> #springMessage("titlelong") </span> </div> <div id="port" class="grid side column"> <ul id="menu"> <li><a href="$request.contextPath/index.html">Home</a></li> ## <li><a href="$request.contextPath/contact/">Contact</a></li> </ul> </div> <div id="starboard" class="grid side column"> </div> <div id="outerhull" class=""> <div id="innerhull" class="grid column middle"> <div id="cargo" class=""> / <a href="$request.contextPath/">home</a> $screen_content </div> </div> </div> <div id="aft" class="grid foot"> </div> </div> </body> </html>

What is of interest is the two #springMessage lines and the $screen_content. The springmessages prints out text from your resource bundles, ie the messageResource in the spring-servlet.xml.

The $screen_content is where your view templates will be inserted. More details here.

Final thing is to include the handler delegate. Here is quick example.

package some.package; import java.util.*; import javax.servlet.http.*; import org.springframework.web.servlet.ModelAndView; import org.apache.commons.logging.*; //import org.apache.commons.collections.*; //import ent.orm.*; //import mng.face.*; //import dao.face.*; //import logic.face.*; public class ViewDelegate { private final Log log = LogFactory.getLog(getClass()); public ModelAndView unspecified( HttpServletRequest req,HttpServletResponse resp ) { log.info("unspecified"); return indexHandler(req,resp); } public ModelAndView indexHandler( HttpServletRequest req,HttpServletResponse resp ) { Map model = new HashMap(); return new ModelAndView("front",model); } public ModelAndView missingHandler( HttpServletRequest req,HttpServletResponse resp ) { log.warn("Page is missing:"); return new ModelAndView("core/missing"); } public ModelAndView accessHandler( HttpServletRequest req,HttpServletResponse resp ) { log.warn("No access"); return new ModelAndView("core/access"); } public ModelAndView errorHandler( HttpServletRequest req,HttpServletResponse resp ) { return new ModelAndView("core/error"); } }

You will need to create some templates, e.g. front.vm. Which need to go into WEB-INF/templates.

Contact me if there is sections missing or if you have any questions.