PageBuilder 2 skin architecuter - skin.html

The PageBuilder 2 theme makes use of theme.html for defining layout of the page, it makes use of skin.html for generating markup for the skin. Note that it does not have UnlayeredContainer-H.jsp, UnlayeredContainer-V.jsp, control.jsp any more. It seems that layout.html will replace the horizontal and vertical container related functionality and the skin.html has functionality corresponding to Control.jsp.

This is how the skin.html from my local machine looks like

<div class="ibmPortalControl lotusWidget2 decoration-aria-region"><!--START LOCALE LINKS-->
<a rel="alternate" href="nls/skin_en.html" hreflang="en" class="ibmHideTemplate"></a>
<!-- decoration marks the Dojo resource name of the decoration object instantiated at the root of this layout control -->
<span style="display:none" class="decoration">com.ibm.skins.Standard.skin</span>
<!-- asa.portlet.id marks the node whose contents are the id of this layout control;
set at runtime by script in the decoration instance -->
<span style="display:none" class="asa.portlet.id"></span>
<!-- decoration classes are used by DecorationManager for adding javascript event handlers -->
<h2 class="decoration-titlebar decoration-dndHandle">
<span class="lotusLeft"> <!-- lm-dynamic-title node marks location for dynamic title support -->
<span class="lm-dynamic-title asa.portlet.title decoration-title">
<a rel="dynamic-content" href="lm:title"></a>
</span>
</span>
<a aria-haspopup="true" title="${nls.Theme:a11y_display_menu:xml}" href="javascript:;"
class="lotusIcon lotusActionMenu decoration-contextMenuAction">
<span class="lotusAltText">${nls.Theme:theme_actions:xml}</span>
</a>
</h2>
<!-- decoration-contextMenu is the anchor node to build the context menu link and widget around -->
<div style="display:none" class="decoration-contextMenu"></div>
<div class="lotusWidgetBody"> <!-- lm:control dynamic spot injects markup of layout control -->
<a rel="dynamic-content" href="lm:control"></a>
</div>
</div>


The skin.html also makes use of concept of dynamic content spot.


  • lm:title : represents the title of the portlet

  • lm:control : represents the body of the portlet

PageBuilder2 theme architecture - Dynamic Content Spot

In the PageBuilder2 theme architecture - theme.html i mentioned that the theme.html makes use of concept of dynamic content spot. The basic concept is that the theme.html want to include .jsp page, since the .html page cannot directly add .jsp page since .jsp pages need servlet context to compile and execute, those .jsps are packaged in the PageBuilder2.war along with Default.jsp.



Ex. the theme.html wants to forward control to asa.jsp for generating active sight analytics(asa) related markup, so you can include that .jsp in the theme.html like this

<a rel="dynamic-content"
href="res:/PageBuilder2/themes/html/PageBuilder2.0/asa.jsp"></a>


But this approach has following problems

  • Reference by name abstracts the dynamic content away from the implementation. This is necessary if the theme needs to run on multiple runtimes, for example WebSphere Portal and IBM® Mashup Center. The portal implementation of the navigation tabs can be a JSP that contains portal specific code. The Mashup Center on the other hand cannot execute portal JSP code, but provides an iWidget instead.

  • Reference by name isolates the theme author from having to know the underlying code information. This is useful if the theme author is an HTML and CSS designer, but not a J2EE or JavaScript developer. The HTML and CSS developer needs to know only the list of named content spots and the simple syntax to add it. This developer can then write code without having to know JSP path names etc.



So in order to provide one more layer of indirection, WPS has WP_DynamicContentSpotMappings resource provider that lets you map a symbolic name to the location of .jsp like this




Now inside your theme.html you can refer to the asa.jsp like this

<a rel="dynamic-content" href="dyn-cs:id:asa@tl:oid:csa2.theme" />


The resolver framework takes care of finding the actual .jsp file from this symbolic name. Also if you start digging into the .jsp files you will notice that they also include other .jsps by using this type of syntax


<r:dataSource uri="dyn-cs:id:configGlobal@tl:oid:csa2.theme" escape="none">
<r:param name="pragma" value="cache"/>
</r:dataSource>
<r:dataSource uri="dyn-cs:id:configDynamic@tl:oid:csa2.theme" escape="none"/>

PageBuilder2 theme architecture - theme.html

In the PageBuilder2 Theme architecture - bootstrap jsps, i mentioned that the Default.jsp of the PageBuilder2 theme does not have any HTML markup, instead it just initializing few values and then forwarding control to theme.html.

This is how the theme.html which ships with the WPS looks like. As you can see the theme.html is pretty clean and small,


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="${locale}" xml:lang="${locale}">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- rel=dynamic-content indicates an element that is replaced with the contents produced by the specified href.
dyn-cs:* URIs are resolved using the WP DynamicContentSpotMappings resource environment provider. These values can
also be set using theme metadata if a theme is specified in the URI (e.g. @tl:oid:theme_unique_name). -->
<link rel="dynamic-content" href="dyn-cs:id:head@tl:oid:csa2.theme">
<script type="text/javascript">
dojo.addOnLoad(function(){
com.ibm.pb.themes.commonInit({
setWindowTitle:true,
useNavigationController: true,
useRenderingController: true,
useDNDController: true,
initLiveTextService: true,
lazyLoadModeWidgets: true,
navPrimingContainers: ["selectionPathPrimer","topNavLinks","navTabsRoot"],
customInit: com.ibm.themes.PageBuilder2.init
});
dojo.publish("com.ibm.portal.theme.portlet_ready"); // notifies ASA that portlet IDs are ready to be found in the DOM
});
</script>
<!-- rendering is delegated to the specified href for each locale --><!--START LOCALE LINKS-->
<link rel="alternate" href="nls/theme_en.html" hreflang="en">
</head>
<body class="lotusui tundra${rtl| lotus_rtl mumrtl} locale_${locale}" ${bidi.dir.attribute} >

<div class="lotusFrame">
<div class="lotusui lotusTitleBar">
<div class="lotusRightCorner">
<div class="lotusInner">
<a rel="dynamic-content" href="dyn-cs:id:tabNav@tl:oid:csa2.theme"></a>
<div style="clear: both;"></div>
</div>
</div>
</div><!--end titleBar-->
<a rel="dynamic-content" href="dyn-cs:id:pageToolbar@tl:oid:csa2.theme"></a>
<div class="lotusMain" id="lotusMain">
<!-- pb-pageMode-edit indicates that an iwidget should be lazy-loaded upon entering edit mode for the page -->
<div class="iw-iWidget iw-Standalone pb-pageMode-edit" id="customizeShelfContainer">
<a class="iw-Definition"
href="/mccbuilder/widget-catalog/customizeShelf.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
</div>
<div style="clear:both;"></div>
<a id="lotusMainContent" name="lotusMainContent"></a>
<div id="layoutContainers" class="ibmLayoutContainers ibmLayoutContainersHidden" role="main">
<a rel="dynamic-content" href="dyn-cs:id:layout@tl:oid:csa2.theme"></a>
</div>
</div><!--end main-->
<div class="lotusFooter"></div><!-- page footer -->
</div><!--end frame-->
<!-- active site analytics additions -->
<a rel="dynamic-content" href="dyn-cs:id:asa@tl:oid:csa2.theme"></a>
<!-- This is responsible for bootstrapping the configuration for the javascript framework.
This is located here instead of the head section to improve client performance. -->
<a rel="dynamic-content" href="dyn-cs:id:config@tl:oid:csa2.theme"></a>

