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!
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.
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:
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:
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!
That’s it for the second (simpler) way!
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.
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.
I wrote this blog post from our own experiences with Liferay Portal. We haven't done a Liferay Portal 6 implementation yet...
I took some to install Liferay Portal 6.0.6 on a JBoss Application Server and started playing with the plug-ins SDK though.
I've created a theme for Liferay Portal 6 with embedded web content according to the methods I provided above. I did not cross any problems with these methods. I could just use the snippets above as I (or you) would do in Liferay Portal 5.
Also pay attention to the syntax of the snippets and especially the typecasts! Take a look at the JournalContentUtil service... If you don't pay attention to the typecasts there, that line will fail without you noticing it.
I'm sorry to say this, but I really don't understand what you mean?
Merci beaucoup j'en avais vraiment besoin, ça etait très util pour moi.
Je veux juste savoire comment vous avez pu faire pour utiliser un ID alphanumérique pour vos portlet, je n'arrive pas.
et SVP comment je peux faire pour integrer ma propre portlete que j'ai developpé avec PluginSDK par example.
Thank you very much I needed it, it was very useful for me.
I just want to know how you were able to use an alphanumeric ID for your portlet, I can not.
and please how can I do to integrate my own portlets that I developed with PluginSDK for example.
The first parameter of the runtime method of the theme object is the portlet namespace.
As you can see, this namespace is made up different parts, in this example:
# 56: the portlet ID, which in this case is the portlet ID of the Web Content Display portlet.
# INSTANCE: this is always included in the portlet namespace.
# a0b1: this is added to create a unique portlet namespace on every page.
For example: if you want to embed 2 Web Content Display portlet in one theme, you have to make sure that their portlet namespaces are unique (different from each other) and the runtime method should still be able to recognise which portlet to embed. In this case both portlet namespaces would start with "56_INSTANCE_" while the last characters should make them unique, for example "56_INSTANCE_a0b1" and "56_INSTANCE_c3d4".
To embed your own custom portlets you can also use this way. Just replace the "56" in the example above with your custom portlet ID. If you're using portlet plug-ins from the plug-ins SDK the complete portlet namespace is usually in the form of "portletname_WAR_portletnameportlet". I suggest you use the following line of code to embed custom portlets:
Close to what I said. :-)
I want to add web content display portlet for header (need to add two buttons and search portlet) and footer(need to add 3 links). I tried as suggested, but I am getting three new web content portlets and not the one created initially with id's "header"
and "footer". Following is code I appended in portal_normal.vm :
The Portlet namespaces - 56_INSTANCE_a0b1, 56_INSTANCE_c3d4, 56_INSTANCE_e5f4, I have chosen randomly. How should I give the portlet namespace in the theme.runtime. Is there any place I create portlet namespace or its set by Liferay if yes, then from where I can retreive the portlet namespace value.
i have a page and have a parent web content which includes my data and template.
I also have a child web content.
i want to embed the child in the parent web content, so that the child takes its data from own dcr and gets included in parent and thus i have a whole page.
http://vendee-globe-junior2008.vendee.fr/longchamp21/1112_longchamp.htmllongchamp accessoires seb
christian louboutin bianca and family http://www.51nxtz.com/images/ChristianLouboutin21/4072_ChristianLouboutin.html
Tissot includes a long and well respected history including many awards and recognitions for innovation and design. Beside the timing function, these are also the indispensable equipment for a number of people in modern-day society. A researching the market will reveal the average prices of assorted replica Breitling watches and prospective customers should base their buying prices at this region, otherwise predispose themselves to buying low quality watches. Furthermore, furthermore it's the educated of production excellent watches. Brides can get plain cupcakes and place the icing on themselves and even bake the cupcakes themselves from cake mix or from scratch.
cartier tank imitation http://www.dailymotion.com/video/x297i77_best-sale-louis-fake-cartier-tank-watches-65-off_lifestyle
HiThank you for sharing this arltice.I just want to know from where we are getting delta and cur in these line:Integer delta = (Integer)request.getAttribute("delta"); Integer cur = (Integer)request.getAttribute("cur"); And also the use of action URl: PortletURL portletURL = renderResponse.createActionURL();
like'. First, Is certainly a perfect deliver for people rare jewels you theory you should never be able to locate. And
For me "journalArticleLocalService.getArticleContent()" worked rather than "journalContentUtil.getContent()".
I have always been attracted towards the animation art work. Love your website. Very informative. Will definitely follow you. Looking forward for more good information.
Making a living selling on ebay http://thisismaik.com/making-a-living-selling-on-ebay/
Whats Takng place im new to this, I stumbled upon this I have discovered It absolutely useful and it has
helped mee out loads. I hope to give a contribution & assist different users like its
helped me. nice job.
It? like y?? read mmy mind! Yo? ?p?ear to know a lot about this, ?ike you wrote the boo? in ?t
or something. I think that you could do with a f?w pics tto drive the message home a little bit, but ther
than that, this ii? wonderful blog. A fantastic read. I'll definitely bbe back.
Greetings from California!I'm bored at work so I decikded to cheeck
out your blog on my iphone during lunch break. I really like
the information you provijde here aand can't waiit to take a look when I geet
home. I'm surprissed at how quick your blog loaded on my cell phone ..
I'm not even using WIFI, just 3G .. Anyhow, awesome blog!