Introduction to Java Standard Portlets
Portlets are small web applications that run in a portion of a web page. The heart of any portal imIntroduction plementation is its portlets, because portlets are where the functionality of any portal resides. Liferay's core is a portlet container, and this container is only responsible for aggregating the set of portlets that are to appear on any particular page. This means that all of the features and functionality of your portal application must be in its portlets.
Portlet applications, like servlet applications, have become a Java standard which various portal server vendors have implemented. The JSR-168 standard defines the initial portlet specification, while the JSR-286 standard defines the Portlet 2.0 specification. We will refer to these together as Java Standard portlets. A Java Standard portlet should be deployable on any portlet container which complies with the standard. Portlets are placed on the page in a certain order by the end user and are served up dynamically by the portal server. This means that certain "givens" that apply to servlet-based projects, such as control over URLs or access to the HttpServletRequest object, don't apply in portlet projects, because the portal server generates these objects dynamically.
Portal applications come generally in two flavors: 1) portlets can be written to provide small amounts of functionality and then aggregated by the portal server into a larger application, or 2) whole applications can be written to reside in only one or a few portlet windows. The choice is up to those designing the application. The developer only has to worry about what happens inside of the portlet itself; the portal server handles building out the page as it is presented to the user.
Most developers nowadays like to use certain frameworks to develop their applications, because those frameworks provide both functionality and structure to a project. For example, Struts enforces the Model-View-Controller design pattern and provides lots of functionality, such as custom tags and validating functionality, that make it easier for a developer to implement certain standard features. With Liferay, developers are free to use all of the leading frameworks in the JavaEE space, including Struts, Spring, and Java Server Faces. This allows developers familiar with those frameworks to more easily implement portlets, and also facilitates the quick porting of an application using those frameworks over to a portlet implementation.
Additionally, Liferay allows for the consuming of PHP and Ruby applications as "portlets," so you do not need to be a Java developer in order to take advantage of Liferay's built-in features (such as user management, communities, page building and content management). You can use the Plugins SDK to deploy your PHP or Ruby application as a portlet, and it will run seamlessly inside of Liferay. We have plenty of examples of this; to see them, check out the Plugins SDK from Liferay's public Subversion repository.
Creating A Portlet
Creating portlets with the plugins SDK is a straightforward process. As noted before, there is a portlets folder inside of the plugins SDK folder. This is where your portlet projects will reside. To create a new portlet, first decide what its name is going to be. You need both a project name (without spaces) and a display name (which can have spaces). When you have decided on your portlet's name, you are ready to create the project. Enter the following command in the portlets folder:
ant -Dportlet.name=<project name> -Dportlet.display.name="<portlet title>" create
ant -Dtheme.name=hello-world -Dtheme.display.name="Hello World" create
You should get a BUILD SUCCESSFUL message from Ant, and there will now be a new folder inside of the portlets folder in your plugins SDK. This folder is your new portlet project. This is where you will be implementing your own functionality.
Alternatively, if you will not be using the Plugins SDK to house your portlet projects, you can copy your newly created portlet project into your IDE of choice and work with it there. If you do this, you may need to make sure the project references some .jar files from your Liferay installation, or you may get compile errors. Since the ant scripts in the Plugins SDK do this for you automatically, you don't get these errors when working with the Plugins SDK.
To resolve the dependencies for portlet projects, see the class path entries in the build-common.xml file in the Plugins SDK project. You will be able to determine from the plugin.classpath and portal.classpath entries which .jar files are necessary to build your newly created portlet project.
Anatomy of a Portlet
A portlet project is made up at a minimum of three components:
Client-side files (*.jsp, *.css, *.js, graphics, etc.)
These files are stored in a standard directory structure which looks like the following.
The example is a fully deployable portlet which can be deployed to your configured Liferay server by running the deploy ant task.
The default portlet is configured as a standard JSR-168 portlet which uses separate JSPs for its three portlet modes (view, edit, and help). Only the view.jsp is implemented in the example; the code will need to be customized to enable the other modes.
The Java Source is stored in the docroot/WEB-INF/src folder. You can go in and customize (and rename) the portlet class and add any classes necessary to implement your functionality.
The Configuration Files are stored in the docroot/WEB-INF folder. The two standard JSR-168 portlet configuration files, web.xml and portlet.xml are here, as well as three Liferay specific configuration files. The Liferay specific configuration files are completely optional, but are important if your portlets are going to be deployed on a Liferay Portal server.
liferay-display.xml: This file describes for Liferay what category the portlet should appear under in the Add Application window.
liferay-portlet.xml: This file describes some optional Liferay-specific enhancements for JSR-168 portlets that are installed on a Liferay Portal server. For example, you can set whether a portlet is instanceable, which means that you can place more than one instance on a page, and each portlet will have its own data. Please see the DTD for this file for further details, as there are too many settings to list here. The DTD may be found in the definitions folder in the Liferay source code.
liferay-plugin-package.properties: This file describes the plugin to Liferay's hot deployer. One of the things that can be configured in this file is dependency .jars. If a portlet plugin has dependencies on particular .jar files that already come with Liferay, you can specify them in this file and the hot deployer will modify the .war file on deployment so that those .jars are on the class path.
The default portlet project that is created is a simple JSR-168 portlet, with no bells and whistles. You can use this framework to write your code to the JSR-168 portlet API and implement all the functionality that you need. There are many portlets that are implemented this way. The standard portlet API is easy to use and straightforward.
Many developers, however, prefer to use a particular framework when developing web applications. Several frameworks, such as Struts, Spring, or Java Server Faces, make the development of web applications more straightforward and easier to follow than a standard servlet implementation would be. All three of the frameworks mentioned can also be used to create portlets. Liferay has many examples of how these frameworks would be used in our public Subversion repository at SourceForge. You can grab them by checking them out of the repository or by accessing our Official Plugins page at http://www.liferay.com/web/guest/downloads/official_plugins.
A Closer Look at the Default JSP Portlet
If you are new to portlet development, this section will take a closer look at the configuration options of a portlet.
Here is a basic summary of what each of the elements represents:
The portlet-name element contains the canonical name of the portlet. Each portlet name is unique within the portlet application. (This is also referred within Liferay Portal as the portlet id)
The display-name type contains a short name that is intended to be displayed by tools. It is used by display-name elements. The display name need not be unique.
The portlet-class element contains the fully qualified class name of the portlet.
The init-param element contains a name/value pair as an initialization param of the portlet.
Expiration-cache defines expiration-based caching for this portlet. The parameter indicates the time in seconds after which the portlet output expires. -1 indicates that the output never expires.
The supports element contains the supported mime-type. Supports also indicates the portlet modes a portlet supports for a specific content type. All portlets must support the view mode.
Portlet-info defines portlet information.
The security-role-ref element contains the declaration of a security role reference in the code of the web application. Specifically in Liferay, the role-name references which role's can access the portlet. (A Power User can personalize the portal, whereas a User cannot.)
docroot/WEB-INF/liferay-portlet.xml - In addition to the standard portlet.xml options, there are optional Liferay-specific enhancements for Java Standard portlets that are installed on a Liferay Portal server.
Here is a basic summary of what some of the elements represents.
The portlet-name element contains the canonical name of the portlet. This needs to be the same as the portlet-name given in portlet.xml
Path to icon image for this portlet
Indicates if multiple instances of this portlet can appear on the same page.
Tells the portal that all requests with the path ext/library/* are considered part of this portlet's scope. For example, a struts-path of ext/library will give us access to /ext/library/view in struts-config.xml, but not /ext/reports/view.
There are may more elements, so you will probably want to look over the DTD for this file since there are many options you will want to be aware of if you do more advance development. The DTD may be found in the definitions folder in the Liferay source code.