<div id="systemWidgets">
<div class="iw-iWidget iw-Standalone" id="templateLayout">
<a class="iw-Definition"
href="/mccbuilder/widget-catalog/templateLayout.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
</div>
<div class="iw-iWidget mumHiddenWidget iw-Standalone" id="pageActionsMenu">
<a class="iw-Definition"
href="/mccbuilder/widget-catalog/ContentSetMenu.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
<span class="iw-ItemSet" title="attributes" style="display: none;">
<a class="iw-Item" href="#contextMenuID">pageActions</a>
<a class="iw-Item" href="#anchorCSSClass">lotusCommonActionMenuAnchor</a>
<a class="iw-Item" href="#menuCSSClass">lotusCommonActionMenu</a>
<a class="iw-Item" href="#resourceType">com.ibm.mashups.enabler.navigation.NavigationNode</a>
<a class="iw-Item" href="#openEvent">PageActions.open</a>
<a class="iw-Item" href="#closeEvent">PageActions.close</a>
</span>
</div>
<div class="iw-iWidget mumHiddenWidget iw-Standalone" id="userActionsMenu">
<a class="iw-Definition" href="/mccbuilder/widget-catalog/ContentSetMenu.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
<span class="iw-ItemSet" title="attributes" style="display: none;">
<a class="iw-Item" href="#contextMenuID">userActions</a>
<a class="iw-Item" href="#anchorCSSClass">lotusCommonActionMenuAnchor</a>
<a class="iw-Item" href="#menuCSSClass">lotusCommonActionMenu</a>
<a class="iw-Item" href="#resourceType">com.ibm.mashups.enabler.user.User</a>
<a class="iw-Item" href="#openEvent">UserActions.open</a>
<a class="iw-Item" href="#closeEvent">UserActions.close</a>
</span>
</div>
<div class="iw-iWidget mumHiddenWidget iw-Standalone pb-pageMode-edit" id="newPage">
<a class="iw-Definition"
href="/mccbuilder/widget-catalog/NewPageDialog.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
<span class="iw-ItemSet" style="display:none" title="attributes">
<a class="iw-Item" href="#controller">ibmCfg.controllers.navigation</a>
<a class="iw-Item" href="#allowFriendlyURL">true</a>
<a class="iw-Item" href="#allowPrivate">true</a>
</span>
</div>
<!-- The lazyLoad attribute is used for widgets that are explicitly loaded by another source at a later point in time
(in this case the displayHelper). -->
<div class="iw-iWidget mumHiddenWidget iw-Standalone" lazyLoad="true" id="sharePage">
<a class="iw-Definition"
href="/mccbuilder/widget-catalog/accessControl.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
</div>
<div class="iw-iWidget mumHiddenWidget iw-Standalone" lazyLoad="true" id="reorderPage">
<a class="iw-Definition"
href="/mccbuilder/widget-catalog/reorderPageWidget.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
</div>
<div class="iw-iWidget mumHiddenWidget iw-Standalone" lazyLoad="true" id="viewMorePage">
<a class="iw-Definition"
href="/mccbuilder/widget-catalog/viewMorePage.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
</div>
<div class="iw-iWidget mumHiddenWidget iw-Standalone" lazyLoad="true" id="wireInterface">
<a class="iw-Definition"
href="/mccbuilder/widget-catalog/wireInterfaceWithSettings.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
<span class="iw-ItemSet" title="attributes" style="visibility: hidden; display: none">
<a class="iw-Item" style="visibility:hidden;display:none;" href="#displaySettings">true</a>
<a class="iw-Item" style="visibility:hidden;display:none;" href="#displayPortletsAndWidgetsWarningMessage">true</a>
</span>
</div>
<div class="iw-iWidget mumHiddenWidget iw-Standalone pb-pageMode-edit" id="autoWiringManager">
<a class="iw-Definition"
href="/mccbuilder/widget-catalog/autoWiringManager.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"></a>
</div>
<div class="iw-iWidget iw-Standalone" id="dialogDisplayer">
<a class="iw-Definition" style="visibility:hidden;display:none;"
href="/mccbuilder/widget-catalog/displayHelper.xml?pragma=cache&max-age=1209600&cache-scope=public&vary=none"> </a>
<span class="iw-ItemSet" title="attributes" style="visibility: hidden; display: none;">
<a class="iw-Item" style="visibility:hidden;display:none;" href="#sharePage">sharePage</a>
<a class="iw-Item" style="visibility:hidden;display:none;" href="#reorderPage">reorderPage</a>
<a class="iw-Item" style="visibility:hidden;display:none;" href="#viewMorePage">viewMorePage</a>
<a class="iw-Item" style="visibility:hidden;display:none;" href="#wireInterface">wireInterface</a>
<a class="iw-Item" style="visibility:hidden;display:none;" href="#autoWiringManager">autoWiringManager</a>
</span>
</div>
</div>
</body>
</html>



If you compare the theme.html to the markup generated for the portal page you will notice that the portal page has more markup(as expected it has markup generated by portal, markup for navigation,..)



Also if you compare this markup to the markup generated for portal page you will notice that most of the markup for normal page is generated inside div class="lotusFrame", which is the highlighted code. There is lot of code under div id="systemWidgets" but my guess is that code kicks in only in case of iwidget on a page.

Now the basic question would be then who is generating the portal markup, who takes care of generating navigation, forwarding control to portal aggregation engine,.. The answer would be its the dynamic content spots in the .html

PageBuilder2 Theme architecture - bootstrap jsps

In the PageBuilder2 theme architecture i mentioned that first thing that Default.jsp does is forward control to bootstrap.jspf and bootstrapPortal.jspf.

These two files are used for calculating portal level variables such as


  • isPageRenderModeCSA: If the page render mode is CSA or SSA

  • Locale: Avaiable locale, default locale

  • user Id: user id of the anonymous and authenticated user, if user is logged in

  • ContentHandlerURI: The URI for the ContentHandler by default it will always be /wps/contenthandler for anonymous or /wps/mycontenthandler for authenticated user, this URI is also used a base for all the resources

  • portalContext: /wps

  • portalProxyUrl: /wps/proxy

  • Dojo information: dojoRoot /portal_dojo/v1.4.3 and dojoContextRoot is /portal_dojo

  • themeWebDAVBaseURI: dav:fs-type1/themes/PageBuilder2/

  • themeWebAppBaseURI: /PageBuilder2/themes/html/PageBuilder2

  • colorPalette: By default its empty but you can override these values at page level

  • pageStyle:By default its empty but you can override these values at page level

  • navTabsLevel,navTabRootNode: Navigation generation related information

PageBuilder2 theme architecture - Default.jsp

IBM introduced PageBuilder2 theme in WPS 7.0, it allows user to define the theme using static html file, it seems that there are different pieces and i wanted to check how the different pieces fit together, so i started debugging theme and these are my notes

Even though the PageBuilder2 theme is changed one thing is still same which is Default.jsp file in the theme acts as entry point, it controls the overall theme. This is how the Default.jsp of PageBuilder2 theme looks like


<%@ page session="false" buffer="none" %>
<%@ page trimDirectiveWhitespaces="true" %>
<%-- Licensed Materials - Property of IBM, 5724-E76, (C) Copyright IBM Corp. 2001, 2004, 2006, 2010 - All Rights reserved. --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v7.0/portal-core" prefix="portal-core" %>
<%@taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v7.0/portal-logic" prefix="portal-logic" %>
<%@taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v7.0/portal-fmt" prefix="portal-fmt" %>
<%@taglib uri="/WEB-INF/tld/portal-internal.tld" prefix="portal-internal" %>
<%@taglib uri="/WEB-INF/tld/resolver-v7.tld" prefix="r" %>
<portal-core:constants/>
<portal-core:defineObjects/>
<portal-internal:adminNavHelper/>
<%@ include file="./bootstrap.jspf" %>
<%@ include file="./bootstrapPortal.jspf" %>
<%-- The theme template is determined by whether there is a value set in page meta data,
if no value is set in the meta data, then it defaults to the template stored in webdav --%>
<c:choose>
<c:when test="${empty themeWebDAVBaseURI}">
<c:set var="themeTemplateURI" value="" />
</c:when>
<c:when test="${empty dirMD['com.ibm.portal.theme.template.file.name.html']}">
<c:set var="themeTemplateURI" value="${themeWebDAVBaseURI}theme.html" />
</c:when>
<c:otherwise>
<c:set var="themeTemplateURI" value="${themeWebDAVBaseURI}${dirMD['com.ibm.portal.theme.template.file.name.html']}" />
</c:otherwise>
</c:choose>
<c:choose>
<c:when test="${!empty themeTemplateURI}">
<r:dataSource uri="spa:${wp.identification[wp.selectionModel.selected]}" escape="none">
<r:param name="themeURI" value="${themeTemplateURI}"/>
<r:param name="mime-type" value="text/html"/>
</r:dataSource>
</c:when><%-- If no theme template is found, the fallback.jsp is rendered--%>
<c:otherwise>
<%@ include file="./fallback.jsp" %>
</c:otherwise>
</c:choose>


