Sunteți pe pagina 1din 18

An Introduction to Portal and Portlets

With the great invention of internet, a new era of software called web or website had
begun. As the time passed, web technologies grew up from just simple static HTML to
very powerful web technologies and frameworks like JSP, Servlets, DHTML, XML, CSS,
Javascript , AJAX, Spring, Struts, Flash, Dreamweaver etc to provide extremely rich web
applications having stunning look and feel, awesome GUI features, great level of user
interactivity, graphics and animation based presentation etc.

The revolution didnt stop and continued to take the web technologies a step further
which introduced a new term called Web Portal or simply Portal. In todays world we
keep on hearing worlds like Portals, Portlets almost every day. Surely, the questions
arise in our mind: What is this portal? What is portlet? Howz it different from a regular
web application?

I will try to explain all these terms in context of Java/J2EE.

Lets being with What is a Portal ?

A portal is a web based application that commonly- provides personalization, single
sign on, content aggregation from different sources and hosts the presentation layer of
Information Systems.

Aggregation means integrating information(content) from various different sources (by
sources, it means web applications) in a single web page.

A portal may also have sophisticated personalization features to provide customized
content to users. Portal pages may have different set of portlets creating content for
different users.

What is a Portlet?

A portlet is a Java technology based web component, managed by a portlet
container. They are pluggable user interface components which works very similar to
web applications (i.e. processes requests and generates dynamic content) and make up
the presentation layer of entire Portal.

The content generated by a portlet is also called a fragment. A fragment is a piece of
markup (e.g. HTML, XHTML, WML) which is aggregated by portal with fragments
generated by other portlets to form a complete portal page which is then presented to
end user. The lifecycle of a portlet is managed by the portlet container.

Web clients interact with portlets via a request/response implemented by the portal.
Normally, users interact with content produced by portlets, for example by following
links or submitting forms, resulting in portlet actions being received by the portal, which
are forwarded by it to the portlets targeted by the user's interactions.

The content generated by a portlet may vary from one user to another depending on
the user configuration for the portlet.


Huh !!! Too much of techi-talk right? Alright, let me try to explain it with simple
example.

I believe, most of all have used i-Google(http://www.google.com/ig). Now thats perfect
example of a Portal.

Following figure shows whats explained above:




Here entire application i-Google can be seen as a Portal and each individual application
(Gmail, Todays Horoscope, Google Translate etc) running on the page (which you see
in above figure) can be seen as individual Portlets.

Here if we see, i-Google provides all the features described in the Portal definition
earlier. For example,

1. Content Aggregation It aggregates content from individual portlet application
and shows it as a single web page which you see in previous figure.

2. Single Sign-On Once you log-in to i-Google. Thats it. You dont need to log-in
again to any portlet application which uses the same authentication platform. For
example, Gmail as shown in previous figure.

3. Personalization Each user can change the look and feel, color scheme etc
according to his own choice by changing the theme.

Good enough ! From so many techie definitions and example, now we can conclude
that a Portal application is made-up of three main building blocks:
Portal
Portlets
Portlet Container

We already saw what is Portal and Portlets. But what is Portlet Container? Well here
it is:

As we understood that a portlet is nothing but another type of java technology based
web component, we definitely need a container where it can be hosted and run similar
to web containers where we host the normal web applications (war files).

A portlet container runs portlets and provides them with the required runtime
environment. A portlet container contains portlets and manages their lifecycle. It also
provides persistent storage for portlet preferences. A portlet container receives
requests from the portal to execute requests on the portlets hosted by it.
A portlet container is not responsible for aggregating the content produced by the
portlets. It is the portal who takes care of it.

A portal and a portlet container can be built together as a single component of an
application suite or as two separate components of a portal application.

Putting it all together, following figure gives a high level view of what a portal
application consists of and how a request is processed.



Here if you see, HTTPRequest from the client is further divided into two sub categories:
Render Request and Action Request. (I will explain these with more details in my future
blogs on Portlets. Keep reading my blogs :-) )


