Developing Integration with External Systems Using JSR Portlets
The Portal Designer solution within Service Catalog provides a rich platform for integrating with external applications through JSR Portlets. The portal front-end uses Apache Pluto 1.1 libraries as the framework. Portlets developed using APIs which meet the Java Portlet Specification (JSR168, JSR286) standards may be deployed along with Service Catalog. Once deployed, these will appear in Portal Designer as “Third-Party Portlets” and can be added to portal pages. For more information on how to maintain JSR portlets and other content in the Portal Designer solution, see the Cisco Prime Service Catalog Designer Guide.
This chapter covers some guidelines on the development and deployment of JSR portlets for the Portal Designer solution. A sample portlet named “MyJSR” is used throughout the chapter as an illustration. The portlet is developed with Spring 3.0 Annotation-based Controller and Sencha’s Ext JS—the JavaScript framework for the portal front-end.
Portlet Structure and Packaging
The portlet files should be packaged according to the JSR 168 or 286 specifications, in the form of web application (war) files appropriate for the application server used. A typical portlet war file may include servlets, resource bundles, images, html, jsp, css files, and so on.
JBoss Application Server
Here is the anatomy of a simple portlet named “MyJSR.war”:
<Custom Images that the Portlet needs can be placed here>
MyJSRApplicationContext.xml
MyJSRView_updateperson.jsp
cxf-rt-transports-http-2.2.12.jar
pluto-portal-driver-2. 0.2.jar
org.springframework.aop-3.1.0.RELEASE.jar
org.springframework.asm-3.1.0.RELEASE.jar
org.springframework.aspects-3.1.0.RELEASE.jar
org.springframework.beans-3.1.0.RELEASE.jar
org.springframework.context-3.1.0.RELEASE.jar
org.springframework.context.support-3.1.0.RELEASE.jar
org.springframework.core-3.1.0.RELEASE.jar
org.springframework.expression-3.1.0.RELEASE.jar
org.springframework.instrument-3.1.0.RELEASE.jar
org.springframework.instrument.tomcat-3.1.0.RELEASE.jar
org.springframework.jdbc-3.1.0.RELEASE.jar
org.springframework.jms-3.1.0.RELEASE.jar
org.springframework.orm-3.1.0.RELEASE.jar
org.springframework.oxm-3.1.0.RELEASE.jar
org.springframework.test-3.1.0.RELEASE.jar
org.springframework.transaction-3.1.0.RELEASE.jar
org.springframework.web-3.1.0.RELEASE.jar
org.springframework.web.portlet-3.1.0.RELEASE.jar
org.springframework.web.servlet-3.1.0.RELEASE.jar
org.springframework.web.struts-3.1.0.RELEASE.jar
jboss-deployment-structure.xml
In this sample portlet, the nsAPI java client—newscale_appclient.jar—is included in the lib folder as the portlet invokes the REST API to retrieve data from Service Catalog. Pluto libraries and other libraries that the nsAPI java client depends on need to be included in the lib folder. In addition, the jboss-deployment-structure.xml is included to describe the dependencies on the JBoss modules.
An additional descriptor—portlet.xml—must be present to specify the portlet-related configurations.
Weblogic Application Server
On WebLogic, the JSR portlet war structure is similar except that it must contain all the libraries the portlet uses because it is deployed outside of the Service Catalog application.
Some of the libraries included below are required for invoking the nsAPI java client and to read portlet common settings. Certain libraries are needed here because the portlet uses JSTL tags in JSPs and Spring portlets MVC.
<Custom Images that the Portlet needs can be placed here>
MyJSRApplicationContext.xml
MyJSRView_updateperson.jsp
commons-beanutils-1.8.3.jar
commons-httpclient-3.1.jar
commons-logging-1.0.4.jar
commons-collections-3.2.1.jar
org.springframework.aop-3.1.0.RELEASE.jar
org.springframework.asm-3.1.0.RELEASE.jar
org.springframework.aspects-3.1.0.RELEASE.jar
org.springframework.beans-3.1.0.RELEASE.jar
org.springframework.context-3.1.0.RELEASE.jar
org.springframework.context.support-3.1.0.RELEASE.jar
org.springframework.core-3.1.0.RELEASE.jar
org.springframework.expression-3.1.0.RELEASE.jar
org.springframework.instrument-3.1.0.RELEASE.jar
org.springframework.instrument.tomcat-3.1.0.RELEASE.jar
org.springframework.jdbc-3.1.0.RELEASE.jar
org.springframework.jms-3.1.0.RELEASE.jar
org.springframework.spring-library-3.1.0.RELEASE.libd
org.springframework.test-3.1.0.RELEASE.jar
org.springframework.transaction-3.1.0.RELEASE.jar
org.springframework.web-3.1.0.RELEASE.jar
org.springframework.web.portlet-3.1.0.RELEASE.jar
org.springframework.web.servlet-3.1.0.RELEASE.jar
org.springframework.web.struts-3.1.0.RELEASE.jar
Dependent Libraries
The set of libraries required for inclusion in the JSR Portlet war file are available in either the deployed RequestCenter application on the application server or the Service Catalog installer image:
-pluto-taglib-2.0.2.jar: under the "preinstall" folder of the product image
-all other files: RequestCenter.war/WEB-INF/lib
Developing Portlets
A typical JSR portlet should cover the three rendering modes —View, Edit, and Help. In addition, the portlet would support different window states—Normal, Minimized, and Maximized.
The MyJSR portlet example shown below provides a user interface that supports two functionalities:
1. List Service Catalog users in a grid.
Figure 7-1 Developing Portlets
2. Allow user to be added/updated.
Figure 7-2 Add User
To achieve the above requirements, the sample code that follows includes these high-level operations:
- Retrieval of Service Catalog users using nsAPI java client
- Returning the user details in JSON format to the user interface
- Rendering the list of users in a Ext JS grid on the browser
- Display/entry of user details in a form designed using Ext JS
- Adding/updating user details in the Service Catalog repository using nsAPI java client
MyJSR.css
#Code Custom Styles for the portlet can be designed here.
Now let us examine the content of each of the components within the MyJSR.war.
MyJSRCreatePersonView.js
Example code using Ext JS to display a form for creating a user.
/* Code custom JavaScript for the portlet here */
var tab2 = new Ext.FormPanel({
title : 'Person Details - Add',
bodyStyle : 'padding:5px',
fieldLabel : 'First Name',
value : personListObj.firstName,
fieldLabel : 'Login Name',
value : personListObj.login,
name : 'homeOrganizationalUnitName',
value : personListObj.homeOrganizationalUnitName,
value : personListObj.timeZoneName,
fieldLabel : 'Last Name',
value : personListObj.lastName,
value : personListObj.email,
value : personListObj.languageName,
bodyStyle : 'padding:10px'
defaultType : 'textfield',
name : 'businessAddress',
defaultType : 'textfield',
Ext.getCmp("personEditForm").getForm().submit({
url : addPersonActionUrl,
success : function(form, action) {
var responseObj = Ext.util.JSON.decode(action.response.responseText);
if(responseObj.success == "true")
Ext.Msg.alert('Success', responseObj.successMsg);
Ext.Msg.alert('Error', responseObj.errorMsg);
window.location=viewPersonUrl;
MyJSREdit.js
This JavaScript can be used to add any custom code for portlet edit mode.
/* Code custom JavaScript for the Portlet here */
MyJSRHelp.js
This JavaScript can be used to add any custom code for portlet edit mode.
/* Code custom JavaScript for the Portlet here */
MyJSRView.js
Example JavaScript to display users in Ext JS grid.
/* Code custom JavaScript for the Portlet here */
// Demonstrates how to getUser info from Java Script and set it to div
varLogin=document.getElementById('MyJSRLoginNameDiv');
Login.innerHTML=nsAPP_CurrentUserLoginName;
varFirstName=document.getElementById('MyJSRFirstNameDiv');
FirstName.innerHTML=nsAPP_CurrentUserFirstName;
varLastName=document.getElementById('MyJSRLastNameDiv');
LastName.innerHTML=nsAPP_CurrentUserLastName;
varHomeOU=document.getElementById('MyJSRHomeOUDiv');
HomeOU.innerHTML=nsAPP_CurrentUserHomeOuId;
var PersonID=document.getElementById('MyJSRPersonIDDiv');
PersonID.innerHTML=nsAPP_CurrentUserId;
var pid = portletId.substr(pidPrefix.length);
if (Ext.getCmp(pid).height && Ext.getCmp(pid).height >= 29) {
var gridHeight = Ext.getCmp(pid).height - 29;
var gridStore = new Ext.data.JsonStore({
proxy : new Ext.data.HttpProxy({
timeout : connectionTimeOut
autoLoad: {params:{start: 0, limit: defaultRecordSize}},
totalProperty: 'results',
name : 'homeOrganizationalUnitName',
name : 'businessAddress',
var expander = new Ext.ux.grid.RowExpander({
'<h2 class="title">Address</h2><table>',
'<tr><td width=400><b>Business</b> {businessAddress}</td>',
'<td width=400><b>Home</b>{homeAddress}</td></tr></table>',
'<h2 class="title">Contact</h2><table>',
'<tr><td width=400><b>Business</b> {businessPhone}</td>',
'<td width=400><b>Home</b> {homePhone}</td></tr>',
'<tr><td width=400><b>Mobile</b> {mobilePhone}</td>',
'<td width=400><b>Fax</b> {faxNumber}</td></tr></table>')
var gridColModel = new Ext.grid.ColumnModel({
dataIndex : 'homeOrganizationalUnitName'
dataIndex : 'timeZoneName'
dataIndex : 'languageName'
window.location=createNewPersonActionUrl;
bbar : new Ext.PagingToolbar({
pageSize : defaultRecordSize,
if ('maximized' == portletWindowState) {
gridConfig.height = document.documentElement.clientHeight - 188;
} elseif ('normal' == portletWindowState) {
gridConfig.viewConfig = viewConfig;
if (gridHeight && gridHeight > -1) {
gridConfig.height = gridHeight;
gridConfig.autoHeight = true;
var grid = new Ext.grid.GridPanel(gridConfig);
portlet.xml
Example of the portlet specification. The portlet-class needs to be set along with a pair of init-params—contextConfigLocation and nsContentPortlet (nsContentPortlet is always set to “false”).
<?xmlversion="1.0"encoding="UTF-8"?>
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http:www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
See the License for the specific language governing permissions and
limitations under the License.
xmlns="http:java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
http:java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd">
<description>MyJSR Description</description>
<portlet-name>nsMyJSR</portlet-name>
<display-name>My JSR Portlet</display-name>
<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
<name>contextConfigLocation</name>
<value>/WEB-INF/classes/config/spring/MyJSRApplicationContext.xml</value>
<name>nsContentPortlet</name>
<expiration-cache>-1</expiration-cache>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
<portlet-mode>EDIT</portlet-mode>
<portlet-mode>HELP</portlet-mode>
<title>My JSR Portlet</title>
web.xml
Example deployment descriptor with the servlet and servlet mapping is required by the portal server; in this case, Apache Pluto.
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEweb-appPUBLIC"-Sun Microsystems, Inc. DTD Web Application 2.3EN""http:java.sun.com/dtd/web-app_2_3.dtd">
<display-name>My JSR Portlet Application</display-name>
<description>My JSR Portlet</description>
<!-- Resources bundle base class -->
<param-name>contextConfigLocation</param-name>
/WEB-INF/classes/config/spring/MyJSRApplicationContext.xml
<param-name>parameter-name</param-name>
<param-value>parameter-value</param-value>
<servlet-name>ViewRendererServlet</servlet-name>
org.springframework.web.servlet.ViewRendererServlet
<servlet-name>MyJSR</servlet-name>
<servlet-class>org.apache.pluto.container.driver.PortletServlet</servlet-class>
<param-name>portlet-name</param-name>
<param-value>MyJSR</param-value>
<load-on-startup>1</load-on-startup>
<servlet-name>ViewRendererServlet</servlet-name>
<url-pattern>/WEB-INF/servlet/view</url-pattern>
<servlet-name>MyJSR</servlet-name>
<url-pattern>/PlutoInvoker/nsMyJSR</url-pattern>
<!- Declare Tag libraries that are used in which are going to use in JSP pages-->
<taglib-uri>http://portals.apache.org/pluto</taglib-uri>
<taglib-location>/WEB-INF/tld/pluto.tld</taglib-location>
<taglib-uri>http://java.sun.com/portlet_2_0</taglib-uri>
<taglib-location>/WEB-INF/tld/portlet_2_0.tld</taglib-location>
<taglib-uri>/WEB-INF/tld/c.tld</taglib-uri>
<taglib-location>/WEB-INF/tld/c.tld</taglib-location>
<taglib-uri>http://java.sun.com/portlet</taglib-uri>
<taglib-location>/WEB-INF/tld/portlet.tld</taglib-location>
<taglib-uri>http://portals.apache.org/pluto/portlet-el</taglib-uri>
<taglib-location>/WEB-INF/tld/portlet-el.tld</taglib-location>
<taglib-uri>http://portals.apache.org/pluto/portlet-el_2_0</taglib-uri>
<taglib-location>/WEB-INF/tld/portlet-el_2_0.tld</taglib-location>
MyJSREdit.jsp
JSP for portlet edit mode.
* Copyright (c) 2012, Cisco Systems, Inc. All rights reserved.
<%@tagliburi="http:java.sun.com/portlet"prefix="portlet"%>
<%@taglibprefix="portlet2"uri="http:java.sun.com/portlet_2_0"%>
<%@taglibprefix="c"uri="/WEB-INF/tld/c.tld"%>
<% String contextPath = request.getContextPath(); %>
<scripttype="text/javascript">
if(document.createStyleSheet) {
document.createStyleSheet('<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>');
var styles = "@import url('<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>');";
var newSS=document.createElement('link');
newSS.href='data:text/css,'+escape(styles);
document.getElementsByTagName("head")[0].appendChild(newSS);
<!-- This is foFirefox -->
<linkrel="stylesheet"type="text/css"href="<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>"></link>
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '<%= response.encodeURL(contextPath + "/js/MyJSREdit.js") %>';
head.appendChild(script);
<!-- Write your JSP Code for Portlet Edit here -->
<c:iftest="${portletWindowState == 'NORMAL' or portletWindowState == 'normal'}">
Portlet Mode = <c:outvalue='${portletMode}'/>
Portlet Window State = <c:outvalue='${portletWindowState}'/>
<c:iftest="${portletWindowState == 'MINIMIZED' or portletWindowState == 'minimized'}">
Portlet Mode = <c:outvalue='${portletMode}'/>
Portlet Window State = <c:outvalue='${portletWindowState}'/>
<c:iftest="${portletWindowState == 'MAXIMIZED' or portletWindowState == 'maximized'}">
Portlet Mode = <c:outvalue='${portletMode}'/>
Portlet Window State = <c:outvalue='${portletWindowState}'/>
<divid="MyJSREditDiv-<portlet:namespace/>"class="x-grid-mso"></div>
var MyJSREditDiv = 'MyJSREditDiv-<portlet:namespace/>';
var addPersonActionUrl = '<portlet2:resourceURL id="addPersonData" escapeXml="false" />';
var personListObj = Ext.util.JSON.decode('<c:out value="${PersonData}" escapeXml="false"/>');
MyJSRHelp.jsp
JSP for portlet help mode.
* Copyright (c) 2012, Cisco Systems, Inc. All rights reserved.
<%@tagliburi="http:java.sun.com/portlet"prefix="portlet"%>
<%@taglibprefix="c"uri="/WEB-INF/tld/c.tld"%>
<% String contextPath = request.getContextPath(); %>
<scripttype="text/javascript">
if(document.createStyleSheet) {
document.createStyleSheet("<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>");
var styles = "@import url('<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>');";
var newSS=document.createElement('link');
newSS.href='data:text/css,'+escape(styles);
document.getElementsByTagName("head")[0].appendChild(newSS);
<!-- This is foFirefox -->
<linkrel="stylesheet"type="text/css"href="<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>"></link>
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '<%= response.encodeURL(contextPath + "/js/MyJSRHelp.js") %>';
head.appendChild(script);
<!-- Write your JSP Code for Portlet Help here -->
<c:iftest="${portletWindowState == 'NORMAL' or portletWindowState == 'normal'}">
Portlet Mode = <c:outvalue='${portletMode}'/>
Portlet Window State = <c:outvalue='${portletWindowState}'/>
<c:iftest="${portletWindowState == 'MINIMIZED' or portletWindowState == 'minimized'}">
Portlet Mode = <c:outvalue='${portletMode}'/>
Portlet Window State = <c:outvalue='${portletWindowState}'/>
<c:iftest="${portletWindowState == 'MAXIMIZED' or portletWindowState == 'maximized'}">
Portlet Mode = <c:outvalue='${portletMode}'/>
Portlet Window State = <c:outvalue='${portletWindowState}'/>
<divid="MyJSRHelpDiv-<portlet:namespace/>"class="x-grid-mso"></div>
var MyJSRHelpDiv = 'MyJSRHelpDiv-<portlet:namespace/>';
MyJSRView_listperson.jsp
JSP code for portlet view mode.
* Copyright (c) 2012, Cisco Systems, Inc. All rights reserved.
<%@tagliburi="http:java.sun.com/portlet"prefix="portlet"%>
<%@taglibprefix="portlet2"uri="http:java.sun.com/portlet_2_0"%>
<%@taglibprefix="c"uri="/WEB-INF/tld/c.tld"%>
<% String contextPath = request.getContextPath(); %>
<scripttype="text/javascript">
if(document.createStyleSheet) {
document.createStyleSheet('<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>');
var styles = "@import url('<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>');";
var newSS=document.createElement('link');
newSS.href='data:text/css,'+escape(styles);
document.getElementsByTagName("head")[0].appendChild(newSS);
var portletId = 'portlet-container-<c:out value="${portlet}"/>';
var pidPrefix = "portlet-container-";
var portletWindowState = "<c:out value='${portletWindowState}'/>";
var portletMode = "<c:out value='${portletMode}'/>";
var defaultRecordSize = <c:out value='${defaultRecordSize}'/>;
var nsappPersonViewDiv = 'nsappPersonViewDiv-<portlet:namespace/>';
var pagingUrl = '<portlet2:resourceURL escapeXml="false" />';
var connectionTimeOut = <c:out value='${connectionTimeOut}'/>;
<!-- This is foFirefox -->
<linkrel="stylesheet"type="text/css"href="<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>"></link>
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '<%= response.encodeURL(contextPath + "/js/MyJSRView.js") %>';
head.appendChild(script);
<!-- Write your JSP Code for Portlet Edit here -->
<c:iftest="${portletWindowState == 'NORMAL' or portletWindowState == 'normal'}">
<!--PortletMode = <c:out value='${portletMode}'/>
Portlet Window State = <c:out value='${portletWindowState}'/> -->
<c:iftest="${portletWindowState == 'MINIMIZED' or portletWindowState == 'minimized'}">
<!--Portlet Mode = <c:out value='${portletMode}'/>
Portlet Window State = <c:out value='${portletWindowState}'/> -->
<c:iftest="${portletWindowState == 'MAXIMIZED' or portletWindowState == 'maximized'}">
<!--Portlet Mode = <c:out value='${portletMode}'/>
Portlet Window State = <c:out value='${portletWindowState}'/>-->
<!-Un-comment this to get User Info from the Portlet Controller that sets user info in model
Logged In User (<c:out value="${userName}" escapeXml="false"/>): <c:out value="${firstName}" escapeXml="false"/> , <c:out value="${lastName}" escapeXml="false"/> , <c:out value="${PersonId}" escapeXml="false"/> , <c:out value="${HomeOUId}" escapeXml="false"/>
<!-Write declare divs to display user info -->
<div>Logged In User (<div id="MyJSRLoginNameDiv" style="text-align:right;display:inline;width:100%;"><span style="padding-left:20px;"></span></div>) : <div id="MyJSRFirstNameDiv" style="text-align:right;display:inline;width:100%;"><span></span></div> ,
<divid="MyJSRLastNameDiv" style="text-align:right;display:inline;width:100%;"><span style="padding-left:20px;"></span></div>
<div>HomeOUId : <div id="MyJSRHomeOUDiv" style="text-align:right;display:inline;width:100%;"><span style="padding-left:20px;"></span></div> ,
PersonId : <div id="MyJSRPortletPersonIDDiv" style="text-align:right;display:inline;width:100%;"><span style="padding-left:20px;"></span>
<divid="MyJSREditDiv-<portlet:namespace/>"class="x-grid-mso"></div>
var MyJSREditDiv = 'MyJSREditDiv-<portlet:namespace/>';
var createNewPersonActionUrl = '<portlet:renderURL><portlet:param name="formAction" value="createNewPerson" /></portlet:renderURL>';
var addPersonActionUrl = '<portlet2:resourceURL id="addPersonData" escapeXml="false" />';
var personListObj = Ext.util.JSON.decode('<c:out value="${PersonData}" escapeXml="false"/>');
MyJSRView_updateperson.jsp
Example JSP code to demonstrate update user operation.
* Copyright (c) 2012, Cisco Systems, Inc. All rights reserved.
<%@tagliburi="http:java.sun.com/portlet"prefix="portlet"%>
<%@taglibprefix="portlet2"uri="http:java.sun.com/portlet_2_0"%>
<%@taglibprefix="c"uri="/WEB-INF/tld/c.tld"%>
<%String contextPath = request.getContextPath(); %>
<!-- This is foFirefox -->
<linkrel="stylesheet"type="text/css"href="<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>"></link>
<scripttype="text/javascript">
if(document.createStyleSheet) {
document.createStyleSheet("<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>");
var styles = "@import url('<%= response.encodeURL(contextPath + "/css/MyJSR.css") %>');";
var newSS=document.createElement('link');
newSS.href='data:text/css,'+escape(styles);
document.getElementsByTagName("head")[0].appendChild(newSS);
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '<%= response.encodeURL(contextPath + "/js/MyJSRCreatePersonView.js") %>';
head.appendChild(script);
<!-- Write your JSP Code for Portlet View here -->
<c:iftest="${portletWindowState == 'NORMAL' or portletWindowState == 'normal'}">
<!--Portlet Mode = <c:out value='${portletMode}'/>
Portlet Window State = <c:out value='${portletWindowState}'/> -->
<c:iftest="${portletWindowState == 'MINIMIZED' or portletWindowState == 'minimized'}">
<!--Portlet Mode = <c:out value='${portletMode}'/>
Portlet Window State = <c:out value='${portletWindowState}'/> -->
<c:iftest="${portletWindowState == 'MAXIMIZED' or portletWindowState == 'maximized'}">
<!--Portlet Mode = <c:out value='${portletMode}'/>
Portlet Window State = <c:out value='${portletWindowState}'/>-->
<divid="MyJSREditDiv-<portlet:namespace/>"class="x-grid-mso"></div>
var MyJSREditDiv = 'MyJSREditDiv-<portlet:namespace/>';
var addPersonActionUrl = '<portlet2:resourceURL id="addPersonData" escapeXml="false" />';
var viewPersonUrl = '<portlet:renderURL></portlet:renderURL>';
var personListObj = Ext.util.JSON.decode('<c:out value="${PersonData}" escapeXml="false"/>');
MyJSRController.java
The steps for developing java portlet controllers typically include:
Step 1 Write handler code for the three portlet modes—View, Edit, and Help.
Step 2 Write handler code for the three portlet views—Normal, Minimized, and Maximized.
Step 3 For JSR portlets that process/display Service Catalog entities, the nsAPI client can be used to invoke the related REST APIs in the portlet controller.
a. Get reference to nsAPI client API.
b. Call nsAPI client to get a list of the instances for the required Service Catalog entity.
c. Optionally get the details for the currently logged-in user; for example, Person ID, First Name, Last Name.
Step 4 Render the instances in a grid or other format (this example also demonstrates how to do paging in nsAPI for a Ext JS Grid).
importjava.io.IOException;
importjava.util.ArrayList;
importjava.util.Iterator;
importjava.util.Properties;
importjavax.portlet.RenderRequest;
importjavax.portlet.RenderResponse;
importjavax.portlet.ResourceRequest;
importjavax.portlet.ResourceResponse;
importnet.sf.json.JSONSerializer;
importjavax.portlet.ActionRequest;
importjavax.servlet.http.HttpSession;
importjavax.portlet.PortletURL;
importorg.apache.commons.collections.map.MultiValueMap;
importorg.apache.commons.lang.StringEscapeUtils;
importorg.apache.commons.lang.StringUtils;
importorg.springframework.ui.Model;
importorg.springframework.web.portlet.ModelAndView;
importorg.springframework.web.bind.annotation.ModelAttribute;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.portlet.bind.annotation.ResourceMapping;
importorg.springframework.web.bind.annotation.RequestParam;
importcom.newscale.comps.conf.domain.AppParamUtil;
importcom.newscale.nsapi.directory.person.Person;
importcom.newscale.nsapi.directory.person.PersonList;
importcom.newscale.nsapiclient.NSApiClient;
importcom.newscale.nsapiclient.NSApiClientConstants;
importcom.newscale.nsapiclient.NSApiClientFactory;
importcom.newscale.portlets.GenericNewScaleSpringPortletBase;
publicclass MyJSRController extends GenericNewScaleSpringPortletBase {
privatestaticfinal String configPropsFile = "jsrportlet.properties";
privatestaticfinal String viewPageList = "MyJSRView_listperson";
privatestaticfinal String viewPageUpdate = "MyJSRView_updateperson";
privatestaticfinal String editPage = "MyJSREdit";
privatestaticfinal String helpPage = "MyJSRHelp";
private NSApiClient nsApiClient = getNSApiClient();
public NSApiClient getNsApiClient() {
public void setNsApiClient(NSApiClient nsApiClient) {
this.nsApiClient = nsApiClient;
public String viewNormal(RenderRequest request, RenderResponse response, Model model) {
super.viewNormal(request, response, model);
getLoginUsername(request, model);
return doView(request, response, model);
public String viewMinimized(RenderRequest request, RenderResponse response, Model model) {
super.viewMinimized(request, response, model);
public String viewMaximized(RenderRequest request, RenderResponse response, Model model) {
super.viewMaximized(request, response, model);
getLoginUsername(request, model);
return doView(request, response, model);
private void getLoginUsername(RenderRequest request, Model model){
Properties properties = getConfigProperties(configPropsFile);
nsApiClient.login(properties.getProperty("BASE_URL"), request.getPortletSession().getId());
// Get Currently Logged-in user from nsAPI client
Person persons = nsApiClient.getDirectory().getCurrentUser();
// Set user info into model so that JSP can access it
model.addAttribute("PersonID", persons.getPersonId());
model.addAttribute("HomeOUId", persons.getHomeOrganizationalUnitId());
model.addAttribute("firstName", persons.getFirstName());
model.addAttribute("lastName", persons.getLastName());
model.addAttribute("userName", persons.getLogin());
private String doView(RenderRequest request, RenderResponse response, Model model) {
Properties properties = getConfigProperties(configPropsFile);
nsApiClient.login(properties.getProperty("BASE_URL"), request.getPortletSession().getId());
int defaultRecordSize = AppParamUtil.getInstance().getMaxMaxPagingSizeInNSApi();
model.addAttribute("defaultRecordSize", "" + defaultRecordSize);
int connectionTimeOut = 0;
if (AppParamUtil.getInstance().isParamExists((AppParamUtil.SESSION_TIMEOUT))) {
connectionTimeOut = AppParamUtil.getInstance().getIntegerParam(AppParamUtil.SESSION_TIMEOUT);
if (connectionTimeOut < 1) {
model.addAttribute("connectionTimeOut", "" + connectionTimeOut * 1000 * 60);
String formAction = request.getParameter("formAction");
String personIdStr = request.getParameter("personId");
if (null != formAction && formAction.equals("createNewPerson")) {
showAddPersonPage(request, response, model);
} elseif(null != personIdStr){
editPerson(request, response, model, new Integer(personIdStr).intValue());
public ModelAndView doPagingOrSavePerson(ResourceRequest request, ResourceResponse response, Person person)
String instanceName= getInstanceName(request.getWindowID());
Save Button is clicked while adding person
if ("createNewPerson".equals(request.getParameter("formAction")) || null != request.getParameter("personId")) {
addPersonData(person,request, response);
} elseif (null != request.getParameter("start") &&null != request.getParameter("limit")) { Paging
int startInt = Integer.parseInt(request.getParameter("start")) + 1; extjs sends 1 less than what nsAPI wants
int limit = Integer.parseInt(request.getParameter("limit")) + 1; extjs sends 1 less than what nsAPI wants
if (request.getWindowState().equals(request.getWindowState().NORMAL)) {
doPagingInternal(request, response, instanceName, 1, startInt, limit);
if (request.getWindowState().equals(request.getWindowState().MAXIMIZED)) {
doPagingInternal(request, response, instanceName, 2, startInt, limit);
private void doPagingInternal(ResourceRequest request, ResourceResponse response, String portletInst,
int windowStateInt, int start, int limit) throws Exception {
Map<String, Object> jsonMap = new HashMap<String, Object>();
List recordList = newArrayList();
String editPersonUrl = request.getParameter("editPersonUrl");
MultiValueMap paramsmap = new MultiValueMap();
paramsmap.put(NSApiClientConstants.QUERYPARAM_START_ROW, "" + start);
paramsmap.put(NSApiClientConstants.QUERYPARAM_RECORD_SIZE, "" + limit);
PersonList personList = nsApiClient.getDirectory().getPeople(paramsmap);
if(personList.getPeople() != null) {
for(Iterator iterator = personList.getPeople().iterator(); iterator.hasNext();) {
Person portalPerson = (Person) iterator.next();
portalPerson.setPersonURL(StringEscapeUtils.escapeXml(portalPerson.getPersonURL()));
PortletURL editPersonURL = response.createRenderURL();
editPersonURL.setParameter("personId", "" + portalPerson.getPersonId());
String firstNameUrl = "<a href='" + editPersonURL.toString() + "'>" + portalPerson.getFirstName() + "</a>";
String lastNameUrl = "<a href='" + editPersonURL.toString() + "'>" + portalPerson.getLastName() + "</a>";
portalPerson.setFirstName(firstNameUrl);
portalPerson.setLastName(lastNameUrl);
recordList.add(portalPerson);
jsonMap.put("success", "true");
jsonMap.put("results", personList.getTotalCount());
jsonMap.put("rows", recordList);
JSON json = (JSON) JSONSerializer.toJSON(jsonMap);
String jsonStr = json.toString();
response.setContentType("text/plain");
response.getPortletOutputStream().write(jsonStr.getBytes());
response.getPortletOutputStream().flush();
private ModelAndView addPersonData(@ModelAttribute("personData") Person person,
ResourceRequest request, ResourceResponse response) throws Exception {
Add Person from Form Data in Request
Map jsonMap = newHashMap();
Person Updateperson = nsApiClient.getDirectory().updatePerson(person);
jsonMap.put("success", "true");
jsonMap.put("successMsg", "Person Added/Updated Successfully");
jsonMap.put("rows", Updateperson);
JSON json = (JSON) JSONSerializer.toJSON(jsonMap);
String jsonStr = json.toString();
response.setContentType("text/plain");
response.getPortletOutputStream().write(jsonStr.getBytes());
response.getPortletOutputStream().flush();
jsonMap.put("success", "false");
jsonMap.put("errorMsg", "Person Add/Update Failed : " + e.getMessage());
JSON json2 = (JSON) JSONSerializer.toJSON(jsonMap);
String jsonStr2 = json2.toString();
response.setContentType("text/plain");
response.getPortletOutputStream().write(jsonStr2.getBytes());
response.getPortletOutputStream().flush();
private void editPerson(RenderRequest request, RenderResponse response, Model model, int personId) {
Map<String, Object> jsonMap = new HashMap<String, Object>();
Person persons = nsApiClient.getDirectory().getPersonById(person);
persons.setPersonURL(StringEscapeUtils.escapeXml(persons.getPersonURL()));
JSON json = (JSON) JSONSerializer.toJSON(persons);
String jsonStr = json.toString();
model.addAttribute("PersonData", jsonStr);
private String showAddPersonPage(RenderRequest request, RenderResponse response, Model model) {
Person DummyPerson = newPerson();
DummyPerson.setPersonURL(StringEscapeUtils.escapeXml(DummyPerson.getPersonURL()));
JSON json1 = (JSON) JSONSerializer.toJSON(DummyPerson);
String jsonStr1 = json1.toString();
model.addAttribute("PersonData", jsonStr1);
public String editNormal(RenderRequest request, RenderResponse response, Model model) {
super.editNormal(request, response, model);
public String editMinimized(RenderRequest request, RenderResponse response, Model model) {
super.editMinimized(request, response, model);
public String editMaximized(RenderRequest request, RenderResponse response, Model model) {
super.editMaximized(request, response, model);
public String helpNormal(RenderRequest request, RenderResponse response, Model model) {
super.helpNormal(request, response, model);
public String helpMinimized(RenderRequest request, RenderResponse response, Model model) {
super.helpMinimized(request, response, model);
public String helpMaximized(RenderRequest request, RenderResponse response, Model model) {
super.helpMaximized(request, response, model);
private NSApiClient getNSApiClient() {
return NSApiClientFactory.getInstance();
MyJSRApplicationContext.xml
Spring application context XML for the portlet.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http:www.springframework.org/schema/beans"
xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance"xmlns:p="http:www.springframework.org/schema/p"
xmlns:context="http:www.springframework.org/schema/context"
http:www.springframework.org/schema/beans http:www.springframework.org/schema/beans/spring-beans-2.5.xsd
http:www.springframework.org/schema/context http:www.springframework.org/schema/context/spring-context-2.5.xsd">
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<propertyname="cache"value="true"/>
<propertyname="viewClass"
value="org.springframework.web.servlet.view.JstlView"/>
<propertyname="prefix"value="/WEB-INF/jsp/"/>
<propertyname="suffix"value=".jsp"/>
<context:annotation-config/>
class="org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<propertyname="interceptors">
class="org.springframework.web.portlet.handler.ParameterMappingInterceptor"/>
<beanid="MyJSRController"class="com.myjsr.MyJSRController">
jsrportlet.properties
URL of the MyJSRerver for the use by nsAPI.
Note In a clustered environment, if the portlet references the Service Catalog application URL, then specify the URL as “http://localhost:<port>/RequestCenter” where <port> is the port number used by each node in the cluster. In other words, do not specify the URL as “http:<host_name>/RequestCenter” where <host_name> is the computer name of the web server or one of the hosts within the cluster.
#(Port number and host has to changed as per the application server).
BASE_URL=http:localhost:8088/RequestCenter
Log4j.properties
log4j.rootCategory=INFO,CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ABSOLUTE}%-5p[%c{1}:%L]%m%n
jboss-deployment-structure.xml
<jboss-deployment-structure>
<module name="javax.portlet" slot="main" export="true"/>
<module name="org.apache.pluto.container.om" export="true"/>
<module name="org.apache.pluto.container.driver" export="true"/>
<module name="org.apache.pluto.tags" export="true"/>
</jboss-deployment-structure>