Fantastic Extension Points - And Where to Find Them

Company Blogs December 2, 2016 By Eduardo P. Garcia Staff

One more year, it's been great to meet many of you at our events. This time I dedicated one of my workshops to the migration of 6.2 plugin projects to Liferay 7.0. I knew that some of you had already started planning this migration and you would find it helpful, so thanks for the good feedback. And thank you even more for all your questions, as they help us know what your concerns are and what you need to move towards Liferay's latest version.
Fortunatelly, it was easy to answer most of your questions. Our Documentation Team has made such a tremendous effort to cover the code migration topics, that I only had to point out the related section in our Developer Network. So kudos to the Docs Teamyes
In some cases, however, there's not just a single section I can refer you to. That's the case of the new extension mechanisms in Liferay, for instance, where you'll find dozens of guides each covering a particular use case. Motivated by this fact and by the many questions received during the workshops about the future of extensibility in Liferay, I decided to write this blog entry and guide you through some useful resources on this topic.

Hook Plugins in Liferay 6.2

Let's start with a quick review of what you already know: what hooks could do for you to customize Liferay Portal 6.2. If you want to refresh your knowledge, I recommend a quick reading of the Customizing Liferay Portal with Hooks section. To summarize, in Liferay 6.2 we used hooks for:
  • Overriding web resources
  • Customizing JSPs by extending the original
  • Overriding language properties
  • Overriding portal services
  • Creating model listeners
  • Overriding and adding struts actions
  • Performing custom actions
  • Extending indexers
  • Extending other plugins
Liferay 7.0 still supports legacy hook plugins. So first take your time to analyze the pros and cons of continuing with the plugin approach. Here you have a couple of readings on this subject:
In this guide I'll cover the alternatives to hook plugins that Liferay 7.0 offers. As you'll discover, not only are the same customization cases covered in a simpler and more flexible way, but also new extension points, tools and samples are provided.

Extenssion Points in Liferay 7.0.

If you're new to OSGi and the modular development in Liferay, let me suggest these articles before you continue reading:
As you see, Liferay 7.0 is about modularity and keeping things small and simple. And the new extension mechanisms follow exactly this pattern. Let's review some of them:

Customizing the Portal UI

A typical task that you face in Liferay projects is customizing Liferay Portal's default UI to match your requirements. In Liferay 6.2 this involved using hooks to change the appearance and behavior of the Dockbar and its sections. Liferay 7.0's UI provides new and much powerful ways to customize the main sections in the Product Navigation:
Furthermore, with Liferay 7.0 it is easier to customize some UI areas where previously hooks or themes were required:
And don't forget about Application Display Templates, one of the easiest, fastest and most powerful ways to customize Liferay applications. With Liferay 7.0 you can customize the portal navigation without writing your own theme. And you can even extend the template context with your custom variables and functionality:

Overriding JSPs

Liferay applications, both in the core and in modules, often contain JSPs. In Liferay 7.0 you can leverage OSGi Fragments hosts to override these files:

Customizing Portlet Behavior

Moving a step down, Liferay also provides extension mechanisms in the control layer. For instance, you can override MVC commands with your own custom logic. If you're migrating from 6.2, take a look to this article about StrutsActionWrappers first. You can even replace the portlet that, by default, is "in charge" of certain actions - like displaying a web content - with yours:

Extending the Model Layer

Liferay's model layer is built with Service Builder. You can learn more about the Service Builder and the generated code in this article. The model layer can be customized and extended for many different purposes. For instance you may want to change how blog entries are created, add some extra fields to the indexed documents or execute your own logic after a web content is updated:

Performing Custom Actions

You can perform custom actions on common portal events (e.g. before or after login) or during module's activation:

Modifying Language Keys

Another common use case in Liferay projects is modifiying or extending the default language keys in core and module applications:

Overriding Portal Properties

Last but not least, in case you need to override Liferay's default properties you can also leverage OSGi fragments (as the ones described for JSPs) for this purpose:

Tools and Samples

What you read in the previous section was just a summary of some Liferay's extension mechanisms. If you really want to learn about them, the best way is to get hands on some code. To make this task easier, Liferay provides code templates for the most common use cases. And this is not all. Developers love examples and replicable code, and we love developers so we have a whole repository full of sample modules for you:
Finally, if you've read the articles I recommended at the beginning of this entry, you should know that all Liferay applications (including Web Content, Wiki, etc.) are now built in the same way as you'll build yours. This means you can also use the Liferay Portal repository as a source of samples for your own projects!

Some Final Notes