Portlets - Relationship With J2EE and Servlet Specification
In my previous post - An Introduction to Portal and Portlets we had an overall idea
about Portal and Portlets and got answer to many common questions like - What is
Portal ? What is Portlet ? What is Portal Container ? What are the features provided by
Portal applications ? etc.

In this post, I will try to explain What is Portlet Specification ? What is
relationship between Portlet API and J2EE specification ? What is similarities
and differences between Portlet API and Servlet Specification ?

Let's start with What is Portlet Specification?

Portlet Specification, or Java Portlet Specification is a specification provided by JCP
(Java Community Process) which defines Portlet API and standardizes rules for various
components of Portlet API (like portlet preferences, user data, portlet request and
response, deployment, packaging, security etc) to achieve interoperability among
various portlets and portals.

The first version of Portlet Specification (JSR-168) was released in October, 2003.
In February 2006, the second enhanced version of Portlet Sepecification (JSR-286).

(To learn about differences between JSR-168 and JSR-286, keep following my future
posts :-) )


Well, we all know that for Web Applications, a specification is already there named:
J2EE (Java 2 Enterprise Edition) specification. Then why we need a separate
specification for Portlets.

The answer lies in similarities and differences between Portal application (or Portlets)
and Web Applications (or Servlets).

Just have a look at following pictorial comparison between a J2EE Web Application and a
Portal Application.
Web Application vs Portal Application
Don't both of them look and work in almost same manner? For example, a web
application can contain multiple servlets and a portal application can contain multiple
portlet applications. Servlets process incoming requets and generates output (HTML),
same way, portlets also process incoming requests and generates markup fragments (a
part of entire output).

Yet, there are some subtle differences. For example, incoming requests in case of
portlets are further divided into two categories: ActionRequests and RenderRequests
(Keep following my future posts for more details about Request Types in Portlets),
portal does content aggregations from different portlets before sending output back to
the client. Each portlet can have their own preferences (called portlet prefrences),
portal provides personalization and other features which a general web application
doesn't do.

From above, what we can say is that portal applications are sophisticated version of
web applications with all the features a web application provides along with some
specialized features like content aggregation, personalization, single sign-on
etc. Similarly, portlets are also analogous to servlets in terms of functionality, concepts
and behavior.

Due to all these reasons, Portlet Specificaiton (or Portlet API V1.0) is based on J2EE
V1.3 specification. Portlets and Portlet Containers meet all the requreiments specified
in J2EE specification. Poerlet API V1.0 derives many functional and behavioral
specifications from Servlet Specificaton 2.3.

Similarly, Portlet API 2.0 is based on J2EE V1.4 and Servlet Specification 2.4.

Following table provides comparision between Portlet and Servlets from various angle:

Servlets Portlets
Servlets are Java technology
based web components which are
managed by Servlet Container or
Servlet Engine
Servlets are Java technology
based web components which are
managed by specialized
containers called Portlet Container
Servlets generates dynamic
content as output
Portlets also generates dynamic
contents as output but the output
is only fragment of the markup
which will be aggregated by portal
into final page
Servlets works via
request/response mechanism
Portlets also work via
request/response mechanism,
however,
portlet request/response
mechanism is more refined
(further categorized into action
request and render request)
Servlets are directly bound to
URLs
Portlets are not directly bound to
URLs
Servlets dont have concept of
modes and window states
Portlets have pre-defined modes
(View,Edit,Help etc) and window
states
(minimized,normal,maximized)
In servlet, there is no concept of
multiple instances because they
do not directly have any visibility
on client side.
Portlet can exists multiple times
on a single page each instance
being independent of each other
Servlets dont have any concept of
preferences to store any
customization data like portlets
Portlets have concept of Portlet
Preferences where you can store
and retrieve any customization
and configuration data specific to
that particular instance of the
portlet on the page
Servlets dont have access to user
profile information (infact in web
app, there is no direct concept of
user profile)
Portlets have access to user
profile information
Servlets do not have URL
rewriting functions similar to
Portlets
Portlets have URL rewriting
functions for creating hyperlinks
within their content, which allow
portal server indenpendent
creation of links and actions in
page fragments
Servlet session has only one Portlet session is further divided
common scope for store session
level data
into two scopes: Application-Wide
scope and Portlets Private scope.
Servlets have access to client
request URLs, can set character
encoding and HTTP headers on
response.
Portlets dont have access to client
request URLs directly and cannot
set character encoding or HTTP
headers on the response.

