February 28, 2021
Hot Topics:

Developing to the Java Portlet Specification

  • By Michael Klaene
  • Send Email »
  • More Articles »

Similar to HttpSession, the PortletSession interface stores data about a user's session. However, PortletSession defines two additional scopes for storing portlet-specific data within that user session. An application session scope stores data across all user portlets in the same session. In our example, we are using the second scope, portlet session scope, which stores information only accessible to the user's QueryPortlet instance. The title and results of the query just performed are assigned to session attributes.

Finally, we use a PortletRequestDispatcher to forward to a JSP page that will generate markup. This is where our URL values read in the init method come in to play.

PortletRequestDispatcher dispatcher =   getPortletContext().getRequestDispatcher(viewUrl);dispatcher.include(request,response);

Our view template, view.jsp, utilizes a portlet taglib. This taglib is used by portlets for building portlet links and performing the necessary includes of required classes. View.jsp then generates markup. This practice follows good MVC design. Our portlet methods receive requests, invoke necessary business logic contained in JavaBeans, and then forward to view pages to render a response.

Editing the QueryPortlet

Figure 2 shows QueryPortlet in edit mode. In Liferay, clicking the pencil icon sends a request to the container to bring a portlet up in edit mode. This results in the doEdit method being called on QueryPortlet. In edit mode, QueryPortlet reads the values of title and sql from PortletPreferences and sets RenderRequest attributes to display this information in an HTML form contained in the file edit.jsp. The first time we bring up the form, it displays our default preferences.

Click here for a larger image.

Figure 2. QueryPortlet in Edit Mode

A user can enter a new SQL query and title, and then submit the form. For this example, we will enter the query 'SELECT emp_id ID, CONCAT(last_name,",",first_name) NAME, TITLE FROM emp, job WHERE emp.job_id = job.job_id order by title' and a title of 'My Employee Information with Job Title!', and click submit. This action brings the processAction lifecycle method into play. Here is processAction:

/**Executed in response to action on portlet, like submitting a  *form.*/public void processAction(ActionRequest request,                          ActionResponse response)throws PortletException, IOException {   log.info("Executing QueryPortlet's processAction method.");   if(request.getPortletMode().equals(PortletMode.EDIT)) {      String errorMessage = null;      boolean isValid = false;      PortletPreferences preferences = request.getPreferences();      //Get our edit form's data...      String sql = request.getParameter("sql");      String title = request.getParameter("title");      preferences.setValue("sql",sql);      preferences.setValue("title",title);      try{         //This will fire our PreferencesValidation validate method.         preferences.store();         isValid = true;      }      catch(ValidatorException ve) {         //Assign values from ActionResponse to RenderRequest for         //redisplay in form.         response.setRenderParameter("sql",                                     request.getParameter("sql"));         response.setRenderParameter("title",                                     request.getParameter("title"));         errorMessage = "An error occurred processing your SQL. " +         "Please check your input and try again.";         response.setRenderParameter("errorMessage",errorMessage);       }      if (isValid) {         response.setPortletMode(PortletMode.VIEW);      }   }}

If mode equals 'EDIT', processAction assigns the form's values to PortletPreferences. However, before we move on, we will want to validate the query. The portlet specification defines a convenient way to validate a user's portlet preferences by implementing the PreferencesValidator interface. We designated a validator class in portlet.xml that is to fire when portletAction invokes the store() method on PortletPrefernces.

<portlet-preferences>      ...      ...   <preferences-validator>QueryPreferencesValidator   </preferences-validator></portlet-preferences>

QueryPortlet is simplistic and does not pretend to be a robust application. QueryPreferencesValidator.java simply reads the value of sql in PortletPreferences and validates the query by invoking the executeQuery method on QueryBean.

Entering the invalid query 'SELECTX * FROM emp' in the form and pressing Enter will generate an Exception. In this case, we log the error and throw a new ValidatorException with a message for users to correct their query and try again:

try {   QueryBean qb = new QueryBean();   qb.executeQuery(sql);}catch(Exception e) {   log.warn("Exception occured executing QueryBean             executeQuery in  " +           "QueryPreferencesValidator. sql : " + sql);   errorsSet.add(sql);   throw new ValidatorException(e.toString(),errorsSet);}

QueryPortlet's portletAction receives the ValidatorException in this case. We want the user to be able to see the invalid form data they've just submitted, not what is in PortletPreferences (which has been reset to its valid state). We do this by calling ActionResponse's setRenderParameter with the user's initial input values:

catch(ValidatorException ve) {   //Assign values from ActionResponse to RenderRequest for   //redisplay in form.   response.setRenderParameter("sql",request.getParameter("sql"));   response.setRenderParameter("title",request.getParameter("title"));   errorMessage = "An error occurred processing your SQL.  " +   "Please check your input and try again.";   response.setRenderParameter("errorMessage",errorMessage);}

Now, if the SQL is corrected and resubmitted, validation will succeed and processAction will change the portlet mode form edit back to view:

try{   //This will fire our PreferencesValidation validate method.   preferences.store();   isValid = true;}catch(ValidatorException ve) {   ...   ...}if (isValid) {   response.setPortletMode(PortletMode.VIEW);}

The container invokes the render method once more, and because QueryPortlet is in view mode, the doView method executes. Figure 3 shows the output.

Click here for a larger image.

Figure 3. QueryPortlet in View Mode

You can download and install the QueryPortlet application, and then follow the execution path of the portlet by viewing the application's log file (I used Apache Commons Logging package for this which uses J2SDK 1.4's logger).


With the growing popularity of enterprise portals, understanding the Java Portlet Specification will become increasingly important to J2EE developers. There are a number of open-source portals available that will allow you to experiment with portlet development and I encourage to learn more about this important technology.

About the Author

Michael Klaene is a Senior Consultant with Sogeti LLC. He has spent over 7 years in IT, specializing in J2EE and Oracle analysis and development.

Page 2 of 2

This article was originally published on June 24, 2004

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date