Setting Up Access Control
MVCPortlet allows portlet deployers to specify access control for each render or action type. The configuration file has a separate section that defines named access control conditions. The permissions section for the FAQ portlet is shown in Listing 3. The configuration defines one precondition that allows access only for the user admin. For the FAQ portlet, we want to allow anyone to view non-admin functionality; i.e., render types corresponding to the VIEW mode. All other screens and actions should only be accessible to the user admin. This is achieved by specifying admin as the precondition name specified by the preCondition attribute of applicable render and action types.
<pre-conditions>
<pre-condition name="admin"
class="com.nabhinc.rules.UserPrecondition">
<users>admin</users>
</pre-condition>
</pre-conditions>
Listing 3. Permissions configuration for the FAQ portlet
Configuring RenderProcessors and ActionProcessors
The MVCPortlet framework provides a number of built-in processors for performing database-related operations. In many cases, including the above FAQ portlet, you can develop fully functional portlets without writing any Java code. As a result, implementing the business logic of a portlet is reduced to simply configuring existing processors. Configuration and mapping of ActionProcessors and RenderProcessors is very similar. A fragment of RenderProcessor configuration for the FAQ portlet is shown in Listing 4. The fragment shows the RenderProcessor for the render type ViewIndex. The render processor name is ViewIndex, which allows MVCPortlet to associate it with the render type with the same name. The configuration specifies the SelectRecords render processor that retrieves a vector of database records and sets the attribute mvcportlet.records to the record vector. The SQL for fetching the records is specified in <sql> element specified in the processor configuration.
<render-processors>
<render-processor name="ViewIndex"
class="com.nabhinc.portlet.mvcportlet.renderprocessor.SelectRecords">
<sql>SELECT catid, cattitle, catrank
FROM SB_FAQ_CATEGORIES ORDER BY catrank</sql>
</render-processor>
:
:
</render-processors>
Listing 4. ViewIndex RenderProcessor configuration
The FAQ portlet requires user input when a category/question is being created or edited. Correspondingly, we have a form for accepting category information and a form for accepting question information. Listing 5 shows the forms configuration for the FAQ portlet. The configuration defines two forms: category and question. A form is associated with an action type by specifying its name in the form attribute of the <action-type> element, as shown in CreateCategory action type configuration shown in Listing 2.
<forms>
<form name="category">
<field name="cat_id" />
<field name="cat_title"
validators="required,maxNameLength" />
<field name="cat_rank"
validators="int" default="0" />
</form>
<form name="question">
<field name="cat_id" />
<field name="q_id" />
<field name="q_title"
validators="required,maxNameLength" />
<field name="q_answer"
validators="required,maxDescrLength" />
<field name="q_rank"
validators="int" default="0" />
</form>
</forms>
Listing 5. Forms configuration for the FAQ portlet
The form named category defines three fields: category ID, category title, and category rank. Each field is optionally associated with one or more validators. For example, the field cat_title references two validators named required and maxNameLength, respectively. This is specified as a comma-delimited list in the validators attribute of the <field> element. The validators configuration section defines corresponding validators, as shown in Listing 6. Each validator has a name that must match the name specified in the form configuration. In addition, a validator can have additional attributes and sub-elements specific to that validator. For example, the maxNameLength validator uses the validator class com.nabhinc.portlet.mvcportlet.validator.MaxLengthValidator with a configuration attribute, maxLength, that provides the maximum length for the form field value.
<validators>
<validator name="required"
class="com.nabhinc.portlet.mvcportlet.validator.RequiredValidator" />
<validator name="int"
class="com.nabhinc.portlet.mvcportlet.validator.IntegerValidator" />
<validator name="maxNameLength"
class="com.nabhinc.portlet.mvcportlet.validator.MaxLengthValidator"
maxLength="100" />
<validator name="maxDescrLength"
class="com.nabhinc.portlet.mvcportlet.validator.MaxLengthValidator"
maxLength="4000" />
</validators>
Listing 6. Validators configuration for the FAQ portlet
Writing JSP Files
JSP files used to generate markup fragments can use all available aids, such as JSP tag libraries. The MVCPortlet framework provides a tag library and helper JSPs to facilitate this task. As an example, consider the JSP file shown in Listing 7 that displays the category creation form. The file first includes a helper JSP file, nav.jsp. This JSP file inserts various information messages set by Action/RenderProcessor objects invoked during the current requests. It also inserts navigation links at the top of the page. The file also uses a number of JSP tags provided by the MVCPortlet framework, including:
<mp:form>: This tag results in an HTML form tag with the form action set to the action URL for the current portlet. In addition, if the attribute validationMethod is specified, it generates client-side validation code for form fields.
<mp:formLabel>: This tag produces internationalized form field labels. If there was a validation error for the named form field, it also highlights those fields, depending on the portal theme styles.
<mp:input>: This tag generates a text input field and populates it based on the corresponding render parameter.
<%@include file="../include/nav.jsp" %>
<%
String catTitle = rReq.getParameter("cat_title");
if (catTitle == null) catTitle = "";
String catRank = rReq.getParameter("cat_rank");
if (catRank == null) catRank = "0";
PortletURL actionURL = rRes.createActionURL();
%>
<table width="100%">
<mp:form name="category"
validationMethod="validateCreateCategory">
<input type="hidden" name="request_type"
value="CreateCategory" />
<tr>
<td class="portlet-font">
<b><mp:formLabel key="faq.title_label"
name="cat_title" /></b>
</td>
<td class="portlet-font">
<mp:input name="cat_title" />
</td>
</tr>
<tr>
<td class="portlet-font">
<b><mp:formLabel key="faq.rank_label"
name="cat_rank" /></b>
</td>
<td class="portlet-font">
<mp:input name="cat_rank" />
</td>
</tr>
<tr>
<td class="portlet-font" align="right" colspan="2">
<br/>
<mp:submit value="faq.create_category_button"/>
<mp:cancel value="mvcportlet.cancel_button" />
</td>
</mp:form>
</table>
Listing 7. Example JSP
Portlet Deployment
At this point we have completed all portlet development tasks and the FAQ portlet is ready for deployment. Actual deployment steps will, of course, depend on the chosen portal server. We tested the FAQ portlet in Stringbeans, an open source portal server. To deploy the FAQ portlet in this container, a portlet entry (shown in Listing 8) is copied to the portlet.xml file located in WEB-INF directory of the portal web application. We then copied all JSP and configuration files to the portlets/faq directory under the web application root, and restarted the server. Finally, we added the portlet to an appropriate portal page to complete the portlet development and deployment process.
<portlet>
<description>Displays Site FAQ.</description>
<portlet-name>FAQ</portlet-name>
<portlet-class>
com.nabhinc.portlet.mvcportlet.core.ControllerPortlet
</portlet-class>
<init-param>
<name>configFile</name>
<value>/portlets/faq/portlet-config.xml</value>
</init-param>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>ADMIN</portlet-mode>
</supports>
<supports>
<mime-type>
application/vnd.wap.xhtml+xml
</mime-type>
</supports>
<portlet-info>
<title>Frequently Asked Questions</title>
<keywords>Collaboration</keywords>
</portlet-info>
</portlet>
Listing 8. FAQ portlet configuration in portlet.xml
Resources