The Holy Java

Building the right thing, building it right, fast

Developing portlets for Liferay in Eclipse

Posted by Jakub Holý on April 20, 2009

In this blog I’d like to tell you how to use Eclipse with Liferay to develop portlets with the ability to change a class or a JSP in Eclipse and have that immediatelly reflected on the server (hot deployment).


  • Liferay Portal 5.2.2 running on Tomcat 5.5.27.
  • Eclipse IDE for Java EE Developers, version Ganymede 3.4.1.
  • (optional) Eclipse Maven plugin m2eclipse 0.9.6.

A note about Eclipse and Maven projects

My web project is actually also a Maven project because we use Maven for building our projects. That means that it has a specific directory structure (src/main/webapp, target/classes, etc.) and that it includes a pom.xml that defines its dependencies on other artifacts, usually JAR libraries. Thanks to the m2eclipse plugin, Eclipse is aware of these dependencies and makes them available to the project during development and deployment.

With the m2eclipse plugin you get the nice feature that if your web application project depends on an artifact produced from another Eclipse project then if you change something in this project you depend upon, Eclipse detect it and pushes the change to the web application deployed on a server.

Normally with maven alone you would need to run mvn install or mvn package on the library project and either copy the produced .jar manually to the deployed webapp’s WEB-INF/lib or do a full rebuild (mvn package) and redeploy of the web app.

Preparing the portlet project for hot deployment to Liferay

Normally you deploy a WAR with portlets by putting them in the Liferay’s hot deploy directory (<liferay>/deploy). It notices that, processes the WAR, and deploys it to Tomcat. However since Eclipse knows nothing about Liferay and can only deploy to Tomcat itself in the normal way, that means by copying the exploded WAR to <liferay>/tomcat-5.5.27/webapps/, we need to do the Liferay’s modifications by ourselves and also modify the way that Eclipse does the deployment. Liferay does monitor Tomcat’s webapps/ directory and will detect a change to an application and redeploy it however this deployment doesn’t include all the operations that are performed when deploying via its hot deploy directory.

Configuring Eclipse

1. Define a Server Runtime Environment for Liferay

  1. Window > Preferences > Server > Runtime Environments > Add… .
  2. Select Apache Tomcat 5.5.
  3. For the Tomcat installation directory browse to or type <liferay>/tomcat-5.5.27 (replace <liferay> with you liferay installation directory, of course).
  4. Name it e.g. “Liferay 5.2.2@Tomcat 5.5.27”.

2. Define a Server instance for Liferay

  1. Window > Show View > Other… > Server > Servers.
  2. Right-click somewhere in the view Servers > New > Server:
    • Server type Tomcat v5.5 Server.
    • Server runtime environment: select the one defined in the previous step (Liferay 5.2.2@Tomcat 5.5.27).

3. Adjust the server’s configuration

In the view Servers, double-click on the newly created server, which will open its configuration. Do the following modifications:

  • In Server Locations change “Use workspace metadata” to “Use Tomcat installation”.
    • Notice: If you have any projects deployed to the server, this section is greyed-out and cannot be edited. Remove all projects from the server, publish, perhaps restart and you should be able to modify this settings.
  • In Server Locations change Deploy path from wtpwebapps to webapps. (Maybe this isn’t necessary but I wanted to be sure I won’t create any troubles for the Liferay’s monitoring.)
  • In Timeouts perhaps increase the Start timeout to some period long enough, e.g. 300 s. (My Liferay usually starts in ~ 70s but once it took over 200 s.)
  • During server startup, if you get

    Exception in thread “main” java.lang.OutOfMemoryError: PermGen space

    then click Open launch configuration in the server’s configuration and add something like -XX:MaxPermSize=128m to Arguments > VM arguments.

Now you should be able to run the server, deploy your portlet webapp to it (view Servers > right-clik the server > Add and Remove Projects …) and see your portlets in the Liferay portal (login, Add application > find it under the category you’ve defined in your liferay-display.xml > add it to a page).

When you deployed the application to the server, you should have been able to see in the log (i.e. in the Eclipse’s Console view) that Liferay has detected it and deployed the portlets. There should be a line like

INFO [PortletHotDeployListener:303] 1 portlets for <your webapp’s name> are available for use

telling you that your portlet is deployed and ready to use.

