Create our own portlet service
Overview
Writing a portlet service consists of four steps:
- Defining the interface
- Write the service implementation
- Making the service accessible for IBM portlets
- Registering the service
The service provider interfaces can be used to write portlet services for IBM portlets as well as for Standard portlets. For backward-compatibility, the service provider interfaces from the org.apache.jetspeed.portlet.service.spi packages are supported. For writing new portlets services, however, use only the service provider interfaces described in this text.
Define the interface
This step is not required to implement the service against an existing interface. Defining a portlet service interface requires the same careful considerations as defining any public API interface. A portlet service interface must extend the PortletService interface defined in the com.ibm.portal.portlet.service package. The following is an example interface for the HelloWorldService .
Figure 1. Extending the PortletService interface
package sample.portletservice; import java.io.IOException; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import com.ibm.portal.portlet.service.PortletService; public interface HelloService extends PortletService { /** print a nice greeting */ public void sayHello(RenderRequest request, RenderResponse response) throws IOException; }
Writing the service implementation
The service implementation must implement the PortletServiceProvider interface of the com.ibm.portal.portlet.service.spi package to be able to make use of the portlet service life cycle methods in addition to the service interface. The PortletServiceConfig parameter of the init() method allows you, for example, to access the configuration of the service (see Registering the service for more information).
Figure 2. Implementing the PortletServiceProvider interface
package sample.portletservice; import java.io.IOException; import java.io.PrintWriter; import java.util.prefs.Preferences; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import com.ibm.portal.portlet.service.spi.PortletServiceProvider; public class HelloServiceImpl implements HelloService, PortletServiceProvider { private String message; // called by the portal when the service is initialized public void init(Preferences servicePreferences) { // read the message from the configuration, default is "Hello" message = servicePreferences.get("message", "Hello"); } public void sayHello(RenderRequest request, RenderResponse response) throws IOException { String user = request.getRemoteUser(); if (user == null) // no user logged in user = "Stranger"; PrintWriter out = response.getWriter(); out.print(message); out.print(", "); out.print(user); } }
Making the service accessible for IBM portlets
This step is optional. If you want the portlet service to be available for IBM portlets, create an additional service interface that extends org.apache.jetspeed.portlet.service.PortletService and provides the same functionality.
Figure 3. Extending the PortletService interface for IBM portlets
package sample.portletservice; import java.io.IOException; import org.apache.jetspeed.portlet.PortletRequest; import org.apache.jetspeed.portlet.PortletResponse; import org.apache.jetspeed.portlet.service.PortletService; public interface HelloServiceIBM extends PortletService { /** print a nice greeting */ public void sayHello(PortletRequest request, PortletResponse response) throws IOException; }We can have a single implementation that is registered for both interfaces and implements both. If the service methods take argumento that are classes or interfaces from the portlet API, the method signatures are different for the two service interfaces. We can still use a common implementation for both interfaces using the APIConverterFactory class of the com.ibm.portal.portlet.apiconvert package. This class includes methods that wrap objects from the IBM portlet API, such as PortletRequest and PortletSession, and implement the corresponding standard portlet API objects on the service side, so that we can re-use the service implementation for standard portlets.
Figure 4. Using the APIConverterFactory class
package sample.portletservice; import java.io.IOException; import java.io.PrintWriter; import java.util.prefs.Preferences; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import org.apache.jetspeed.portlet.PortletRequest; import org.apache.jetspeed.portlet.PortletResponse; import com.ibm.portal.portlet.apiconvert.APIConverterFactory; import com.ibm.portal.portlet.service.spi.PortletServiceProvider; public class HelloServiceImpl2 implements HelloService, HelloServiceIBM, PortletServiceProvider { private String message; // called by the portal when the service is initialized public void init(Preferences servicePreferences) { // read the message from the configuration, default is "Hello" message = servicePreferences.get("message", "Hello"); } public void sayHello(RenderRequest request, RenderResponse response) throws IOException { String user = request.getRemoteUser(); // no user logged in if (user == null) user = "Stranger"; PrintWriter out = response.getWriter(); out.print(message); out.print(", "); out.print(user); } public void sayHello(PortletRequest request, PortletResponse response) throws IOException { sayHello (APIConverterFactory.getInstance().getRenderRequest(request), APIConverterFactory.getInstance().getRenderResponse(response)); } }
Registering the service
- Put all service interface and implementation classes into a JAR file.
- Place the JAR file in the WP_PROFILE/PortalServer/config directory.
- Register the new portlet service with the WP PortletServiceRegistryService resource environment provider in the WAS admin console.
- Create an entry to register the implementation in the JNDI directory. The name for this entry is jndi.service_interface and the value is service_implementation. The fully qualified service interface name can then be used to lookup the service.
- If you provide a service interface for IBM portlets, create an entry to register the implementation for this interface as well. The name for this entry is service_interface and the value is service_implementation. Services that are registered this way are not retrieved from JNDI, but from the PortletContext interface of the IBM portlet API.
- Optional: Provide configuration parameters for the implementation. The name for this entry is service_implementation.parameter and the value is the required parameter value.
- Restart WebSphere Portal to activate the new settings.
In the following example, HelloService is the name of the portlet service, HelloServiceIBM is the name of the interface for IBM portlets, and the message configuration parameter is set with the value Greetings.
The colon (:) used in previous versions of WebSphere Portal to designate JNDI entries with jndi: is not supported for resource environment providers. Use jndi. instead. To register this portlet service, add the following property names and values to the PortletServiceRegistryService:
Property name Value jndi.sample.portletservice.HelloService sample.portletservice.HelloServiceImpl2 sample.portletservice.HelloServiceIBM sample.portletservice.HelloServiceImpl2 sample.portletservice.HelloServiceImpl2.message Greetings To check whether the service has been registered successfully, use the application server dumpNamespace tool. The following command, executed from the PROFILE_ROOT/bin directory, will list all portlet service entries in JNDI:
dumpNamespace -port bootstrap_port -root server -startAt portletserviceUse the WAS admin console, we can find the bootstrap port of the portal server in the "End Points" section of the settings for the server "WebSphere_Portal".
Parent: Portlet services