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
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.
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!"