A portlet application can contain JSPs and Servelts bundled with Portets and shares
classloader, application context and session.

Portlets can leverage servlets, JSPs and JSP tab libraries to generate output markup
fragments. A portlet can call a JSP or Servlet using portlet request dispatcher just like a
servlet can invoke another servlet or JSP.

When a portlet invokes a servlet or JSP,
All the portlet request attributes gets transferred to servlet request.
Attributes set in portlet session are accessible from servlet session and vice-
versa.
Both portlet and servlet shares same output stream.
A portlet container is nothing but extension of servlet container. It can be built on top of
existing servlet container or a portlet container itself can implement all the features of a
servlet container.

That's it on Portlet Specification and it's relationship with J2EE and Servlets.
Keep following my future posts on more details about Portlet API.


Ajax Best Practice in Portlets

Since the time AJAX has come into picture and with various new AJAX frameworks (like DOJO,
JQuery, Yahoo UI Library, Google Web Tollkit etc), most of the websites now-a-days are
enriched with AJAX to provide Outstanding and Stunning GUI features to the users. With
Portals and Portlet technologies, the web development has become even better than ever
before.

This being said, definitely there are plenty of scenarios where we would like to use AJAX with
Portlets too. Now this is a bit tricky. There is a subtle difference in implementation (processing
user request, serving web response, maintaining state, maintaining lifecycle of server side
components like servlets, jsp etc) between regular web applications and portlet based
applications. This difference makes AJAX implementation a bit tricky when it comes to Portlets.

Here, I will explain how to implement AJAX in both JSR 168 and JSR 286 Portlets.

Let's start understanding it with the difference I described above. Web applications don't have
states/modes similar to Portlets (View Mode, Edit Mode etc).

Following is a lifecycle diagram of a java based web application.


Life cycle Of A Servlet Based Web Application


Here as we see, all the request (be it a normal web request or an AJAX request) are processed
by only 1 method: service method of the servlet. Also there is no need of generated markup
(output HTML, XML etc by service method) aggregation as there is only 1 application running at
a time.

Now, moving to Portlets from Web Application, the scenario is a bit different. In case of
portlets, there are multiple web-applications (called portlets) which runs in small i-frame like
windows on a single web page. All of these portlets run under a Portal application (controller by
portal container) which controls multiple aspects of the entire application like user-interaction
with individual portlets, their window states (Minimized, Maximized etc), entire web-page output
(which is eventually aggregation of markup generated by individual portlets) etc. Following
block diagram illustrates how overall portal application works:


Portal Web Application

When user interacts with a particular portlet, portal container makes sure request is passed to
appropriate portlet, and generated output (markup) is aggregated appropriately with entire web
page output without affecting other portlets.

Following diagram shows how request are processed in a portlet based application.





Here we can see that web requests are divided into two categories:

RenderRequest: These are the requests when portlets are in view mode and being rendered
(e.g. when the first time users requests a web page via HTTP GET or POST URL request)

ActionRequest: These are HTTP GET or POST requests initiated due to user interaction with
portlet (e.g. clicking any URL on the page, submitting form etc).


Here if we see, every request - be it a render request or action request, goes through render
phase (doView() method). This means, Portlet URLs enable window state changes and mode
changes that require a subsequent render request to the portal or portlet container. The result?
The response contains not only the content for the target portlet, but also that for the entire
portal, including all the other rendered portlets. This is true in case of AJAX request
too. Following figure shows an example of a Sample JSR168 Portlet that made an asynchronous
call with actionURL, causing the entire portal page to be embedded in the portlet window as a
part of AJAX response. This is obviously what we don't want.