The Default.jsp is very simple and it does not have any HTML markup generation code at all. The functionality of Default.jsp can be broken into 3 parts


  • Initializing variables required for the theme: At the start of the Default.jsp it is forwarding control to bootstrap.jspf and bootstrapPortal.jspf, It looks like these two files are used for initializing all the variables that are required for theme. Things like if user is logged in, if yes what is userId, available locale, paths to contenthandler and also some variables that are required for calculating themeTemplateURI

  • Cacluate value of themeTemplateURI Next it tries to calculate value of themeTemplateURI. In the default implementation it will always be dav:fs-type1/themes/PageBuilder2/theme.html but your allowed to override this value at page level as well as at theme level

  • Forwarding control to r:dataSource for generating markup Once the value of themeTemplateURI is calculated control will fowarded to r:dataSource jsp tag, and this tag will be responsible for parsing theme.html, evaluating dynamic content spot, and generating final html markup

Where is source code for Page Builder 2 theme

The WebSphere portal server has a very different directory layout/ application deployment structure compared to the previous version, i think this was done to support multiple profiles but i need to dig into that part.

I am trying to learn about PageBuilder2(CSA2) theme that was introduced in WPS 7.0, so i thought i will look into the source code to find out how it works so i went to wp_profiles/installedApps folder but i could not see PageBuilder2.ear. In fact it seems that installedApps folder has few applications



But when i tried accessing any portal page i could see some PageBuilder2 theme related jsp's being initialized

[9/29/10 6:24:12:832 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/Default.jsp]: Initialization successful.
[9/29/10 6:24:14:684 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/head.jsp]: Initialization successful.
[9/29/10 6:24:21:426 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/bannerNav.jsp]: Initialization successful.
[9/29/10 6:24:21:581 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/search.jsp]: Initialization successful.
[9/29/10 6:24:21:598 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/bannerCommonActions.jsp]: Initialization successful.
[9/29/10 6:24:22:210 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/status.jsp]: Initialization successful.
[9/29/10 6:24:22:460 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/tabNav.jsp]: Initialization successful.
[9/29/10 6:24:22:501 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/pageToolbar.jsp]: Initialization successful.
[9/29/10 6:24:23:306 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/skins/html/UnlayeredContainer-H.jsp]: Initialization successful.
[9/29/10 6:24:23:331 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/skins/html/UnlayeredContainer-V.jsp]: Initialization successful.
[9/29/10 6:24:24:628 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/asa.jsp]: Initialization successful.
[9/29/10 6:24:24:759 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/config.jsp]: Initialization successful.
[9/29/10 6:24:24:987 PDT] 00000081 servlet I com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I: [PageBuilder2_Theme] [/PageBuilder2] [/themes/html/PageBuilder2/configDynamic.jsp]: Initialization successful.


So i went to wps_profile/temp folder, which will have .class file for every .jsp file that gets complied into .java first and then .class file and i could see a PageBuilder2_Theme and many other folders related application that are not there in installedApps




Since the temp folder had a PageBuilder2_Theme folder and it had .class files corresponding to .jsp's used by theme that confirmed that there is a .ear file behind it. So i checked the wp_profile/config/cells/localhost/application folder which is used for storing configuration for every .ear file that is installed on the server and there i could see PageBuilder2_Theme.ear file like this




Once you find the directory corresponding to the application that your looking for in wp_profile/config/cells/localhost/application folder, it becomes easy, you can go to PageBuilder2_theme/deployments/PageBuilder2_Theme folder and there you can find the deployment.xml which has information about where this application is actually installed. This is how the deployment.xml for PageBuilder2_Theme looks like on my machine


<?xml version="1.0" encoding="UTF-8"?>
<appdeployment:Deployment xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:appdeployment="http://www.ibm.com/websphere/appserver/schemas/5.0/appdeployment.xmi"
xmi:id="Deployment_1282248412893">
<deployedObject xmi:type="appdeployment:ApplicationDeployment" xmi:id="ApplicationDeployment_1282248412894"
deploymentId="0" startingWeight="100" binariesURL="${WPS_HOME}/theme/wp.mashup.cc.theme/installedApps/wp.mashup.cc.theme.ear"
useMetadataFromBinaries="false" enableDistribution="false" createMBeansForResources="true" reloadEnabled="false"
appContextIDForSecurity="href:localhost/PageBuilder2_Theme" zeroEarCopy="true"
filePermission=".*\.dll=755#.*\.so=755#.*\.a=755#.*\.sl=755" allowDispatchRemoteInclude="false" allowServiceRemoteInclude="false"
asyncRequestDispatchType="DISABLED">
<targetMappings xmi:id="DeploymentTargetMapping_1282248412894" enable="true" target="ServerTarget_1282248412894"/>
<classloader xmi:id="Classloader_1282248412894" mode="PARENT_LAST"/>
<modules xmi:type="appdeployment:WebModuleDeployment" xmi:id="WebModuleDeployment_1282248412894" deploymentId="1"
startingWeight="10000" uri="PageBuilder2.war">
<targetMappings xmi:id="DeploymentTargetMapping_1282248412895" target="ServerTarget_1282248412894"/>
<classloader xmi:id="Classloader_1282248412895"/>
</modules>
<properties xmi:id="Property_1282248412894" name="metadata.complete" value="true"/>
</deployedObject>
<deploymentTargets xmi:type="appdeployment:ServerTarget" xmi:id="ServerTarget_1282248412894" name="WebSphere_Portal"
nodeName="localhost"/>
</appdeployment:Deployment>


In this file if you search for binariesUrl you will find the location where this .ear file is actually installed which is ${WPS_HOME}/theme/wp.mashup.cc.theme/installedApps/wp.mashup.cc.theme.ear. So i went to that folder and i could find the source code for PageBuilder2 theme there.

Theme in WPS 7.0

One of the biggest change in the WebSphere Portal Server 7.0 is that it has a new theme called PageBuilder2(CSA2) theme, which has a different architecture that allows you to write theme in .html and use webdav,.. I wanted to learn how this theme works and how different pieces fit together, and these are my notes

Until version 6.1 source code for all the different themes that were shipped with WebSphere portal used to be located in wp_profile/installedApps/localhost/wps.ear/wps.war/themes/html/ directory, so i went to check that directory first and it seems that now that directory is almost empty, this is the default content.



Now it only as Default.jsp and CloseWindow.jsp. If you open the Default.jsp you will notice its much simpler and smaller compared to previous versions and from the comment it looks like this is the fallback minimal version of theme which will get called if your actual theme does not work and it gives you chance to recover.

So i did full export of websphere portal using xmlaccess and searched for <theme> element and i can find 4 theme elements with PageBuilder2 theme set as default theme