Adjusting the portlet project

When you add you portlet to a portal page, you will be most likely surprised to see there
The requested resource (/example-portlet/MyPortlet/invoke) is not available.
instead of the expected portlet content. (Of course it will differ if your project/webapp context root isn’t example-portlet and the portlet’s name isn’t MyPortlet.)

Google won’t reveal any solution but I’ll will🙂. Try to deploy the application first from Eclipse (which you’ve just done) and then in the regular way by exporting it as a WAR file from Eclipse and putting it into <liferay>/deploy/ and waiting for Liferay to pick it up and deploy it to Tomcat. Then compare the two resulting directories from Tomcat’s webapps/ folder. Thus you will learn what you will need to modify. Or simply keep on reading🙂.

Adjust web.xml

Liferay needs to have a servlet defined for each portlet. The error above (The requested resource (/example-portlet/MyPortlet/invoke) is not available.) indicates that a servlet MyPortlet is missing. So we will add it together with the proper servlet mapping:

web.xml modification:

            <param-value>eu.ibacz.example.MyPortlet</param-value> <!--replace with your portlet class -->

Add portlet TLD

We will likely (though I’m not 100% sure about this) need to replicate yet another change done by Liferay and that is adding it’s TLD for portlet 2.0 and a link for it to web.xml. Liferay adds taglibs also for all its other taglibs but I suppose you don’t need them. (I suppose you develop a JSR 286 portlet but you could do the same for a JSR 168 portlet by using its specific uri and tld file.)

1. Copy liferay-portlet.tld to WEB-INF/tld/liferay-portlet.tld. Get it from the Liferay-deployed WAR or find in somewhere under <liferay>.

2. Add a taglib declaration to web.xml:


Adding Liferay libs

You will likely need to add at least the Liferay library
to your projet’s WEB-INF/lib. If you ommit that you may, when accessing the portlet, get for example one of the following errors:

 javax.portlet.PortletException: javax.servlet.ServletException: java.lang.NoClassDefFoundError: com/liferay/taglib/portlet/DefineObjectsTag
JasperException: Impossible de charger ou d'instancier la classe TagExtraInfo: com.liferay.taglib.portlet.ActionURLTei

That’s all, folks!

That’s all! Your portlet should work now (tough Eclipse may require Tomcat restart for that). Enjoy!

About the portlet project

Selected files of the project’s WAR:

  • WEB-INF/
    • lib/
      • util-taglib.jar
    • tld/
      • liferay-portlet.tld
    • classes/
      • eu.ibacz.example.MyPortlet.class
    • liferay-display.xml
    • liferay-portlet.xml
    • portlet.xml
    • web.xml
  • myPortlet_view.jsp


package eu.ibacz.example;

import javax.portlet.*;

