Sun Java System Portal Server 7.2 Developer's Guide

Resource Serving

The resource serving feature enables a portlet to serve a resource. Portlets can create two kinds of resource links to serve requests:

The portlet can create resource URLs pointing back to itself in the following ways:

When an end user invokes such a resource URL the portlet container calls the serveResource() method of the portlet and renders the content returned by the serveResource call.

The serveResource() method can also be used to implement AJAX use cases by invoking the resourceURL() method through the XMLHttpRequest in client-side JavaScript code. The client-side code of the portlet is then responsible for inserting either the markup or update the page DOM in a non-disruptive manner for the other components on the page.

The presentation logic for the resource serving portlet looks as below and shows how to serve portlet fragments by using the serveResource method:


<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
.........
<portlet:defineObjects/>
........
........

<portlet:resourceURL var="jsURL" id="js" escapeXml="false" />

/* Load Dojo library, if it hasn't already */
if (typeof dojo == "undefined") {
   /* build script tag */
   var script = document.createElement("script");
   script.src = "<%=renderResponse.encodeURL(jsURL.toString())%>;
        .........
}
        ......... 
<portlet:resourceURL var="invoiceURL" id="invoice" escapeXml="false" />

<script type="text/javascript">
/* Use Dojo.io.bind to asynchronously get invoice content */
function <portlet:namespace/>_loadInvoice(invoice) {
   /* If an invoice was selected */
   if (invoice != null && invoice != "null") {
        .........
       var bindArgs = {
           url: "<%=renderResponse.encodeURL(invoiceURL.toString())%>",
           method: "POST",
           content: querystring,
           handle: function(type, data, evt) {
               if (type == "error") {
                   /* Swap returned error message */
                   data = "<p style='color:red'>" + data.message + "</p>";

                }

                /* Swap returned data into div tag */
                var div = document.getElementById("<portlet:namespace/>_content");
                div.innerHTML = "";
                div.innerHTML = data;
            },
            mimetype: "text/html"
        };
        dojo.io.bind(bindArgs);
    }

};

The portlet class that serves the resource looks as below:


public class InvoicePortlet extends GenericPortlet {
      .........
      @Override
   public void serveResource(ResourceRequest request, ResourceResponse response) throws PortletException, IOException {
              response.setContentType("text/html");
       String resourceID = request.getResourceID();
       Locale locale = request.getLocale();
              if (resourceID.equals("invoice")) {
           String invoice = request.getParameter("invoice");
           if (invoice == null) {
               throw new PortletException("Required parameter, invoice, is missing.");
           } else {
               String path = "/html/" + invoice + ".html";
               String content = getContents(path, locale, true);
               PrintWriter writer = response.getWriter();
               writer.print(content);
           }
       } else if (resourceID.equals("js")) {
           String content = getContents(jsPage, locale, false);
           PrintWriter writer = response.getWriter();
           writer.print(content);
       }
   }
      .........
}

Sample Application

The following figure shows the Invoice Portlet. When the user selects a invoice number in the drop-down box, an asynchronous request (AJAX call) is made by the JavaScript client to the portlet. The serveResource() method of the portlet is invoked to serve the content.

Figure 16–4 Sample Application for Resource Serving

Sample Application for Resource Serving

Portlet Policy

Portlet Container 2.0 introduces a Portlet Policy that governs policies related to events, container events and public render parameters. The policy specifies how the events, container events, and public render parameters are distributed. It also specifies the maximum generation of events to prevent endless loops. If a portlet sends an event to other portlets, it is considered as one event generation. If the other portlets send events, that is considered as two event generations and so on. It also provides the ability to enable/disable the container events.

The portlet-policy.xml file is located in PortalServer-Data-Directory/portals/portal-id/config. The schema is located at https://portlet-container.dev.java.net/xml/portlet-policy.xsd.

The portlet-policy.xml file looks like this:


<portlet-policy
	xmlns="https://portlet-container.dev.java.net/xml/portlet-policy.xsd"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://portlet-container.dev.java.net/xml/portlet-policy.xsd"
	version="1.0">

<event-policy>
	<event-distribution>VISIBLE_PORTLETS_ON_PAGE</event-distribution>
	<max-event-generation>3</max-event-generation>
</event-policy>

<container-event-policy>
	<event-distribution>ALL_PORTLETS</event-distribution>
	<max-event-generation>2</max-event-generation>
	<event>
		<name>login</name>
		<status>enabled</status>
	</event>
	<event>
		<name>logout</name>
		<status>enabled</status>
	</event>
</container-event-policy>

<public-render-parameter-policy>
	<public-render-parameter-distribution>VISIBLE_PORTLETS_ON_PAGE</public-render-parameter-distribution>
</public-render-parameter-policy>

</portlet-policy>

The above example shows that only visible portlets on the page will receive events and public render parameters. This also specifies that the maximum number of events permitted to be generated is two. This also specifies that the container events, login and logout are enabled. Currently, only login and logout container events are supported.

Any portlet interested in login event should specify the following in its portlet.xml. The processEvent() method of the portlet will be called when the user logs in.


<supported-processing-event>
	<qname xmlns:x="urn:oasis:names:tc:wsrp:v2:types">
		x:login
	</qname>
</supported-processing-event>

Any portlet interested in logout event should specify the following in its portlet.xml. The processEvent() method of the portlet will be called when the user logs out.


<supported-processing-event>
	<qname xmlns:x="urn:oasis:names:tc:wsrp:v2:types">
		x:logout
	</qname>
</supported-processing-event>