<theme action="update" active="true" context-root="/PortalTheme" default="false" defaultskinref="ZK_CGAH47L0085810IAHU76SD20S4"
domain="rel" objectid="ZJ_CGAH47L0085810IAHU76SD20H0" resourceroot="Portal" uniquename="ibm.portal.theme.Portal">
<localedata locale="en">
<title>Portal</title>
</localedata>
<allowed-skin skin="ZK_CGAH47L0085810IAHU76SD20S2" update="set"/>
<allowed-skin skin="ZK_CGAH47L0085810IAHU76SD20S4" update="set"/>
<allowed-skin skin="ZK_CGAH47L0085810IAHU76SD20S6" update="set"/>
<parameter name="com.ibm.portal.theme.hasBaseURL" type="string" update="set"><![CDATA[true]]></parameter>
</theme>

<theme action="update" active="true" context-root="/PageBuilder2" default="true" defaultskinref="ZK_CGAH47L00OES90IAH10FQR3KJ2"
domain="rel" objectid="ZJ_CGAH47L00OES90IAH10FQR3KJ6" resourceroot="PageBuilder2" uniquename="csa2.theme">
<localedata locale="en">
<title>Page Builder</title>
</localedata>
<allowed-skin skin="ZK_CGAH47L0085810IAHU76SD20S5" update="set"/>
<allowed-skin skin="ZK_CGAH47L00OES90IAH10FQR3KJ2" update="set"/>
<parameter name="com.ibm.portal.themetype" type="string" update="set"><![CDATA[CSA2]]></parameter>
<parameter name="theme.capability.dojo" type="string" update="set"><![CDATA[1.4.3]]></parameter>
<parameter name="theme.capability.oneUI" type="string" update="set"><![CDATA[2.1]]></parameter>
<parameter name="com.ibm.portal.layout.template.href" type="string" update="set"><![CDATA[dav:fs-type1/layout-templates/2ColumnEqual/]]></parameter>
<parameter name="theme.capability.mashups.enabler" type="string" update="set"><![CDATA[2.4]]></parameter>
<parameter name="com.ibm.portal.theme.template.ref" type="string" update="set"><![CDATA[dav:fs-type1/themes/PageBuilder2/]]></parameter>
</theme>

<theme action="update" active="true" context-root="/themes" default="false" defaultskinref="ZK_OGFLMKG108IGF0IQCG6O9610O3"
domain="rel" objectid="ZJ_OGFLMKG108IGF0IQCG6O961045" resourceroot="defaultTheme" uniquename="com.ibm.portal.mashup.theme.defaultTheme">
<localedata locale="en">
<title>Breadcrumb - Free Form Layout </title>
<description>Breadcrumb - Free Form Layout</description>
</localedata>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O9610O1" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O9610O2" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O9610O3" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O9610O4" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O9610O5" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O9610O6" update="set"/>
<parameter name="com.ibm.portal.themetype" type="string" update="set"><![CDATA[mashup]]></parameter>
<parameter name="preview-url" type="string" update="set"><![CDATA[preview.png]]></parameter>
<parameter name="com.ibm.portal.themestructure" type="string" update="set"><![CDATA[mashup]]></parameter>
<parameter name="com.ibm.mashups.theme.body.class" type="string" update="set"><![CDATA[mashups]]></parameter>
</theme>
<theme action="update" active="true" context-root="/themes" default="false" defaultskinref="ZK_OGFLMKG108IGF0IQCG6O961041" domain="rel"
objectid="ZJ_OGFLMKG108IGF0IQCG6O961043" resourceroot="defaultThemeColumned" uniquename="com.ibm.portal.mashup.theme.defaultThemeColumned">
<localedata locale="en">
<title>Breadcrumb - Column Layout</title>
<description>Breadcrumb - Column Layout</description>
</localedata>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O961040" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O961041" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O961042" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O961044" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O961046" update="set"/>
<allowed-skin skin="ZK_OGFLMKG108IGF0IQCG6O9610O7" update="set"/>
<parameter name="com.ibm.portal.themetype" type="string" update="set"><![CDATA[mashup]]></parameter>
<parameter name="preview-url" type="string" update="set"><![CDATA[preview.png]]></parameter>
<parameter name="com.ibm.portal.themestructure" type="string" update="set"><![CDATA[mashup]]></parameter>
<parameter name="com.ibm.mashups.theme.body.class" type="string" update="set"><![CDATA[mashups]]></parameter>
</theme>


The xmlaccess export of the portal has 4 themes

  1. Portal

  2. PageBuilder

  3. Breadcrumb - Free Form Layout

  4. Breadcrumb - Column Layout



But if you login into WPS admin console and go to Themes and Skins portlet you will notice that it displays only 2 themes one is Portal and other is Page Builder. Also when you try to change theme of your portal page you will see only these two themes there. I guess the themes with themetype equal to mashup cannot be applied to page and it does not show up in the Theme and skin portlet



It looks like the WPS 7.0 makes use of packaging theme in separate ear concept that was introduced in the WPS 6.1. The source code for theme is distributed in 3 separate .ear files. This the mapping for the theme name to the context root.


  1. Portal -> /PortalTheme

  2. Page Builder -> /PageBuilder2

  3. Breadcrumb - Free Form Layout -> /themes

  4. Breadcrumb - Column Layout -> /themes



Also it seems that the source code for the theme is distributed at different locations and all of them are installed inside PortalServer directory which is a read only directory.

  • Portal : ${WPS_HOME}/installer/wp.ear/installableApps/wps_theme.ear

  • Page Builder : ${WPS_HOME}/theme/wp.mashup.cc.theme/installedApps/wp.mashup.cc.theme.ear

  • Breadcrumb - Free Form Layout : ${WPS_HOME}/base/wp.mmi.deploy/installedApps/MashupMaker_Integration.ear/theme.war

  • Breadcrumb - Column Layout : ${WPS_HOME}/base/wp.mmi.deploy/installedApps/MashupMaker_Integration.ear/theme.war

How to configure WebDav connection in Linux

In the Using WebDav to work with theme in WPS 7 entry you can find details about how to configure a WebDav client on Windows. But i use CentOS on my development machine and i wanted to figure out how to connect to the WebDav server on Linux machine.

It turns on the Nautilus file explorer that i use on my Linux box has native support for connecting to WebDav and its more easier to user then the couple of windows based options

In the Nautilus file explorer click on File -< Connect to Server like this


It will open a Connect to server dialog box, where you can provide details for connecting to the WebDav server like this



Once click on Connect it will ask you for the password and once you provide the password it will connect to server and show the webdav folder like normal file system folder. It will also add this webdav connection in the left hand palette like this. Now your free to navigate in the WebDav folder and work with files like any normal file system files



I used wasadmin as connection name and the themes/PageBuilder2 is the WebDav folder

How to find port number

When your administrator/part of infrastructure team that manages lot of portal installations, its sometime difficult to remember important port numbers on different server. You have two options to deal with this situation. If you remember the port number for WAS Admin Console then login and use the WAS Admin UI to find out value of port number

But if not you can login and find out the serverindex.xml file for either your server or deployment manager, That file has details about different port number, what all applications are installed, etc. This is serverinde.xml from my default WebSphere Portal 7.0 installation, as you can see i have two serverEntries element one for server1, which is default server profile and other for WebSphere_Portal, which is the server profile for WebSphere Portal installation


  • BOOTSTRAP_ADDRESS

  • SOAP_CONNECTOR_ADDRESS: Port for SOAP connection, you should use this port number while connecting to server using wsadmin tool

  • ORB_LISTENER_ADDRESS

  • SAS_SSL_SERVERAUTH_LISTENER_ADDRESS

  • CSIV2_SSL_SERVERAUTH_LISTENER_ADDRESS

  • CSIV2_SSL_MUTUALAUTH_LISTENER_ADDRESS

  • WC_adminhost: This is port number for connecting to Admin console. Ex. You can connect to admin console using http://localhost:<wp_adminHost>/ibm/console

  • WC_defaulthost: This port is used for accessing web applications on the server Ex. http://localhost:<wc_defaulthost> would be the start point for connecting user application

  • DCS_UNICAST_ADDRESS

  • WC_adminhost_secure: Use this port if you want to connect to admin console using SSL Ex. http://localhost:<wp_adminHos_securet>/ibm/console

  • WC_defaulthost_secure: Use this port if you want to connect to web application using secured port

  • SIP_DEFAULTHOST

  • SIP_DEFAULTHOST_SECURE

  • IPC_CONNECTOR_ADDRESS

  • SIB_ENDPOINT_ADDRESS

  • SIB_ENDPOINT_SECURE_ADDRESS

  • SIB_MQ_ENDPOINT_ADDRESS

  • SIB_MQ_ENDPOINT_SECURE_ADDRESS