public class MyPortlet extends GenericPortlet {
	protected void doView(RenderRequest request, RenderResponse response)
			throws PortletException, IOException {		

		PortletRequestDispatcher dispatcher = getPortletConfig().getPortletContext().getRequestDispatcher(
		if (dispatcher != null) {
			//dispatcher.forward(request, response); // this displays an empty page instead of the JSP?!
			dispatcher.include(request, response);	// this works
		} else {
			throw new IllegalStateException("Failed to get a PortletRequestDispatcher, can't forward to the JSP");


<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE display PUBLIC "-//Liferay//DTD Display 5.2.0//EN" "">
  <category name="My Experiments">
    <portlet id="MyPortlet">My Test Portlet</portlet>
</display> (I suppose this actually isn’t need or could be empty):



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 5.2.0//EN" "">
        <role-link>Power User</role-link>


<?xml version='1.0' encoding='UTF-8' ?>
<portlet-app xmlns='' xmlns:xsi='' xsi:schemaLocation='' version='2.0'>    


<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_ID" version="2.4" xmlns="" xmlns:xsi="" xsi:schemaLocation="">
    <display-name>My Test Portlet Webapp</display-name>





<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%>

<h1>MyPortlet is alive!</h1>

Known issues

Omission of .properties during deploy

Sometimes Eclipse omits to copy .properties files to the server. I don’t know whether it’s Eclipse problem or my Eclipse Maven plugin problem. I don’t know why because .settings/org.eclipse.wst.common.component does contain <wb-resource deploy-path=”/WEB-INF/classes” source-path=”/src/main/resources”/>. I’ve open the bug report MECLIPSE-556 regarding this.

Enforcing a particular JDK version

If you use the maven enforcer plugin to enforce a particular version of Java, like this:


then you may have troubles building your Maven project with Eclipse if running Eclipse under another JVM version. For example my default system JVM used also for Eclipse is 1.6 but for a particular project I need 1.5. When you try to build the project, it will fail with

Build errors for jpivot-portlet-liferay-classes; org.apache.maven.lifecycle.LifecycleExecutionException:
 Internal error in the plugin manager executing goal 'org.apache.maven.plugins:maven-enforcer-plugin:1.0-beta-1:enforce':
 Mojo execution failed.

I’ve tried the following to force Maven to use JVM 1.5 for building the project:

  1. Set the JRE System Library in Project – Properties – Java Build Path – Libraries.
  2. Set the Eclipse’s command line option -vm to point to the desired JVM in eclipse.ini:
    -vm /usr/lib/jvm/java-1.5.0-sun
  3. Set JAVA_HOME to point to the desired JVM prior to starting Eclipse:
    bash$ export JAVA_HOME="/usr/lib/jvm/java-1.5.0-sun/jre"bash$ ./eclipse
  4. Setting PATH to point to 1.5 JVM prior to startin Eclipse:
    bash$ export PATH="/usr/lib/jvm/java-1.5.0-sun/bin:$PATH"bash$ ./eclipse

Of those only nr. 4, setting the PATH, had the desired effect of running Eclipse and thus also the Maven build under the required JVM 1.5. The conclusion is that you must run Eclipse using the same JVM you want to use for Maven builds.

There is the bug report MNGECLIPSE-1091 regarding this problem with many votes but no resolution or workaround.

Why not to use m2eclipse

A nice post (6/2009) lists some reasons why not to use m2eclipse for Maven-Eclipse integration:

  1. No real support for separate output folder.
  2. It uses the Maven Embedder, which is not Maven but more of an experiment.
  3. It wants to use the JDK associated with the JRE that launched Eclipse.

According to Brian Fox, the upcoming M2e 0.9.9 should address this issues.

Another reader , Benedikt, recommends solutions:

  1. Of course you can change the output-folder by modifying your pom.xml to have separate output-folders for your class-files.
  2. You can tell the plugin which maven installation it should use and it doesn’t break anything if you do so.
  3. If you don’t use the internal maven builder then maven will use the JRE configured under “Installed JREs”.

So maybe its usable after all? Or you may also give try to Eclipse IAM (former Q4E), the new Maven-Eclipse integration, currently v. 0.1.0. It seems to be yet no as mature as m2eclipse, see a comparison.

Additional notes

You may want to follow the instructions on Liferay site and use Liferay in a development mode by using special that prevent some caching etc. (Add -Dexternal-properties=$CATALINA_BASE/webapps/ROOT/WEB-INF/classes/ to <liferay>/tomcat-5.5.27/bin/

You may also want to try to install JBoss Tools into your Eclipse and use its Servers view, which also supports Tomcat and may be better than the standard one.

Another interesting SW – Eclipse Portal Pack for developing JSR168 and JSR286 portlets with Eclipse, currently v2.0M1.

An alternative: the Liferay way

The upcoming book Liferay in Action by R. Sezov describes how to set up portlet development environment for Liferay 6 using either Eclipse or NetBeans in its chapter two. He recommands to create and deploy a portlet using the Ant-based Liferay Plugins SDK and use an IDE only to import and develop the portlet while invoking ant deploy for the deployment. I don’t know wheter that supports hot deployment of only changed files (provided that it matters at all) and of course it has a completely different structer than Maven assumes, complicating if not rendering it impossible to use Maven.

15 Responses to “Developing portlets for Liferay in Eclipse”

  1. Johan said

    Excellent post! It really helped me a lot.

  2. Anonymous said

    it is not working plz explain agin. step by step with screen shot.

  3. Jakub Holý said

    Dear, I’d gladly help you but you’d need to provide more information on your particular problems. It would be surely nice to provide a step-by-step guide with screenshots but unfortunately I haven’t the time to do that. But I can try to help with concrete problems.

    Best Regards

  4. Mladen said

    Hello Jakub,
    I’ve applied all steps but still receive the same error
    The requested resource (/example-portlet/MyPortlet/invoke) is not available
    I’m using Lifery bundled with JBoss 5 + Tomcat.
    Do you know wheather I should apply anithing else if I’m using JBoss? May I ask you to attach the example project you described? I’ll try to directly deploy it and see what the differences are.
    Kind regards,

  5. Jakub Holy said

    To Mladen:

    I’m quite sure that Liferay on top of JBoss will need different set-up from Liferay deployed on a standalone Tomcat. Try to deploy your WAR not via Eclipse but manually in the way recommended for Liferay on JBoss and compare the resulting deployed application (which gets modified by Liferay during the deployment) with that what you deploy. It may be also good idea to try to get this working with the recommended setup, i.e. Liferay on pure Tomcat, to find out whether it’s Jboss who’s causing troubles or whether there is something else wrong.

    I’ve unfortunately already deleted the project😦

    Good luck.

  6. Jean-Marie Hermelin said

    Hi Jakub,

    Great tutorial, really helps me !

    However I’ve still a concern with hot deployment : deploying war file to liferay/deploy works well, but auto deploy to liferay/tomcat/webapps does nothing (I mean not even an info in console) ! Any ideas ?

  7. Jean-Marie Hermelin said

    Found by myself !

    Just deploy war, then have a look to the deployed WEB-INF directory (in tomcat\webapps\MyPortlet dir), and copy all missing files back to my sources.

    Bravo !

  8. glowi said

    Hi Jakub
    I have the deploy problem as well.
    Auto deploy to liferay/tomcat/webapps does nothing.
    I tried to deploy war first and compare diferences, the missing file was liferay-plugin-package.xml.
    If I add the file and edit the name and module-id tags, the portlet is found, but an Exception is thrown.
    I think the module-id value is generated during deployment from war file name and stored in DB.
    Custom value is not found and thus I get an exception.

  9. GLOWi said

    Ok, for other people that can encounter the problem I described in the previous post, here’s my solution (LFR 5.2.3):
    1) I downloaded LFR plugin SDK
    2) I set up the ant build file in the SDK accoding to my system (see SDK docs)
    3) I compiled and deployed the war file of the example portlet bundled in the SDK with Ant (You may rename the war file to have more meaningful module-id) to LFR deploy dir.
    4) I started LFR, which installed the portlet.
    5) I stopped LFR, deleted all files except for config LFR xml files. I put my portlet files into the portlet dir and modified the config xml files accordingly.
    (You have to keep module-id in liferay-plugin-package.xml otherwise you get and exception).
    You can delete all files and put inside the portlet directory your files, only remember to keep module-id in the liferay-plugin-package.xml.

  10. Jakub Holy said

    Thanks, Glowi!

  11. Robert said

    Thanks for your post, it helped me in telling me I have to add the liferay-portlet.tld to my web.xml

  12. Thorsten said

    Hi, I followed your instructions regarding util-taglib.jar, but the ant process removes all files, which are already present in the classpath (ant-target clean-portal-dependencies). So I keep stuck with “Failed to load or instantiate TagExtraInfo class: com.liferay.taglib.portlet.ActionURLTei” and the resulting cast error “java.lang.ClassCastException: com.liferay.taglib.portlet.ActionURLTei cannot be cast to javax.servlet.jsp.tagext.TagExtraInfo”

    Do you have any hint for me? I’m not sure if this is a problem with the tld-files or in the classpath.

  13. Thorsten said

    In all my tries to keep this file: It’s auto-copied by the ant task. So my problems moves from “Why is this class not found in the liferay classloader” to “Why is this class not found in the portlet classloader”😦

  14. Thorsten said

    Problem resolved. I had the “display.jar” included, which seems to make trouble. If you’re going to use the display taglib, make sure you download the *-bin.jar, not the “display.jar”. Something’s wrong with it.

    I have really no idea, how a simple and very small file can cause that much trouble.

    Sorry for the triple post, editing would be a nice feature😉

  15. Jakub Holy said

    @Thorsten: I’m glad you resolved your issue. And editing would indeed be a nice feature but I’m stuck with what JRoller provides😦

Sorry, the comment form is closed at this time.

%d bloggers like this: