Friday, March 12, 2010

Creating a JSR-168 compatible Hudson Portlet to Integrate to Liferay

For Setting up the IDE and creating a basic JSR -168 portlet please refer to the article on 9th March 2010 named, “Setting up the IDE for portlet Development”.

Create a standard JSR-168 portlet named Hudson with 3 JSPs each for hudson_view, hudson_edit and hudson_help. And class will automatically be created. This class has extended the GenericPortlet class by default.

In the hudson_view.jsp All the Hudson jobs status, name and URL to project should be displayed. Other than that the facility to dynamically filter the jobs by name is also should be given as in the following figure. Both error messages while connecting to Hudson server, filtering projects and success messages while retrieving jobs from the Hudson server should be displayed in the hudson_view.jsp

Figure1: Image of VIEW mode
Let’s look into imporant code segments used in creating this view mode.

Portlet preference will save user specific data for the portlet. In this portlet we are saving both Hudson URL and the user’s default filter as portlet preferences in hudson_edit.jsp page which will discuss later.

In the first line portlet preference instant is created.

In portlets to send data from a form or link in a JSP page actionURL is used. There are 2 ways of creating action URLs. In the 2nd line one of those methods are used to create an action URL.
Now I’m checking whether the user has configured the Hudson server URL previously. If he hasn’t then the portlet will provide a link to hudson_edit.jsp asking the user to configure the URL. Link will send a actionURL to the class with the parameter set to edit=link.
If the user has already configured the Hudson server URL, then show the dynamic project filtering form. Now again in this form we are sending data to class. To separate it from the data sent by the link lets change the edit parameter value to form.
In the html code of the form the css classes are called according to the JSR-168 portlet standard to maintain the same look and feel inside the portal page.
Then error messages and success messages are caught for display as follows. When there are no error messages we catch the HudsonPortlet ArrayList send by the class having details about the individual projects in the hudson repository.

Then the results are displayed inside a loop, in a table. At the end link to Hudson Dashboard is given separately.
In this JSP page first error and success messages are caught and displayed. And a form to set Hudson URL and Default Project Filter is given. This form has the other way of providing an actionURL to send data for the class.
Prefs.getValue(“hudUrl”, “”) will get the portlet preference named hudUrl, but if that portlet preference is not set it will display an empty string.

This is a static page containing information regarding how to use the portlet and how to input data to different forms in both edit and view JSPs.
This is a serializable class that represents a single Hudson job. It has an empty constructor and has getters and setters for all the private variables. Other than 8 getters and setters there is another class that gets a color name as the input parameter and use that to set both lastBuildStatus and lastBuildImage.
This class will get the Hudson URL and Filter from the class and use that URL in conjunction with the string “/api/xml” to create remote api call to Hudson repository which sends back an xml file in the following format.
Figure 2: Hudson remote api xml
Then class will read this xml as a normal xml file as follows.

And for every element with the name “job” a HudsonProject object is created in memory and all the variables of that object is then set according to the sub elements of that job element as follows. In the mean time filter value is also been considered when initializing the created project. If it satisfies the conditions the new HudsonProject is added to the HudsonProject ArrayList named “project”.
The function “getTagValue()” is as follows,
This is the extended class of GeneralPortlet class which is automatically created when creating the portlet. It has a processAction() method and 3 render methods each for different portlet mode. The 3 render methods are doView(), doEdit() and doHelp() which correspond to view, edit and help modes.

When viewing a page from decorators and controls or for the first time after adding the portlet portlet container will call directly the respective render method. This is a doEdit() method,
In this render method hudson_edit.jsp is dispatched. And the only method in PortletRequestDispatcher class, include() is called to pass the render request and response to the hudson_edit.jsp page.

doHelp() method is also similar to this above render method. But doView() has some differences. It gets a value for filter and URL and pass them to Drive instance as follows.

After setting proper values to filter and URL variables they are been passed to Drive class to get an ArrayList of HudsonProject objects. This ArrayList, errors and filter is passed to the request by setAttribute() method before dispatching the hudson_view.jsp page.
The processAction() method is called when a link is clicked or a form is submitted in any of the 3 JSP pages. From which page does the request is originated will be determined by the current portlet mode. This is the action to be carried out when the request is made by the hudson_view.jsp in view mode.
It will catch the parameter named “edit” from the request and if the value of the edit is equal to link the portlet mode is changed to EDIT so doEdit() will be executed. If the edit’s value is not equal to link request is coming from the form in the view page. So the form input is captured to string filter and that value is passed to doView() method.

This is the code to execute when an action request originated from the hudson_edit.jsp.
Capture the URL and filter sent from the edit form.
By pref.setValue(“hudFilter”, filter) method preference with the name hudFilter is set with the filter input set by the form. After setting both portlet preferences there are stored in an atomic function store() which need to be surrounded by try catch.

If this store() action was successful, a success message is set and send to the hudson_edit.jsp . Then sending messages to respective JSP page from processAction() method they need to be wrapped in URLEncoder.encode() function.
This is Liferay specific code and this will help to change or create a new category in which the portlet will appear in the available portlet stack. By changing the value of category name this can be set to appear under different category other than Continuous Integration.

In order for this portlet to work as desired there is one step left. And that is to add the portlet preferences tags inside </ portlet="">as follows,

The names of the preferences should exactly match those we used in the code for proper operation.

The full code of this project can be downloaded from here:

No comments:

Post a Comment