« Back

Embedding portlets in themes on Liferay

Company Blogs October 21, 2011 By Ray Augé Staff

Liferay has long had the ability to embed portlets in themes. This is convenient for implementors to get highly functional design into the look and feel of a site. In my years at Liferay I've seen and heard many different attempts at doing this with various levels of success. There are a number of things to consider when embedding portlets in the theme and the same method does not apply in all cases.

The original motive behind embedded portlets was for integrating WCM content or simple functional features such as Search or Language selection. As such the complexity of these portlets was understood to be low and without significant performance costs either due to not having any direct service calls (search & language selection portlets don't have any initial service calls), or having service calls which were highly cached (such as is the case with web content).

There is more than one technique for embedding portlets into the theme, and several different issues to consider when choosing any of those.

Method One: Using $theme.runtime()

This is by far the most common method. There are of course a few gotchas with this method.

1) it renders the portlet synchronously in the theme regardless of the ajaxable settings on the portlet ( via liferay-portlet.xml).

This means if the portlet is expensive to render because it a) has lots of data to process on render, b) uses synchronous web service calls, or c) calculates the fibonacci sequence up to a million, DON'T EMBED IT IN THE THEME! You're just killing the performance of your portal whenever that theme is on any page.

Rule of Themes #1: This is a good rule of thumb to follow regardless of embedded portlets or not: "Themes should be SUPER FAST! They should be the fastest component of your portal view at any given time."

If you don't follow this rule how will you expect the experience to be once you start actually putting more things on the page? It's a different topic entirely, but you should generally performance test your theme with no portlets on the page. Once you know it's blazing fast then proceed to test your portlets' performace.

But I digress! Back to portlets embedded in the theme.

2) portlets rendered in the theme don't have their js/css resources loaded at the top of the page with all the rest of the portlets. Liferay doesn't yet implement "streaming portlet" mode (this is optional in the spec, this doesn't mean Liferay is not fast, it's just a name they chose for the feature of calling the portlet's header altering methods separately from the rendering methods). So the issue with this is that if you embed a portlet that uses something like JSF dynamic javascript features and there happens to be more than one of this type of portlet on the page, the ordering of these dynamic resources may get fouled up and cause general mayhem to their behavior.

On the other hand, I would argue that such portlets are already, by their very nature, TOO complex and expensive to be embedded in the theme. They are quickly diverging from the rule above that the theme should be SUPER FAST!

Rule of Themes #2: "Only use $theme.runtime() to embed portlets that are extremely fast. If they make expensive service calls, MAKE SURE those are not calls that happen all the time, and MAKE SURE they use great caching."

 

Method Two: Ajax / Iframe!

This is a "currently" seldom used method, but one that I would HIGHLY recommend using! Why?

1) It's Asynchronous with the rendering of the theme. This is HUGE! It means that regardless how slow your portlet(s) is(are), the general experience of the portal will remain fast!

2) It means that you can still put that fairly complex portlet into the theme without killing the overall performace.

3) It doesn't suffer from the limitation of the resource loading that the $theme.runtime() method suffers from.

So how do I do it?

Ok, so generally what you do to embed a portlet via ajax or iframe is to create a portlet url (either server side or client side) and then request for it, placing it somewhere in the page. With an iframe you can of course interact with the portlet in place. If you use an ajax call and embed the output of the portlet directly it will of course cause page refresh.

Here is the code for doing it with the iframe:

 

One thing you'll note with this code is that it's making the assumption that the portlet is at the current page! But it's not on the current page yet!

There are a couple of ways of handling this.

1) The portlet is specifically designed to be in the theme and should be visible to anyone seeing the page.

In this case I recommend setting these attributes in your liferay-portlet.xml file:

These will allow your portlet to safely added to any page in the portal automatically (otherwise you may get permission issues because the user viewing the portlet may not have permission and all that jazz.)

2) You can't do as above because you still want to control permissions of the portlet using roles.

In this case, you'll have to add the portlet to something like a hidden page, from which you can manage it's permissions. When creating the url in the code above, you'll then use the page "plid" of that target page instead of the current one.

 

Well, I hope that helps!

I hope that I hear far less talk about $theme.runtime()issues and Liferay performance problems that end up being directly related to expensive operations embedded in the theme.

 

And please heed these words:

"Embed portlets with impunity! Just make sure to do it carefully!"

