📜 ⬆️ ⬇️

Create a portlet application for JSR286, part one

purpose

To join the portal technologies, explore the possibilities offered by the JSR286 specification

Work plan

1. Create a project
2. Create portlet settings, display them on the portal page
3. Save settings, check settings with validator.
4. Create a view mode depending on the portlet settings
5. Generate and handle events within a single portlet application.

I have already written earlier about how the JSR286 specification is actively developing, how Sun, one by one, rivets versions of portals, stuffing them with various goodies. After the release to free navigation, GlassFish, which is a direct relative of the Sun Java system Server, is expected to be given to the free community by the portal branch, which, as I wrote earlier, is now only slightly inferior to the IBM portal. We must carefully look at the portlets and the bonuses that appear when using them. On the spoons of tar, too, will not be gone.

Application Description


There are two portlets in the portlet application: SearchPortlet and DetailsPortlet . Using the first portlet, the user searches for employees, and on the second portlet, the user views the results.
')
project outline with a brief description

To achieve a similar result, create a project.
File -> New project -> Web -> Web Application with the name HRPortletExample .
As a server, select OpenPortal Portlet Container 2.0 , previously registered (see my previous articles). Select Portlet Support , create a portlet with the name of the SearchPortlet class.
Do not forget to place the portlet in the specified package.
And so, we have a portlet application and a dummy portlet. Now let's do other things.

Project infrastructure

Person class

Create a class ru.habr.utils.Person . This class will be responsible for the employee.

package ru.habr.utils;
import java.io.Serializable;
public class Person implements Comparable <Person>, Serializable {
private int id;
private String name;
private String surname;
private String department;
private string rank;

public Person () {
}

public Person ( int id, String ... data) {
// TO-DO insert length check to avoid ArrayIndexOutOfBoundsException
this .id = id;
this .name = data [0];
this .surname = data [1];
this .department = data [2];
this .rank = data [3];
}

@Override
public String toString () {
StringBuilder sb = new StringBuilder ();
sb.append (name) .append ( "" ).
append (surname) .append ( ":::" ).
append (department) .append ( ":::" ).
append (rank);
return sb.toString ();
}

public String getFullString () {
StringBuilder sb = new StringBuilder ();
sb.append (name) .append (surname) .append (department) .append (rank);
return sb.toString ();
}

public String getTokenizedRepersentation () {
StringBuilder sb = new StringBuilder ();
sb.append ( this .id) .append ( ":" );
sb.append ( this .name) .append ( ":" );
sb.append ( this .surname) .append ( ":" );
sb.append ( this .department) .append ( ":" );
sb.append ( this .rank);

return sb.toString ();
}

public static Person restorePersonFromTokenizedRepresentation (String tokenizedRepresentation) {
Person person = null ;
String [] dataStr = tokenizedRepresentation.split ( ":" );
if (dataStr.length == 5) {
person = new Person ();
person.setId (Integer.valueOf (dataStr [0]));
person.setName (dataStr [1]);
person.setSurname (dataStr [2]);
person.setDepartment (dataStr [3]);
person.setRank (dataStr [4]);
}
return person;
}

@Override
public int hashCode () {
return department.hashCode ();
}

@Override
public boolean equals (Object obj) {
boolean isEqual = false ;

if (obj instanceof Person) {
if ( this .getId () == ((Person) obj) .getId ()) {
isEqual = true ;
}
}

return isEqual;
}

public int compareTo (Person inputPerson) {
return surname.compareTo (inputPerson.getSurname ());
}
// ...
}

Instead of // ... we insert getters and setters for class fields.
The public String method getFullString () will be needed to search for employees, and the public String method getTokenizedRepersentation () and public static Person restorePersonFromTokenizedRepresentation (String tokenizedRepresentation) will be needed to easily store an instance of the class as a string. What is this extravagant way for, I will explain below. If dear readers tell me how to get rid of it, I will be immensely grateful.
Note that the class describes the methods of the Comparable interface (so that employees can be sorted), and is marked with an interface — a Serializable token, so that the employee can be serialized.
Sorting is useful for displaying the list of employees on the page, and serialization is needed to transfer the found employee from one portlet to another through events.

Class utilclass

This class reads a file with employees, creates instances of the Person class, and stuffs it into the Map, where the key is the employee id, and the value is the employee himself.
The details you look at the source code, show only the method that performs the search:
public ArrayList <Person> searchForPerson (String searchString) {
ArrayList <Person> resultList = null ;
if (searchString == null || searchString.trim (). replace ( "" , "" ) .length () <1) {
return null ;
} else {
resultList = new ArrayList <Person> ();
searchString = searchString.trim (). replace ( "" , "" );
for (Person p: mapWithPersons.values ​​()) {
if (p.getFullString (). toLowerCase (). contains (searchString.toLowerCase ())) {
resultList.add (p);
}
}
}
return resultList;
}