<?xml version="1.0" encoding="UTF-8"?>
<serverindex:ServerIndex xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:serverindex="http://www.ibm.com/websphere/appserver/schemas/5.0/serverindex.xmi" xmi:id="ServerIndex_1" hostName="www.webspherenotes.com">
<serverEntries xmi:id="ServerEntry_1183122129640" serverName="server1" serverType="APPLICATION_SERVER">
<deployedApplications>WebSphereWSDM.ear/deployments/WebSphereWSDM</deployedApplications>
<deployedApplications>isclite.ear/deployments/isclite</deployedApplications>
<deployedApplications>DefaultApplication.ear/deployments/DefaultApplication</deployedApplications>
<deployedApplications>ivtApp.ear/deployments/ivtApp</deployedApplications>
<deployedApplications>query.ear/deployments/query</deployedApplications>
<deployedApplications>ibmasyncrsp.ear/deployments/ibmasyncrsp</deployedApplications>
<specialEndpoints xmi:id="NamedEndPoint_1183122129640" endPointName="BOOTSTRAP_ADDRESS">
<endPoint xmi:id="EndPoint_1183122129640" host="www.webspherenotes.com" port="10004"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129641" endPointName="SOAP_CONNECTOR_ADDRESS">
<endPoint xmi:id="EndPoint_1183122129641" host="www.webspherenotes.com" port="10005"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129642" endPointName="ORB_LISTENER_ADDRESS">
<endPoint xmi:id="EndPoint_1183122129642" host="www.webspherenotes.com" port="10010"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129643" endPointName="SAS_SSL_SERVERAUTH_LISTENER_ADDRESS">
<endPoint xmi:id="EndPoint_1183122129643" host="www.webspherenotes.com" port="10007"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129644" endPointName="CSIV2_SSL_SERVERAUTH_LISTENER_ADDRESS">
<endPoint xmi:id="EndPoint_1183122129644" host="www.webspherenotes.com" port="10008"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129645" endPointName="CSIV2_SSL_MUTUALAUTH_LISTENER_ADDRESS">
<endPoint xmi:id="EndPoint_1183122129645" host="www.webspherenotes.com" port="10009"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129646" endPointName="WC_adminhost">
<endPoint xmi:id="EndPoint_1183122129646" host="*" port="10001"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129647" endPointName="WC_defaulthost">
<endPoint xmi:id="EndPoint_1183122129647" host="*" port="10000"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129648" endPointName="DCS_UNICAST_ADDRESS">
<endPoint xmi:id="EndPoint_1183122129648" host="*" port="10011"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129649" endPointName="WC_adminhost_secure">
<endPoint xmi:id="EndPoint_1183122129649" host="*" port="10003"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129650" endPointName="WC_defaulthost_secure">
<endPoint xmi:id="EndPoint_1183122129650" host="*" port="10002"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129651" endPointName="SIP_DEFAULTHOST">
<endPoint xmi:id="EndPoint_1183122129651" host="*" port="10016"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129652" endPointName="SIP_DEFAULTHOST_SECURE">
<endPoint xmi:id="EndPoint_1183122129652" host="*" port="10017"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129653" endPointName="SIB_ENDPOINT_ADDRESS">
<endPoint xmi:id="EndPoint_1275503456584" host="*" port="10012"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129654" endPointName="SIB_ENDPOINT_SECURE_ADDRESS">
<endPoint xmi:id="EndPoint_1275503456590" host="*" port="10013"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129655" endPointName="SIB_MQ_ENDPOINT_ADDRESS">
<endPoint xmi:id="EndPoint_1275503456594" host="*" port="10014"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129656" endPointName="SIB_MQ_ENDPOINT_SECURE_ADDRESS">
<endPoint xmi:id="EndPoint_1275503456599" host="*" port="10015"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1183122129657" endPointName="IPC_CONNECTOR_ADDRESS">
<endPoint xmi:id="EndPoint_1183122129657" host="${LOCALHOST_NAME}" port="10006"/>
</specialEndpoints>
</serverEntries>
<serverEntries xmi:id="ServerEntry_1282248059970" serverName="WebSphere_Portal" serverType="APPLICATION_SERVER">
<deployedApplications>ibmasyncrsp.ear/deployments/ibmasyncrsp</deployedApplications>
<deployedApplications>isclite.ear/deployments/isclite</deployedApplications>
<deployedApplications>WSPolicyManager.ear/deployments/WSPolicyManager</deployedApplications>
<deployedApplications>TemplateLibrary_Servlets.ear/deployments/TemplateLibrary_Servlets</deployedApplications>
<deployedApplications>AJAX Proxy Configuration.ear/deployments/AJAX Proxy Configuration</deployedApplications>
<deployedApplications>WebResourceServlet.ear.ear/deployments/WebResourceServlet.ear</deployedApplications>
<deployedApplications>MashupMaker_Integration.ear/deployments/MashupMaker_Integration</deployedApplications>
<deployedApplications>CatalogHandler.ear/deployments/CatalogHandler</deployedApplications>
<deployedApplications>UserProfileRESTServlet.ear/deployments/UserProfileRESTServlet</deployedApplications>
<deployedApplications>content_j2ee.ear/deployments/content_j2ee</deployedApplications>
<deployedApplications>IEHS_war.ear/deployments/IEHS_war</deployedApplications>
<deployedApplications>wps_theme.ear/deployments/wps_theme</deployedApplications>
<deployedApplications>wps_scheduler.ear/deployments/wps_scheduler</deployedApplications>
<deployedApplications>JavaContentRepository.ear/deployments/JavaContentRepository</deployedApplications>
<deployedApplications>odc.ear/deployments/odc</deployedApplications>
<deployedApplications>SpellChecker.ear/deployments/SpellChecker</deployedApplications>
<deployedApplications>LWP_Mail_Servlets.ear/deployments/LWP_Mail_Servlets</deployedApplications>
<deployedApplications>lwp.addtosametimelist_war.ear/deployments/lwp.addtosametimelist_war</deployedApplications>
<deployedApplications>lwp_groupsViewer_war.ear/deployments/lwp_groupsViewer_war</deployedApplications>
<deployedApplications>lwp_peoplefinder_war.ear/deployments/lwp_peoplefinder_war</deployedApplications>
<deployedApplications>lwp_peoplePicker_war.ear/deployments/lwp_peoplePicker_war</deployedApplications>
<deployedApplications>lwp_dynamicPersontag_war.ear/deployments/lwp_dynamicPersontag_war</deployedApplications>
<deployedApplications>ibm_personTagServlet_war.ear/deployments/ibm_personTagServlet_war</deployedApplications>
<deployedApplications>LWP_People.ear/deployments/LWP_People</deployedApplications>
<deployedApplications>pznscheduler.ear/deployments/pznscheduler</deployedApplications>
<deployedApplications>pznpublish.ear/deployments/pznpublish</deployedApplications>
<deployedApplications>PZN_Utilities.ear/deployments/PZN_Utilities</deployedApplications>
<deployedApplications>Personalization_Workspace.ear/deployments/Personalization_Workspace</deployedApplications>
<deployedApplications>Personalization_Lists.ear/deployments/Personalization_Lists</deployedApplications>
<deployedApplications>PSESearchAdapter.ear/deployments/PSESearchAdapter</deployedApplications>
<deployedApplications>Feed_Servlet.ear/deployments/Feed_Servlet</deployedApplications>
<deployedApplications>Seedlist_Servlet.ear/deployments/Seedlist_Servlet</deployedApplications>
<deployedApplications>PageBuilder2_Theme.ear/deployments/PageBuilder2_Theme</deployedApplications>
<deployedApplications>Dojo_Resources.ear/deployments/Dojo_Resources</deployedApplications>
<deployedApplications>MashupCommonComponent.ear/deployments/MashupCommonComponent</deployedApplications>
<deployedApplications>feedReader.ear/deployments/feedReader</deployedApplications>
<deployedApplications>eventExplorer.ear/deployments/eventExplorer</deployedApplications>
<deployedApplications>websiteDisplayer.ear/deployments/websiteDisplayer</deployedApplications>
<deployedApplications>Live_Object_Framework.ear/deployments/Live_Object_Framework</deployedApplications>
<deployedApplications>PA_Login_Portlet_App.ear/deployments/PA_Login_Portlet_App</deployedApplications>
<deployedApplications>PA_Selfcare_Port_App.ear/deployments/PA_Selfcare_Port_App</deployedApplications>
<deployedApplications>PA_PortalWSRPProxy.ear/deployments/PA_PortalWSRPProxy</deployedApplications>
<deployedApplications>PA_WPS_Welcome.ear/deployments/PA_WPS_Welcome</deployedApplications>
<deployedApplications>PA_SearchSitemapPort.ear/deployments/PA_SearchSitemapPort</deployedApplications>
<deployedApplications>PA_portletWiring.ear/deployments/PA_portletWiring</deployedApplications>
<deployedApplications>PA_Portlet_Manager.ear/deployments/PA_Portlet_Manager</deployedApplications>
<deployedApplications>PA_Manage_Webservices.ear/deployments/PA_Manage_Webservices</deployedApplications>
<deployedApplications>PA_ThemesAndSkinsMgr.ear/deployments/PA_ThemesAndSkinsMgr</deployedApplications>
<deployedApplications>PA_Eecontentandlayout.ear/deployments/PA_Eecontentandlayout</deployedApplications>
<deployedApplications>PA_Properties.ear/deployments/PA_Properties</deployedApplications>
<deployedApplications>PA_MPagesandFavorites.ear/deployments/PA_MPagesandFavorites</deployedApplications>
<deployedApplications>PA_FrequentUsers.ear/deployments/PA_FrequentUsers</deployedApplications>
<deployedApplications>PA_Credential_Admin.ear/deployments/PA_Credential_Admin</deployedApplications>
<deployedApplications>PA_Settings.ear/deployments/PA_Settings</deployedApplications>
<deployedApplications>PA_Markups_Manager.ear/deployments/PA_Markups_Manager</deployedApplications>
<deployedApplications>PA_appearance.ear/deployments/PA_appearance</deployedApplications>
<deployedApplications>PA_Set_Permissions.ear/deployments/PA_Set_Permissions</deployedApplications>
<deployedApplications>PA_ResourceView.ear/deployments/PA_ResourceView</deployedApplications>
<deployedApplications>PA_PolicyExplorer.ear/deployments/PA_PolicyExplorer</deployedApplications>
<deployedApplications>PA_PolicyEditor.ear/deployments/PA_PolicyEditor</deployedApplications>
<deployedApplications>PA_PolicyEditorCA.ear/deployments/PA_PolicyEditorCA</deployedApplications>
<deployedApplications>PA_Principals_Manager.ear/deployments/PA_Principals_Manager</deployedApplications>
<deployedApplications>PA_Tracing.ear/deployments/PA_Tracing</deployedApplications>
<deployedApplications>PA_Clients_Manager.ear/deployments/PA_Clients_Manager</deployedApplications>
<deployedApplications>PA_UniqueNames.ear/deployments/PA_UniqueNames</deployedApplications>
<deployedApplications>PA_URL_mapping.ear/deployments/PA_URL_mapping</deployedApplications>
<deployedApplications>PA_Blurb.ear/deployments/PA_Blurb</deployedApplications>
<deployedApplications>PA_Blurb_1.ear/deployments/PA_Blurb_1</deployedApplications>
<deployedApplications>PA_Web.ear/deployments/PA_Web</deployedApplications>
<deployedApplications>PA_Import_XML.ear/deployments/PA_Import_XML</deployedApplications>
<deployedApplications>PA_MageVirtualPortals.ear/deployments/PA_MageVirtualPortals</deployedApplications>
<deployedApplications>PA_WebScanner.ear/deployments/PA_WebScanner</deployedApplications>
<deployedApplications>PA_Palette_Port_App.ear/deployments/PA_Palette_Port_App</deployedApplications>
<deployedApplications>PA_Resource_Manager.ear/deployments/PA_Resource_Manager</deployedApplications>
<deployedApplications>PA_Impersonation.ear/deployments/PA_Impersonation</deployedApplications>
<deployedApplications>PA_ParamConfig.ear/deployments/PA_ParamConfig</deployedApplications>
<deployedApplications>PA_PropertiesPortApp.ear/deployments/PA_PropertiesPortApp</deployedApplications>
<deployedApplications>PA_Roles.ear/deployments/PA_Roles</deployedApplications>
<deployedApplications>PA_Community_Port_App.ear/deployments/PA_Community_Port_App</deployedApplications>
<deployedApplications>PA_Policy_Status.ear/deployments/PA_Policy_Status</deployedApplications>
<deployedApplications>PA_IWidget_Wrapper.ear/deployments/PA_IWidget_Wrapper</deployedApplications>
<deployedApplications>PA_DynamicUIApp.ear/deployments/PA_DynamicUIApp</deployedApplications>
<deployedApplications>PA_PTransformationApp.ear/deployments/PA_PTransformationApp</deployedApplications>
<deployedApplications>PA_Search_Center.ear/deployments/PA_Search_Center</deployedApplications>
<deployedApplications>PA_TCustomizerPortApp.ear/deployments/PA_TCustomizerPortApp</deployedApplications>
<deployedApplications>PA_Tag_Cloud.ear/deployments/PA_Tag_Cloud</deployedApplications>
<specialEndpoints xmi:id="NamedEndPoint_1282248059970" endPointName="BOOTSTRAP_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059970" host="www.webspherenotes.com" port="10035"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059971" endPointName="SOAP_CONNECTOR_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059971" host="www.webspherenotes.com" port="10025"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059972" endPointName="ORB_LISTENER_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059972" host="www.webspherenotes.com" port="10034"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059973" endPointName="SAS_SSL_SERVERAUTH_LISTENER_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059973" host="www.webspherenotes.com" port="10041"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059974" endPointName="CSIV2_SSL_SERVERAUTH_LISTENER_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059974" host="www.webspherenotes.com" port="10036"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059975" endPointName="CSIV2_SSL_MUTUALAUTH_LISTENER_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059975" host="www.webspherenotes.com" port="10033"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059976" endPointName="WC_adminhost">
<endPoint xmi:id="EndPoint_1282248059976" host="*" port="10042"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059977" endPointName="WC_defaulthost">
<endPoint xmi:id="EndPoint_1282248059977" host="*" port="10039"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059978" endPointName="DCS_UNICAST_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059978" host="*" port="10030"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059979" endPointName="WC_adminhost_secure">
<endPoint xmi:id="EndPoint_1282248059979" host="*" port="10032"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059980" endPointName="WC_defaulthost_secure">
<endPoint xmi:id="EndPoint_1282248059980" host="*" port="10029"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059981" endPointName="SIP_DEFAULTHOST">
<endPoint xmi:id="EndPoint_1282248059981" host="*" port="10027"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059982" endPointName="SIP_DEFAULTHOST_SECURE">
<endPoint xmi:id="EndPoint_1282248059982" host="*" port="10026"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059983" endPointName="IPC_CONNECTOR_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059983" host="localhost" port="10037"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059984" endPointName="SIB_ENDPOINT_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059984" host="*" port="10028"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059985" endPointName="SIB_ENDPOINT_SECURE_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059985" host="*" port="10038"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059986" endPointName="SIB_MQ_ENDPOINT_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059986" host="*" port="10040"/>
</specialEndpoints>
<specialEndpoints xmi:id="NamedEndPoint_1282248059987" endPointName="SIB_MQ_ENDPOINT_SECURE_ADDRESS">
<endPoint xmi:id="EndPoint_1282248059987" host="*" port="10031"/>
</specialEndpoints>
</serverEntries>
</serverindex:ServerIndex>

