« Back

Tricks of Velocity class loading

Company Blogs September 16, 2010 By Ray Augé Staff

Recently I was asked to solve a WCM dynamic Template problem which involved listing articles using the business logic of the template.

One of the first problems I encountered was of course doing a search for the Articles via the JournalArticleLocalService which, in the case of the searchs which return List<JournalArticle>, require an OrderByComparator. Since there is no way to directly instantiate classes in Velocity I wondered how I was going to handle this issue.

Luckily my colleague Thiago was working with a community member (Sabrina Schürhaus Locks) who had already solved the problem in a rather interesting and simple way:

 

#set ($obc = $portal.getClass().forName("com.liferay.portlet.journal.util.comparator.ArticleDisplayDateComparator").newInstance())

 

It's so simple I feel silly that I never thought of this myself.

Kudos Sabrina!

Threaded Replies Author Date
I ran into this issue as well and found this... Amos Fong September 16, 2010 10:38 AM
Ah, but you can my friend! #set ($obcClass =... Ray Augé September 16, 2010 11:53 AM
Note, this is complicated by the fact that it's... Ray Augé September 16, 2010 11:56 AM
wow cool, velocity java magic! thanks for the... Amos Fong September 16, 2010 12:21 PM
Neat trick! I'll have to remember that one. Gregory Amerson September 16, 2010 1:45 PM
I posted something similar to the forums a... Jelmer Kuperus September 27, 2010 9:30 AM
Until recently (I just did a svn update of the... Ian White October 19, 2011 9:28 PM
Hey Ian, I tried this with the same old test... Ray Augé October 20, 2011 8:47 PM
hello ray, how to get value from a field which... Arya Nugroho October 28, 2011 1:29 PM
Hey Arya, Can you clarify a little? I'm not... Ray Augé November 3, 2011 6:24 AM
Hello! I also tried Ray's test-velotool-hook... oscar caro puerto March 6, 2012 3:40 AM
Hi, I am facing on problem with the Caroussel... Mehdi Khan November 9, 2012 4:13 AM
I don't think that relates to the post. If so,... Ray Augé November 9, 2012 4:49 AM
Hello! I've tried velocity class loading in... Matej Dolanc January 16, 2014 2:20 PM
We added some security around classloading. You... Ray Augé January 16, 2014 2:43 PM
Thank you very much... Matej Dolanc January 16, 2014 2:55 PM

I ran into this issue as well and found this same solution. However, you can't pass any parameters so you can't do ascending obc's.
Posted on 9/16/10 10:38 AM.
Ah, but you can my friend!


#set ($obcClass = $portal.getClass().forName("com.liferay.portlet.journal.util.comparator.ArticleD­isplayDateComparator"))
#set ($booleanType = $portal.getClass().forName('java.lang.Boolean'))
#set ($obcConstructor = $obcClass.getConstructor($booleanType.getField('TYPE').staticValue))

#set ($obc = $obcConstructor.newInstance(true))
Posted on 9/16/10 11:53 AM in reply to Amos Fong.
Note, this is complicated by the fact that it's a constructor having primitive args, on top of which you can't directly reference static fields in velocity, so getting the primitive type of a class required more reflection tricks. But this example demonstrates all of that!
Posted on 9/16/10 11:56 AM in reply to Ray Augé.
wow cool, velocity java magic! thanks for the lesson
Posted on 9/16/10 12:21 PM in reply to Ray Augé.
Neat trick! I'll have to remember that one.
Posted on 9/16/10 1:45 PM.
I posted something similar to the forums a while back that was even hackier (due to the difficulty of getting to int.class)

http://www.liferay.com/community/forums/-/message_boards/message/55148­92

these are pretty dirty tricks tho
Posted on 9/27/10 9:30 AM.
Until recently (I just did a svn update of the portal trunk) the velocity hook approach was working well, whereby you simply defined your java interface + impl pair in an applicationContext.xml file. See Ray's test-velotool-hook sample.

Alas, with the latest trunk code, your beans are not able to be loaded. Fingers crossed this is just a bug and not a decision to stop supporting velocity hooks.
Posted on 10/19/11 9:28 PM in reply to jelmer kuperus.
Hey Ian,

I tried this with the same old test velo hook:

#set ($myTool = $utilLocator.findUtil('test-velotool-hook','com.mytool.MyTool'))

$myTool
<br />
$myTool.operationOne()
<br/>
$myTool.operationTwo($text.data)

and got back:
com.mytool.MyToolImpl@5741bf0e
Hello out there!
Hello Ray!

Is it still not working?
Posted on 10/20/11 8:47 PM in reply to Ian White.
hello ray, how to get value from a field which is characterized by a specific tags on the article?

thanks
Posted on 10/28/11 1:29 PM in reply to Ray Augé.
Hey Arya,

Can you clarify a little? I'm not exactly sure what you mean!
Posted on 11/3/11 6:24 AM in reply to Arya Nugroho.
Hello!
I also tried Ray's test-velotool-hook sample in liferay 6.0.6 and is working fine, but I recently downloaded liferay-portal-6.1.0-ce-ga1 bundled with tomcat, deployed the hook, and tested from a velocity template, but in this version I'm getting:
NoSuchBeanDefinitionException: No bean named 'com.mytool.MyTool' is defined
Posted on 3/6/12 3:40 AM.
Hi, I am facing on problem with the Caroussel ,(1)when i refresh the page Caroussel loading slowly some time its take more than 5 minutes to load the message Caroussel.
(2).Sometimes when I log on, the caroussel is just blank. It takes around 2 - 5 minutes till the caroussel loads on the page.
And its happening only on Ineternet Explorer(IE)
Posted on 11/9/12 4:13 AM.
I don't think that relates to the post. If so, can you explain how?
Posted on 11/9/12 4:49 AM in reply to Mehdi Khan.
Hello!

I've tried velocity class loading in LIferay 6.2 (liferay-portal-6.2.0-ce-ga1) and it doesn't work for me. It works fine in LIferay 6.1.

Example:
#set ($obc = $portal.getClass().forName("com.liferay.portlet.journal.util.comparator.ArticleD­isplayDateComparator").newInstance())
$obc

I get the following warning message ( LIferay 6.2):

21:44:52,996 WARN [RuntimePageImpl-3][velocity:145] Cannot retrieve method forName from object of class java.lang.Class due to security restrictions.
21:44:52,997 DEBUG [RuntimePageImpl-3][velocity:155] RHS of #set statement is null. Context will not be modified. 10157#10197#11456[line 1, column 1]

Does anyone know where could be the issue?

Thanks
Matej
Posted on 1/16/14 2:20 PM.
We added some security around classloading. You can adjust the settings to your usage. http://docs.liferay.com/portal/6.2/propertiesdoc/portal.properties.html#Velocity­%20Engine
Posted on 1/16/14 2:43 PM in reply to Matej Dolanc.
Thank you very much...
Posted on 1/16/14 2:55 PM in reply to Ray Augé.