Threaded Replies Author Date
Right now I embed portlets in the theme because... Jelmer Kuperus October 22, 2011 11:56 AM
I don't believe I suggested NOT to embed... Ray Augé October 22, 2011 1:28 PM
yes that point was quite clear. Let me rephrase... Jelmer Kuperus October 22, 2011 4:34 PM
We have several arguments for this! 1) Simply... Ray Augé October 23, 2011 7:34 AM
The problem with page templates is that... Jelmer Kuperus October 24, 2011 4:34 AM
Liferay also has "copy page" ability... with a... Ray Augé October 24, 2011 7:21 AM
Yes i am familiar with copy page. A... Jelmer Kuperus October 24, 2011 8:27 AM
I'm having difficulties understanding why you... Kyrre Myrbostad October 26, 2011 12:47 AM
Forgot to mention: the ajax call could be done... Kyrre Myrbostad October 26, 2011 12:48 AM
@Kyrre, You're absolutely correct! "Method... Ray Augé October 26, 2011 5:48 AM
nice post! Jonas Yuan January 23, 2012 11:54 AM
I am not sure of what i am asking makes sense,... Satish Bhor April 11, 2012 5:47 AM
@Ray : what about redirecting issue from Iframe... KK rajput September 10, 2012 10:07 PM
very useful post Anant Sengar April 7, 2013 7:23 PM
Hello Ray, this is quite useful, but can we... Onochie Ojekwe August 12, 2014 6:56 AM
Hi Ray, moreover, if I'm not wrong, embedded... Denis Signoretto October 2, 2014 7:04 AM
Yup! Ray Augé October 2, 2014 7:07 AM
Hallo! i try to embedding assetPublisher... Cyber Katze March 5, 2015 1:19 AM
I think you need to grant Guest the view... Ray Augé March 5, 2015 9:47 AM
Hi Ray, Sorry about this strange request, I'm... Nabil Bahtat April 19, 2016 2:08 PM
Hi Ray, Many thanks for your posts,is it... Hany Bonyadi October 26, 2015 9:18 AM
I tried your iframe method for Language... Jatinderpal Singh December 3, 2015 9:38 PM

Right now I embed portlets in the theme because I haven't found an easy way to "nest" portlet pages so to speak. Say you have a sidebar that contains the same portlets over 30 pages. You don't want to define these same 30 portlets on all the pages. To my knowledge using themes is the only way to avoid this. Are there any plans to come up with a solution for this ?
Posted on 10/22/11 11:56 AM.
I don't believe I suggested NOT to embed portlets! In fact I clearly stated "Embed portlets with impunity! Just make sure to do it carefully!" which means DO embed portlets in themes, just make sure to consider the consequences and use the appropriate method for the type of scenario you are planning.
Posted on 10/22/11 1:28 PM in reply to jelmer kuperus.
yes that point was quite clear. Let me rephrase my question. The gist of your post is that portlets that take a while to render will cause performance problems when embedded in a theme. Suppose you have a sidebar that is common across 30 pages and it contains a portlet that calculates the fibonacci sequence to 1 million. Then basically using iframes / ajax right now is your only option to make things perform. But there are many reasons why one may not want to do this, seo being one of them. So i was wondering if something is in the works for this. I guess what i am really hoping for is something like apache tiles. that lets you nest and extend layouts. Using themes for this kind of stuff always felt like a hack. Right now it feels like liferay is missing a concept
Posted on 10/22/11 4:34 PM.
We have several arguments for this!

1) Simply create a re-usable Page Template.
2) Unless the portlet is the main focus of the page how does SEO become an issue? Also, why does an iframe play a lesser role in SEO? There are two main points here, The URL used for the iframe is as likely to have as much meaning as any other link in the page. Second, using portlet friendly url router for your portlet is also usable in this case as any other, so the iframe will have a meaningful url. Sure the content is not inline, but I don't see the purpose of having expensive portlets that are NOT the focus of the page have significant weight on the SEO of the page to begin with.
3) Why not cache the result of the portlet and re-use it for some time? Even if the portlet is expensive, if you want it's SEO weight to be high, then SURELY you are not changing it so frequently from the page! It must have some direct correlation with the rest on the content of the page in order for SEO to be a relevant argument in my opinion.
4) SEO is never user relative! There is no point because in that case the search bots would behave as a different user and the search engine would have irrelevant results that are not searchable for anyone else! Again, this means that you can either cache the output, or take the content out of line!
Posted on 10/23/11 7:34 AM in reply to jelmer kuperus.
The problem with page templates is that applying them is a one off. All the portlets defined in the page template are copied to the page but if the
page template changes afterwards, all pages based on it do not change automatically. To work around this I sometimes embed portlets in the theme