PageBuilder2 theme in WebSphere Portal 7.0

WebSphere Portal 7 provides improved page builder and improved client side rendering and has a new default portal theme, the Page Builder theme. Themes define how your portal site will look. After installation, a default theme is deployed and you can either customize that theme or create your own. The new themes approach introduced in 7 involves less editing of JSPs and allows you to mix iWidgets and portlets on the same portal page and take advantage of both client side and server side rendering mode. WebSphere Portal 7 continues to support other themes, including your custom themes. If you have an existing portal site you can continue to use your existing themes or you can migrate your themes to the new standard.

These are some of the main points about the new Page Builder theme

  • Static pages use plain HTML. This can include placeholders for dynamic content, such as portlets or iWidgets. You can create and edit static pages by using an HTML editor tool of your choice.

  • The Page Builder theme allows you to render and edit static pages that which include portlets and iWidgets. The theme allows you for each page to configure whether that page is rendered in client side aggregation mode, or in server side aggregation mode. Users with editor rights on the page can toggle pages between client side and server side mode. The Page Builder theme consists of a plain HTML file. You can customize it by using a HTML editor tool of your choice. The portal provides several include files that you can use to add the logic for starting and editing the page.

  • You can use portlets and iWidgets to add application logic to a static page. JSR168 and 286 define the standard for portlets, and the iWidget specification 2.0 defines iWidgets. Both portlets and iWidgets are self-contained pieces of application logic that you can develop, deploy, and use in a flexible manner. You need to distinguish between the types of code and its execution:

    1. Portlets are written as Java code. They are designed to be executed in a portlet container on the server side. If they are rendered by client side execution instead, the portal translates them into iWidgets markup that can be executed in the browser.

    2. iWidgets are written as Javascript logic. They are designed to be executed in the browser on the client side. For server side execution the portal wraps iWidgets into portlets.