If you read this far (I know, I know, it's been a long entry) then you have the docs, the tools and the samples to start writing extensions for Liferay 7.0. Please give it a try! Don't forget we're here to help you, so use the Forums to share any questions or issues you may find.
We'll also appreciate any feedback about these materials and how to improve them. And don't forget that you can contribute to the documentation, the tools and the samples yourself!

Integrating Audience Targeting with your Apps – Part II: Rules

Company Blogs October 18, 2015 By Eduardo P. Garcia Staff

Liferay Developer Conference and Unconference 2015 were simply great. Lots of sessions, games and chances to meet some of the most active Liferay developers. It was also very exciting and encouraging to register the attention that Audience Targeting has drawn among developers in just one year. Both the session and the workshop led by Julio, Pavel and me were packed and we hope that you enjoyed them as much as we did.

Previously on Integrating Audience Targeting with your Apps…

A couple of weeks ago we started a series of blog entries about the integrability features included in Audience Targeting 2.0. As you may recall, in the first entry we compared Audience Targeting with a machine that helped you to move users from one state to other. This machine consists of three processes: classification, targeting and monitoring. 

User classification based on 3rd party information: Rules as integration points

In this entry we will focus on the first process of our Audience Targeting machine: user classification. User classification is based on rules that evaluate if a certain user attribute matches a given configuration. Audience Targeting provides out of the box a number of rules that evaluate in-Liferay information such as user profile attributes or session attributes, but also information from external sources such as Facebook.
Therefore, rules are a very powerful integration point since they allow to classify users based on information provided by any external app that exposes an API. As promised, this time we’ll show some code that you can take as example for your own experiments. 

Segmenting users by their influence in Twitter

Imagine that your company wants to increase the impact of a certain topic on the social networks. A good start would be to find the most influent users (e.g. in terms of connections) and have them talking about your topic. In other words, you need a rule that evaluates if the user’s influence is above a certain threshold, so that you can create user segments with the most influent users.
Most popular social networks offer APIs and documentation for developers to obtain information from a user’s profile. In this example we’ll use the Twitter API to obtain the number of followers of the current user (if he/she has filled the Twitter profile field in the Liferay user profile). Admins will be able to set a threshold that determines if the user is influent or not based on the number of followers.

Setting up the environment

In order to follow this example you need to setup a suitable development environment. Read the instructions in our Github repository and in the Liferay Development Network to install the latest version of the Audience Targeting SDK (use the develp branch). This is how your environment should look like:

Creating the rule project

Audience Targeting SDK is basically an extension of the Liferay Plugins SDK. If you have ever worked with it, the steps will sound familiar. Let’s start by creating a new rule project with these very simple commands:
at-sdk-dir>./ twitter-sample “Twitter Sample” 
You should now find a rule-twitter-sample folder in your SDK. It contains the skeleton of our rule project. Move to that directory and execute this command:
at-sdk-dir/rule-twitter-sample>ant deploy
Now your rule has been deployed in your Liferay bundle and you will find it in the list of rule (under the Sample category) when editing a user segment in Audience Targeting:

Customizing the rule

It’s been quite easy to add a new rule to Audience Targeting, but so far it’s nothing but a dummy box in our user segment builder. It’s time to implement our user classification project based on Twitter followers.Let’s start by changing some visual aspects such as the icon or the category:
package com.liferay.content.targeting.rule.twitter.sample;

import com.liferay.content.targeting.api.model.BaseRuleCategory;
import com.liferay.content.targeting.api.model.RuleCategory;

import org.osgi.service.component.annotations.Component;

 * @author Eduardo Garcia
@Component(immediate = true, service = RuleCategory.class)
public class TwitterSampleRuleCategory extends BaseRuleCategory {

	public static final String KEY = "twitter";

	public String getCategoryKey() {
		return KEY;

	public String getIcon() {
		return "icon-twitter";

	public String getIcon() {
		return "icon-twitter";

	public String getRuleCategoryKey() {
		return TwitterSampleRuleCategory.KEY;
With this our rule looks more “Twitter”. Now since we want our rule to accept a threshold value for user classification, we’ll customize the UI of our rule this way:
<@liferay_ui["message"] arguments=selectorField key="users-that-have-more-than" />

<@aui["input"] inlineField=true label="" name="followersThreshold" style="margin-bottom: 0; width: auto;" suffix="followers" title="number-of-followers" type="text" value=followersThreshold>
	<@aui["validator"] name="number" />
	public String processRule(
		PortletRequest request, PortletResponse response, String id,
		Map<String, String> values) {

		int followersThreshold = GetterUtil.getInteger(

		JSONObject jsonObj = JSONFactoryUtil.createJSONObject();

		jsonObj.put("followersThreshold", followersThreshold);

		return jsonObj.toString();

	protected void populateContext(
		RuleInstance ruleInstance, Map<String, Object> context,
		Map<String, String> values) {

		int followersThreshold = 0;

		if (!values.isEmpty()) {
			followersThreshold = GetterUtil.getInteger(
		else if (ruleInstance != null) {
			String typeSettings = ruleInstance.getTypeSettings();

			try {
				JSONObject jsonObj = JSONFactoryUtil.createJSONObject(

				followersThreshold = GetterUtil.getInteger(
			catch (JSONException jse) {

		context.put("followersThreshold", followersThreshold);
Notice that the processRule and populateContext methods simply store/read the value of the threshold field. Don’t forget to add your keys and translations to the files.
So far so good but, where’s the Twitter-integration logic? The classification algorithm of Audience Targeting rules is defined in the evaluate method of the Rule.class. Here is where we take the context (request) and the rule configuration (stored in the RuleInstance object) and determine if the current user (represented by the AnonymousUser object) matches or not the rule. 

Consuming the Twitter API

To consume Twitter’s API you need an access token. Depending on your use case, you can obtain it in different ways. In our simple example we’ll create and use our own account to access the API
Twitter exposes several flavours of APIs for different purposes (Web, mobile…), and there are also many libraries available to consume them. In our example we’ll use Twitter4j by @yusuke under Apache License 2.0, but of course you can use your favorite one.
This is how the evaluate method of our rule looks with the Twitter-integration logic:
	public boolean evaluate(
			HttpServletRequest request, RuleInstance ruleInstance,
			AnonymousUser anonymousUser)
		throws Exception {

		User user = anonymousUser.getUser();

		if (user == null) {
			return false;

		Contact contact = user.getContact();

		String twitterScreenName = contact.getTwitterSn();

		if (Validator.isNull(twitterScreenName)) {
			return false;

		JSONObject jsonObj = JSONFactoryUtil.createJSONObject(

		int followersThreshold = jsonObj.getInt("followersThreshold");

		ConfigurationBuilder cb = new ConfigurationBuilder();


		try {
			TwitterFactory twitterFactory = new TwitterFactory(;

			Twitter twitter = twitterFactory.getInstance();

			IDs followerIDs = twitter.getFollowersIDs(
				twitterScreenName, -1, followersThreshold);

			long[] ids = followerIDs.getIDs();

			if (followersThreshold == ids.length) {
				return true;
		catch (TwitterException te) {
			_log.error("Cannot retrieve data from Twitter", te);

		return false;
First we discard non registered users (they don’t have a Liferay profile we can get the Twitter profile from). Then, we discard registered users without a Twitter profile. After that we access the Twitter API with our credentials and obtain the number of followers for the user’s profile. Finally, we compare this number with the threshold stored in the rule configuration and return true if it’s equal or greater*, or false otherwise.
*Notice that the third parameter getFollowersIDs is the limit to the results and has been set to the threshold value. Thus, it’s enough if the result is equal to the threshold (greater than would return the same). 

Setting rule dependencies

You can declare twitter4j as a build-time dependency the ivy.xml file of your rule project, so that the library is resolved and downloaded when you deploy the rule:
	<dependencies defaultconf="default">
		<dependency name="twitter4j-core" org="org.twitter4j" rev="4.0.4" />
To make sure the library is packaged with your rule (to resolve runtime-dependencies) add this line to the bnd.bnd file of your rule project:

Testing our rule

Did it work? Well, let’s test it by following these steps:
  1. Create a couple of users (A and B), each with a different Twitter profile. 
  2. Add a user segment “Twitter Influencers” with your brand new rule and set a number of followers that is greater than the number of followers of B but lower than the number of followers of A. 
  3. Go to the homepage and add a User Segment Content Display portlet. 
  4. Edit the portlet configuration so that a certain image is displayed for users that belong to the “Twitter Influencers” user segment. 
  5. Finally, log in with users A and B. User A will see the image, while user B won’t.
Now your company is ready to target Twitter influencers to increase its presence in social networks! How? We’ll you’ll have to wait for the next entrywink.

Best practices and improvements

That our example is functional doesn’t mean that it’s ready for use. Make sure you follow the API best practices and note the possible limitations. For instance, Twitter’s REST API has a limit of 15 to 180 calls every 15 mins. You should consider caching or using other API such as the Streaming API.
Regarding Twitter credentials, it’s not a good idea to have them declared as constants in your code even if tokens can be reverted and regenerated. In this series of blog entries we’ll show you a better approach based on Consumer Manager, a new Liferay tool to manage application settings.

Try this at home!

Though this example was quite simple, you can take it as a basis for more complex rules. Just image the possibilities, given the amount of potential external sources for user classification. Try to build your own rules and if you feel proud of them, contribute the code to our repository and write an entry about them!  

Reach the Right Audience: Integrating Audience Targeting with your Apps

Company Blogs October 4, 2015 By Eduardo P. Garcia Staff

Liferay Developer Conference (aka DEVCON) is a great chance for us to meet Liferay developers from all around the world every year. As for the last months we’ve been working on the new version of Audience Targeting, Julio and I very willingly proposed a talk about its new features and how to use them to integrate your apps with it. 
But preparing the talk turned out to be more difficult than we expected. Though our goal was clear (we want to have more and more developers creating cool stuff with Audience Targeting), we weren’t sure about how to transmit our message to the attendees.  For sure most of them will be techy guys, but what about the other profiles? And Audience Targeting is quite new… what will they know about it? Have they ever used it? Do they actually know it? 
If only we had a way to reach the right audience with the right message to meet our goal… Oh, but wait a minute… This is exactly what Audience Targeting is for cool!


Introducing Audience Targeting (for beginners)

In a very simplistic approach, you can think of Audience Targeting as a machine that helps you to move users from an status to another, in order to reach a certain goal. For instance, if you don’t know anything about Audience Targeting, your initial status would be “Beginner”, and your final status should be “Expert”. Of course the information you’d get would be adapted to your level. If you progress well, your status might upgrade to “Intermediate”, “Advanced”…
Audience Targeting - Machine Approach
Now think about the possibilities of such a machine built on top of a powerful enterprise-oriented platform like Liferay Portal. By exploiting Liferay user’s information (e.g. profile, roles) and context (e.g. session attributes), you can use Audience Targeting out-of-the-box to increase your sales, improve your product awareness or enhance your customer loyalty. 


More than a Developer Friendly Application

So far it sounds great for marketers and salesmen, but what offers you Audience Targeting as a developer? Well, the question should be “What doesn’t it offer you”… Audience Targeting leverages Liferay’s OSGi support to provide a completely modular architecture. The application is made up of more than 40 modules, most of which can be hot-switch off or replaced. And if those modules are not enough for you, Audience Targeting provides you with an SDK to create your own modules and extend its features.
But even the best applications can’t do everything on their own. And when it comes to matters like user segmentation or digital marketing, integration with 3rd party apps is really a must. This is precisely one of the areas in which we have been working more intensively for version 2.0, and the main topic of our talk.
Audience Targeting - Modularity, Extensibility and Integrability

Audience Targeting Integration Points

To understand the integration capabilities of Audience Targeting, let’s take a look inside the machine and see how it works.
The first stage in the user processing is classification. Based on certain rules, users are classified into one or more user segments. Rules make use of Liferay information (such as user’s attributes) or session information (such as current location), but they can also consume external data sources providing a very powerful integration mechanism. For instance, we could classify the attendees to our talk with a rule that queries GitHub API and finds out who forked our repository and who contributed it.
Once your users are classified, you can send them information that fits their needs. This content targeting phase is perfomed with campaigns and promotions through different channels. A channel could be a Liferay portlet (e.g. displaying certain content on the home page based on the user segment) or a external system through which you can deliver your message to the users. What if we created a channel that integrates with your Agenda app and notifies the most relevant talks for your profile? Channels are another powerful integration tool that you’ll find in Audience Targeting 2.0. 
By monitoring users activity you can measure the performance of your campaigns and obtain very valuable information. For actions performed in the Liferay, Audience Targeting provides out-of-the-box mechanisms for tracking. But for those performed in external apps, you can generate custom metrics and reports that are integrated with the app monitoring systems. Twitter or Stack Overflow could be good sources to measure the impact of Audience Targeting with a custom report.
Audience Targeting - Iteration
But the story doesn’t end here. Actually, it hasn’t but started.Using  Audience Targeting is an iterative process where parts must be tuned in order to get the best performance.


And of course, the APIs

Rules, channels, metrics and reports are extension of Audience Targeting that provide integration points. But what if you want to extend your own app to integrate with Audience Targeting?
Audience Targeting provides an out-of-the-box API that gives you access to all the information about the existing user segments (including which users were last assigned to them), campaigns and analytics.
Audience Targeting - Core API
And yes, you’ve guessed it: these APIs can be extended! (we love extensions). Any rule, channel, metric or report can expose its own API to the world, making bi-directional integration simple. Actually, you have ever used Liferay Service Builder to generate consumible APIs, you already know how to do it with Audience Targeting.
Audience Targeting - Custom APIs


To be continued…

You might be wondering “And that’s all?” “Not a single code line?” “Where are the examples?”
Don’t worry. This is just the first of a series of entries where we’ll guide you on how to integrate Audience Targeting with external applications by different mechanisms. Stay tuned!
PS. If you just cannot wait (we understand), take a look to this entry by Abdon about Audience Targeting integration with Salesforce.

Leveraging OSGi to Create Extensible Applications for Liferay 6.2

Company Blogs October 20, 2014 By Eduardo P. Garcia Staff

It was great to participate in the Liferay North American Symposium this year. With hundreds of Liferay users (customers, partners, community members...) and dozens of presentations, it was not only a huge success but also a great opportunity to share user experiences and get your feedback. North American Symposium is over, but Liferay World Tour 2014 is not! There are still many important events in our calendar so you still have the chance to learn about Liferay latest features firsthand. 
Julio Camarero and I will be talking about Extensible Liferay Applications in the Spanish Symposium next week and in the Developer Conference in early November. This is probably one of the most relevant features in Liferay 6.2 because it's meant to completely change how Liferay applications are developed. Let's find out how with a simple example:

A Shipping Cost Calculator

Suppose you have an online shop and you need an application to calculate the final cost of purchasing an item, including its shipping to destination and considering not only the distance but also the currency, the local taxes and any other particularities. Thus, the final cost would be:
Final cost = [no. of items x item price] + [shipping cost to selected destination]
As a developer you could implement a very complex application that contains all possible shipping destinations. Every time you wanted to add or modify a shipping destination, you’d have to release a new version of your application. And likely your application would be more and more complex with every new release.
Alternatively, you could implement just the core functions of your calculator and define the shipping destinations as extensions to your application. This way, if you needed to add or modify a shipping destination those changes would not affect to the core functions, but only to an specific extension. With this approach, the release frequency of your core application as well as its complexity would decrease. Instead, new features would be added through small extensions with their own release frequency.

Modular and Extensible Applications: the OSGi Way

Probably at this point you’ve already realized the benefits of the second approach: 
  • Simpler maintenance of the core application by reducing its complexity
  • Better performance (only required extensions would be installed)
  • Support for third party extensions
  • New market opportunities (e.g. purchasing shipping extensions)
This type of modular and extensible applications are defined by the OSGi  (Open Service Gateway initiative) specification. Thanks to Liferay support for OSGi since version 6.2, you can now apply this pattern to your plugins. 
We recommend you to go through the documentation about OSGi apps in Liferay. For now we’ll show some quick guidelines to apply this pattern to the Shipping Cost Calculator project. You can also have a look to the complete source code of this project.

Required Services for an Extensible Shipping Cost Calculator

OSGi services consist of:
  • An interface, defining the service “contract”
  • One or more implementations of the interface
To make our shipping cost calculator extensible, we need two types of OSGi services:

Shipping Extensions:

The ShippingExtension interface contains the methods that any shipping extension must implement. Implementations of this interface (e.g. ShippingExtensionUSA) are annotated with @Component, which allows OSGi to dynamically detect a new shipping extension when it’s deployed.
@Component(immediate = true, service = ShippingExtension.class)
public class ShippingExtensionUSA implements ShippingExtension {

ShippingExtension Registry

In order to have an up-to-date list with all the available shipping options, we need to track when these extensions (annotated with @Component) are deployed or undeployed. Through the @Referecene annotation the registerShippingExtension method of ShippingExtensionRegistryImpl is bound to the ShippingExtensionService, so it will be invoked every time an implementation of ShippingExtension is deployed. The unregisterShippingExtension method is called when an implementation is undeployed.
	unbind = "unregisterShippingExtension",
	cardinality = ReferenceCardinality.MULTIPLE,
	policy = ReferencePolicy.DYNAMIC)	
public void registerShippingExtension(ShippingExtension shippingExtension) {
		shippingExtension.getShippingExtensionKey(), shippingExtension);


Accessing OSGi services from a non OSGi context: the ServiceTrackerUtil

We’re almost done. All we need to do is to list the shipping extensions registered by the ShippingExtensionRegistry in our GUI and process the resulting form according to the selected option. Since our GUI is still a Liferay portlet, which is not handled by the OSGi service container (yet), we cannot use the @Reference annotation to obtain the ShippingExtension service. Liferay provides a util class for this purpose: the ServiceTrackerUtil.
_shippingExtensionRegistry = ServiceTrackerUtil.getService(
	ShippingExtensionRegistry.class, bundle.getBundleContext());
You can now test the app. First deploy all modules to your Liferay server, except for the shipping extensions. Then browse any site page and add the Shipping portlet. Notice that the calculator is functional, but it displays no shipping options. Now deploy the shipping extensions one by one, refreshing the page every time. You’ll now see a list with the available shipping extensions. Selecting a shipping extension will modify the form and the final result.

Going even deeper in modularization

If you have worked with the sample code, you may have noticed that the core application is not contained in a single project, but in three: 
  • shipping-api: Contains only the interfaces of the OSGi services that make up the app
  • shipping-impl: Contains the implementation of the core OSGi services of the app
  • shipping-web: Contains the user interface of the app
With this approach, the core of application can be easily modified by changing the implementation or the web interface, without changing the public API. 
Audience Targeting is the first official Liferay application that is built following this OSGi way, but this is actually how all Liferay apps will be in the next version of Liferay Portal so WELCOME TO THE FUTURE!!

Application Display Templates: Challenge Accepted!

Company Blogs September 29, 2014 By Eduardo P. Garcia Staff

It’s less than a week left until Liferay North America Symposium (NAS), the first of a series of events where we’ll have the chance to first-hand explain to our users what we’ve been working on this year. In particular, workshops will give us the opportunity to go deeper in some of our most popular features, as we will have the time to review and solve some real use cases.

In previous events we had shown you how Application Display Templates can change not only the look and feel but also the function of some applications. But in the NAS workshop we will demonstrate how they be used to change a whole site.  For this challenge we’ve prepared a full demo music site.

Our goal during the workshop will be not only to improve the design, but also to add new features by creating and applying new Application Display Templates to Liferay applications. For instance, among other many exercises we’ll see how to display our content as a chart or even as a map with the Asset Publisher.

And the challenge will go even further. Since our music site uses some custom applications, we will learn how to make them support Application Display Templates, so that we can also extend their display modes with new templates. See before and after:

Finally, for those of you who are so proud of your Application Display Templates that can’t wait for the world to see them, we will show you how make them distributable through Liferay Marketplace.

Sounds good,  doesn’t it? If you haven’t yet, visit the NAS site and register now! And for those of you who cannot make it for the NAS, you’ll have yet another chance in the Liferay Spanish Symposium and the Liferay Developer Conference.

Thanks a lot to Marcos Castro, for his wonderful design for the Music Site :-).

See you in Boston!

Upcoming customization options with Application Display Templates

Company Blogs June 12, 2014 By Eduardo P. Garcia Staff

Application Display Templates have become one of the most popular features in Liferay Portal 6.2. Last year we reviewed how to use this powerful tool to customize some Liferay portlets. Furthermore we explained how developers can apply the same feature to their custom portlets in just a few steps.

The Liferay Community provides a great feedback about how you use Application Display Templates and also about the Liferay portlets where you miss this feature. And of course, we have attended your requests cool

Customizing the Language Portlet

The Language Portlet as you know it

Definitely one of your favorites to join the Application Display Templates family. You can now customize every single detail of this portlet. For example, you can turn it into an icon-menu list like this:

The Language Portlet displayed as an icon-menu thanks to Application Display Templates


Your breadcrumb will never look the same

The Breadcrumb Portlet as you know it

The Breadcrumb portlet already included some customization options. But you wanted more, and we’ve given you all yes. With Application Display Templates, there’s no limit to your creativity. See how different your breadcrumb can look with just a very simple template:

The Breadcrumb Portlet with a brand new style thanks to Application Display Templates

Thanks Jose Manuel!

Displaying content on a map? Yes, you can!

We are not only extending the support for Application Display Templates to more portlets, but we are also extending the possibilities that this tool provides to display content in a completely new way.

Just a very cool example of this is the work that our colleagues Sergio, Bruno and Adolfo have done with the content geolocation feature. In a nutshell, you can define your content associated coordinates through a new geolocation input field. Among the number of possibilities that this information brings, you can now display your content on a map with the Asset Publisher portlet and a very simple Application Display Template. For example, you can change from this:

A typical list of content with the Asset Publisher

to this:

Content on a Map with Application Display Templates and Google Maps

Content on a Map with Application Display Templates and OpenStreetMap

And these are just the first of a number of new features that Application Display Templates will include in the next version of Liferay Portal. Remember that you can request new features through our website. Thanks for helping us make Liferay Portal a little better everyday heart!

Making Liferay Portal 6.2 RTL friendly - The Right to Left plugin

Company Blogs May 29, 2014 By Eduardo P. Garcia Staff

Middle Eastern languages, such as Hebrew and Arabic, are written predominantly right-to-left (RTL). However, many sites written RTL also have left-to-right (LTR) content mixed in, making them bidirectional in nature. Conveniently, browsers use language and direction information of HTML tags to automatically adapt and align page content. However, sites may consist of elements that are absolutely positioned on the page by a style sheet; these elements aren't automatically aligned by the browser. Rather, you must adapt your style sheets to handle such elements. Since style sheets are usually designed for LTR languages, the typical challenge is creating alternative versions of the CSS for RTL languages. This can be an arduous task.
A few weeks ago our colleague Iliyan described on his blog how automatic adjustment to RTL will be supported out of the box in future Liferay Portal versions. In this blog we introduce the “Right to Left” plugin, a new Liferay application that automatically adapts Liferay Portal 6.2 styles for RTL languages.

Using the Right to Left plugin

To test how the Right to Left plugin works, lets create a simple site with one page and one single content translated to several languages, including LTR and RTL ones.

Before installing the Right to Left plugin, try to set your user language to Arabic or Hebrew. You’ll notice that some elements (such as paragraphs) are mirrored to match the RTL orientation. But some others (dockbar, images…) aren’t.

Now install the Right to Left plugin and reload the page. This time, every element on the page is mirrored for a full RTL experience.

Support for custom plugins

The simple test described above works fine with Liferay Portal default theme and portlets. But if you are using any custom plugins, such a theme, you will notice that its styles are not fully mirrored.

In order to provide full RTL support in custom plugins, developers have to go through a few steps described in the technical documentation of the Right to Left plugin. Then, once the plugin is redeployed its elements will be displayed mirrored for RTL languages (for LTR languages, they will be displayed as usual).

Fine style tuning for RTL languages

Through the steps described in the previous section, the styles in a custom plugin are automatically adapted so that the page elements are mirrored for RTL languages. This automatism covers most of the common scenarios. But developers can override it, so that they define how the page elements should behave for RTL languages.

For example, observe the header of our sample theme. It contains a line with hands pointing to the appropriate reading direction. But even after a developer has adapted the theme for RTL languages, the hands still point to the initial direction. Thanks to the overriding mechanism provided by the Right to Left plugin, our developer is able to set an alternative image for RTL languages only.

The same mechanism could be applied to force an element to be right or left aligned for both LTR and RTL languages, for example.

The Right to Left plugin is coming soon to our Marketplace. Enjoy it!

Did you know...?

The topic "The City  of Three Cultures" that was used for the screenshots in this blog refers to the time when Jewishs, Muslims and Christians coexisted peacefully in the city of Toledo, the ancient capital of Spain. Back then, king Alfonso X "The Wise" employed Jewish, Christian and Muslim scholars at his court, primarily for the purpose of translating books from Arabic and Hebrew into Latin and Castilian. This group of scholars formed his royal scriptorium, known as the "Escuela de Traductores de Toledo" (Toledo School of Translators). 

New Ways of Customization with Application Display Templates (Part II)

General Blogs October 9, 2013 By Eduardo P. Garcia Staff


The first Liferay DevCon has just started in Berlin and we just can't wait to present the world all new features in version 6.2. So I'm writing the second part of my blog about New Ways of Customization with Application Display Templates for those of you (eager like me) who just can't wait to use ADT in your portlets.
As you know Liferay is a Developer Friendly platform. We love developing and we love developers using and extending our product. So everytime we add a new framework we make sure it's not only accessible in the portlal, but also in the plugins. Security, Workflow, Asset... are only some examples of powerful features that can be exploded by your plugins. And in 6.2. we've added quite a few more! Let's focus on the ADT framework and see what you need to support this feature in your portlets.

Add ADT to your portlets in just 4 steps

In the first part of the blog we explained how ADT was implemented by reusing other existing services and features. We just added a management application to the Site Administration and a mechanism to allow any portlets to have and render their own templates. 
This second component is the key to have ADT in your portlets, and we'll describe how to use it in 4 simple steps:

1. Custom PortletDisplayTemplateHandler

To join the exclusive ADT club your portlet has to sign a contract committing itself to fulfill all the ADT features. In other words, you have to create a your own PortletDisplayTemplateHandler implementation by extending the BasePortletDisplayTemplateHandler methods. You can check the TemplateHandler interface javadoc to learn what every method is for. Basically:

public class MyAppPortletDisplayTemplateHandler extends BasePortletDisplayTemplateHandler { 
public String getClassName() {//Defines the type of entry your portlet is rendering}
   public String getName(Locale locale) {//Declares the name of your ADT type (typically, the name of the portlet)}  
public String getResourceName() {//Here you specify which resource is using the ADT (e.g. a portlet) for permission checking}  

public String getTemplatesHelpPath(String language) {//Adds a custom hint to the top of the ADT in the template editor}
public String[] getRestrictedVariables(String language) {//Provides a list with the restricted variables}   
public Map<String, TemplateVariableGroup> getTemplateVariableGroups(long classPK, String language, Locale locale) throws Exception {//Defines the variables exposed in the template editor}   


Once you've created your handler, you have to declare it in the right section of your liferay-portlet.xml.

2. Permissions

The action of adding ADTs is new to your portlet, so you want to be sure you can grant specific permissions for it. Just add this line to your resource actions file:

3. Display settings configuration

Let's move to the frontend side of your portlet. Now your portlet officially supports ADT, you'll want to expose this option to your users. Just include the liferay-ui:ddm-template-selector taglib in your portlet configuration view providing the required information, like this:
<aui:form action="<%= configurationURL %>" method="post" name="fm">
 TemplateHandler templateHandler =

 classNameId="<%= PortalUtil.getClassNameId(templateHandler.getClassName()) %>"
 displayStyle="<%= displayStyle %>"
 displayStyleGroupId="<%= displayStyleGroupId %>"
 refreshURL="<%= PortalUtil.getCurrentURL(request) %>"
 showEmptyOption="<%= true %>"


4. Render templates

Last but not least, you have to extend your view code to render it with the selected ADT. Here is where you decide exactly which part of your view will be rendered by the ADT and what will be available in the template context.
 List<MyType> myList = ...;

long ddmTemplateId = PortletDisplayTemplateUtil.getPortletDisplayTemplateDDMTemplateId(
 displayStyleGroupId, displayStyle);
 Map<String, Object> contextObjects = new HashMap<String, Object>();
 contextObjects.put("myExtraObject", someExtraObject);


<c:when test="<%= portletDisplayDDMTemplateId > 0 %>">
 <%= PortletDisplayTemplateUtil.renderDDMTemplate(pageContext, ddmTemplateId, myList, contextObjects) %>

Ok, has it worked for you? Try this:
  1. Add your portlet to a page
  2. Edit configuration
  3. Display Settings selector is displayed (COOL!)
  4. Click Manage Display Settings and create new ADT
  5. The template editor displays your portlet variables (GREAT!)
  6. Save and choose your new ADT
  7. The portlet is rendered with your ADT (NICE!)



In order to show how to integrate 6.2 new frameworks in your plugins, Sergio and Julio have created a very complete sample plugin with several portlets using the Recycle Bin, the new Staging and Search framework features... and also ADT! It's called the jukebox project. This time I decided to use the power of ADT to create a cool iTunes-like coverflow carrousel for the album covers. See the before:
And with a little bit of ADT magic...
... this is how it looks at the end:
I've shared the code of this example, but remember you'll first need to install the jukebox plugin to make it work (hold on!).
I hope you'll enjoy using ADT as much as we did when developing and testing it. Please let us know about any issue or improvement through our issue tracker and the community tools.
I'm running to see the next DevCon talk, see you!


New Ways of Customization with Application Display Templates (Part I)

General Blogs October 1, 2013 By Eduardo P. Garcia Staff


Next week Liferay will hold the first Developer Conference (DevCon) in Berlin. Liferay experts from all around the world will meet up to share their experience and review the latest features of version 6.2.
We'll have the chance to introduce Application Display Templates (ADT), a new framework to add custom display options for portlets. Juan Fernández had already given us a glipse of the power of this new tool in one of his blogs last year. This time we'll go deeper into the technical details and even show you how to support ADT in your plugins.
In this first part of the blog, we'll focus on how ADT works and how to use it.

The ADT concept

Portlet Display Settings are the simpliest way to customize portlet display.  Unlike themes or hooks, they don't require deployment and they affect specific portlet instances. But, they are limited to those that come out of the box... Wouldn’t it be great to have as many of them as we wanted? As a user, this would simplify the task of customizing the portlet display. And as developers, we wouldn’t have to change our portlet configuration code every time a new setting is required.
That’s exactly what Application Display Templates  (also known as ADT) provides Adding custom display settigs to our portlets. Actually, this is not a new concept in Liferay. In some portlets such as Web Content, Document and Media or Dynamid Data Lists we can add as many display options (or templates) as we want.


Since we already had similar features in Liferay, we tried not to reinvent the wheel with ADT. Actually, we aimed to reuse as much logic as possible. Basically, ADT is based on two preexisting Liferay components:
  • For the service layer, we used the Dynamic Data Mapping (DDM) portlet. It manages all the operations for structures and templates in every Liferay applications.
  • We used the existing Template Engine that renders Velocity or Freemarker templates based on a given context.
So we just had to add a new portlet to the Site Administration to manage the display templates, and provide a mechanism such that any portlet can define its own template context and show its custom display settings.


At this point some of you may believe that ADT is too good to be true. During the DevCon we'll do a demo to show how easy it is indeed to customize a portlet display with our new tool. Here you have a preview:
1. Adding a new ADT for the Media Gallery
2. Introducing the new advanced template editor to write a Freemarker script that displays our pictures in a fancy way using the  Masonry Library
3. Apply our new ADT to the Media Gallery...
..and check the effect
4. Extend our template to display a tooltip with more information about the pictures and include the ratings taglib.
You can checkout the complete demo from gihub and try it out yourself. (You will need to install the Resource Importer plugin to get the demo contents installed).


As we have seen, ADTs bring a great power. But if there's something we've learnt, is that with great power, comes great responsability!  Let’s go through some good practices  in ADT design:


You may want to hide some classes or packages from the template context, to limit the operations that ADTs can perform on your portal. Liferay provides some portal  properties to define the restricted classes, packages and variables:


ADTs add extra processing task in portlet render. This inevitably has effect in the performance. To reduce this effect, make your ADT as minimal as possible: focus on the presentation and use the existing API for complex operations. Don't forget running performance tests and tuning the template cache options:
freemarker.engine.resource.modification.check.interval velocity.engine.resource.modification.check.interval


The best way to make great ADTs is to know your template context well and what you can use from it. Now you don’t need to know them by heart thanks to the advanced tempalte editor!

Error handling

Finally, you can improve the error handling of your templates by setting these properties:

Learn more

An this is all for the first part of the introduction to ADT. Soon we'll go through the second part: Supporting ADTs in your plugins. In the meantime you can learn more about ADT in our User Guide or promt your questions in our Forums.
See you in Berlin! 


Showing 9 results.
Items 20
of 1