I brought up SEO as just one of many possible reasons why you may not want to use an iframe / ajax based solution. I think the argument is valid if
you're taling about say an rss portlet or perhaps the new "related assets" portlet where the content is meaningful to the page.
And sure often caching can be employed as a workaround.

But I think it would be a lot nicer if other solutions where available that don't make it as easy to shoot yourself in the foot.
Even something as simple as named static layouts that you could assign to a page would go a long way
Posted on 10/24/11 4:34 AM.
Liferay also has "copy page" ability... with a single selection you could create your new pages derived from any other existing page in the site!

It doesn't solve the change management issue.

We will have Page Template change management/propagation (not the official name I'm sure) in 6.2.

We already have it in 6.1 for Site template change management/propagation. Perhaps that may help somewhat.

I do see your point! But as you say, it's just not something we've implemented yet.
Posted on 10/24/11 7:21 AM in reply to jelmer kuperus.
Yes i am familiar with copy page. A particularly nasty piece of functionality from a usability standpoint. I have yet to come across someone that has not inadvertedly changed the webcontent on the page the content was copied by editing the webcontent on the copied page. But I digress. Yes it also does not solve the change management issue.

So I guess i'll have to wait for 6.2 , but it's good to know it's being worked on. Thanks for the update!
Posted on 10/24/11 8:27 AM in reply to Ray Augé.
I'm having difficulties understanding why you want to use an iframe here. Why not just create a normal portlet with a fast renderMethod, and then do all the heavy lifting through an ajax-call to a resourceMethod in the portlet. It would achieve the same performance benefits without the extra complexity (and possible usability issues) of an iframe would it not?
Posted on 10/26/11 12:47 AM in reply to jelmer kuperus.
Forgot to mention: the ajax call could be done on dom ready. We are currently doing this with some of our portlets that are not embedded in the theme.
Posted on 10/26/11 12:48 AM in reply to Kyrre Myrbostad.
@Kyrre, You're absolutely correct!

"Method Two: Ajax / Iframe!"

Any technique that avoids heavy synchronous processing should work! Iframe is simply the easiest for existing portlets. I as I was impling above you could even load those using AJAX with a slight alteration to the example code I provided.
Posted on 10/26/11 5:48 AM in reply to Kyrre Myrbostad.
Posted on 1/23/12 11:54 AM in reply to Ray Augé.
I am not sure of what i am asking makes sense, but can we do other way round where i can have specific themes for my specific portlets configured in my portlet itself.
Posted on 4/11/12 5:47 AM in reply to Jonas Yuan.
@Ray : what about redirecting issue from Iframe something like this http://www.liferay.com/community/forums/-/message_boards/message/13967650
Posted on 9/10/12 10:07 PM in reply to Satish Bhor.
very useful post
Posted on 4/7/13 7:23 PM.
Hello Ray, this is quite useful, but can we have the freemarker syntax version?
Posted on 8/12/14 6:56 AM.
Hi Ray,

moreover, if I'm not wrong, embedded runtime portlets are renderer serially. Do you confirm ?
Posted on 10/2/14 7:04 AM.
Posted on 10/2/14 7:07 AM in reply to Denis Signoretto.
Hallo!

i try to embedding assetPublisher portlet in my Theme. But this portlet will be showed only if I logged in system. can I change permission for guest-users?
Posted on 3/5/15 1:19 AM.
I think you need to grant Guest the view permission on this portlet.
Posted on 3/5/15 9:47 AM in reply to Cyber Katze.
Hi Ray,
Many thanks for your posts,is it possible put multiple portlets in one IFrame ?
Posted on 10/26/15 9:18 AM.
I tried your iframe method for Language portlet, It embeds well into theme. But it does not work as expected. It just refreshes the page but does not translate the page. So, purpose of embedding language portlet is defeated.
Posted on 12/3/15 9:38 PM.
Hi Ray,
Sorry about this strange request, I'm new to liferay and I wanted touse liferay polls portlet and set friendlu url using routes like explained in many wiki and docs resources in internet. Unfortunatly I didnotmanage to have a clean url.
Can you please help to make a polls-friendly-url-routes.xml file ?

Thanks alot.

Nabil
Posted on 4/19/16 2:08 PM in reply to Ray Augé.