AJAX Implementation in JSR-168 using processAction() method
In above figure, we are supposed to get only "AJAX Response using Portlet 1.0 Spec -
processAction() method ..." as AJAX response, however along with that, we got entire HTML
of the portlet which got appended to the response by doView() method after request was
processed by processAction() method.

To resolve this problem, we have two solutions depending on which portlet spec. you are using.

For JSR-168 based portlets, there is no provision in the portlet specification which says how to
deal with AJAX requests.

So for JSR-168 portlets, we have to follow a trick. Well, what's that ?

Answer to this question lies in Portlet Specification 1.0 (JSR-168).

Following is the snippet from Portlet Specification 1.0 :

"A Portlet Application is also a Web Application. The Portlet Application may contain servlets and
JSPs in addition to portlets. Portlets, servlets and JSPs may share information through their
session.

The PortletSession must store all attributes in the HttpSession of the portlet application. A
direct consequence of this is that data stored in the HttpSession by servlets or JSPs is accessible
to portlets through the PortletSession in the portlet application scope. Conversely, data stored
by portlets in the PortletSession in the portlet application scope is accessible to servlets and
JSPs through the HttpSession."

This means, we can divide our logic into two pieces:

For regular portlet requests, we can extend GenericPortlet class and implement doView() and
processAction() methods in the normal way we always do.

For Ajax requests, we can write a separate Servlet which will handle ajax requests like normal
web applications do.

Following figure shows what exactly I am talking about.


Ajax Implementation Best Practice for JSR-168 Portlet


So what all we need to do is:

1. Write a class extending GenericPortlet (or any other portlet like MVCPortlet in Liferay etc) for
regular general portlet request processing.

2. Write a servlet to handle ajax requests like following:

public class AjaxServlet extends HttpServlet {
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

//Write your business logic for Ajax processing here
}

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}

}


3. Write javascript functions to implement ajax call (preferably using some good javascript/ajax
library like jquery, dojo etc).

Following in an example of such a javascript function using jquery.

function <portlet:namespace/>_callAjax()
{
var url='<%=(request.getContextPath() + "/AjaxServlet")%>';

//Make ajax call

$.ajax({
type : "POST",
url : url,
cache:false,
dataType: "text",
success : function(data)
{
//Write you success logic here
},
error : function(XMLHttpRequest, textStatus, errorThrown)
{
//Write you error-handling logic here
}
});
};


That's it. You are done :)


Now, lets's move to JSR-286 Portlets (Portlet Specification 2.0). Here, the situation is better in
a way that we don't have to worry about writing a separate servlet for Ajax requests. Portlet
itself provides special method called serveResource(ResourceRequest request,
ResourceResponse response) to do this.

Requests made using ResourceRequest (generated by resourceURL tags provided by portlet
taglib), are served by serveResource() methods.

Following figure shows how it works:



Ajax Implementation in JSR-286 Portlet

Following is a sample PortletClass (extending GenericPortlet) showing how to do it.

package com.jsr286.portlets;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;

import com.liferay.portal.util.PortalUtil;

