« 返回到 Templating Languages

Access Objects from Velocity

Overview #

There are 3 different places to use Velocity templating in Liferay Portal. Each place introduces its own slight difference in behavior. These differences are noted below.

The places in Liferay that support Velocity templating are:

  1. theme
  2. layout templates
  3. CMS Content Templates

In the theme, we assume 1) that more power is greater flexibility to develop cool stuff... and 2) the portal admin is taking FULL responsibility for installing a theme that might potentially have code which could kill the entire system (this is why we have official and non-official plugins as the same could be said for webs, portlets and hooks).

Objects Available in Themes, Layouts, and CMS #

In the theme, layout templates and CMS Templates we load all the tools found in the com.liferay.portal.velocity.VelocityVariables insertHelperUtilities() method:

  • arrayUtil
  • browserSniffer
  • dateFormats
  • dateTool
  • dateUtil
  • escapeTool
  • expandoColumnLocalService
  • expandoRowLocalService
  • expandoTableLocalService
  • expandoValueLocalService
  • getterUtil
  • htmlUtil
  • httpUtil
  • imageToken
  • iteratorTool
  • journalContentUtil
  • languageUtil
  • unicodeLanguageUtil
  • listTool
  • localeUtil
  • mathTool
  • numberTool
  • paramUtil
  • portalUtil
  • portal
  • prefsPropsUtil
  • propsUtil
  • portletURLFactory
  • velocityPortletPreferences
  • randomizer
  • saxReaderUtil
  • serviceLocator
  • sessionClicks
  • sortTool
  • staticFieldGetter
  • stringUtil
  • timeZoneUtil
  • utilLocator
  • unicodeFormatter
  • validator
  • accountPermission
  • commonPermission
  • groupPermission
  • layoutPermission
  • organizationPermission
  • passwordPolicyPermission
  • portalPermission
  • portletPermission
  • rolePermission
  • userGroupPermission
  • userPermission
  • locationPermission

Objects Which Can Be Restricted From Access by CMS #

We call these restricted variables. They are restricted by adding them to the following portal property:

    #
    # Input a comma delimited list of variables which are restricted from the
    # context in Velocity based Journal templates.
    #
    journal.template.velocity.restricted.variables=serviceLocator

Following are the list of variables that can be restricted:

  • portalUtil
  • portal
  • prefsPropsUtil
  • propsUtil
  • velocityPortletPreferences
  • serviceLocator
  • sessionClicks
  • utilLocator

Now, on the issue of what other variables are accessible where.

Run Time Variables #

In each of the three contexts there are some "run-time" variables which are available only in those contexts.

Layout Templates #

The only additional runtime variable for layouts is:

  • processor

Themes #

  • request
  • portletConfig
  • renderRequest
  • renderResponse
  • xmlRequest
  • themeDisplay
  • company
  • user
  • realUser
  • layout
  • layouts
  • plid
  • layoutTypePortlet
  • scopeGroupId
  • permissionChecker
  • locale
  • timeZone
  • theme
  • colorScheme
  • portletDisplay
  • navItems
  • fullCssPath
  • fullTemplatesPath
  • init
  • portletGroupId
  • processor
  • taglibLiferay
  • theme

These are all objects are you might expect them to be... real

HttpServletRequest
, real User, etc...

CMS Templates #

The processing of a template is handled in such a way that it is not dependent on access to a real HttpRequest of any kind. Why? Because it's done WITHIN the service call. We do not allow our service layer objects to have an HttpRequest or HttpResponse of any kind as parameters. Thus, we can't add any of those NON-serializable objects like

HttpServletRequest
,
ThemeDisplay
,
PortletDisplay
,
PortletPreferences
, etc...

As such we have the following variables:

  • xmlRequest
  • request
  • company
  • companyId
  • groupId
  • journalTemplatesPath
  • viewMode
  • locale
  • permissionChecker
  • randomNamespace

Request is NOT an Http Request of any kind. We have "mocked up" these items into what we call and "xmlRequest".

    String xmlRequest = PortletRequestUtil.toXML(PortletRequest portletRequest, PortletResponse portletResponse);

