Message Boards

Overriding search results FTL template

Jan Tošovský, modified 3 Years ago.

Overriding search results FTL template

Liferay Master Posts: 565 Join Date: 7/22/10 Recent Posts
In latest LR portal search result page is rendered using FTL template (not JSP anymore), which takes all data from passed SearchResultSummaryDisplayContext object.
https://github.com/liferay/liferay-portal/blob/master/modules/apps/portal-search/portal-search-web/src/main/resources/com/liferay/portal/search/web/internal/search/results/web/portlet/template/dependencies/portlet_display_template_list.ftl
It means that you have no direct access to the Document object and all the fields added in your indexer.
So my question:
1. Can I somehow access the original Document object with all indexed fields?
2. How can I use my custom service in FTL template (as a workaround, to get fields I can't access from indexed Documents)?
I've tried this, but serviceLocator seems to be null:
<#assign myEntityLocalService = serviceLocator.findService("com.server.service.MyEntityLocalService") />
I couldn't find any tutorial how to customize these templates so I am stuck now.
Thanks
Jan Tošovský, modified 3 Years ago.

RE: Overriding search results FTL template

Liferay Master Posts: 565 Join Date: 7/22/10 Recent Posts
ad 2) The serviceLocator variable in FTL templates is restricted by default. So if available objects/properties/variables are not sufficient for your use case so additional service needs to be called, that restriction has to be elevated first:
Go to: Control Panel | System Settings | Template Engines | FreeMarker Engine, remove "serviceLocator" Restricted Variables entry and Save the config. After saving there is error displayed " Unsupported template resource loader ftl ", but it seems to be harmless as your settings is updated.
No restart of the server is required.
thumbnail
Krzysztof Gołębiowski, modified 3 Years ago.

RE: Overriding search results FTL template

Liferay Master Posts: 549 Join Date: 6/25/11 Recent Posts
Hi Jan,
I recently did the FTL for search and instead of lucene Document I found it easier to retrieve the asset:

&lt;#assign assetEntry = assetEntryLocalService.getEntry(entry.getClassName(), entry.getClassPK()) /&gt;
and then the article itself with its content:

&lt;#assign docXml = saxReaderUtil.read(assetEntry.getAssetRenderer().getArticle().getContent()) /&gt;
&lt;#assign myFieldContent = docXml.valueOf("//dynamic-element[@name='MyField']/dynamic-content/text()") /&gt;
Is there any specific data you need to get from the Document that cannot be obtained from Asset or the final object?
KG
Jan Tošovský, modified 3 Years ago.

RE: Overriding search results FTL template

Liferay Master Posts: 565 Join Date: 7/22/10 Recent Posts
Krzysztof Gołębiowski:

Is there any specific data you need to get from the Document that cannot be obtained from Asset or the final object?

Performance. To get desired value I have to call two services as that information is stored in different table. I did this in the indexer and stored the result in the specific field. When serving results, I just used this value directly.
I now call it for every item dynamically, again and again when it appears in search results.
thumbnail
Christoph Rabel, modified 3 Years ago.

RE: Overriding search results FTL template

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
I am with you here. When I saw the feature I was assuming that I was simply getting the search document to iterate through it.
The search document is a wealth of information. Especially for webcontent where it helps me to avoid parsing the article xml itself. The search document for webcontent is more useful then the actual content itself. And for other objects, usually everything relevant is in the document.
thumbnail
Christoph Rabel, modified 3 Years ago.

RE: Overriding search results FTL template

Liferay Legend Posts: 1554 Join Date: 9/24/09 Recent Posts
Another way to make your service available are Templace Context contributors.
https://help.liferay.com/hc/en-us/articles/360018162111-Context-Contributors-
You implement your service and deploy it and it automatically is available.
You can use just by writing ${myEntityLocalService.doSomething()}
We usually check if it is indeed there with <#if myEntityLocalService??> if it is indeed there to make the templates more resilient.