View Full Version : Spring and velocity
prabhakarlal
Oct 5th, 2004, 09:41 AM
Hi All
I am new to Spring and trying to use it with velocity template engine.
I have two vm(velocity templates) namely a.vm and b.vm.
I am including a.vm in b.vm by doing this
#parse("a.vm")
For the spring part, I have two separate controllers to display each vm files.
When I access them separately thro' url like localhost:8080/a.vm
or localhost:8080/b.vm they work fine. In the case of include the engine is not able to reference the values which are there in a.vm such as ${model.now}
What could be the reason?
Do I need to do some extra setup?
Currently I am putting this piece in []-servlet.xml
<!-- Controller for the initial "Hello" page -->
<bean
id="velocityConfig"
class="org.springframework.web.servlet.view.velocity.Velo cityConfigurer">
<property name="resourceLoaderPath"><value>/WEB-INF/velocity/en/</value></property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.Velo cityViewResolver">
<property name="suffix"><value>.vm</value></property>
</bean>
Thanks in advance
feester
Oct 5th, 2004, 10:37 AM
You can't do what you want with org.springframework.web.servlet.view.velocity.Velo cityView. This Spring class is based on org.apache.velocity.servlet.VelocityServlet, which comes with the Velocity distribution.
What you want is an implementation--for Spring environment--that works like VelocityLayoutView that comes with the VelocityTools, I believe.
Below is an implementation that works almost exactly like VelocityLayoutView and inherits from Spring's VelocityView. Note: the only difference is the layout cannot be changed from the inner template. To override default layout "layout/default.vm", instead specify the new "defaultLayoutUrl" property in the Spring bean definition.
import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest;
import org.apache.velocity.Template;
import org.apache.velocity.context.Context;
import org.springframework.web.servlet.view.velocity.Velo cityView;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
public class VelocityLayoutView extends VelocityView
{
private String screenContentUrl = null;
/**
*
*
*/
public void setDefaultLayoutUrl(String url)
{
super.setUrl( url );
}
/**
*
*/
public String getDefaultLayoutUrl()
{
return super.getUrl();
}
/**
* Set the URL of the resource that this view wraps.
* The URL must be appropriate for the concrete View implementation.
*/
public void setContentUrl(String url)
{
screenContentUrl = url;
}
/**
* Return the URL of the resource that this view wraps.
*/
public String getContentUrl()
{
return screenContentUrl;
}
protected void exposeHelpers( Context velocityContext, HttpServletRequest request )
throws Exception
{
// add variables request, cPath, userLogin and session
velocityContext.put( "request", request );
velocityContext.put( "cPath", request.getContextPath() );
String userLogin = request.getRemoteUser();
if( userLogin != null ) {
velocityContext.put( "userLogin", userLogin );
}
Object session = request.getSession();
if( session != null ) {
velocityContext.put( "session", session );
}
renderScreenContent( velocityContext, screenContentUrl );
}
/**
* resulting context contains any mappings from render, plus screen content
*
* @param velocityContext
* @param contentUrl
* @throws BeansException
*/
private void renderScreenContent( Context velocityContext, String contentUrl )
throws BeansException
{
StringWriter sw = new StringWriter();
try {
Template template = getVelocityEngine().getTemplate( contentUrl );
template.merge( velocityContext, sw );
// velocity context now includes any mappings that
// were defined--via #set--in screen content template
// Put rendered content into context
velocityContext.put( KEY_SCREEN_CONTENT, sw.toString() );
} catch ( Exception e ) {
throw new FatalBeanException
( "bean=" + getBeanName() + " render failed url=" + contentUrl, e );
} finally {
try { sw.close(); } catch ( Exception ioe ){} /* do nothing */
}
return;
}
protected void initApplicationContext() throws BeansException
{
if ( super.getUrl() == null ) {
super.setUrl( DEFAULT_LAYOUT );
}
super.initApplicationContext();
}
/**
* The default filename for the servlet's default layout
*/
public static final String DEFAULT_LAYOUT = "layout/default.vm";
/**
* The context key that will hold the content of the screen.
*
* This key ($page_content) must be present in the layout
* template for the current screen to be rendered.
*/
public static final String KEY_SCREEN_CONTENT = "page_content";
}
view's bean definition
<bean id="myContent" class="pkg.VelocityLayoutView">
<property name="contentUrl"><value>myContent.vm</value></property>
</bean>
See how page title, menu and body_onload can be passed to layout template.
#*
myContent.vm this is inner content
*#
#set( $page_title = "myContent Title" )
#set( $page_menu = 'menu/menu1.vm' )
#set( $body_onload = 'onload="document.some_form.some_input_field.focus();"' )
<!-- BEGIN myContent content -->
This is the screen content
<!-- END content -->
Since bean desriptor "defaultLayoutUrl" property not set, defaults to layout/default.vm
#*
default.vm this is the default layout
*#
<html>
#parse( "layout/head.vm" )
<body $!body_onload text="#000000" bgcolor="#ffffff" leftmargin="0"
topmargin="0" marginwidth="0" marginheight="0">
#parse( "layout/pageHeader.vm" )
<table width="100%">
<tr>
#parse( $page_menu )
<td valign="top">
<h5>${page_title}</h5>
$page_content
</td>
</tr>
</table>
#parse( "layout/pageFooter.vm" )
</body>
</html>
davison
Oct 5th, 2004, 10:39 AM
it seems odd that those URL's work - do you have controllers configured and URL mappings set up in your *-servlet.xml file too or not? Can you post those definitions?
Do you also have the VelocityServlet running? (You don't need it if so).
prabhakarlal
Oct 6th, 2004, 12:48 AM
it seems odd that those URL's work - do you have controllers configured and URL mappings set up in your *-servlet.xml file too or not? Can you post those definitions?
Do you also have the VelocityServlet running? (You don't need it if so).
How do I check if velocity servlet is running?
Here is my *-servlet.xml file. I am including ticker.vm in user_choice.vm
<bean
id="velocityConfig"
class="org.springframework.web.servlet.view.velocity.Velo cityConfigurer">
<property name="resourceLoaderPath"><value>/WEB-INF/velocity/en/</value></property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.Velo cityViewResolver">
<property name="suffix"><value>.vm</value></property>
</bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlH andlerMapping">
<property name="mappings">
<props>
<prop key="/user_choice.vm">reportController</prop>
<prop key="/ticker.vm">tickerController</prop>
</props>
</property>
</bean>
<bean id="reportController" class="com.transource.rtmcui.controllers.ReportController">
<property name="reportManager">
<ref bean="reportMan"/>
</property>
</bean>
<bean id="tickerController" class="com.transource.rtmcui.controllers.TickerController">
<property name="tickerManager"><ref bean="tkkManager"/></property>
</bean>
Thanks in Advance.
davison
Oct 6th, 2004, 07:18 AM
ok, your original post made it look as if you were loading the templates directly in the browser hence my red herring enquiry about VelocityServlet.
Having re-read the original post, your issue I think is that you are trying to access the model data incorrectly. Change ${model.now} to ${now}.
Spring exposes the model map diretly as VelocityContext attributes, so you never need to use a "model." prefix.
Regards,
mishtt
Jan 20th, 2006, 12:31 PM
hey Darren,
I am using spring for the first time and I need to have the same functionality and after much research I have finally managed to configure the class in my xxx-servlet .xml file but I am not sure if I have to implement the class myself like it has been done above or it should work as it is?
Thanks.
-Mish
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.