This serializes all the most important pieces required into a hierarchical HashMap called "request" ("xmlRequest" is still just the string from before... so that you can further call

JournalContentUtil
from within a template...).

So, if you were to dump a $request variable from a template it would look like this:

render-url-exclusive=[[http://localhost:8080/web/workshop/home|http://localhost:8080/web/workshop/home]] ?p_p_id=56_INSTANCE_6860&p_p_lifecycle=0 &p_p_state=exclusive&p_p_mode=view& p_p_col_id=column-1&p_p_col_count=1, auth-type=, scheme=http, render-url-normal=[[http://localhost:8080/web/workshop/home|http://localhost:8080/web/workshop/home]] ?p_p_id=56_INSTANCE_6860&p_p_lifecycle=0& p_p_state=normal&p_p_mode=view& p_p_col_id=column-1&p_p_col_count=1, locale=en_US, attributes={ COMPANY_ID=10095, PORTLET_ID=56_INSTANCE_6860, RENDER_PORTLET_COLUMN_POS=0, CURRENT_COMPLETE_URL=[[http://localhost:8080/web/workshop/home|http://localhost:8080/web/workshop/home]], LAST_PATH={ contextPath=/web, path=/workshop/home }, FRIENDLY_URL=/web/workshop/home, com.liferay.portal.servlet.filters.strip.StripFilterSKIP_FILTER=true, PORTLET_PARALLEL_RENDER=true, RENDER_PORTLET_COLUMN_ID=column-1, LAYOUT_FRIENDLY_URL=/home, CURRENT_URL=/web/workshop/home, RENDER_PORTLET_COLUMN_COUNT=1, org.apache.struts.action.mapping.instance=ActionConfig [path=/journal_content/view, scope=session, type=com.liferay.portlet.journalcontent.action.ViewAction, validate=true,cancellable=false, LIFERAY_SHARED_PAGE_KEYWORDS=[ad], USER_ID=10150, PORTLET_STRUTS_ACTION=/journal_content/view, com.liferay.portal.servlet.filters.gzip.GZipFilterSKIP_FILTER=true }, render-url-pop-up=[[http://localhost:8080/web/workshop/home|http://localhost:8080/web/workshop/home]] ?p_p_id=56_INSTANCE_6860&p_p_lifecycle=0& p_p_state=pop_up&p_p_mode=view&p_p_col_id=column-1 &p_p_col_count=1, render-url-maximized=[[http://localhost:8080/web/workshop/home|http://localhost:8080/web/workshop/home]] ?p_p_id=56_INSTANCE_6860&p_p_lifecycle=0& p_p_state=maximized&p_p_mode=view& p_p_col_id=column-1&p_p_col_count=1, render-url-minimized=[[http://localhost:8080/web/workshop/home|http://localhost:8080/web/workshop/home]] ?p_p_id=56_INSTANCE_6860&p_p_lifecycle=0& p_p_state=minimized&p_p_mode=view& p_p_col_id=column-1&p_p_col_count=1, server-port=8080, portlet-mode=view, secure=false, action=false, theme-display={ secure=false, scope-group-id=10174, portal-url=localhost:8080, plid=10265, path-main=/c, i18n-language-id=, url-portal=localhost:8080, do-as-user-id=, path-context=, path-image=/image, user-id=10150, language-id=en_US, company-id=10095, locale=en_US, time-zone=UTC, path-friendly-url-public=/web, path-theme-images=/sesameworkshop-theme/images, real-user-id=10150, cdn-host=, path-friendly-url-private-group=/group, server-name=localhost, path-friendly-url-private-user=/user, server-port=8080, portlet-display={ title=Journal Content, portlet-name=56, instance-id=6860, resource-pk=10265_LAYOUT_56_INSTANCE_6860, root-portlet-id=56, id=56_INSTANCE_6860 } }, parameters=, container-type=portlet, context-path=/, content-type=text/html, render-url=[[http://localhost:8080/web/workshop/home|http://localhost:8080/web/workshop/home]] ?p_p_id=56_INSTANCE_6860&p_p_lifecycle=0& p_p_state=normal&p_p_mode=view& p_p_col_id=column-1&p_p_col_count=1, remote-user=10150, window-state=normal, server-name=localhost, container-namespace=/, portlet-session={ portlet-attributes=, application-attributes={ com.liferay.portal.kernel.util.ProgressTracker_PERCENT=100, j_username=10150, HTTPS_INITIAL=false, LIFERAY_SHARED_VISITED_GROUP_ID_PREVIOUS=10100, LAST_PATH={ contextPath=/web, path=/workshop/home }, USER_ID=10150, LIFERAY_SHARED_VISITED_GROUP_ID_RECENT=10174, org.apache.struts.action.LOCALE=en_US } }, portlet-namespace=_56_INSTANCE_6860_, portlet-session-id=1D8EA0980982E0C4DD5199B092450A2E

Note that it contains a VERY good selection of runtime values, all of which must be serializable.

Now, suppose you want to pass a runtime value to a template. Just add it as either a request parameter or a request attributes, both of which are made available here, as well as session vars in both scopes. Important pieces of

ThemeDisplay
and
PortletDisplay
are also included.

Variables defined in init.vm #

From Alimozzaman blog:

These are the default Liferay 6 theme variables defined in init.vm.
I was searching but did not get any link ,so I hope this will help lot of
people also around  the globe. If anything goes  wrong, pls make a comment
and also try to add something that will help people around us.

## ———- Common variables ———- ##

$theme_display
$portlet_display
$theme_timestamp
$theme_settings
$css_class
$layout
$page_group
$liferay_toggle_controls
$liferay_dockbar_pinned
$css_folder
$images_folder
$javascript_folder
$templates_folder
$full_css_path
$full_templates_path
$css_main_file
$js_main_file
$company_id
$company_name
$company_logo
$company_logo_height
$company_logo_width
$company_url

$user_id
$is_default_user
$user_first_name
$user_middle_name
$user_last_name
$user_name
$is_male
$is_female
$user_birthday
$user_email_address
$language_id
$w3c_language_id
$time_zone
$user_greeting
$user_comments
$user_login_ip
$user_last_login_ip
$is_signed_in
$group_id

## ———- URLs ———- ##
$show_add_content
$add_content_text
$add_content_url
$layout_text
$layout_url
$show_control_panel
$control_panel_text
$control_panel_url
$show_home
$home_text
$home_url
$show_my_account
$my_account_text
$my_account_url
$show_page_settings
$page_settings_text
$page_settings_url
$show_sign_in
$sign_in_text
$sign_in_url
$show_sign_out
$sign_out_text
$sign_out_url
$show_toggle_controls
$toggle_controls_text
$toggle_controls_url
$update_available_url

## ———- Page ———- ##

$the_title
$selectable
$is_maximized
$is_freeform

$page_javascript_1
$page_javascript_2
$page_javascript_3
$layout
$page = $layout
$is_first_child
$is_first_parent
$the_title
$is_portlet_page

$all_portlets
$column_1_portlets
$column_2_portlets
$column_3_portlets
$column_4_portlets
$column_5_portlets
$maximized_portlet_id
$typeSettingsProperties
$page_javascript_1
$page_javascript_2
$page_javascript_3
$community_name
$css_class
$my_places_portlet_url
$community_default_public_url
$community_default_private_url
$community_default_url
$the_title
$layouts
$pages

## ———- Navigation ———- ##
$nav_items
$has_navigation

## ———- Staging ———- ##
$show_staging
$staging_text
## ———- My places ———- ##
$show_my_places
$my_places_text

## ———- Includes ———- ##
$dir_include
$bottom_include
$bottom_ext_include
$content_include
$top_head_include
$top_messages_include

## ———- Date ———- ##
$date
$current_time
$the_year

Final Notes #

Additionally, providing further complex tools to template in all cases, themes, layout templates and CMS Contents is best done through Spring as previously demonstrated in Ray Auge's blog, and is also available from plugins and no longer requires your plugin to use ServiceBuilder as of recently.

Note -- the Velocity Variables Explorer portlet is no longer available! The Velocity Variables Explorer portlet can also be used to browse through run-time generated velocity variables, separately for CMS content, layout and themes, as well as for Request and Helper sets (see VelocityVariables.java). Portlet generates variables display in accordance to Liferay version it is running on. For each velocity variable this tool displays list of public methods and, when available, provides access to extended description, use samples, source of an appropriate java class.

0 附件
307561 查看
平均 (9 票)
满分为 5,平均得分为 4.44444444444445。
评论
讨论主题回复 作者 日期
Great start for this article. Only suggestion... Andy Harb 2010年3月18日 上午10:37
Andy I would agree with you however seeing how... Dmitry Brin 2010年7月13日 下午7:04
ok, how do I create a portletUrl in a CMS... Thiago Leão Moreira 2010年10月13日 下午12:38
Here is the answer to my question! ... Thiago Leão Moreira 2010年10月13日 下午1:01
Hi guys. I'd like to create a navigation... Achmed Tyrannus Albab 2011年6月15日 上午1:50
why I have the browserSniffer object at CMS... S I 2011年10月27日 上午3:57
How to access these variables in portlets..code... Raja Nagendra Kumar 2011年12月15日 下午7:19
I dont have access to those variables.... Christopher Jimenez 2011年12月23日 下午2:47
boa referencia essa ricardo wolosker 2012年1月20日 上午10:13
How is build/obtain the $layout variable ? Thanks. Antoine Comble 2012年10月25日 上午7:19
I've found the solution : $layout... Antoine Comble 2012年10月25日 上午7:22
This is a great article but doesn't seem to... Dave Weitzel 2012年12月17日 上午6:33
As Dave Weitzel mentioned, I am having a... Enrique Valdes Lacasa 2015年1月20日 下午12:54
How can i access hidden pages from liferay... Pradip A Bhatt 2014年1月28日 下午9:12
Perhaps this link could help you :... Antoine Comble 2014年1月29日 上午12:12
Perhaps this link could help you :... Antoine Comble 2014年1月29日 上午12:12
noob ? How would I retrieve the value of... John Nowlin 2014年1月31日 下午1:01
Is there an equivalent wiki or blog posting for... Dave Weitzel 2014年10月22日 下午12:25
I found this article very useful to access many... Enrique Valdes Lacasa 2015年2月2日 上午11:07
Can we add additional variable to the list to... Adnan Yaqoob 2015年3月13日 上午9:47

Great start for this article. Only suggestion I have is to link the variables to their corresponding Javadoc so new developers can quickly see what each object has to offer in terms of methods.

Example
navItems link to http://docs.liferay.com/portal/5.1/javadocs/portal-service/com/liferay/portal/th­eme/NavItem.html
在 10-3-18 上午10:37 发帖。
Andy I would agree with you however seeing how Javadoc has absolutely no explanation of any kind it's pretty lame.
在 10-7-13 下午7:04 发帖以回复 Andy Harb
ok, how do I create a portletUrl in a CMS context, since I don't have access to the real HttpServletRequest?
在 10-10-13 下午12:38 发帖以回复 Dmitry Brin
Here is the answer to my question!

http://www.liferay.com/web/eduardo.lundgren/blog/-/blogs/liferay-portle­turl-in-javascript
在 10-10-13 下午1:01 发帖以回复 Thiago Leão Moreira
Hi guys.
I'd like to create a navigation portlet via structure and template.
Basically i want the default navigation to be drag able to be placed around.
I have tried adding a carbon copy of the navigation.vm inside a template + blank structure.
What i am wondering is how do i get the template to get the data from the pages ive created via control panel.
Thanks very much.

Oh yea and i im not using source version.
在 11-6-15 上午1:50 发帖。
why I have the browserSniffer object at CMS level if I cant use any of it's methods?
在 11-10-27 上午3:57 发帖。
How to access these variables in portlets..code snipped would help
在 11-12-15 下午7:19 发帖。
I dont have access to those variables....
在 11-12-23 下午2:47 发帖以回复 Raja Nagendra Kumar
在 12-1-20 上午10:13 发帖以回复 Christopher Jimenez
How is build/obtain the $layout variable ?
Thanks.
在 12-10-25 上午7:19 发帖。
I've found the solution : $layout =$theme.getLayout()
在 12-10-25 上午7:22 发帖以回复 Antoine Comble
This is a great article but doesn't seem to cover the situation where you are including journal content WITHIN a theme using $journalArticleLocalService.getArticle() .
can you advise how request variables in particular can be accessed in this scenario ?
$request just returns {}
在 12-12-17 上午6:33 发帖。
How can i access hidden pages from liferay theme??
in navigation i can find only visible pages ?

But my requriement is finding hidden pages from theme?
在 14-1-28 下午9:12 发帖。
Perhaps this link could help you : http://liferayui.blogspot.fr/2011/02/display-hidden-childs-page-in-footer.html :
#set($layoutLocalServiceUtil = $serviceLocator.findService("com.liferay.portal.service.LayoutLocalService"))
#se­t($topPublicLayouts = $layoutLocalServiceUtil.getLayouts($layout.getGroupId(),false))
#foreach ($lay_item in $topPublicLayouts)
#if ($lay_item.getHidden())
#if ($lay_item.isSelected())
#set ($lay_item_class = "selected")
#else
#set ($lay_item_class = "")
#end

<li class="$lay_item_class">
<a href="$lay_item.getURL()" class="$lay_item_class" $lay_item.getTarget()><span>$lay_item.getName()</span></a>
</li>
#end
#end
</ul>
在 14-1-29 上午12:12 发帖以回复 Pradip A Bhatt
Perhaps this link could help you : http://liferayui.blogspot.fr/2011/02/display-hidden-childs-page-in-footer.html :
#set($layoutLocalServiceUtil = $serviceLocator.findService("com.liferay.portal.service.LayoutLocalService"))
#se­t($topPublicLayouts = $layoutLocalServiceUtil.getLayouts($layout.getGroupId(),false))
#foreach ($lay_item in $topPublicLayouts)
#if ($lay_item.getHidden())
#if ($lay_item.isSelected())
#set ($lay_item_class = "selected")
#else
#set ($lay_item_class = "")
#end

<li class="$lay_item_class">
<a href="$lay_item.getURL()" class="$lay_item_class" $lay_item.getTarget()><span>$lay_item.getName()</span></a>
</li>
#end
#end
</ul>
在 14-1-29 上午12:12 发帖以回复 Pradip A Bhatt
noob ? How would I retrieve the value of url-portal from the $request object? I have tried $request("url-portal"), $request.getValue("url-portal") and url-portal.url-portal without success.
在 14-1-31 下午1:01 发帖。
Is there an equivalent wiki or blog posting for Freemarker? In particular looking at how to use taglibs in web content templates based on freemarker in 6.2CE. Im sure it is possible if themes and ADT can use them but cant seem to get right way of assigning the hash. but shouldnt there be a section in this wiki for freemarker?


.
在 14-10-22 下午12:25 发帖。
As Dave Weitzel mentioned, I am having a similar issue. The $request variable in my Liferay 6.2.1 CE shows up as empty {} when I add web content via a CMS Template. I found this LPS issue...it might be related to this problem...
https://issues.liferay.com/browse/LPS-32074
Any help would be appreciated.
Thanks!
在 15-1-20 下午12:54 发帖以回复 Dave Weitzel
I found this article very useful to access many variables needed from a Velocity template, I hope it helps. https://www.liferay.com/web/raymond.auge/blog/-/blogs/journal-vm-template-meets-­saxreaderutil
在 15-2-2 上午11:07 发帖。
Can we add additional variable to the list to expose custom services. So that we can keep serviceLocator restricted
在 15-3-13 上午9:47 发帖。