Using the Turbine Context
The Turbine Templating Services attach references to default Objects in the Turbine Context as part of their initialization. In the case of the TurbineVelocityService these references point to RunData, TemplateLink and TemplatePageAttributes. These three are put into the Context in the TurbineVelocityService class. The Context stores the Objects in a Hashtable with a key and the Object.
Using the RunData Object
The RunData Object is referenced by the "data" keyword, which when using this in the templating system is referenced by $data. As the Context contains a link to the RunData object all the public methods in the RunData Object are made available to the template. For example, typing $data.getMessage() will access the message String being stored in the RunData Object and print that as part of the templates output.
RunData exposes an extremely rich series of methods and fields, for a full list of these methods refer to the Javadocs for RunData. Some of the useful methods exposed in RunData include;
-
addMessage(String msg)
getMessage()
getParameters()
getServerName()
getTitle()
getUser()
removeUserFromSession()
setMessage(String message)
setRedirectUri(String ruri)
setTitle(String title)
setLayoutTemplate(String title)
The RunData also allows for access to the TemplateInfo Object via getTemplateInfo() and several convenience methods. This allows for properties of the Templates to be modified for a Request when using templating systems like Velocity, WebMacro or Freemarker.
As an example assume we want a printable page that contains only the Templating Screen and not all the navigational components. To achieve this we can strip out all the non screen templating components by describing a new Layout Template called PrintableLayout.vm in the templates/layouts directory. All the PrintableLayout needs contain is;
$screen_placeholder
Without the references to the $navigation.setTemplate() methods in the template no navigational screen will be called. In the Screen Template that wants to take advantage of the PrintableLayout Template add to the Template;
$data.setLayoutTemplate("/PrintableLayout.vm")
This will strip the Screen Template of its Navigational components. These convenience methods can also be used to expose and to set the Layout when the Template is processed. Through this a User can potentially choose how they would like their webpage to appear by choosing one of many differant Layouts or choices you, the webdesigner provide.
Using the TemplateLink Object
The TemplateLink is an extended version of DynamicURI customised to be used in the templates. The TemplateLink is referenced in the templates via $link and exposes convenience methods for building URI's on the fly. For example in a template to build the URI to another template, TemplateLink would be referenced via;
$link.setPage("newpage.vm")
which when added to a Velocity template would (depending on the servlet configuration) return;
http://127.0.0.1:8080/newapp/servlet/newapp/template/index.vm
where "newapp" is the chosen webapp deployment name.
This same mechanism can also be used to link to static html;
$link.setPage("/path/to/static.html")
However the HTML page will load itself into a screen and not be embedded withint the Layouts and Navigations. If you still wish static content to be embedded within the specified layouts and navigations it is easier to add the static content as a velocity template and not take advantage of any of the dynamic content addition the Velocity Context allows.
TemplateLink and DynamicURI again expose a rich set of methods and fields to the link reference, for a full list of fields and methods please refer to TemplateLink and DynamicURI in the javadocs. Some of the useful methods exposed are;
-
setPage(String templatename)
addPathInfo(ParameterParser pp)
addPathInfo(String name, String value)
addQueryData(ParameterParser pp)
addQueryData(String name, String value)
getScriptName()
getServerData()
getServerPort()
setAction(String action)
setScreen(String screen)
setSecure()
Using the TemplatePageAttributes Object
The TemplatePageAttributes is accessed from within the context by the keyword "page" and provides methods to modify the various HTML attributes of the templating system. The Template context can be used to dictate the style of the HTML page in the navigation and layout templates as well as modify these attributes from within a screen.
As an example in the default.vm the page can be set to a maroon background with;
$page.setBgColor("#800000")
the screen template may need to set a new title to the page being displayed in the browser, this can be done in the screen template via;
$page.setTitle("New Title to Page")
Non standard attributes can be added to the Body tag, for instance the leftmargin or topmargin attributes via;
$page.addAttribute("topmargin", 0)
Note though that the addAttribute method only adds attributes to the Body tag. For a full list of methods exposed to the page reference view the Javadocs for TemplatePageAttributes. Other methods exposed to the page reference are;
-
addAttribute(String name, String value)
getTitle()
setBackground(String url)
setBgColor(String color)
setDescription(String description)
setKeywords(String description)
setLinkColor(String color)
setStyleSheet(String url)
setTextColor(String color)
setTitle(String title)
setVLinkColor(String color)
Adding your own Objects to the Context
As the Context is stored as a Hashtable any Object can be placed inside it and be accessed from a template. For instance, in a Velocity Screen in the doBuildTemplate() method, a String could be added to the Context. Please refer to the Getting Started documentation for more examples of using the Velocity Context with screens and events.
context.put("hello",new String("testing"));
This can be referenced from within the template via;
$hello the hello reference
which would be output as;
testing the hello reference
Using an Image Object in the Context
Creating an HTML link to an image from a template could be done by;
$link.getServerScheme() :// $link.getServerName() : $link.getServerPort() /context/imagename.jpg
This has been split up into multiple lines for clarity. Doing this once is a pain, doing it twice stinks, if the screen requires several images .... and there are many screens .... it is a productivity killer. The Velocity Context can be used to store this information and expose it to all the Screens requiring it. To do this we can create an Image Object which extends the Turbine DynamicURI Object. The following class is Jakarta Tomcat specific;
//Turbine import org.apache.turbine.util.DynamicURI; import org.apache.turbine.util.RunData; public class Image extends DynamicURI { /** The images directory */ public static final String DIR = "images"; /** tomcat specific - tomcat context */ private String contextpath; /** Constructor */ public Image (RunData data) { super(data); //the Tomcat context contextpath = data.getRequest().getContextPath(); } /** set the image and URI */ public String setImage(String imagename) { return ( getServerScheme() + //http "://" + getServerName() + //www.foo.com ":" + getServerPort() + //port webserver running on //the context for tomcat adds a / so no need to add another contextpath + //the tomcat context "/" + Images.DIR + "/" + imagename); } }
This can be instantiated from within the doBuildTemplate method in a Velocity Screen and added to the context from there;
public void doBuildTemplate(RunData data, Context context) throws Exception { Image image = new Image(data); context.put("image",image); }
from this the Image Object is accessible from within the corresponding screen template and can be accessed by;
$image.setImage("imagename.jpg");
Which is much simpler than the original attempt at dynamically creating an image URL. To make this Image object accessible across all Screens, sublass the VelocityScreen Object with one that overrides the doBuildTemplate() method by adding the Image object to the Velocity Context. Then use this class as the parent class for the Screens that need access to the Image Object. For more detail on taking advantage and extending the VelocityScreen Object, please view the Getting Started Document.
The above Image Object can also be modified to include any static data required by the templates. For instance CSS files, JavaScript files etc. Instead of an Image Object, it can be rewritten as a StaticLink Object;
//Turbine import org.apache.turbine.util.DynamicURI; import org.apache.turbine.util.RunData; public class StaticLink extends DynamicURI { /** the images directory */ public static final String IMAGES = "images"; /** the css directory */ public static final String CSS = "css"; // etc /** tomcat specific - tomcat context */ private String contextpath; /** Constructor */ public Image (RunData data) { super(data); //the Tomcat context contextpath = data.getRequest().getContextPath(); } /** set the image and URI */ public String setImage(String imagename) { //URI Logic } /** set the CSS style and URI*/ public String setCss(String stylesheet) { //URI Logic } /** general set method, input as string * ie can be set as $staticlink.setStaticLink("images/imagename") */ public String setStaticLink(String staticlink) { //URI Logic } }
Using the Context Object with the Base/Peer OM
As a more complex example, assume we are building a book archive system, where users can search for books by author and title. If we search on author "Greg Egan" and title "Permutation City", we can query the database through the base\peer system and return a Book Object that contains the information on the book "Permutation City". The Book Object would be placed in the context via;
Book book = new Book(); //add the data to the Book Object //from the Base/Peer Objects for Book context.put("book", book);
and then accessed in the velocity template by;
$book.getAuthor() $book.getTitle()
where the two methods are public methods in the Book Object, in this case built by the Torque Tool. These methods would return;
Greg Egan Permutation City
It is important not to try and put Objects with value null into the Context. A NullPointerException will be returned. This above example is intended to get across how the Velocity Context can be used to store data from the Base/Peer system that can be accessed from the Templates.