A while back I wrote a post about adding custom tools to the Liferay Velocity context.
In 6.0 a change was made such that the behaviour has changed slightly. Now all such tools are plain old beans which must implement an interface.
The changes also means that I have a lot less code to write and less wiring to do. Let's see how we'd do it now using exactly the same tool as that old post.
The interface again:
package com.mytool;
public interface MyTool {
public String operationOne();
public String operationTwo(String name);
}
We need an implementation of the interface:
package com.mytool;
public class MyToolImpl implements MyTool {
public String operationOne() {
return "Hello out there!";
}
public String operationTwo(String name) {
return "Hello " + name + "!";
}
}
Our spring configuration only requires a single bean definition:
<?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="com.mytool.MyTool" class="com.mytool.MyToolImpl" /> </beans>
Of course in order for our bean definitions to be read we need to make sure it gets loaded, so we'll name it so that it's found by the context loader WEB-INF/applicationContext.xml (We could have used the portal-esk spring config mechanism, but I wanted to demonstrate that Liferay is flexible and sensitive to existing coding behaviors.
I mentioned that we need a context loader, so there is one more change required. While before you could only add tools within a ServiceBuilder enabled plugin, that is no longer required. All you have to do is add the following context loader listener the your web.xml (but only if your plugin is not a portlet type plugin):
<listener>
<listener-class>com.liferay.portal.kernel.spring.context.PortletContextLoaderListener</listener-class>
</listener>
This effectively tells the portal to create a BeanLocator object associated with your plugin and to read the beans definitions that were defined in WEB-INF/applicationContext.xml.
Now we're ready to use our tool in a Velocity template:
Since we've done this in a plugin, you will have to specify the 'contextPathName' of the plugin so that the appropriate BeanLocator can be used to lookup your tool. For example, the context path name of your plugin being "test-velotool-hook", then you'd use the following in your template:
#set ($myTool = $utilLocator.findUtil('test-velotool-hook', 'com.mytool.MyTool'))
$myTool.operationOne()
$myTool.operationTwo('Ray')
I've linked a source hook plugin that you can drop into your plugins SDK and deploy just by doing ant deploy.


