PDA

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