Automatic login with the login URL

If your writing unit tests for portal or you deleted the login portlet from page then it is also possible to log into the portal by using the following URL which includes the user ID and password:

http://server:port/wps/portal/cxml/04_SD9ePMtCP1I800I_KydQvyHFUBADPmuQy?userid=userid&password=password

where you need to replace the variables for server,port, userid, and password with the values set for your environment. For example, th

Delete login portlet how to get it back

If you accidently deleted login portlet from the login page, then you can use xmlaccess to restore it.

Either you can use xmlaccess to export the login page from some other environment and then import it on your server. Or you can use the xmlaccess script in this post to import login portlet.

The way xmlaccess script works is that first you locate the portlet using <web-app action="locate" element. To locate the login portlet you can use the uid for both web application(uid="login.war.webmod"), portlet(uniquename="wps.p.Login"). Portal server reads these values from the web.xml, portlet.xml so unless you went and changed the uid in your login portlet it should not be same on your environment as that used in this post. ONce the login portlet is located <component action="update" element will take care of adding that portlet on the page.




<?xml version="1.0" encoding="UTF-8"?>
<!-- IBM WebSphere Portal/6.1.0.1 build wp6101_115_01 exported on Tue Mar 31 18:32:25 PDT 2009 from sunpatil-wxp/192.168.2.105 -->
<!-- 1 [content-node 6_000000000000000000000000A0] -->
<!-- 2 [content-node 6_CGAH47L00G72502N5S2MAV00M1 uniquename=wps.Login] -->
<!-- 3 [component 7_CGAH47L00G72502N5S2MAV00M7] -->
<!-- 4 [component 7_CGAH47L00G72502N5S2MAV00E0] -->
<!-- 5 [skin K_CGAH47L00G72502N5S2MAV00C6] -->
<!-- 6 [component 7_CGAH47L00G72502N5S2MAV00E4] -->
<!-- 7 [web-app 1_CGAH47L00G72502N5S2MAV00C3] -->
<!-- 8 [portlet-app 2_CGAH47L00G72502N5S2MAV00C7] -->
<!-- 9 [servlet V_CGAH47L00G72502N5S2MAV00S0] -->
<!-- 10 [portlet 3_CGAH47L00G72502N5S2MAV00S4] -->
<!-- 11 [portletinstance 5_CGAH47L00G72502N5S2MAV00E2] -->
<request xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" build="wp6101_115_01" type="update" version="6.1.0.1" xsi:noNamespaceSchemaLocation="PortalConfig_6.1.0.xsd">
<portal action="locate">
<skin action="locate" domain="rel" objectid="K_CGAH47L00G72502N5S2MAV00C6" uniquename="wps.skin.thinSkin"/>
<web-app action="locate" domain="rel" objectid="1_CGAH47L00G72502N5S2MAV00C3" uid="login.war.webmod">
<servlet action="locate" domain="rel" name="Login Portlet" objectid="V_CGAH47L00G72502N5S2MAV00S0"/>
<portlet-app action="locate" domain="rel" name="wp.ap.login" objectid="2_CGAH47L00G72502N5S2MAV00C7" uid="login.war">
<portlet action="locate" domain="rel" name="Login Portlet" objectid="3_CGAH47L00G72502N5S2MAV00S4" uniquename="wps.p.Login"/>
</portlet-app>
</web-app>
<content-node action="locate" domain="rel" objectid="6_000000000000000000000000A0" uniquename="wps.content.root"/>
<content-node action="update" active="true" allportletsallowed="true" content-parentref="6_000000000000000000000000A0" create-type="explicit" domain="rel" objectid="6_CGAH47L00G72502N5S2MAV00M1" ordinal="350" type="page" uniquename="wps.Login">
<supported-markup markup="html" update="set"/>
<localedata locale="ar">
<title>بدء الاتصال</title>
</localedata>
<localedata locale="ca">
<title>Inicia una sessió</title>
</localedata>
<localedata locale="cs">
<title>Přihlásit se</title>
</localedata>
<localedata locale="da">
<title>Logon</title>
</localedata>
<localedata locale="de">
<title>Anmelden</title>
</localedata>
<localedata locale="el">
<title>Σύνδεση</title>
</localedata>
<localedata locale="en">
<title>Login</title>
</localedata>
<localedata locale="es">
<title>Iniciar sesión</title>
</localedata>
<localedata locale="fi">
<title>Kirjaudu sisään</title>
</localedata>
<localedata locale="fr">
<title>Connexion</title>
</localedata>
<localedata locale="hu">
<title>Bejelentkezés</title>
</localedata>
<localedata locale="it">
<title>Collegamento</title>
</localedata>
<localedata locale="iw">
<title>התחברות</title>
</localedata>
<localedata locale="ja">
<title>ログイン</title>
</localedata>
<localedata locale="ko">
<title>로그인</title>
</localedata>
<localedata locale="nl">
<title>Aanmelden</title>
</localedata>
<localedata locale="no">
<title>Logg på</title>
</localedata>
<localedata locale="pl">
<title>Logowanie</title>
</localedata>
<localedata locale="pt">
<title>Iniciar sessão</title>
</localedata>
<localedata locale="pt_BR">
<title>Efetuar Login</title>
</localedata>
<localedata locale="ro">
<title>Logare</title>
</localedata>
<localedata locale="ru">
<title>Вход в систему</title>
</localedata>
<localedata locale="sk">
<title>Prihlásiť</title>
</localedata>
<localedata locale="sl">
<title>Prijava</title>
</localedata>
<localedata locale="sv">
<title>Inloggning</title>
</localedata>
<localedata locale="th">
<title>ลงชื่อเข้าใช้</title>
</localedata>
<localedata locale="tr">
<title>Oturum Aç</title>
</localedata>
<localedata locale="uk">
<title>Вхід до системи</title>
</localedata>
<localedata locale="zh">
<title>登录</title>
</localedata>
<localedata locale="zh_TW">
<title>登入</title>
</localedata>
<localedata locale="hr">
<title>Prijava</title>
</localedata>
<parameter name="RenderMode" type="string" update="set"><![CDATA[force_ssa]]></parameter>
<parameter name="com.ibm.portal.Hidden" type="string" update="set"><![CDATA[true]]></parameter>
<parameter name="com.ibm.portal.PageIcon" type="string" update="set"><![CDATA[icons/page/login.gif]]></parameter>
<parameter name="com.ibm.portal.ThemePolicy" type="string" update="set"><![CDATA[theme/SingleTopNavMinimal]]></parameter>
<access-control externalized="false" owner="undefined" private="false">
<role actionset="User" update="set">
<mapping subjectid="anonymous portal user" subjecttype="user" update="set"/>
<mapping subjectid="all authenticated portal users" subjecttype="user_group" update="set"/>
</role>
</access-control>
<component action="update" active="true" deletable="undefined" domain="rel" modifiable="undefined" objectid="7_CGAH47L00G72502N5S2MAV00M7" ordinal="100" orientation="H" skinref="undefined" type="container" width="undefined">
<component action="update" active="true" deletable="undefined" domain="rel" modifiable="undefined" objectid="7_CGAH47L00G72502N5S2MAV00E0" ordinal="99" orientation="V" skinref="undefined" type="container" width="700">
<component action="update" active="true" deletable="undefined" domain="rel" modifiable="undefined" objectid="7_CGAH47L00G72502N5S2MAV00E4" ordinal="99" skinref="K_CGAH47L00G72502N5S2MAV00C6" type="control" width="undefined">
<portletinstance action="update" domain="rel" objectid="5_CGAH47L00G72502N5S2MAV00E2" portletref="3_CGAH47L00G72502N5S2MAV00S4"/>
</component>
</component>
</component>
</content-node>
</portal>
<status element="all" result="ok"/>
</request>

Best practice for using dojo dijit in WebSphere Portal 6.1

WebSphere Portal ships with IBM's Dojo Toolkit. This version is based on Dojo 1.1.1 but has some additional fixes and features that are added by IBM. Also IBM can update or move to different version of Dojo framework in future fixes. You can find IBM Dojo Toolkit 1.1.1 in the theme



Important Note As per IBM support team, they wont support changing the version of Dojo that is shipped with WPS. It means that if you replace the Dojo version that is shipped with IBM's WebSPhere Portal and break the client side code then IBM wont support you.

