Two ways to embed web content in Liferay themes
Op 01 juni 2011 door Kristof Verbraeken in categorie Liferay
Introduction
Sometimes a client needs to be able to modify web content that appears on multiple pages. In some occasions you just can’t put the web content in the right place using the “basic” WCM features like Layout Templates and/or Journal Templates.
Consider things like a short introduction text in a header, a doormat, a footer, static navigation menu’s that rarely need to be updated, places for banners for temporary promotions and so on. What all these things have in common is that they don’t fit in the scope of Layout Templates or Journal Templates. You can’t reach the places I mentioned before with those facilities, because they mostly reside somewhere in the theme itself.
In this blog post/tutorial I will demonstrate and explain 2 ways to embed web content in a Liferay theme — using a demo theme which you can download below!
Demo theme
Take a look at the screenshot below:

The layout (theme) is made up out of four important areas:
- header: the area in the top of the layout;
- footer: the area in the bottom of the layout;
- sidebar: the area in the right center of the layout;
- content: the area in the left center of the layout. The layout of this area is determined by the configured Layout Template.
The first three areas (header, footer and sidebar) are the ones that should contain embedded web content which can be edited by the client through the Liferay Control Panel.
Create a journal article (or web content) for every area first as I have done in the screenshot below:

Note that I have used alphanumeric ID’s for the journal articles listed above instead of generated (numerical) ID’s. I will explain later why I’ve done that.
First way (complex)
The first way is based upon embedding the Web Content Display portlet: this portlet comes out the of box with Liferay.
Below is the configuration file (liferay-look-and-feel.xml) of the demo theme.
I’ve added the journal article ID of every journal article I need to embed in the theme (they are added as theme settings).
There’s also an extra setting portlet-setup-show-borders-default configured to hide the portlet wrapper of the embedded Web Content Display portlets.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE look-and-feel PUBLIC "-//Liferay//DTD Look and Feel 5.2.0//EN" "http://www.liferay.com/dtd/liferay-look-and-feel_5_2_0.dtd"> <look-and-feel> <compatibility> <version>5.2.3</version> </compatibility> <company-limit> <company-includes /> <company-excludes /> </company-limit> <theme name="Demo" id="demo"> <template-extension>vm</template-extension> <settings> <setting key="portlet-setup-show-borders-default" value="false" /> <setting key="header-article-id" value="HEADER" /> <setting key="sidebar-article-id" value="SIDEBAR" /> <setting key="footer-article-id" value="FOOTER" /> </settings> </theme> </look-and-feel>
Next you need to add some Velocity code to the init_custom.vm file in the templates directory.
In this example I will only embed the sidebar as a separate Web Content Display portlet.
#set ($portletSetupShowBordersDefault =
$theme_settings.getProperty("portlet-setup-show-borders-default"))
#set ($sidebarArticleId = $theme_settings.getProperty("sidebar-article-id"))
In this Velocity template the theme settings are loaded as Velocity variables.
When this file is set, we can proceed to the last step: modifying the portal_normal.vm file. In this file the init_custom.vm is executed thanks to the following statement:
#parse ($init)
The needed variables are injected in the theme and now we have all the information available that is needed to embed the web content.
You can now embed the web content with the following Velocity code:
$velocityPortletPreferences.setValue("portlet-setup-show-borders",
$portletSetupShowBordersDefault)
$velocityPortletPreferences.setValue("group-id", "$group_id")
$velocityPortletPreferences.setValue("article-id", "$sidebarArticleId")
$theme.runtime("56_INSTANCE_a0b1", "", $velocityPortletPreferences.toString())
#set ($VOID = $velocityPortletPreferences.reset())
First we need to configure the portlet preferences for the portlet we’re about to embed.
$portletSetupShowBordersDefault:injected setting from the XML configuration. This setting hides the portlet borders.$sidebarArticleId:injected setting from the XML configuration. This variable contains the journal article ID of the sidebar.$group_id:this variable is automatically set in the theme and contains the community ID.
Next, the portlet is embedded using the runtime method of the variable $theme. Notice that you have to provide this method with a portlet namespace, which in this case is 56_INSTANCE_a0b1. Make sure that this namespace always starts with 56_INSTANCE_ or else Liferay might embed a wrong portlet!
Notice the last line of code: the portlet preferences are reset. Always reset your portlet preferences after embedding the Web Content Display portlet or else you might get duplicate content in your theme! Also make sure that the portlet namespaces are unique within a page.
You might wonder why I’ve added all the variables as theme settings first. This approach makes the theme configurable. If something needs to be changed afterwards, you don’t need to modify the Velocity code, but just reconfigure the theme through the XML file liferay-look-and-feel.xml.
Also notice that I’ve used alphanumerical ID’s instead of numerical (generated) ID’s. I highly recommend using alphanumerical ID’s over the generated ones, simply because the generated ID’s might be different between other environments (development, integration, staging, production). If you use alphanumerical ID’s you don’t need to reconfigure the theme for every environment.
You can disable auto-generating ID’s with the following setting in portal-ext.properties:
journal.article.force.autogenerate.id=false
So far for the first way!
Second way (simple)
The second way makes use of the Liferay services. Instead of embedding a whole portlet in the theme we just load the web content to embed in the HTML of the theme.
The theme configuration was already discussed in the first way. In this explanation that same configuration is used again.
The init_custom.vm file must be modified again. In this example I will embed the header and footer content through this alternative way.
Take a look at the new content of the init_custom.vm file:
#set ($headerArticleId = $theme_settings.getProperty("header-article-id"))
#set ($footerArticleId = $theme_settings.getProperty("footer-article-id"))
#set ($headerContent = $journalContentUtil.getContent($group_id, $headerArticleId,
null, "$locale", $theme_display))
#set ($footerContent = $journalContentUtil.getContent($group_id, $footerArticleId,
null, "$locale", $theme_display))
Again, the theme settings are loaded as Velocity variables. Next, the web content service (JournalContentUtil) is used to load the content through the getContent method.
This method accepts 4 arguments:
$group_id:the community ID of the web content article.$article_id:the web content article ID.$template_id:the web content template ID. You are free to use any web content template that is associated with the web content structure used by the article.$locale:the portal locale (which is set by default).$theme_display:the theme display object (which is set by default).
This web content is immediately set as Velocity variables.
Now in the portal_normal.vm file you just have to put these content variables in the right place and we’re done!
<div id="header">$headerContent</div>
Or:
<div id="footer">$footerContent</div>
That’s it for the second (simpler) way!
Conclusion
Both ways are very efficient and clean ways to embed web content in Liferay themes.
The second way is simpler than the first way, but you will not be able to embed the web content with the portlet wrapper. If this wrapper is needed or useful for any reason, I suggest you to use the first way.
In all the other cases, I recommend using the second (simpler) way.
Feel free to ask questions and don’t hesitate to download the demo theme below! This theme contains all the code discussed above.
Cheers!
Downloads
The two ways described above are applied in the demo theme which you can download below! Make sure to create three web content articles with ID’s HEADER, SIDEBAR and FOOTER. If these articles don’t exist, Liferay will tell you that the content is expired.



