Recently the JSR 286 draft was available for public review which can be downloaded from this link. It includes some of the major features which were missed in the JSR 168 spec. You can visit Deepak’s blog to get a list of all those major changes. One of the major feature introduced in this new Portlet specification is “Resource Serving“ . In this blog I will explain this feature in detail.
In one line “The resource serving feature provides the ability for a portlet to serve a resource”.
Why it is needed ?
Direct links to the resources in the same portlet web application are not guaranteed to pass through the portal server and will not have portlet context available. So direct link should be used for the use case where access to the portlet context and access through portal server is not needed.
But the resource url link points back to the portlet. A new interface “ResourceServingPortlet” is introduced in the JSR 286 spec. Via these resource url links serveResource method of ResourceServingPortlet interface is called and portlet can serve the resource which may be protected by the portal security and can leverage portlet context. Portlet container does not render any output in addition to the content returned by the serveResource call. Thus this new life cycle method serveResource() provides more
control to the portlet developer by giving access to write directly on the response object where portal server just acts as a proxy.
The serveResource call can also be used to implement AJAX use cases by invoking resourceURL through XMLHttpRequest in client side javascript. The client side code of the portlet is then responsible for inserting either the markup or otherwise update the page DOM in a non disruptive manner for the other components on the page.
How to Create a Resource URL ?
A resource url can be generated by invoking createResourceURL() method of the RenderResponse object in render phase of the portlet or doView() method of the Generic Portlet.
The resouce url can also be created inside serveResource() method of the ResourceServingPortlet. In that case portlet developers need to call createResourceURL() method on ResouceResponse object passed to the serveResource() method.
In the following code snippet we will create a resource url inside the doView() and then we will set that url as a IMG source in the rendered output.
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
response.setContentType(“text/html”);
PrintWriter writer = response.getWriter();
ResourceURL resURL = response.createResourceURL();
resURL.setResourceID(“image”);
writer.println(“<IMG src=”" + resURL+ “” >”);
//Render other markups
}
So when the browser loads the portal page to show the view mode of the portlet, it automatically sends the request for the resURL which goes through portal and finally serveResouce() of GenericPortlet is called to serve the resource (in this case “image”).
The serveResource() for this example should look like below
public void serveResource(ResourceRequest resRequest, ResourceResponse resResp) throws PortletException, IOException {
resResp.setContentType(“image/png”);
byte[] b = getImage(“MyImage.PNG”); //Returns image bytes
resResp.getPortletOutputStream().write(b);
}
I have taken the above image example to explain the usefulness of this new feature properly. But you may also want to create a link for a resource url in your doView() and then on clicking on that link, serverResource() will be called which will only show the output returned from the serveResource().
You can also set a resource id of the resourceURL to enable same serveResource() serving multiple resources. You can also create new resource urls inside serveResource().
The cache level of a resource url can be set through setCacheability() of ResourceURL class though there are certain restrictions in setting cache level. Possible values are: FULL, PORTLET
or PAGE
. This helps for Caching of Resouces. To know more about caching in JSR 286 check Karthik’s blog.
You can check out the sources of OpenPortal Portlet Container which has the implementation for serve resource feature of JSR 286. Try it out.