One of the common requirements is that what if i want to use a Dijit Widget which was introduced in say Dojo 1.2.3 framework. THere are three options

  1. Replacing the Dojo Framework shipped with WPS with version 1.2.3: Biggest problem with this case is that IBM wont support you, Second issue is that WPS has close to 20000 lines of code, how would you test it with new version of dojo. And third issue is that IBM has built quite lot of logic for CSA theme as well as client side API(User Profile, Portlet preference access on client side) using Dojo framework modules. Replacing DOjo version might break this logic

  2. Including multiple versions of DOjo on page: As per Infocenter you cannot have multiple versions of Dojo on one page. I tried following Multiple Versions of Dojo on Page instructions but it did not work for me

  3. Back port your widgets: This is the preferred option, try implementing the Dojo widget that you want using IBM's Dojo Framwork. You should be able to copy the template file and .js file widget as it is

Using Dijit widgets in WebSphere Portal 6.1

Starting from Version 6.1 the Dojo framework is shipped with IBM WebSphere Portal Server. As a result you can assume that Dojo framework would be available on every page. If you want to use Dijit widgets in your portlet or theme code you will have to take some precautions. I did built a sample portlet to demonstrate how you can use Dijit widgets in your portlet.

This is how my sample portlet looks like. It has one dijit.form.Button button.



This is the dijitpage.jsp that i am using to generate markup for the view mode

<%@page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" session="false"%>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet"%>
<%@taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v6.1/portlet-client-model" prefix="portlet-client-model"%>
<%@taglib uri="http://java.sun.com/portlet" prefix="portletx"%>
<portlet-client-model:init>
<portlet-client-model:require module="ibm.portal.xml.*" />
<portlet-client-model:require module="ibm.portal.portlet.*" />
</portlet-client-model:init>
<portlet:defineObjects />
<script>
dojo.require("dojo.parser");
dojo.require("dijit.form.Button");
dojo.addOnLoad( function (){
console.log("Inside dojo.addOnLoad()");
dojo.parser.parse( "portletWidgetContainer");
});
function call_function(){
console.log("Inside the button event handler");
alert("Inside the button event handler")
}
</script>
<div id="portletWidgetContainer">
<button dojoType="dijit.form.Button" onclick="call_function">
Hi I am the One !!
</button>
</div>


You should follow these guidelines in your portlets

  • You should enclose the markup of your portlet or the markup that is using Dijit widget in div or someother enclosing element

  • Add dojo.addOnLoad() function inside your code and call the dojo.parser.parse(<enclosingelementid>) to parse the markup of the portelt for dijit widgets

  • Dojo framework would be included by theme on the page so dont include it explicitly. Trying to override dojo included by theme might break your theme



You can download the sample DijitPortlet from here

Accessing User Information from JSR-168 compliant portlet

If you want to access users information such as first name and last name which is normally stored in coroporate directory in JSR-168 compliant way then use these steps
First add these entries in

<user-attribute>
<description xml:lang="en">User Given Name</description>
<name>user.name.given</name>
</user-attribute>
<user-attribute>
<description xml:lang="en">User Last name</description>
<name>user.name.family</name>
</user-attribute>

After that you should be able to access those two attributes in your java code by using code like this

Map userInfo = (Map)request.getAttribute(PortletRequest.USER_INFO);
if(userInfo != null){
String givenName = (String)userInfo.get("user.name.given");
String lastName =(String)userInfo.get("user.name.family");
response.getWriter().println("Hello " + givenName +" " + lastName);
}

At deployment time the portal can map the requested user profile attributes to the supported profile attributes or the portal can ignore the requested attributes.

Sample PUMA COde

If you want to use PUMA in IBM WebSphere Portal Server Version 6.0 then you might be interested in this sample code

public class PUMAPortlet extends javax.portlet.GenericPortlet {
private PumaHome pumaHome = null;
public void init() throws PortletException{
super.init();
PortletServiceHome portletServiceHome =null;

try {
Context context = new InitialContext();
portletServiceHome = (PortletServiceHome)
context.lookup("portletservice/com.ibm.portal.um.portletservice.PumaHome");
if(portletServiceHome != null){
pumaHome =(PumaHome)portletServiceHome.getPortletService(PumaHome.class);
}
} catch (NamingException e) {
e.printStackTrace();
}
}


public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
response.setContentType(request.getResponseContentType());
demoCurrentUser(request, response);
demoFindingUserByAttribute(request, response);
demoFindUserByDn(request,response);
}