Everything is simple, flat and parallel - the employee is pulled into a string and then a search is made by matching part of the employee’s string and the characters entered by the user. In short, the point is not in the search, we go further.

Portlet SearchPortlet

On this portlet will be a string to search for and a button to find. To demonstrate the editing mode, we will add the ability to display a full list of employees in viewing mode. It will look like this:
project outline with a brief description


Adding settings to portlet.xml

Portlet settings are written in portlet.xml , let's take a look and prescribe them:
< portlet >
< description > SearchPortlet </ description >
< portlet-name > SearchPortlet </ portlet-name >
< display-name > SearchPortlet </ display-name >
< portlet-class > ru.habr.portlet.SearchPortlet </ portlet-class >
< expiration-cache > 0 </ expiration-cache >
< supports >
< mime-type > text / html </ mime-type >
< portlet-mode > VIEW </ portlet-mode >
< portlet-mode > EDIT </ portlet-mode >
< portlet-mode > HELP </ portlet-mode >
</ supports >
< resource-bundle > ru.habr.portlet.messages </ resource-bundle >
< portlet-info >
< title > SearchPortlet </ title >
< short-title > SearchPortlet </ short-title >
</ portlet-info >
< portlet-preferences >
< preference >
< name > showPersonsList </ name >
< value > false </ value >
</ preference >
</ portlet-preferences >
</ portlet >

The < portlet-preferences > section contains the names of the settings (so that they can be accessed) and default values. Both are stored as strings, input errors are correspondingly inevitable. Validators are used to verify the correctness of the settings being installed. We will talk about them next time.

Editing the doEdit method in the SearchPortlet portlet

Go to the SearchPortlet class, look for the doEdit method that corresponds to the display of the portlet configuration mode:
@Override
public void doEdit (RenderRequest request, RenderResponse response) throws PortletException, IOException {
// transfer preference value to jsp
String prefValue = request.getPreferences (). GetValue (PREF_SHOWPERSONS, "" );
request.setAttribute (PREF_SHOWPERSONS, prefValue);

response.setContentType ( "text / html" );
PortletRequestDispatcher dispatcher =
getPortletContext (). getRequestDispatcher ( "/WEB-INF/jsp/SearchPortlet_edit.jsp" );
dispatcher.include (request, response);
}

The current portlet settings can be accessed through request.getPreferences (). GetValue (PREF_SHOWPERSONS, "")
PREF_SHOWPERSONS is a static class field that stores the name of the showPersonsList setting.
If you read it carefully, you can see that the settings are recommended to be transferred to jsp as attributes, although at jsp itself you can also access the settings in the same way via renderRequest.getPreferences (). GetValue (PREF_SHOWPERSONS, "") Why this is not clear.

SearchPortlet_edit.jsp

Looks like that:
<% @ page contentType = "text / html"%>
<% @ page pageEncoding = "UTF-8"%>
<% @ page import = "javax.portlet. *"%>
<% @ page import = "javax.portlet. *"%>
<% @ page import = "ru.habr.portlet.SearchPortlet"%>
<% @ taglib uri = " java.sun.com/portlet_2_0 " prefix = "portlet"%>
< portlet: defineObjects />

<% boolean showPersonList = Boolean.valueOf (( String ) renderRequest.getAttribute (SearchPortlet.PREF_SHOWPERSONS)); %>
< H4 > Editing the Employee Search portlet. </ H4 >

< form method = "post" action = "& # 60 ; portlet: actionURL /> " >
Display a list of employees on the page? <br>
< select name = "<% = SearchPortlet.PREF_SHOWPERSONS%>" >
< option value = "true" & # 60 ;% = showPersonList ? "SELECTED" : "" % & # 62 ; > Yes </ option >
< option value = "false" & # 60 ;% =! showPersonList ? "SELECTED" : "" % & # 62 ; > No </ option >
</ select >
< input type = "submit" value = "Save" >
</ form >

We take out the attribute value, display the value, wait for the button to be pressed. The edit mode itself looks like this:
project outline with a brief description

The URL for the form is generated at the jsp compilation stage using the actionURL tag.

How to save the new settings and what happens when you click on the "Save" button I will tell in the next series!

* This source code was highlighted with Source Code Highlighter .

Source: https://habr.com/ru/post/27450/


All Articles