Extending the Liferay BackOffice: A Clean Solution

>> Saturday, April 23, 2011

Liferay is a sophisticated system covering a wide range of needs but, as with any solution, the customer (or business) always needs something that is not available out of the box. That's what keeps our industry going and helps us pay the mortgage. In such a situation, the reflex is usually to go out and rewrite the function to accommodate the additional needs. But there is possibly a better approach.

Basically, I am interested in using Liferay as an applications platform and in leveraging existing Liferay functionality. So the problem is, how do we extend the basic Liferay backoffice functions without having to implement a completely new UI component? Liferay has a few solutions for that, namely: extension and hook plugins. Extensions plugin allow you to extend and modify the core Liferay functionnality. It's very powerful but you do not really want to abuse of this approach since it introduces tight couplings and it is somewhat intrusive and more tricky to deploy and update than other types of Liferay plugins.

Hook plugins are a more elegant and easy to manage solution but they do not always allow you to do what you want. After some time playing around with the two techniques it struck me that the solution for what I was trying to accomplish consisted in combining the two approaches: First, use a very simple extension plugin to insert a hookable extension point in your LR system and then implement and deploy the functionality as a hook that exploits the inserted extension point.

As it turns out, this solution works really well and since nobody else has mentioned this before (as far as I can tell), I thought it would be cool to share this solution with the community. I won't get into all the technical details but will outline the procedure I used to achieve this.

Basically, what we want to do is add one or more sub-sections to the Liferay Organization editor. While you can achieve the same result using another toolset, the following assumes you are using the Liferay IDE with Eclipse.

First, create a new Liferay project of type "Ext" (i.e. Extension project) using the LR new project wizard. You should end-up with a new project in your Eclipse workspace containing the base files for an extension plugin. We need to modify the file called [PROJECT_NAME]-ext/docroot/WEB-INF/ext-impl/src/portal-ext.properties. An empty file with that name should have been created by the new project wizard. This file is used to override or add to the base portal.properties. Simply add the following lines to this file:

    #
    # Input a list of sections that will be included as part of the organization
    # form when updating an organization.
    #
    organizations.form.update.main=details,pages,categorization,main-extension

The above is a copy of what you should find in portal.properties. We just added the ",main-extension" term at the end. This tells Liferay to add a sub-section called "main-extension" in the Organization editor after the "categorization" sub-section.

Next, create a file at [PROJECT_NAME]-ext/docroot/WEB-INF/ext-impl/src/content/Language-ext.properties to contain the localized string for the sub-section name. For example:

  main-extension=Extension

Finally, we need to add a default view for this sub-section. Put this view in [PROJECT_NAME]-ext/docroot/WEB-INF/ext-web/docroot/html/portlet/enterprise_admin/organization/main_extension.jsp (note the naming convention, you must replace dashes with underscores). Since, this is just a placeholder view, it only contains the following:

  <%@ include file="/html/portlet/enterprise_admin/init.jsp" %>
  <h3><liferay-ui:message key="main-extension" /></h3>

Finally, run the Ant deploy target on your project and make sure everything is OK. You should restart your Liferay instance after deployment and check that your files are deployed in the ROOT folder of your LR server. For instance, your ROOT context should contain the following file: ROOT/html/portlet/enterprise_admin/organization/main_extension.jsp.

Navigate to your LR control panel and click on an organization in the "Organizations" view to launch the organization editor. In the right panel containing the list of sections and sub-sections, you should see a new sub-section named "Extension" and if you click on this item, you should have a view containing only the "Extension" title.

We now have a hookable extension point so we can proceed with the creation of our hook. If you have a complete business application packaged in a Liferay plugin, you may want to put your hook in this plugin especially if it needs access to your application services. We will just create a new hook plugin using the same approach as for the extension plugin. What we will want to do is hook the Organization service so we can intercept the following method that is called to update an organization:

  com.opnworks.portal.service.ExtOrganizationService.updateOrganization(...) 

We also need to hook the JSP for our extension point to provide our own form/view and finally, we hook the language.properties so we can use our application-specific labels.

I won't get into the details of the implementation but here is the contents of my liferay-hook.xml file:

  <hook>
   <language-properties>content/org-hook-language_en.properties</language-properties>
   <custom-jsp-dir>/custom_jsps</custom-jsp-dir>
   <service>
    <service-type>
   com.liferay.portal.service.OrganizationService
    </service-type>
    <service-impl>
   com.opnworks.portal.service.ExtOrganizationService
    </service-impl>
   </service>
  </hook>

The hook plugin also contains the following service, view and language files:

  • docroot/WEB-INF/src/com/opnworks/portal/service/ExtOrganizationService.java
  • docroot/custom_jsps/html/portlet/enterprise_admin/organization/main_extension.jsp
  • docroot/WEB-INF/src/content/org-hook-language_en.properties

The service class has the following definition:

  public class ExtOrganizationService extends OrganizationServiceWrapper

Et voila, that was easy wasn't it? The hard part is to implement the service and the view. But that is left as an exercise ;-).

Have fun in the Liferay lane...

Laurent

1 commentaires:

Adam Hardy 26 June, 2012 05:44  

Hi Laurent,

very interesting to see someone's efforts with Liferay IDE and the ext and hook plugins, which is something I'm doing at the moment.

Are you still involved in this sort of stuff? I am trying to work out how to solve some big issues that I have in implementing a large set of inter-dependent Liferay plugin projects with the Liferay IDE.

I get error messages that are just not clear at all and I can't find any good docs or help from Liferay - so how did you work this stuff out? Did you really just play with it until it worked? I seem to be standing at a cross-roads where I either manage to get it going and I can finally use Liferay IDE to improve my dev cycle, or I just give up on it and revert to the command line with maven and ant.

Post a Comment

  © Blogger template Webnolia by Ourblogtemplates.com 2009

Back to TOP