public void demoCurrentUser(RenderRequest portletRequest, RenderResponse portletResponse){

try {
PumaProfile pumaProfile = pumaHome.getProfile(portletRequest);
User user = pumaProfile.getCurrentUser();
List attributeList = new ArrayList();
attributeList.add("sn");
attributeList.add("givenName");
attributeList.add("uid");
attributeList.add("preferredLanguage");

Map userAttributeMap = pumaProfile.getAttributes(user, attributeList);
PrintWriter out = portletResponse.getWriter();

out.println("DN of current User " + pumaProfile.getIdentifier(user) + "");
out.println("Attributes Values for current user
" );
Iterator userAttributeIt = userAttributeMap.keySet().iterator();
while(userAttributeIt.hasNext()){
String attributeName = (String)userAttributeIt.next();
Object attributeValue = userAttributeMap.get(attributeName);
out.println(attributeName + " = " + attributeValue);
out.println("
");
}
out.println("
");

System.out.println("Inside demoCurrentUser " + pumaProfile.getIdentifier(user));

} catch (PumaAttributeException e) {
e.printStackTrace();
} catch (PumaSystemException e) {
e.printStackTrace();
} catch (PumaModelException e) {
e.printStackTrace();
} catch (PumaMissingAccessRightsException e) {
e.printStackTrace();
} catch (PumaException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public void demoFindingUserByAttribute(PortletRequest portletRequest, RenderResponse portletResponse){
try {
PumaLocator pumaLocator = pumaHome.getLocator(portletRequest);
PumaProfile pumaProfile = pumaHome.getProfile(portletRequest);
List userList = pumaLocator.findUsersByAttribute("uid", "sunilpatil");
List attributeList = new ArrayList();
attributeList.add("sn");
attributeList.add("givenName");
attributeList.add("uid");
attributeList.add("preferredLanguage");

User firstUser = (User)userList.get(0);
Map userAttributeMap = pumaProfile.getAttributes(firstUser, attributeList);
PrintWriter out = portletResponse.getWriter();
out.println("Attributes Values for uid=sunilpatil user
" );
Iterator userAttributeIt = userAttributeMap.keySet().iterator();
while(userAttributeIt.hasNext()){
String attributeName = (String)userAttributeIt.next();
Object attributeValue = userAttributeMap.get(attributeName);
out.println(attributeName + " = " + attributeValue);
out.println("
");
}


out.println("
");
} catch (PumaSystemException e) {
e.printStackTrace();
} catch (PumaModelException e) {
e.printStackTrace();
} catch (PumaMissingAccessRightsException e) {
e.printStackTrace();
} catch (PumaAttributeException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public void demoFindUserByDn(RenderRequest renderRequest, RenderResponse renderResponse){
try {
PumaLocator pumaLocator = pumaHome.getLocator(renderRequest);
PumaProfile pumaProfile = pumaHome.getProfile(renderRequest);
User user = pumaLocator.findUserByIdentifier("uid=wasadmin,o=default organization");
List attributeList = new ArrayList();
attributeList.add("sn");
attributeList.add("givenName");
attributeList.add("uid");
attributeList.add("preferredLanguage");


Map userAttributeMap = pumaProfile.getAttributes(user, attributeList);
PrintWriter out = renderResponse.getWriter();
out.println("Attributes Values for 'uid=wasadmin,o=default organization' user
" );
Iterator userAttributeIt = userAttributeMap.keySet().iterator();
while(userAttributeIt.hasNext()){
String attributeName = (String)userAttributeIt.next();
Object attributeValue = userAttributeMap.get(attributeName);
out.println(attributeName + " = " + attributeValue);
out.println("
");
}


out.println("
");
} catch (PumaSystemException e) {
e.printStackTrace();
} catch (PumaModelException e) {
e.printStackTrace();
} catch (PumaMissingAccessRightsException e) {
e.printStackTrace();
} catch (PumaAttributeException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

It has three methods first demonstrates how to get list of attributes for current users, second is how to search user with value of particular attribute equal to something and third is how to find user based on DN

Mapping LDAP Attribute

The wp-query-attribute-config task explained in Querying LDAP attribute gives you high level mapping of LDAP attribute vs WebSphere Portal attribute.
In addition to that WebSphere Portal has ./ConfigEngine.sh wp-validate-standalone-ldap-attribute-config task that can be used to get more detailed information

After executing this mapping open the ConfigTrace.log file which is in /wp_profile/ConfigEngine/log directory, you should see messages like this

[wplc-validate-ldap-attribute-config] The following attribues are defined in Portal but not in LDAP - You should either flag them as unsupported or define an attribute mapping:
[wplc-validate-ldap-attribute-config] [groups, identifier, ibm-jobTitle, entitlementInfo, realm, viewIdentifiers, certificate, stateOrProvinceName, createTimestamp, modifyTimestamp, ibm-primaryEmail, children, parent, c, partyRoles, principalName, countryName, localityName]

[wplc-validate-ldap-attribute-config] The following attributes are flagged as required in LDAP but not in Portal - You should flag them as required in Portal, too:
[wplc-validate-ldap-attribute-config] [sn, cn]

[wplc-validate-ldap-attribute-config] FYI: The following attributes have a diffenrent type in Portal and in LDAP - No action is required:
[wplc-validate-ldap-attribute-config] jpegPhoto: Base64Binary <> 1.3.6.1.4.1.1466.115.121.1.5
[wplc-validate-ldap-attribute-config] password: Base64Binary <> 1.3.6.1.4.1.1466.115.121.1.5
[wplc-validate-ldap-attribute-config] seeAlso: String <> 1.3.6.1.4.1.1466.115.121.1.12
[wplc-validate-ldap-attribute-config] Possible problems for Group:

[wplc-validate-ldap-attribute-config] The following attribues are defined in Portal but not in LDAP - You should either flag them as unsupported or define an attribute mapping:
[wplc-validate-ldap-attribute-config] [modifyTimestamp, groups, members, identifier, displayName, parent, children, entitlementInfo, partyRoles, viewIdentifiers, createTimestamp]

[wplc-validate-ldap-attribute-config] The following attributes are flagged as required in LDAP but not in Portal - You should flag them as required in Portal, too:
[wplc-validate-ldap-attribute-config] []

[wplc-validate-ldap-attribute-config] FYI: The following attributes have a diffenrent type in Portal and in LDAP - No action is required:
[wplc-validate-ldap-attribute-config] seeAlso: String <> 1.3.6.1.4.1.1466.115.121.1.12
[wplc-validate-ldap-attribute-config] Status = Complete
Target finished: wp-validate-standalone-ldap-attribute-config
Mon Mar 30 12:51:21 EDT 2009
Target started: action-post-config


The ConfigTrace.log file has information on what are required attributes in LDAP but are not configured in WebSphere Portal and other way round also attributes where types in LDAP and WebSphere Portal does not match.

Once you have the validation messages either change wkplc.properties or create manageattributes.properties file like this

standalone.ldap.attributes.nonSupported=certificate, members
standalone.ldap.attributes.nonSupported.delete=

standalone.ldap.attributes.mapping.ldapName=mail,title
standalone.ldap.attributes.mapping.portalName=ibm-primaryEmail, ibm-jobTitle
standalone.ldap.attributes.mapping.entityTypes=PersonAccount, Group


and execute the ConfigEngine.bat wp-update-standalone-ldap-attribute-config task to either map attributes from LDAP to portal or mark attributes as not supported.

Adding new attribute to WebSphere Portal

WHen you configure websphere portal to use LDAP as a user repository, it only maps the standard set of attributes from WebSphere Portal to underlying LDAP. But what if your LDAP has some business specific attribute that you want to access through either theme or portlets Ex. Tivoli Directory Server 6.2 has postOfficeBox attributes that you want to access either from your theme or portlet using PUMA API but that attribute is not defined in WebSphere Portal In situations like that you might want to add new attribute in WebSphere Portal.

Follow these steps to add new attribute

  • Execute ./ConfigEngine.sh wp-la-install-ear task, this task will install WIMSYSTEM.ear which contains wimejb.jar on your portal server. The wimejb.jar is used for actual attribute addition

  • After installing WIMSystem.ear restart both server1 and WebSphere_Portal

  • The configuration task makes calls to wimejb for adding attributes. The wimejb is secured so in order to access it you will have to either Change the sas.client.properties to set values for these two properties

    com.ibm.CORBA.loginUserid=wasadmin
    com.ibm.CORBA.loginPassword=wasadmin

    or enter WAS admin's user id and password at the time of executing the configuration task.

  • YOu will have to set following 5 properties in order to add new attribute. You have two options either you can set these properties in wkplc.properites or you can create addattribute.properties file like this

    la.providerURL=corbaloc:iiop:localhost:10031
    la.propertyName=postOfficeBox
    la.entityTypes=PersonAccount
    la.dataType=String
    la.multiValued=yes

    In this file value of propviderURL should be the servername:bootstapport number.

  • Execute the following configuration task to add the postOfficeBox as attribute to the WebSphere Portal

    ./ConfigEngine.sh wp-add-property -DparentProperties=/software/IBM/WebSphere/wp_profile/ConfigEngine/config/helpers/addattribute.properties


  • Query WebSphere Portal using ./ConfigEngine.sh wp-query-attribute-config to check the updated attribute attribute mapping, you should see name of the postOfficeBox attribute in the list

    Take a look at Querying LDAP Attributes for further details on querying LDAP attributes

  • Restart the WebSphere_Portal server so that your changes take effect

Querying LDAP attributes

IBM WebSphere Portal has a predefined set of attributes for users and groups. Your LDAP server may have a different set of predefined user and group attributes. To ensure proper communication between WebSphere Portal and your LDAP Server, you can configure additional attributes and flag existing attributes as required or unsupported on a per repository basis for all configure repositories.

LDAP server can only handle the attributes explicitly defined in their schema. The task to add the LDAP user registry does some basic attribute configuration depending on the type of LDAP server that you choose. You may however still need to adapt the the WPS configuration to match the LDAP schema: for example if an attribute is defined in WPS but not in the LDAP server, you will need either flag the attribute as unsupported for the LDAP server or introduce attribute mapping that maps the WPS attribute to an attribute defined in the LDAP schema.

Querying attributes mapping



You can query portal for all the configured attributes using ConfigEngine.bat wp-query-attribute-config configuration command. This command creates availableAttributes.html in the wp_profile/ConfigEngine/log directory. This HTML file has table with two columns. First column lists out the attributes defined in the WebSphere Portal and second column lists out how it is mapped to LDAP attribute. If there is a match it will show checked sign. If not it will show "not supported" to indicate that this attribute is not supported. If the attribute in LDAP has different name then it will display the attribute name in ldap in second column. Take a look at this screen shot which says that homePostalAddress attribute is not supported and password is mapped to userPassword in LDAP.

Configuring Stand-alone LDAP registry

These are the steps that i followed to configure Stand-alone LDAP registry for the WebSphere Portal Server.

  • Start the server1 and WebSphere_Portal server

  • First change the software/IBM/WebSphere/wp_profile/ConfigEngine/config/helpers/wp_security_ids.properties file like this. Since i used the PortalUsers.ldif file to create users in LDAP, i had to make very few changes in the wp_security_ids.properties. I had to replace youco with spinfotech and use wpsbind for bind user id and wasadmin as websphere application server admin user id.

    # The id specifies a unique identifier for the repository within the cell
    # Characters that are not allowed in normal XML strings ( & < > " ' ) cannot be used in the repository ID.
    standalone.ldap.id=spinfotech

    # Specifies the host name of the primary LDAP server. This host name is either an IP address or a domain name service (DNS) name.
    standalone.ldap.host=192.168.174.1

    # Specifies the LDAP server port.
    standalone.ldap.port=389

    # Specifies the distinguished name for the application server to use when binding to the LDAP repository.
    standalone.ldap.bindDN=uid=wpsbind,cn=users,dc=spinfotech,dc=com

    # Specifies the password for the application server to use when binding to the LDAP repository.
    standalone.ldap.bindPassword=wpsbind

    # Specifies the type of LDAP server to which you connect
    # Supported values on WAS 6.1: IDS4, IDS51, IDS52, IDS6, SECUREWAY
    # Note: If your LDAP server version is not listed, enter the value for the highest listed version of your server
    # Supported values on WAS 7: IDS
    standalone.ldap.ldapServerType=IDS6

    # Specifies the LDAP filter that maps the short name of a user to an LDAP entry.
    # For example, to display entries of the object class = inetOrgPerson type by their IDs, specify inetOrgPerson:uid.
    # This field takes multiple objectclass:property pairs delimited by a semicolon (;).
    # note: not used during node federation to DMGR with WAS ldap security enabled
    standalone.ldap.userIdMap=*:uid

    # Specifies the LDAP filter that maps the short name of a group to an LDAP entry.
    # Specifies the piece of information that represents groups when groups display. For example, to display groups by their names, specify *:cn.
    # The asterisk (*) is a wildcard character that searches on any object class in this case.
    # This field takes multiple objectclass:property pairs, delimited by a semicolon (;).
    # note: not used during node federation to DMGR with WAS ldap security enabled
    standalone.ldap.groupIdMap=*:cn

    # Specifies the LDAP filter that identifies user-to-group relationships.
    # Specifies which property of an objectclass stores the list of members belonging to the group represented by the objectclass.
    # For directory types SecureWay, and Domino, this field takes multiple objectclass:property pairs, delimited by a semicolon (;).
    # For IBM Directory Server, Sun ONE, and Active Directory, this field takes multiple group attribute:member attribute pairs delimited by a semicolon (;).
    # For more information about this syntax, see the LDAP directory service documentation.
    # note: not used during node federation to DMGR with WAS ldap security enabled
    standalone.ldap.groupMemberIdMap=

    # Specifies the LDAP user filter that searches the user registry for users.
    # For example, to look up users based on their user IDs, specify (&(uid=%v)(objectclass=inetOrgPerson))
    # note: not used during node federation to DMGR with WAS ldap security enabled
    standalone.ldap.userFilter=(&(uid=%v)(objectclass=inetOrgPerson))

    # Specifies the LDAP group filter that searches the user registry for groups.
    # note: not used during node federation to DMGR with WAS ldap security enabled
    standalone.ldap.groupFilter=(&(cn=%v)(objectclass=groupOfUniqueNames))

    # Specifies a user ID and password in the repository that is used for internal process communication.
    # note: not used during node federation to DMGR with WAS ldap security enabled
    standalone.ldap.serverId=uid=wpsbind,cn=users,dc=spinfotech,dc=com
    standalone.ldap.serverPassword=wpsbind

    # The security context of this server. A realm with this name will be created.
    standalone.ldap.realm=spinfotech


    # The ID of the WAS admin user. The ID must exist in the LDAP server.
    standalone.ldap.primaryAdminId=uid=wasadmin,cn=users,dc=spinfotech,dc=com
    standalone.ldap.primaryAdminPassword=wasadmin

    # The ID of the portal admin user. The ID must exist in the LDAP server.
    standalone.ldap.primaryPortalAdminId=uid=wasadmin,cn=users,dc=spinfotech,dc=com
    standalone.ldap.primaryPortalAdminPassword=wasadmin

    # The user group with admin permission in portal. The group must exist in the LDAP server.
    standalone.ldap.primaryPortalAdminGroup=cn=wpsadmins,cn=groups,dc=spinfotech,dc=com

    # The LDAP base entry.
    # This is the startpoint for all LDAP searches of Websphere Application Server Security
    standalone.ldap.baseDN=dc=spinfotech,dc=com

    ########################
    ##
    ## LDAP entity types
    ##
    ########################

    # Entity type Group

    # The search filter that you want to use to search the entity type.
    # VMM uses this filter as an addition during search requests in your environment
    # The syntax is like a standard LDAP searchfilter like (objectclass=groupOfUniqueNames)
    # In general this value can be left blank
    standalone.ldap.et.group.searchFilter=

    # One or more object classes (separated by ';') for the entity type.
    standalone.ldap.et.group.objectClasses=groupOfUniqueNames

    # The object class(es) (separated by ';') to use when an entity type is created. If the value of this parameter is the same as the objectClass parameter, you do not need to specify this parameter.
    standalone.ldap.et.group.objectClassesForCreate=

    # The search base or bases to use while searching the entity type.
    standalone.ldap.et.group.searchBases=


    # Entity type PersonAccount

    # The search filter that you want to use to search the entity type.
    # VMM uses this filter as an addition during search requests in your environment
    # The syntax is like a standard LDAP searchfilter like (objectclass=inetOrgPerson)
    # In general this value can be left blank
    standalone.ldap.et.personaccount.searchFilter=

    # One or more object classes (separated by ';') for the entity type.
    # Please check this value with the objectclass used in your LDAP for type User
    standalone.ldap.et.personaccount.objectClasses=inetOrgPerson

    # The object class(es) (separated by ';') to use when an entity type is created. If the value of this parameter is the same as the objectClass parameter, you do not need to specify this parameter.
    standalone.ldap.et.personaccount.objectClassesForCreate=

    # The search base or bases to use while searching the entity type.
    standalone.ldap.et.personaccount.searchBases=

    ########################
    ##
    ## End LDAP entity types
    ##
    ########################

    ###################################################
    ##
    ## Group member attributes
    ##
    ###################################################

    # The name of the LDAP attribute that is used as the group member attribute. For example, member or uniqueMember.
    standalone.ldap.gm.groupMemberName=uniqueMember

    # The group object class that contains the member attribute. For example, groupOfNames or groupOfUnqiueNames.
    # If you do not define this parameter, the member attribute applies to all group object classes.
    standalone.ldap.gm.objectClass=groupOfUniqueNames

    # The scope of the member attribute. The valid values for this parameter include the following:
    # direct - The member attribute only contains direct members.
    # nested - The member attribute that contains the direct members and the nested members.
    standalone.ldap.gm.scope=direct

    # If you create a group without specifying a member, a dummy member will be filled in to avoid creating an exception about missing a mandatory attribute.
    standalone.ldap.gm.dummyMember=uid=dummy


    ###############################
    # Default parent, RDN attribute
    ###############################

    # The default parents to be set for the the entity types PersonAccount and Group
    standalone.ldap.personAccountParent=cn=users,dc=spinfotech,dc=com
    standalone.ldap.groupParent=cn=groups,dc=spinfotech,dc=com

    # The RDN attribute names for the entity types PersonAccount and Group
    # To reset all the values of the rdnProperties parameter, specify a blank string ("").
    standalone.ldap.personAccountRdnProperties=uid
    standalone.ldap.groupRdnProperties=cn

    ###################################################
    ##
    ## End Group member attributes
    ##
    ###################################################



    ###############################################################################
    ##
    ## Advanced Properties
    ##
    ###############################################################################


    ###################
    # Group config
    ###################

    # The name of the membership attribute. For example, memberOf in an active directory server and ibm-allGroups in IDS.
    standalone.ldap.gc.name=

    # Updates the group membership if the member is deleted or renamed. Some LDAP servers, for example, Domino server, do not clean up
    # the membership of the user when a user is deleted or renamed. If you choose these LDAP server types in the ldapServerType property,
    # the value of this parameter is set to true. Use this parameter to change the value. The default value is false.
    standalone.ldap.gc.updateGroupMembership=

    # The scope of the membership attribute. The valid values for this parameter include the following:
    # direct - The membership attribute only contains direct groups.
    # nested - The membership attribute that contains the direct groups and the nested groups.
    # all - The membership attribute contains direct groups, nested groups, and dynamic members.
    # The default value is direct.
    standalone.ldap.gc.scope=direct


    # Controls how aliases are dereferenced. The default value is always. Valid values include:
    # always - always deference aliases
    # never - never deference aliases
    # finding - deference aliases only during name resolution
    # searching - deference aliases only after name resolution
    standalone.ldap.derefAliases=always

    # Indicates the authentication method to use. The default value is simple. Valid values include: none or strong.
    standalone.ldap.authentication=simple

    # The LDAP referral. The default value is ignore. Valid values include: follow, throw, or false.
    standalone.ldap.referral=ignore

    # Specifies the delimiter used for this realm. The default value is /.
    standalone.ldap.delimiter=/

    # Whether the query matches case sensitivity.
    # note: not used during node federation to DMGR with WAS ldap security enabled
    standalone.ldap.ignoreCase=true

    # Specifies whether secure socket communication is enabled to the LDAP server.
    # When enabled (sslEnabled=true), the Secure Sockets Layer (SSL) settings for LDAP are used.
    # The default value is false.
    standalone.ldap.sslEnabled=false

    # Specifies the name of the application server SSL configuration to be used for SSL enabled LDAP server.
    # This property is used to specify a non default SSL configuration if standalone.ldap.sslEnabled=true is set
    standalone.ldap.sslConfiguration=

    # Specifies whether to map X.509 certificates into a LDAP directory by exact distinguished name or certificate filter.
    # Specify the certificate filter to use the specified filter for the mapping, if client certificate authentication is used
    # for portal server.
    # Valid values include: EXACT_DN, CERTIFICATE_FILTER
    standalone.ldap.certificateMapMode=EXACT_DN

    # Specifies the filter certificate mapping property for the LDAP filter, if client certificate authentication is used
    # for portal server.
    # The filter is used to map attributes in the client certificate to entries within the LDAP repository.
    standalone.ldap.certificateFilter=

    # Should be set to true by default to reuse the LDAP connection.
    # note: not used during node federation to DMGR with WAS ldap security enabled
    standalone.ldap.reuseConnection=true

    # Specifies the timeout value in miliseconds for an LDAP server to respond before aborting a request.
    standalone.ldap.searchTimeLimit=120000

    # Defines if VMM will enable the ConnectionPool
    standalone.ldap.connectionPool=false

    # Indicates if sorting is supported or not. The default value is false.
    standalone.ldap.supportSorting=false

    # Indicates if paging is supported or not.
    standalone.ldap.supportPaging=false

    # Indicates if transactions are supported or not. The default value is false.
    standalone.ldap.supportTransactions=false

    # Specifies if the external ID is unique. The default value is true.
    standalone.ldap.isExtIdUnique=true

    # Indicates if external names are supported or not. The default value is false.
    standalone.ldap.supportExternalName=false

    # Indicates to translate RDN or not. The default value is false.
    standalone.ldap.translateRDN=false

    # The value of the search count limit.
    standalone.ldap.searchCountLimit=500

    # The value of search page size.
    standalone.ldap.searchPageSize=

    # Indicates to return to the primary LDAP server when it is available. The default value is true.
    standalone.ldap.returnToPrimaryServer=

    # Indicates the polling interval for testing the primary server availability.
    # The value of this parameter is specified in minutes. The default value is 15.
    standalone.ldap.primaryServerQueryTimeInterval=

    # Indicates the property name used for login.
    standalone.ldap.loginProperties=uid

    # The maximum number of context instances that can be maintained concurrently by the context pool.
    # The default value is 20.
    standalone.ldap.cp.maxPoolSize=20


  • Once the wp_security_ids.properties is ready use it as parentProperties file to execute validate ldap task. This task makes sure that the values that your settings are Ok.

    ./ConfigEngine.sh validate-standalone-ldap -DWasPassword=wasadmin -DparentProperties=/software/IBM/WebSphere/wp_profile/ConfigEngine/config/helpers/wp_security_ids.properties


  • Once the validation is successful you can execute the wp-modify-ldap-security task to enable the security

    ./ConfigEngine.sh wp-modify-ldap-security -DWasPassword=wasadmin -DparentProperties=/software/IBM/WebSphere/wp_profile/ConfigEngine/config/helpers/wp_security_ids.properties


  • Restart both the server1 and WebSphere_Portal server



After enabling security you can see all the properties that you set from the WAS Admin Console like this.



Click on configure button and you will see the detailed configuration

WebSphere Application Servers backupConfig command

The backupConfig command is a simple utility to back up the configuration of your node to a file. It is highly recommended that you backup your configuration before you make any major configuration change. When you execute the backupConfig command it will take backup of your profile configuration and if something goes wrong you can restore configuration by using restoreConfig command

I took backup of my WebSphere Portal profile by going to portal_profile_root/bin directory and executing this command


./backupConfig.sh /tmp/WebSphere_Portal_03_29_2009.zip


It took 4-5 minutes and after that i could see WebSphere_Portal_03_29_2009.zip file in the /tmp directory. When i looked inside that .zip file it looks like it copied content of portal_profile_root/config directory. On my portal installation i could see four folders under /config directory backup,cells,temp and template out of that it ziped cells and templates folders

This is how my config directory looks like

This is how my WebSphere_Portal_03_29_2009.zip looks like.


the .repository directory is also part of portal_profile_root/config directory but it is hidden. The backup does not include tmp and backup sub-folders of config directory

After reading the Infocenter the impression that i get is we can also copy config directory manually and restore it instead of using backupConfig and restoreConfig command but never tried that so not sure how it works

Installing TDS 6.2

I want to learn about how to configure WebSphere Portal to use Standalone LDAP as well as federated LDAP so i decided to install IBM's Tivoli Directory Server on my machine.
First of all i could not figure out how to use the couple of TDS 6.1 related CDS that are shipped with Portal Installer to install LDAP, so i did download 7 cds related to Tivoli Directory server 6.2 from IBM partnerworld. First i tried installing Tivoli Directory server on CentOS vmware image, but problem is the Graphical UI wont work because it is not supported. I spent quite a bit of time trying to use console mode to install TDS but somehow i could never get past the Accept License part. After spending 1 day trying to figure it out i decided to install TDS 6.2 on my Windows machine (And i decided that i need to improve my TDS Skills) and connect to it from my WPS installed on CentOS VMWare. These are the steps that i followed


  • Download the 6 Tivoli Directory Server 6.2 installer CDS from the IBM Partnerworld

  • After that i followed these Installing Tivoli Directory Server 6.1 On RHEL5.1 instructions for installing TDS. One important point, after installing DB2 and GSKit i did restart the server. When i tried using typical installation it failed on db instance creation step. Also try loggin as db2admin for db2instance creation task.

  • Once TDS was installed i tried importing PortalUsers.ldif from IL-Setup CD for WebSphere Portal Installer. Db2 kept throwing "Access denied" error, so i ended up creating wpsadmin,wpsbind users and wpsadmins group manually using the Admin UI.



Now my LDAP server is setup so i am going to first try configuring Standalone LDAP and then federated User repository for WPS on my VMware. I do have backup of WPS VMWare so if it fails i can go back to base image.

Managing replication in your cluster

Replication is a service provided by WAS that transfers data, objects or events among application servers. Data replication can be used to make data for session managerm dynamic cache and stateful session beans available across many application servers in cluster


  • Dynamic caching: Data replication service (DRS) is the internal WebSphere Application Server component that replicates data among application servers. There are several types of data replication, and WebSphere Portal can make use of data replication for dynamic caching and for memory-to-memory replication of session data. Enabling data replication for dynamic caching in a cluster environment is absolutely necessary to maintain data integrity between multiple WebSphere Portal nodes in the cluster. Replication also helps improve performance by generating data once and then replicating it to other servers in the cluster.

  • Distributed sessions: WebSphere Portal can use the WebSphere Application Server capabilities to support HTTP session failover, which enables one node in a cluster to access information from the existing HTTP session in case of a failure in the cluster node originally handling that session. This capability is referred to as distributed sessions. WebSphere Application Server provides two techniques that can be used for distributed sessions, either of which can be used in a WebSphere Portal cluster. Distributed session support is not enabled by default, so you will have to determine whether to provide this capability in your cluster, and, if so, which of the two techniques you will use: memory-to-memory session replication and database session persistence.

WSRP Portlet in cluster

By providing a portlet as WSRP service, a Producer makes the deployed portlet available remotely to Consumers. The WebSphere Portal database stores information about whether a portlet deployed in the cluster is provided as a WSRP service. Because the WebSphere Portal database is shared between the nodes in a cluster, all nodes are updated when providing a portlet as a WSRP service.

The URLs of the Producer services definitions in the Web Services Description Language (WSDL) document always automatically point to the Web server performing load balancing in the cluster. This ensures that all requests of Consumers invoking WSRP services of the Producer will be correctly load balanced.

The Producers URLs are generated by first checking the settings of the WSRP SOAP ports, as described in the WSRP documentation. If the SOAP port values are not set, the values of the host.name and host.port properties in ConfigService are used. These values typically point to the load balancing traffic dispatcher. If no values are specified for either the SOAP ports or in ConfigService, the host name and port of the request used to reference the Producer WSDL document is used.

Manage portlets in a cluster

When you deploy a portlet, WebSphere Portal stores the portlet configuration data in the WebSphere Portal database and then forwards the portlet applications Web Module and associated configuration to the deployment manager. The DM is responsible for pushing the Web Modules to each node in the cluster. Since all the nodes in the cluster same share same database any portal in the cluster can be used to manage portlet.

Once the portlet is deployed, the DM will push these changes to all the portal servers and once the portal application is updated on all the Portal Server you can activate it. Now problem is we dont know how much time this process will take. SO irrespetive of if you deployed a portlet using either XMLAccess or "Manage Portlets" portlet, you should execute the ConfigEngine.bat activate-portlets task to synchronize changes to all portals and activate deployed portlet.

If a portlet is deployed through WebSphere Portal, it first takes whatever configuration information it needs from the portlet’s WAR file, and then it generates a unique object ID for this portlet. WebSphere Portal then wraps the portlet’s WAR within an EAR definition, giving it a name based on the portlet’s display name, suffixed with the generated object ID. This guarantees that the portlet’s underlying enterprise application name is unique to this portal. In the event that this portal is clustered, the new enterprise application will be common to this cluster, but unique from any other cluster in the cell, because again the object ID is guaranteed to be unique.

Important Note: You can use the XMLAccess task to delete a portlet common across clusters. If the portlet was predeployed as a standard EAR, then each cluster must be first notified of the portlet removal before the EAR can be uninstalled. The administrator must use the XMLAccess application to import a definition similar to the ones used in the previous two sections, except the action is to delete the definition instead of update it. For example:.

User Rights for portlet

You need following roles to perform following actions on portlets


  • Personalize: You need at least Privileged User role on the portlet and page in order to personalize portlet. The changes that you make would be visible to you only

  • Edit Shared Settings: You need at least Privileged User role on the portlet and page in order to personalize portlet. The changes that you make would be visible to all the users of the portlet on current instance

  • Configure: You need at least Manager role on the portlet and page in order to change configuration of portlet. The changes that you make would to all the users of the portlet on all pages


Installing portlet


When you deploy a portlet two things should happen first the portlet should get deployed on the underlying WebSphere Application Server as enterprise application and second thing is the portlet information should be stored in the database. How this works depends on how to deploy portlet there are two different ways of deploying portlets


  • As .war file using Manage Web Modules portlet or using xmlaccess script. You can use Manage Web Modules Portlet by going to Portal Admin Console and clicking on Portlet Management -> Web Modules. Once on this page click on Install button and on next screen enter path of the portlet .war file.


  • As .ear file, you can deploy a portlet as enterprise application, which might be useful if your portlet wants to use EJB and as a result you want to package .war file and ejb in same .ear file. You can deploy .ear file through WAS Admin console or wsadmin script. But once the application is deployed you will have to execute xmlaccess scritp to register it as portlet i.e. do the part of reading portlet.xml configuration and storing that information in the database.



Important Note: You need at least Manager role on the Portal to be able to deploy portlet on it. The user who deploys the portlet automatically gets owner role on that portlet.

1. You can register predeployed applications into the portal only by using the XML configuration interface. Once you have registered a predeployed application, the Manage Web Modules portlet shows this application.
2. You can later use the portal administration portlets to remove the portlet definitions from the portal database. However, this does not remove the EAR file from WebSphere Application Server.
3. You can update a predeployed portlet application only by using the XML configuration interface.
4. You cannot update a deployed portlet application WAR file with a predeployed EAR file and vice versa. If you want to change between the two types of files, you need to delete the existing portlet application and deploy the new one. However, deleting the existing portlet application will also delete all configuration data of that application. A predeployed application can only be updated via update of the EAR file in WebSphere Application Server and subsequent update of the contained WAR file in portal by using the XML configuration interface. Cross updates of a predeployed EAR file with a real WAR and vice versa are not possible.
5. The WebSphere Application Server administrator must take care of correctly configuring the dispatch mechanisms for these applications.

Frequently used trace Strings

These are some of the most commonly used trace strings. For details on the components that your looking for go to Infocenter
























Portal Search

com.ibm.portal.search.*=all

Virtual Member Manager

com.ibm.ws.security.*=all:com.ibm.websphere.wim.*=all:
com.ibm.wsspi.wim.*=all:com.ibm.ws.wim.*=all

Web Content Management

com.ibm.workplace.wcm.*=all:
com.aptrix.*=all:
com.presence.*=all

Access Control

com.ibm.wps.ac.*=all

XMLAccess

com.ibm.wps.command.xml.*=all

System Event Logging

The WebSphere Portal Server generates two types of information one is messages and other is detailed trace information.

Important Note: Starting from WebSphere Portal Server Version 6.1, the location of log and trace file is changed. Now these files get generated under wp_profile\logs\WebSphere_Portal folder.


Messages


WebSphere Portal provides the logging of messages that report errors and status information.


  • Informational:A condition worth noting but does not require the user to perform an action.

  • Warning: An abnormal condition has been detected. The user may have to take action. However, WebSphere Portal code is able to handle the condition without failing.

  • Error: A serious failure in the execution of the application that requires further action.




Tracing



Portal provides the logging of debugging messages called traces. These traces are useful for fixing problems.

Important Note Enabling trace is resource intensive so traces are disable by default.

You can enable traces either temporarily or permanently(Enable trace across server restart.)

Temporarily



When it comes to enabling tracing for temporary period of time you have two options you can use either the Portal Admin Section or WAS Admin Console.

Enable Tracing Portlet

You can enable trace for particular component by going to Portal Admin Console -> Portal Analysis -> Enable Tracing. You should get screen like this. By default it will have trace string "*=info". If you want to enable trace for say access control enter "com.ibm.wps.ac.*=all" and click on add.



WAS Administration Console
You can enable tracing using the WAS Admin console too. Follow these steps for that


  • Log in into WAS Admin console. By default it is available at https://localhost:10041/ibm/console.

  • Go to Trouble Shooting -> Log and Trace. Select WebSphere_Portal or whatever is your server name.

  • Click on the Diagnostic Trace it will open Diagnostic Trace Service page.

  • Switch to Runtime tab. Which looks like this.


  • Now Click on Change Log Details Level link on the right hand side.It will open a page like this. On this page you have two options either click on the package that your interested in and it will open context menu select Messages and Trace Level -> Finest in that or you enable trace string by entering the trace string directly in the Text Area where it says *=info.


  • Click Ok and your changes should take effect immediately.


Once you enable trace you will trace.log file in wp_profile\logs\WebSphere_Portal folder thats the file which you should use for looking at the trace information.

Extended

If you want your trace changes to persist across server restart then you will have to use the WAS Admin Console.

Follow the same steps as turning on the trace for turning on temporary trace but click on the Change Log Details level link on Configuration tab instead of Runtime tab. Your changes would be persisted in wp_profile\config\cells\sunpa\nodes\sunpa\servers\WebSphere_Portal file.

<services xmi:type="traceservice:TraceService" xmi:id="TraceService_1226779529755" enable="false" startupTraceSpecification="*=info:com.ibm.wps.ac.*=all" traceOutputType="SPECIFIED_FILE" traceFormat="LOG_ANALYZER">
<traceLog xmi:id="TraceLog_1226779529758" fileName="${SERVER_LOG_ROOT}/trace.log" rolloverSize="20" maxNumberOfBackupFiles="3"/>
</services>

Open the server.xml file and search for traceService you will see the trace service related configuration.

Important NoteAny changes that you make on the Configuration tab or in the server.xml file directly wont take effect unless you restart the server.

How to use IBM Support Assistance Lite for WebSphere Portal

After downloading the IBM Support Assistance Lite for WebSphere Portal, i did extract the .zip file in wp_profile\PortalServer folder. THen go to wp_profile\PortalServer\ISALite and execute runISALite.bat to start the ISALite.

After opening ISALite you can select the problem that you want to collect trace for. I tried collecting trace for XMLAccess and decided to save the .zip file on the desktop like this



NOw click on Collect Data button. It will start collecting the trace. At this point it ask me few more questions about what is the Root directory of WAS, Portal, Login information for portal, the xmlaccess script that is failing,.. etc. At this point its started collecting trace but my machine hanged for some reason but when i rebooted my machine, i could see the xmlaccess.zip being created on my desktop that has all trace files for my server.

IBM Support Assistance Lite for WebSphere Portal

The IBM Support Assistant Lite for WebSphere Portal tool (formerly known as the IBM WebSphere Portal Automated Problem Determination tool) is provided as an aid for troubleshooting WebSphere Portal. The tool focuses on automatic data collection and provides symptom analysis support for WebSphere Portal Problem Determination Scenarios. Information pertinent to a problem scenario is collected and analyzed to help identify the origin of the problem being encountered

You can download it from IBM Support Assistant Lite for WebSphere Portal Tool

IBM Self Help Central for WebSphere Portal has more information for administrators

IBM Support Assistance

IBM Support assistance is a Utility that helps you diagnose and solve problems related to IBM products without contacting support. THe IBM SUpport assistance itself is built using Eclipse platform and is qutie generic but you can download and install product specific plugins in it.

You can install IBM Support assistance from the installation media for WebSphere Portal or you can download it from IBM Support Site

IBM Support assistance provides following functionality

  • To collect the diagnostic data that you need to open PMR with IBM

  • Open PMR with IBM, it provides customized on-line interface that also allows you to attach data to the PMR

  • To search through IBM and non-IBM knowledge and information sources across multiple IBM products to answer a question or solve a problem

  • To extend your ability to diagnose product-specific problems with targeted diagnostic tools available via the Support Assistant

  • To search through IBM and non-IBM knowledge and information sources across multiple IBM products to answer a question or solve a problem

Understanding standard portlet life cycle

A portlet is managed through a well defined life cycle that defines how it is loaded,
instantiated and initialized, how it handles requests from clients, and how it is taken out of service. This life cycle of a portlet is expressed through the init, processAction, render and destroy methods of the Portlet interface.


  • init: When portal server gets request for a page it will check if all the portelts on that page are initialized or not if not it will create new instance of portlet call its init() method.

  • processAction: Whenever user clicks on an action URL or submits a form to action URL the portal server will call processAction() method of the portlet. IN this method your suppose to change state of the portlet by setting render parameter, storing data in database,..etc

  • render: THis is the most common method of the portlet, whenever you go to page which has the portlet or click on the action URL of any other portlet on the page or click on the render URL within the same portlet, refresh page, the render method of the portlet will be called. The render method is responsible for generating markup of the portlet based on its current state.

  • destroy: When portal server decides to take portlet out of the request it will call its destroy method to give it a chance to release resources



Important Point: The Portal server will create only one instance of portlet per JVM and it will create different threads for every request and call appropriate methods of portlets from that thread.

In addition to this your portlet can decide to implement EventPortlet interface which says that portlet can be target of event (Target of inter portlet communication). The EventPortlet interface defines processEvent() method that you should override to implement the logic that should be executed when portlet receives event. THis is useful if you want to use inter portlet communication

If your portlet wants to support Ajax access then you can also implement ResourceServingPortlet interface, that defines serveResource() method. Once you define this method you can create a resource URL from your portlet using resourceURL tag and make request to the URL to get the fragment of portlet. This helps you avoid creating a Servlet in same application as that of the portelt just to support Ajax

Proxy Configuration Level

The Ajax Proxy is configured at two levels

Global Proxy Configuration


There is AJAX Proxy Configuration.ear file that define Ajax Proxy at the level of portal. All portlets, themes, other enterprise applications can use it.

If you want to change the Global proxy configuration then you will have to change wp_profile\installedApps\sunpa\AJAX Proxy Configuration.ear\wp.proxy.config.war\WEB-INF\proxy-config.xml and restart the Ajax Proxy Configuration application.

The actual AJax Proxy servlet is defined in wp_profile\installedApps\sunpa\wps.ear\wps.war\WEB-INF\web.xml. By default it is configured to forward every request to /wps/proxy and /wps/myproxy to the Ajax Proxy Servlet. So if you want to support any other url mapping such as /ibm then you will have to change the web.xml file in the wps.war and redeploy it.


Application Level Proxy Configuration


You can override the proxy configuration at your application level. When you do that the proxy configuration defined in your portlet will take precedence over the global proxy. Take a look at AjaxProxySample for sample of how to configure application level proxy.

Important Note As portal server administrator you can configure portal to rule application level ajax proxy configuration by setting this property in the config service.

proxy.enforce.global.config = true

Ajax Proxy file configuration

The Ajax proxy configuration is specified using an XML file called proxy-config.xml.

This is how a sample Ajax Proxy Configuration file looks like

<?xml version="1.0" encoding="UTF-8"?>
<proxy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:proxy="http://www.ibm.com/xmlns/prod/sw/ajax/proxy-config/1.0">
<proxy:mapping contextpath="/ibm" url="http://www.ibm.com" />
<proxy:policy url="http://www.ibm.com/*" acf="none">
<proxy:actions>
<proxy:method>GET</proxy:method>
<proxy:method>POST</proxy:method>
</proxy:actions>
</proxy:policy>
<proxy:meta-data>
<proxy:name>max-connections-per-host</proxy:name>
<proxy:value>5</proxy:value>
</proxy:meta-data>
<proxy:meta-data>
<proxy:name>max-total-connections</proxy:name>
<proxy:value>100</proxy:value>
</proxy:meta-data>
</proxy-rules>


The proxy-config.xml file has three main elements

  • policy: The policy element defines an access policy for specific URL pattern. Value of the url attribute of proxy element defines what URL pattern this policy is addressing. . In our sample configuration you can make GET and POST request to ibm.com, if you try to make either PUT or DELETE that it will deny access

    • actions:Required subelement defines defines the list of HTTP methods that can be used to access resource in the target domain

    • headers: Optional element that defines the list of header names that you want the proxy to forward to the target domain. By default it will forward Cache-Control, Pragma, User-Agent, Accept*, and Content*

    • cookies: Optional element that defines the list of cookies that you want to forward in the target request. If no cookie names are specified then proxy wont forward any cookies

    • mime-types:This element is optional. Use it to specify the list of accepted mime types.If no mime type is specified, the proxy accepts all responses

    • user: Optional element that defines the user roles that are allowed to make the request. If you set AllAuthenticatedUsers here then proxy will only allow requests from authenticated users.


    In our sample configuration file we are saying that Proxy will only accept GET and POST requests to http://www.ibm.com and both authenticated and non-authenticated users are allowed to make request and it will forward the default headers from incoming request to the request that it makes to http://www.ibm.com and it wont forward any cookies.

  • mapping: The mapping element is used to map incoming request to a target URL, based on their context path.The proxy resolves context path mappings prior to applying the matching access policy. The mapping element has two attributes

    • contextpath: The context path is short name for the actual URL that developer will use for making the request

    • url:Actual URL where the proxy will forward the request


    In our sample case whenever proxy servlet gets a request for /ibm it will forward that request to http://www.ibm.com. Request to /ibm/en/us would be forwarded to http://www.ibm.com/en/us

  • meta-data: Use the meta-data to specify general configuration properties of the proxy.The following HTTP related parameters are defined:

    • socket-timeout:This defines the default socket timeout in milliseconds. The socket timeout defines the timeout the proxy server waits for data after successfully establishing a connection with the target server. The default value is 20 seconds. A timeout value of zero is interpreted as an infinite timeout.

    • retries:TThis defines the number of retries that should be performed if the proxy could not establish a connection with the target server. The default value is 2 retries.

    • max-total-connections:This defines the maximum number of HTTP connections that the proxy can open to connect to arbitrary target hosts. The default value is 100 connections.

    • max-connections-per-host:This defines the number of HTTP connections the proxy can open to connect to a specific host. The default value is 5 connections per host.





Once your proxy is configured use appropriate URL for making request. For example in our case you can use this code to get response from http://www.ibm.com/en/us

function getYahooData(){
console.log("getYahooData.xhrGet()");
try{
dojo.xhrGet({
url: "/ibm",
load: function(data,error){
alert(data)
},
error: function(data, error){
alert("Error occured in accessing http://www.yahoo.com")
}
});
}catch(e){
alert(e);
}
}


DOwnload the AJaxSamplePortlet to see how it works

Introduction to Ajax Proxy

To prevent cross siste scripting browsers introduced the so called same-origin policy. This policy prevents client side scripts in particular JavaScript, from loading content from an origin that has a different protocol, domain name or port. What that means is if you try to send Ajax request to any server other than the document.location, browser would throw access denied exception.


The solutation that WebSphere portal server (WAS server also includes Ajax PRoxy in Web 2.0 feature pack) offers is a server side HTTP proxy. The Ajax Proxy HTTP proxy is a web application that is deployed in same WAS server as that of the portal server. The way it works is if you want to make Ajax request to remote web application say www.google.com, instead of sending request directly to www.google.com you send it to Ajax Proxy, the Ajax Proxy in turn will make request to www.google.com and return the response to you.

As adminster you can configure Ajax Proxy to either allow or deny access to particular remote web application i.e. you can say that portlets are allowed to make GET and POST request to www.google.com but not to www.yahoo.com. Similarly you can configure what all headers, cookies AJax Proxy can copy from incoming AJax request to the outgoing remote web application request.

Important Note: The AJAX Proxy can be used for developing themes, skins, static pages, or portlets.

Resources that are nots coped at Virtual portal level


  • Not all resources can be scoped to individual virtual portals. For example, all themes and skins are available to all virtual portals without restrictions. Credential vault, portlet services, and portal services are also common for an entire portal installation. They cannot be scoped to an individual virtual portal.

  • The settings which are defined in the portal property files apply for the entire portal installation. You cannot specify separate settings for individual virtual portals.

  • If you want to make use of the single signon feature that is provided by WebSphere Application Server, you have to use the same common domain suffix for all virtual portals.

  • Portal search, personalization, and templates, are not aware of virtual portals.

  • There are no virtual portal specific enhancements to the published portal commands and application programming interfaces.

  • A URL mapping that is defined for a resource in a particular virtual portal must use the same URL context as the friendly URL context for that virtual portal itself. Example: In a virtual portal that uses the friendly URL mapping wps/portal/vp_1, all URL mappings for portal resources must start with wps/portal/vp_1, for example wps/portal/vp_1/url_1 and wps/portal/vp_1/url_2. Within this virtual portal a URL mapping such as wps/portal/url_1 is not valid, as the portion vp_1 of the URL Context is missing.

  • All virtual portals on a portal installation share a common logging and tracing.

  • You cannot create custom URLs in one virtual portal that address portal resource in another virtual portal. The reason is that both object IDs and unique names relate to resources of the local virtual portal. For details about how to create URLs refer to Creating custom links to portlets and pages.

Creating Virtual Portal

You have two options for creating virtual Portal

Use Virtual Portal Manager Portlet


Click on the "New Virtual Portal" button in the Virtual Portal Manager portlet. You will get a screen like this



Enter the appropriate values on this screen and click ok.

Use create-virtual-portal task



You can use the ConfigEngine.sh create-virtual-portal task to create virtual portal. Please note one important point that when you create a virtual portal using configuration task, portal will create blank/empty virtual portal.

If you want to use Configuration task then you have two options either you set all the configuration parameters on the command line using -D parameter or set values in C:\WebSphere\wp_profile\ConfigEngine\config\helpers\virtual_portal.properties file and pass absolute path of this helper file to ConfigEngine using -DparentProperties=<pathofvirtualportal.properties> command line parameter

While creating virtual portal, you will have to set these properties

  • Virtual Portal title: Title for the virutal portal, it is used to display the virtual portal name in VIrtual Portal Manager portlet, it is not displayed to end users

  • Virtual Portal description: Description of virtual portal

  • URL Context: URL for accessing virtual portal. This URL is mapped to the actual internal URL of the virtual portal.

  • hostname: The hostname of the virtual portal. This attribute is optional. Use it to add a hostname of your choice for the virtual portal

  • User realm:The realm that represents the user population for the virtual portal. This field is only shown if your portal configuration supports realms.

  • Initial admin user group:The user group of subadministrators who will be able to administer the virtual portal.

  • Default theme:The theme of the virtual portal.

Preconfiguring the subadministrators for virtual portals

When you create a new virtual portal using Virtual Portal Manager Portlet, it also takes care of accessing appropriate role to the sub administrator of the virtual portal.



It will read value of portletListNeedAccess which is list of portlet names and will assign role defined by actionSetName to subadminister on all the portlets in the list. In default configuration it will assign Editor role to subadminister on all the portlets defined in portletListNeedAccess list.

You can change these configuration parameters using "Manage Portlet" portlet, you can change either value of actionSetName to some other role such as Manager, Administrator,.. or add remove portlet names from portletListNeedAccess

The Manage Search portlet requires that you assign the following additional role and access rights on it to the virtual portal administrators so that they can use the full functionality of the portlet: Editor@Virtual Resource PSE_SOURCES.

Virtual portal administrators do not automatically have access to work with Web content libraries when using the administration portlet. To enable a virtual portal administrator to work with Web content libraries you will need to assign them access to either the JCR content root node or individual Web content libraries:

If you use the configuration task create-virtual-portal to create a virtual portal, this configuration task does not assign roles to the subadministrators of the virtual portal. In this case assign the required roles manually or by using the portal XML configuration interface. For more information about the XML configuration interface and how to use it refer to the XML configuration interface topic.

Populating Virtual Portal


When you create the virtual portal by using the Virtual Portal Manager portlet, the virtual portal is pre-filled with default content. This default content is determined by the default XML script file for initializing virtual portals.


You can change name of this file by clicking on Edit Shared Settings button for Virtual Portal Manager Portal. The value of "xml script to create virtual portal content here" defines which XML script file should be used to configure content of VP. In my case its the default file initVirtualPortal.xml. The actual XML Access Script file is located in was_profile_root/installedApps/cellname/wps.ear/wps.war/virtualportal. If you go to this directory you will notice that there are 4 templates that you can choose from


  1. InitAdminVirtualPortal.xml

  2. InitFullVirtualPortal.xml

  3. InitVirtualContentPortal.xml

  4. InitVirtualPortal.xml



In addition to this you can create your own template or modify the existing template. The following portal resources are mandatory content of a virtual portal and must be included in a customized XML initialization script for virtual portals:

  • Content Root (wps.content.root)

  • Login (wps.Login)

  • Administration (ibm.portal.Administration).



ONce you have your template ready copy that file in was_profile_root/installedApps/cellname/wps.ear/wps.war/virtualportal folder and specify name of the template file on the Edit Shared Settings. Thereafter whenever you create a new virtual portal using Virtual Portal Manager portlet, this template will be used

When you create a virtual portal, the portlets associated with IBM® Lotus Web Content Management are not included in the virtual portal, even if you have deployed these portlets as part of your original portal installation. To use any of these portlets in a virtual portal, you must manually create a page and add the portlets:

* Authoring portlet: Select Web Content Authoring when adding the portlet.
* Local or Remote Rendering portlet: Select Web Content Viewer when adding the portlet

Virtual Portal Realm

WebSphere Portal has this concept of realms based on federated repository. Realm allows you to create sub group of users from all your repositories, Ex. you can create a realm which only has users from say File System based User Repository or create a Second realm that only has users from one of your LDAP server. Once you create this realm you can attach it to virtual portal so that only users from that sub group can login into the virtual Portal.

Ex. In your organization you have 2 LDAP's one IBM Tivoli directory server is maintained by sales team that has entries for all the employees from Sales department. The finance team is using say Active directory server that has entries for Finance department employees. Now you want to configure your Portal Server to host one Virtual portal for Sales team and one virtual portal for Finance team. You want to configure it so that only employees from Sales team would be allowed to login into sales virtual portal and employees from Finance team would be allowed to access Finance portal. There is third employee virtual portal that both finance and sales team employees can access.

You can use Federated repository + Realms to solve this use case. By default portal is configured to use Federated User repository and it has only one File base user repository as it is member, you can configure it to add both sales and finance department LDAP user repository under the federated user repository. Once that is done you can create 3 different realms one is Sales Realm which is configured to use Sales LDAP Server, other would be Finance Realm that would be configured to use only user from finance ldap and third would be employee realm that contains users from both Sales and Finance LDAP. Once this is done you can create 3 virtual portal and use appropriate realms for them

These are some of the important points related to realms


  • A realm contains the entire user population of one virtual portal.

  • Each virtual portal can have its own realm of users associated, but it is also possible that multiple virtual portals can share their user population by using the same realm in parallel.

  • In order to be able to log in to a particular virtual portal, a user must be a member of the realm that is associated with that virtual portal.

  • A virtual portal is associated with one realm. Each virtual portal uses exactly one realm, but a realm can be used by multiple virtual portals.

  • A virtual portal can also be associated with no realm. If no realm is assigned for a virtual portal, the user population that was defined for the super realm can log on to the virtual portal.

  • The individual user IDs must be unique across all realms.

  • In order to log in to a virtual portal, the virtual portal administrator and all users must be a member of the realm for that virtual portal. To allow a user access to more than one virtual portal, that user (and thereby the Virtual Member Manager node to which the user belongs in the hierarchy of the user directory) must be a member of all the realms associated with these virtual portals. For example, this applies to a super administrator who is responsible for all virtual portals within an entire Portal installation.

  • In order to administer the virtual portals, the master administrator must be a member of the realms of these virtual portals.

  • User populations of realms can overlap. In other words, users can be members of multiple realms. If realms overlap, that is if some users are in different realms for different virtual portals, then these users can work in all the virtual portals which are associated with these realms.



By default WebSphere Portal is configured with Federated Repositories as User Registry provider. By default only the super realm, or default realm, is configured. After you have configured your portal instance against your user backend repositories you can use tasks provided by the portal to configure the realms


When users access a virtual portal, the portal installation selects the appropriate realm based on the current virtual portal context. Within a virtual portal, only users of that corresponding realm are "visible". The administrator of a particular virtual portal can only give access rights to users and groups in the population of that virtual portal. Therefore, when you create a virtual portal, the realm that represents the population of the new virtual portal must be a subset of the realm used by your portal installation.