Portal, Express Beta Version 6.1
Operating systems: i5/OS, Linux,Windows |
Before you begin developing portlets, you should setup an environment that makes the tasks of writing, compiling, and testing portlets easier. Rational Application Developer includes a test environment that you can use to run and debug your portlets without having to manually deploy them to the server. You can setup the runtime environment for debugging portlets on the local development machine or on a remote server. Refer to the documentation for Rational Application Developer for complete setup instructions.
Rational Application Developer provides wizards to help you build, test, and deploy portlets using all of the APIs and related classes and interfaces available in the portlet runtime environment. You can also build portlets using your own development environment and tools. If you are not using wizards to develop portlets, the following topics describe the mechanics of building a simple portlet.
package com.ibm.wps.samples.jsr; import javax.portlet.*; import java.io.*; public class HelloWorld extends GenericPortlet { public void init (PortletConfig portletConfig) throws UnavailableException, PortletException { super.init(portletConfig); } public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { // set return content type response.setContentType("text/html"); PrintWriter writer = response.getWriter(); writer.println("<p class='wpsPortletText'>Hello Portal World!</p>"); } }
If you are familiar with writing to the IBM portlet API, here are some of the key differences between this standard API example and the corresponding Figure 6.
API element | IBM portlet API | Java Portlet Specification |
---|---|---|
import statements | org.apache.jetspeed.portlet | javax.portlet |
Portlet class | PortletAdapter | GenericPortlet which also can throw a PortletException |
Request object | PortletRequest | RenderRequest |
Response object | PortletResponse | RenderResponse |
Also notice that the content type must be set in the response.
Jar file | Purpose |
---|---|
wp.pe.api.standard.jar | Java Portlet Specification |
wp.portletservices.api.standard.jar | Portlet services |
Jar file | Purpose |
---|---|
wp.pe.api.legacy.jar | IBM portlet API |
wp.portletservices.api.legacy.jar | Portlet services |
wp.pe.rt.api.jar | Portlet menus |
javac -classpath %CLASSPATH% com.ibm.wps.samples.jsr.HelloWorld.java
javac -classpath %CLASSPATH% com.ibm.wps.samples.v4.HelloWorld.java
WebSphere Portal Express classloading follows the WebSphere Application Server hierarchy for classpaths and search orders. A particular classloader can reference other classes as long as the other classes can be loaded by the same classloader or any of its ancestors, but not its children. The graphic illustrates where WebSphere Portal Express and portlet applications fit into the classloading hierarchy.
As illustrated, WebSphere Portal Express is an application extension (AEX) under WebSphere Application Server. Consequently, the WebSphere Portal Express core classes are in the classpath portal_server_root/shared/app. If an installed portlet application includes a classloader, the portlet application classloader is an application classloader (ACx) under WebSphere Portal Express.
If you suspect a classloading problem, ensure that the required classes are in the appropriate classpath according to the classloading hierarchy.
Next, the portlet must be packaged in the JAR file format. To create a JAR file with the name HelloWorld.jar, enter the following command:
jar -cf HelloWorld.jar HelloWorld.class
Refer to the JDK documentation for more information about the JAR command.
The following samples can be packaged with the Hello World portlet.
describes the portlet application.
indicates the portlet application name.
indicates the portlet application security role mapping. Omit this tag if the portlet does not use this feature.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app id="WebApp"> <display-name>Hello World (JSR)</display-name> <description>Basic JSR 168 portlet</description> </web-app>
If you are familiar with the web.xml for IBM portlets, the key difference between this example and the corresponding Figure 7 is the required <servlet/> element in the web.xml for IBM portlets.
<?xml version="1.0" encoding="UTF-8"?> <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"> <portlet> <portlet-name>HelloWorld portlet name</portlet-name> <display-name>Hello World portlet (JSR)</display-name> <display-name xml:lang="en">Hello World portlet (JSR)</display-name> <portlet-class>com.ibm.wps.samples.jsr.jsrHelloWorld</portlet-class> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <supported-locale>en</supported-locale> <portlet-info> <title>Hello World (JSR)</title> </portlet-info> </portlet> </portlet-app>
There are number of differences between the elements in this example and the corresponding Figure 8. In addition, the standard portlet descriptor is defined by an XML schema and does not require a DTD.
Before you package your portlet, the class files and resources must be arranged in the WAR file directory structure described here. A portlet application exists as a structured hierarchy of directories.
Note: Do not package the portlet_1.1.dtd or the portlet.tld with the portlet application WAR file.The portlet information directory is not part of the public document tree of the application. Files that reside in /WEB-INF are not served directly to a client.
To deploy a portlet and run it on the server, it must be packaged in the form of a Web application ARchive or WAR file. The WAR file format contains the Java classes and resources that make up one or more portlets in a portlet application. The resources can be images, JSP files, Writing the portlet descriptors, and property files containing translated message text. Packaging portlet classes, resources, and descriptive information in a single file makes distribution and deployment of portlets easier.
WebSphere Portal Express includes an administrative portlet for installing, uninstalling, and updating portlets. Portlets contained in WAR files have the advantage of being dynamically downloaded and installed. The portal administrator can download a WAR file from the Internet and then use the portal administration interface to install the portlet to WebSphere Portal Express. After installation, the portlet is ready for use and does not require the server to be restarted. To package your portlet in a WAR file, you can use the JAR utility to package the portlet into a WAR file.
Note: Because Windows limits the maximum path length to 260 characters, the name of the WAR file must be less than 25 characters. On a portal server running on Windows, installing a WAR file with a name that is more than 25 characters will result in an error.Any JAR utility may be used to build a WAR file. Below are examples of how to use the JAR utility provided by WebSphere Application Server.
jar -cf HelloWorld.war images WEB-INF
jar -uf HelloWorld.war WEB-INF/portlet.xml
jar -xf HelloWorld.war WEB-INF/portlet.xml
jar -xf HelloWorld.war
After the WAR file is created, it can be installed to WebSphere Portal Express as described in Portal administration portlets.
To facilitate deployment of portlet applications and complex portlets, you can provide a portlet configuration file that can be invoked by the XML configuration interface (XMLAccess). The XML configuration interface allows the portlet developer to specify places, pages, themes, skins, supported markups and clients, and other settings for a portlet application. This is especially useful for portlets that use messaging because these portlets have to be placed on the same page. For more information, see The XML configuration interface. There is also some helpful information about XMLAccess in the IBM WebSphere Portal Zone.
When constructing XMLAccess scripts for use in installing standard portlets, use the following values:Use the uid attribute of the <portlet-app/> subelement with a .webmod suffix. As described subsequently in this topic, the uid attribute of the <portlet-app/> subelement is dependent on the presence of the id attribute of the <portlet-app/> element from the portlet.xml.
Use the id attribute of the <portlet-app/> element from the portlet.xml. If this value has not been specified, specify the WAR file name of the portlet application in its place. For portlet updates, the WAR file name must be the original name of the WAR file used to install the portlet application. That is, the WAR file name can be changed, but the uid must indicate the original uid used during portlet installation.
Use the content of the <portlet-name/> element from the portlet.xml.
Use the content of the <portlet-name/> element from the portlet.xml appended with the .servlet suffix.
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation= "http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"> <portlet> <portlet-name>External Bookmarks</portlet-name> ...
In this example, there is no id attribute provided on the <portlet-app/> element. Therefore, the <portlet-app/> element of the XMLAccess script would use the WAR file name, as follows:
Figure 5. Example <web-app/> element in XMLAccess<web-app action="update" active="true" uid="bookmarks.war.webmod"> <url>file:///$server_root$/installableApps/bookmarks.war</url> <servlet action="update" active="true" referenceid="External Bookmarks.servlet"/> <portlet-app action="update" active="true" uid="bookmarks.war"> <portlet action="update" active="true" name="External Bookmarks"> </portlet-app> </web-app>
package com.ibm.wps.samples.v4; import org.apache.jetspeed.portlet.*; import java.io.*; public class HelloWorld extends PortletAdapter { public void init (PortletConfig portletConfig) throws UnavailableException { super.init(portletConfig); } public void doView(PortletRequest request, PortletResponse response) throws PortletException, IOException { PrintWriter writer = response.getWriter(); writer.println("<p class='wpsPortletText'>Hello Portal World!</p>"); } }Figure 7. Example: Web application deployment descriptor (IBM)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app id="WebApp"> <display-name>HelloWorld</display-name> <servlet id="com.ibm.wps.samples.HelloWorld.a0ae41f2d3c1001710b7b313e1a97"> <servlet-name>HelloWorld</servlet-name> <servlet-class>com.ibm.wps.samples.v4.HelloWorld</servlet-class> </servlet> <servlet-mapping id="ServletMapping_com.ibm.wps.samples.HelloWorld.a0ae41f2d3c1001710b7b313e1a97"> <servlet-name>HelloWorld</servlet-name> <url-pattern>/HelloWorld/*</url-pattern> </servlet-mapping> </web-app>
As described in Deployment descriptors, the href attribute of the <portlet/> element references the servlet ID from Web deployment descriptor.
Note: The portlet deployment descriptor references the portlet_1.1.dtd, which portal server finds in the was_profile_root/installedApps/hostname/wps.ear/wps.war/dtd directory. Do not package the DTD with the portlet application WAR file. Figure 8. Example: Portlet deployment descriptor (IBM)<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN" "portlet_1.1.dtd"> <portlet-app-def> <portlet-app uid="com.ibm.wps.samples.HelloWorld.a0ae41f2d3c1001710b7b313e1a97" major-version="1" minor-version="0"> <portlet-app-name>HelloWorld application</portlet-app-name> <portlet id="com.ibm.wps.samples.HelloWorld" href="WEB-INF/web.xml#com.ibm.wps.samples.HelloWorld.a0ae41f2d3c1001710b7b313e1a97" major-version="1" minor-version="0"> <portlet-name>HelloWorld portlet</portlet-name> <cache> <expires>0</expires> <shared>NO</shared> </cache> <allows> <maximized/> <minimized/> </allows> <supports> <markup name="html"> <view/> </markup> </supports> </portlet> </portlet-app> <concrete-portlet-app uid="com.ibm.wps.samples.HelloWorld.313e1a97f47.2"> <portlet-app-name>HelloWorld application</portlet-app-name> <concrete-portlet href="#com.ibm.wps.samples.HelloWorld"> <portlet-name>HelloWorld portlet</portlet-name> <default-locale>en</default-locale> <language locale="en"> <title>HelloWorld portlet</title> <title-short></title-short> <description></description> <keywords></keywords> </language> </concrete-portlet> </concrete-portlet-app> </portlet-app-def>