Lotus OneUi

The WebSphere Portal 7.0 theme makes use of Lotus OneUi for look and feel. The Lotus OneUi enables a common look and feel and a common code base for Lotus web applications. The goal is to remove arbitrary differences between products thereby improving ease-of-use and making it easier to customize products when deployed in an enterprise.



These are the advantages of using Lotus One ui

  • vision issues - it is developed to work well in screen readers, for adjusting text sizes, and to work in high contrast mode.

  • keyboard accessibility - where we have hover effects, we also provide focus effects or equivalent facilitation.

  • The code base is themeable. Customers can easily modify colors and background images using industry standard CSS techniques.

  • Products ship CSS and images used for theming separate from other CSS so it is easier to find the files that apply the theme.

  • IBM's product user interfaces are usually localized to multiple languages. We keep our components fluid so they can handle varying-sized text strings.

  • The code is tested in right-to-left languages. Making our UI work correctly in right-to-left languages sometimes influences how we code our HTML components (browser support of bi-directionality can be buggy).

  • The code base is tested for stability, accessibility, and bi-directionality in multiple browsers. Rendering of the UI across browsers is not always pixel-perfect, but the goal is for it to be as identical as is possible.

Using iWidgets in portlet

For easy handling of iWidgets WebSphere Portal provides a dedicated IWidget Wrapper portlet(Unique name for the portlet is wp.p.IWidgetWrapper). As name suggests this portlet wraps a iWidget into a portlet.