public class TestPortlet extends GenericPortlet {

protected String viewJSP;


public void init() throws PortletException
{
viewJSP = getInitParameter("view-jsp");
}

protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {

System.out.println("########### Inside com.jsr286.portlets.TestPortlet ... doView()
method.....");
include(viewJSP, request, response);

}


public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {

System.out.println("########### Inside com.jsr286.portlets.TestPortlet ...
processAction() method.....");

HttpServletResponse httpResp = PortalUtil.getHttpServletResponse(response);
httpResp.setContentType("text");
httpResp.getWriter().print("AJAX Response using Portlet 2.0 Spec - processAction()
method .... ");
httpResp.flushBuffer();
return;
}


protected void include(String path, RenderRequest renderRequest,RenderResponse
renderResponse) throws IOException, PortletException
{
PortletRequestDispatcher portletRequestDispatcher =
getPortletContext().getRequestDispatcher(path);
if (portletRequestDispatcher == null)
{
System.out.println(path + " is not a valid include");
} else
{
portletRequestDispatcher.include(renderRequest, renderResponse);
}
}

public void serveResource(ResourceRequest request, ResourceResponse
response) throws PortletException,IOException
{
System.out.println("########### Inside com.jsr286.portlets.TestPortlet ...
serveResource() method.....");

response.setContentType("text");
response.resetBuffer();
response.getWriter().print("Correct Ajax Resopnse from Portlet 2.0 Spec -
serveResource() method .... ");
response.flushBuffer();
}


}


And following is a JSP fragment showing how to place AJAX call using resourceURL.

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

<portlet:defineObjects />

<portlet:resourceURL var="ajaxResourceUrl"/>

<script type="text/javascript">


function <portlet:namespace/>_callAjax()
{
var url = <%=ajaxResourceUrl%>';

//Make ajax call

$.ajax({
type : "POST",
url : url,
cache:false,
dataType: "text",
success : function(data)
{
//Write you success logic here
},
error : function(XMLHttpRequest, textStatus, errorThrown)
{
//Write you error-handling logic here
}
});
};

</script>

That's it on how to implement AJAX in both JSR-168 and JSR-286 portlets.

Please provide your valuable comments/suggestions.
Opening Portlet with Maximized Window in Render Mode
There is no provision in portlet API for opening a portlet with maximized window in render mode
(doView() method). When a portlet gets loaded into browser for the first time, it always opens
up in normal window.

I happened to come across a scenario where I had to open-up portlet in a maximized window
which I achieved in following way:

javax.portlet.PortletURL object allows to set Window State. We can utilize this facility in
following way to open a portlet with maximized window in render (doView() method) mode.

1. In doView method, Generate a render URL from renderResponse.
2. Add all the request parameters from renderRequest to these new URL.
3. Set window state to Maximized on this new URL.
4. Set this new URL value as renderRequest attribute and pass the control to view.jsp (your jsp
file which generates output in render mode).
5. In view.jsp, retreive the URL we created in step-1 and redirect the page to this new URL
using javascript by setting location.href value.

That's it. Next time, when the portlet will be rendered, it will open up in Maximized mode.

Following is the piece of code for both doView() method of Portlet class and view.jsp.

In Portlet Class,

public void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws
IOException, PortletException
{

if(renderRequest.getWindowState() != WindowState.MAXIMIZED)
{
//Create a render URL
PortletURL url = renderResponse.createRenderURL();

//Pass all the parameters from existing request to this new URL
Enumeration params = renderRequest.getParameterNames();

while(params.hasMoreElements())
{
String pname = params.nextElement().toString();
url.setParameter(pname, renderRequest.getParameter(pname));
}

//Set window state to Maximized on newly created URL
url.setWindowState(WindowState.MAXIMIZED);

//Set this URL as attribute in renderRequerst
renderRequest.setAttribute("maximizedUrl", url.toString());


renderRequest.setAttribute("isMaximized", "false");

}
include(viewJSP, renderRequest, renderResponse);
}


protected void include(String path, RenderRequest renderRequest,RenderResponse
renderResponse) throws IOException, PortletException
{
PortletRequestDispatcher portletRequestDispatcher =
getPortletContext().getRequestDispatcher(path);
if (portletRequestDispatcher == null)
{
Logger.error(path + " is not a valid include");
}
else
{
portletRequestDispatcher.include(renderRequest, renderResponse);
}
}


In view.jsp,

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

<jsp:useBean class="java.lang.String" id="maximizedUrl"
scope="request" />
<jsp:useBean class="java.lang.String" id="isMaximized"
scope="request" />

<portlet:defineObjects />


<script type="text/javascript">
var maximizedFlag = '<%=isMaximized%>';

//Redirect to New Render URL only if current window is not in maximized state
if(maximizedFlag=='false')
{
location.href='<%=maximizedUrl%>';
}
</script>

S-ar putea să vă placă și