I wanted to try how the IWidgets Wrapper portlet works so these are the steps that i followed

  • Create a iWidget application. In my case i used RAD 8.0 to create simple Hello iWidget portlet
  • , if you want you can directly download the sample application from here
  • Install the HelloWidget.war file as J2EE application using WAS Admin Console, While installing make sure that you select WebSPhere Portal as target server and use /HelloIWidget as the context root

  • Start the HelloWidget.war file after installing it and make sure that you access the the http://localhost:10039/HelloIWidget//HelloWidget.xml url


  • The last step would be to register this iWidget with the IWidgetWrapperPortlet, you will have to execute register-iwidget-definition ConfigEngine task for that

    /ConfigEngine.sh register-iwidget-definition -DIWidgetDefinition=/HelloIWidget/HelloWidget.xml

    Execute this task and wait for it to complete successfully. This task downloads the HelloWidget.xml and parses it to find some values and then makes use of those values to create a clone of IWidgetWrapperPortlet, you can see this task executing few xmlaccess scripts

  • After the portlet is created you should be able to add it to any page using HelloIWidget as portlet name


  • If you take full export of your portal server and search for /HelloIWidget/HelloWidget.xml you should find following portlet definition

    <portlet action="update" active="true" defaultlocale="en" domain="rel"
    name="IWidgetWrapper.$cloned.Z3_8000CB1A008RE0IQCHVQBR20G0"
    objectid="Z3_8000CB1A008RE0IQCHVQBR20G0" provided="false" servletref="ZV_CGAH47L0085810IAHU76SD2OK1">
    <localedata locale="en">
    <title>HelloIWidget</title>
    </localedata>
    <preferences name="com.ibm.portal.iw:content:edit:value" update="set">
    <value><![CDATA[<div>Hello From WebSpherenotes.com - Edit Mode</div>]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:content:view:value" update="set">
    <value><![CDATA[<div>Hello From WebSpherenotes.com</div>]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:itemSet:idescriptor:iw:item:mode:value" update="set">
    <value><![CDATA[en]]></value>
    <value><![CDATA[view]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:itemSet:idescriptor:private" update="set">
    <value><![CDATA[true]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:iwidget:allowInstanceContent" update="set">
    <value><![CDATA[false]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:iwidget:base" update="set">
    <value><![CDATA[res:/HelloIWidget/HelloWidget.xml]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:iwidget:id" update="set">
    <value><![CDATA[HelloIWidget]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:iwidget:lang" update="set">
    <value><![CDATA[en]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:iwidget:sandbox" update="set">
    <value><![CDATA[false]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:iwidget:supportedModes" update="set">
    <value><![CDATA[view edit_defaults]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iw:iwidget:supportedWindowStates" update="set">
    <value><![CDATA[normal]]></value>
    </preferences>
    <preferences name="com.ibm.portal.iwidget.definition.expiration" update="set">
    <value><![CDATA[1285168645750]]></value>
    </preferences>
    <access-control externalized="false" owner="uid=wasadmin,o=defaultwimfilebasedrealm" private="false"/>
    </portlet>


Portal light mode vs develop mode startup performance

WebSphere Portal Server 7.0 has introduced a concept of portal light mode, which is supposed to improve start up time and memory consumption of production environment. But interestingly it still has support for enable-develop-mode-startup-performance

The WPS 7.0 Info center has following information about enable-develop-mode-startup-performance task "The developer mode allows you to improve start up performance and to configure IBM WebSphere Portal for development. Developer mode is for a development environment only and should not be used in a production environment. Install WebSphere Portal with the Base installation option."

From the documentation it looks like the portal light mode is only for the production environment. When i tried running this task on my local WPS 7.0 installation, i did not get much improvement in the server startup performance the startup time for base installation is close to 9-10 min. Also i did not see any change in the memory size of the server.

But when i executed the enable-develop-mode-startup performance on my local i could see that the server startup time came down to 5 min from 10 min and also the memory size came down from 700 + mb to 500 mb.

Creating iWidget project using RAD 8

Starting from Version 8.0, Rational Application Developer provides support for creating iWidget project. It provides Create iWidget project wizard as well as wizard for creating iWidget.

  • Click on File -< New -< Web -< iWidget Project.


  • First screen in the wizard will ask you what type of technology you want to use Web Technology, means the project will not be a J2EE application instead it will be simple project that will let you package .xml,.css and other files in archive the Web And JavaEE Technology option will create a Dynamic web project with WEB-INF/web.xml file, which you can use for creating servlet,..


  • On the next screen it will ask you for name of the project and what type of wizard you want it to generate, i selected HelloIWidget and Simple Wizard like this


  • Once the wizard is completed it will create a project with HelloIWidget.xml which has sample source code for the wizard like this




I also tried creating a Widget project with J2EE component and compared it with wizard project without J2EE component

What is iWidget ?

IBM has introduced widget technology similar to Google's gadget technology. The basic idea behind widget is that you develop them using client side technologies such as HTML, JavaScript,.. and then you can place that dynamic content on any web page. Widgets can be as simple as displaying static HTML on a page and they can be complex in which they can take input from user, make REST call to get data, communicate with other widgets on a page

In other words, an iWidget is an XML file. It can contain markup that is rendered and can be supported by JavaScript files for dynamic client-side scripting and CSS files for styling the markup. JSP, HTML, or HTML fragments can also contain markups, which can also be written in Ajax. Once the iWidget is in the framework, it can generate and receive client-side events, as specified in the widget wrapper. This is a sample HelloWorld iwidget


<?xml version="1.0" encoding="UTF-8" ?>
<iw:iwidget id="HelloIWidget" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
supportedModes="view edit" mode="view" lang="en" name="Hello iWidget" >
<iw:content mode="view">
<![CDATA[
<div>Hello From WebSpherenotes.com</div>
]]>
</iw:content>

<iw:content mode="edit">
<![CDATA[
<div>Hello From WebSpherenotes.com - Edit Mode</div>
]]>
</iw:content>
</iw:iwidget>


This XML file defines Hello iWidget, you can develop it using either RAD 8 or you can use notepad.

Widget xml file will have at least one iw:content element, this element defines what content should be displayed to the user. In my case i have two iw:content elements one with mode="view", and other with mode="edit". The markup inside the CDATA section of iw:content mode="view" will be displayed to the user during normal operation of the widget and the markup inside the iw:content mode="edit" would be displayed to the user when he switches mode to edit for configuring widget settings.

Once your widget definition is ready you can execute it any iwidget runtime. There are multiple IBM products that provide iWidget runtime environment such as Project Zero, IBM WebSphere Mashup Center, WebSphere Portal,... WebSphere Portal 7.0 allows you to wrap a widget in a Portlet and add it on portal page along with other portelts or you can add it on dedicated mash up page.

This is how the view mode of the widget looks like when wrapped inside a portlet



If you click on Edit Shared Settings link it will take you to the edit mode of the widget and display content under iw:content mode="edit", this is how it looks like

Enabling mashup integration

After installing WPS 7.0, you can enable mashup integration by running following task


./WPConfigh.sh deploy-portal-mashup-ui -DWasPassword=wasadminpassword -DPortalAdminPwd=portaladminpassword


This task run series of xmlaccess scripts, that create Mashup page and configure it. Once that is done you can login into portal and you should see "My Mashup" link is added at the top, at the same level as that of Home, Administration



If you click on that link, it will take you to Mashup page



In this page click on the Go to Edit button in the top right corner and it will display same page in the edit mode, here you can add widgets to the page, this is how my screen looks like after adding pre-installed Feed reader widget

Setting headers and cookies through portlet

You can use the two phase rendering concept to set both headers and cookies through a portlet, I wanted to try that so i built this TwoPhaseRenderingPortlet.java, you can download the sample code from here


package com.ibm.webspherenotes.jsr286;

import java.io.IOException;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.servlet.http.Cookie;

public class TwoPhaseRenderingPortlet extends GenericPortlet {
protected void doHeaders(RenderRequest request, RenderResponse response) {
System.out.println("Entering TwoPhaseRenderingPortlet.doHeaders()");

Cookie c = new Cookie("myCookieName", "myCookieValue");
c.setPath(request.getContextPath());
response.addProperty(c);

response.setProperty("myHeaderName", "myHeaderValue");

System.out.println("Exiting TwoPhaseRenderingPortlet.doHeaders()");
}

protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
System.out.println("Entering TwoPhaseRenderingPortlet.doView()");
response.setContentType("text/html");
response.getWriter().println("Hello from two phase rendering portlet");
System.out.println("Exiting TwoPhaseRenderingPortlet.doView()");
}
}


The Response.setProperty() method is used for setting header and you can use it even for setting cookie. But for setting cookie there is specialized Response.setProperty() method that takes cookie object

Including JavaScript file in the Head of the page from portlet

One of the common requirement for portlet developer is how do i include a JavaScript file in the Head section of portal response page. I used the concept of Two phase rendering to build a sample portlet that includes JavaScript file in the head of the portal response.

This is how my TwoPhaseRenderPortlet.java looks like

package com.ibm.webspherenotes.jsr286;

import java.io.IOException;

import javax.portlet.GenericPortlet;
import javax.portlet.MimeResponse;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

import org.w3c.dom.Element;

public class TwoPhaseRenderingPortlet extends GenericPortlet{
protected void doHeaders(RenderRequest request, RenderResponse response) {
System.out.println("Entering TwoPhaseRenderingPortlet.doHeaders()");
Element script = response.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", request.getContextPath()+"/js/test.js");
response.addProperty(MimeResponse.MARKUP_HEAD_ELEMENT, script);

System.out.println("Exiting TwoPhaseRenderingPortlet.doHeaders()");
}
protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
System.out.println("Entering TwoPhaseRenderingPortlet.doView()");
response.setContentType("text/html");
response.getWriter().println("Hello from two phase rendering portlet");
System.out.println("Exiting TwoPhaseRenderingPortlet.doView()");
}
}


In the doHeaders() method i am creating a script element and setting its src attribute to point to test.js which is part of the portlet web application.
This approach is same as that i used for changing portal page title

When i access the page with the portlet, i can see the test.js being called, i kept this invalid URL so that its easier to see in firebug

Changing title of portal page

The JSR 286 specification has a concept of two phase rendering, you can use it to add element in the portal document's head section, one use case for doing that would be if you want to change the title of the portal page.

I wanted to try that so i created this TwoPhaseRenderingPortlet.java like this

package com.ibm.webspherenotes.jsr286;

import java.io.IOException;

import javax.portlet.GenericPortlet;
import javax.portlet.MimeResponse;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

import org.w3c.dom.Element;

public class TwoPhaseRenderingPortlet extends GenericPortlet{
protected void doHeaders(RenderRequest request, RenderResponse response) {
System.out.println("Entering TwoPhaseRenderingPortlet.doHeaders()");

Element title = response.createElement("title");
title.setTextContent("www.webspherenotes.com portal page");
response.addProperty(MimeResponse.MARKUP_HEAD_ELEMENT, title);

System.out.println("Exiting TwoPhaseRenderingPortlet.doHeaders()");
}
protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
System.out.println("Entering TwoPhaseRenderingPortlet.doView()");
response.setContentType("text/html");
response.getWriter().println("Hello from two phase rendering portlet");
System.out.println("Exiting TwoPhaseRenderingPortlet.doView()");
}
}


In the TwoPhaseRenderingPortlet, i am overriding doHeaders() method and inside the method, first i am creating a title element then i am setting the value of that element to www.webspherenotes.com portal page and the last step is to call response.addProperty(MimeResponse.MARKUP_HEAD_ELEMENT, title); method which asks the RenderReponse object to insert newly created title element in the head section of the document.

Once the portlet is deployed i tried accessing it and i can see that the title that i set is displayed in the title bar of the browser, also when i tried looking at the source code i could see that the <title> element is added