Sunday, March 29, 2009

ClearHistory with WCM 6.1

If you are using 6.1x a new module was delivered in Cummulative fix 6.

"Creation of a module that will allow for the deletion of history log entries."
To enable the library delete module:

1. Add the following lines to the WCMConfigService.properties file located in the portal_server_root/wcm/shared/app/config/wcmservices directory:

connect.businesslogic.module.historycropper.class=com.aptrix.history.HistoryCropperModule
connect.businesslogic.module.historycropper.remoteaccess=true
connect.businesslogic.module.historycropper.autoload=false

2. add ",historycropper" (without quotes) at the end of the "connect.businesslogic.module=" property in the same file.
3. Restart the server for the configuation changes to take effect.

To view a report, use the following URL:
http://HOST:PORT/wps/wcm/myconnect?MOD=HistoryCropper&day=DATE&month=MONTH&year=YEAR&keep=LOG_ENTRIES_TO_KEEP&restrictOn=CONTROLLABLE_TYPES&library=LIBRARY

The day, month, year and keep parameters must all be numbers.

The day, month and year parameters combine to make up a date object which is used to determine whether a certain history log entry is removed from a Web Content Management item. Any history log entries that occurred before the specified date will be deleted. If no date is specified, then the date will default to one year before the current date.

The keep parameter specifies the minimum number of history log entries to keep on Web Content Management items. If a number is not specified, then the minimum number of history control entries to keep will default to 10.

The library parameter tells which library to process. If this attribute is not specified, then all libraries will be processed.

The restricOn parameter tells the module to process only controllable of the specified types. If this attribute is not specified, then all controllables types will be processed.

Friday, March 27, 2009

How to count WCM content items in v6 JCR database ?

As we did have big performances issues in portal v5 due to the high number of WCM content items in our database, we have decided to continue monitoring this count also in v6.
Of course the new JCR design in v6, the WCM software is now supposed to support about 500.000 content entries....but anyway I think it is still a good idea to monitor the volume of data you have in your system (this could be useful to report that to your management, and/or just to prevent reaching the limit).

Now, in v6 counting and analyzing the number of items is little bit more complex than in v5, mainly because the JCR database design is really different compare to a standard SQL schema design.

Actually, the v5 database request for counting the total number of content items are quite similar:
- Old request (in v5):
select count(*) from AJPE where COMPONENT_TYPE='AJPE_CONTENTS'
- New request (in v6.x):
SELECT COUNT(*) FROM JCR.EV_ENTRY WHERE ITEMCLASS=1762875877

But the problem is that in JCR database, there is no simple 1 to 1 correspondancy between the WCM content items and the number of entries in db...
In v5, when creating a new content or deleting it, you can see that the count is simply increased (+1) or decreased (-1) accordingly, whatever the status of the content.

Now in v6 JCR model, here is the behaviour of the system:

Let's assume at start you have:
select count(ITEMID) from JCR.EV_ENTRY -> 39004
select count(ITEMID) from JCR.EV_ENTRY where ITEMCLASS=1762875877 -> 27818

I will give you more details in the next section below, but basically:
- select count(ITEMID) from JCR.EV_ENTRY : this request gives you the total number of WCM objects in the db (could be content, but also design elements).
- select count(ITEMID) from JCR.EV_ENTRY where ITEMCLASS=1762875877 : give you only the WCM content items (like news, etc), assuming in your db "1762875877" also corresponds to the content item object type.

After creating 1 Published content, you will see that the count is increased by "+2":
select count(ITEMID) from JCR.EV_ENTRY -> 39006
select count(ITEMID) from JCR.EV_ENTRY where ITEMCLASS=1762875877 -> 27820

After creating 1 new Draft content, you will see that the count is increased only by "+1":
select count(ITEMID) from JCR.EV_ENTRY -> 39007
select count(ITEMID) from JCR.EV_ENTRY where ITEMCLASS=1762875877 -> 27821

Also, please note that deleting content does not affect the above count values.


All these results clearly show that:
- 1 WCM content item can correspond to several JCR nodes,
- Deleting a WCM content will not necessarily decrease the database count (as content is probably not deleted physically, but its status might only be updated).


To validate this last hypothesis (regarding delete management), I did the following tests:

Get the total number of content items:
db2 => SELECT COUNT(*) FROM JCR.EV_ENTRY WHERE ITEMCLASS=1762875877
-----------
27818

Get the distinct 'ITEMTYPE' values that exist in the db:
db2 => SELECT DISTINCT ITEMTYPE FROM JCR.EV_ENTRY
ITEMTYPE
--------
D
L
P

Then check the corresponding content items count, depending on the 'ITEMTYPE':
SELECT COUNT(*) FROM JCR.EV_ENTRY WHERE ITEMCLASS=1762875877 AND ITEMTYPE='D'
=> 566
SELECT COUNT(*) FROM JCR.EV_ENTRY WHERE ITEMCLASS=1762875877 AND ITEMTYPE='L'
=> 0
SELECT COUNT(*) FROM JCR.EV_ENTRY WHERE ITEMCLASS=1762875877 AND ITEMTYPE='P'
=> 27252

Now we can see that the count of ITEMTYPE='P' and ITEMTYPE='D' is equal to the total 27818 of content items.

An obvious assumption is that 'D' corresponds to DRAFT contents, and 'P' to PUBLISHED content. These results match the status of our contents in our db : we have about 500 draft content items, and about 13.500 published content items (remind that a published item = 2 entries in JCR.EV_ENTRY table).


So basically, to evaluate the count of WCM content items, I think the following equation makes sense:
[SELECT COUNT(*) FROM JCR.EV_ENTRY WHERE ITEMCLASS=1762875877 AND ITEMTYPE='D'] + 0,5*[SELECT COUNT(*) FROM JCR.EV_ENTRY WHERE ITEMCLASS=1762875877 AND ITEMTYPE='P']

Note: I have no idea for the moment of what could be the meaning of ITEMTYPE='L' ? (if 'P' is published, and 'D' is draft, then it could correspond to EXPIRED status, but this count does not match our number of expired content....).


Hope this will help you to better understand the structure of the WCM JCR database. Also please find below the detail of the database requests I made to understand the model.

==========================
To connect to the JCR database, you first have to get the following values (in our case, we are using DB2):
# DbType: The type of database to be used for WebSphere Portal JCR domain
jcr.DbType=db2
jcr.DbName=jcrdbe6
jcr.DbSchema=jcr


v6.x PORTAL DATABASES configuration file can be found here:
/portal/WebSphere/wp_profile/ConfigEngine/
properties/wkplc_comp.properties

The table JCR.EV_ENTRY contains the reference to all the content items.

db2 => DESCRIBE TABLE JCR.EV_ENTRY
Column Type Type
name schema name Length Scale Nulls
------------------------------ --------- ------------------ -------- ----- ------
IGID SYSIBM CHARACTER 64 0 No
ITEMID SYSIBM CHARACTER 64 0 No
ITEMCLASS SYSIBM INTEGER 4 0 Yes
ITEMTYPE SYSIBM CHARACTER 1 0 No
STATE SYSIBM BIGINT 8 0 Yes
DELETED SYSIBM CHARACTER 1 0 Yes
PARENTID SYSIBM CHARACTER 64 0 Yes
TSTAMP SYSIBM TIMESTAMP 10 0 Yes

The table JCR.EV_TYPES gives you the list of WCM object types:

SELECT TYPENAME FROM JCR.EV_TYPES
com.ibm.workplace.wcm.services.library.Library
com.aptrix.pluto.site.Site
com.aptrix.pluto.site.SiteArea
com.aptrix.pluto.presentation.Template
com.aptrix.pluto.workflow.stages.WorkflowStage
com.aptrix.pluto.workflow.Workflow
com.aptrix.pluto.workflow.actions.PublishAction
com.aptrix.pluto.content.Content
com.aptrix.pluto.taxonomy.Taxonomy
com.aptrix.pluto.taxonomy.Category
com.aptrix.pluto.content.link.ContentLink
com.aptrix.pluto.presentation.Style
com.aptrix.pluto.workflow.actions.ExpireAction
com.aptrix.pluto.cmpnt.FileResourceCmpnt
com.aptrix.pluto.cmpnt.ImageResourceCmpnt
com.aptrix.pluto.cmpnt.MenuCmpnt
com.aptrix.pluto.cmpnt.HTMLCmpnt
com.aptrix.pluto.cmpnt.NavigatorCmpnt
com.aptrix.pluto.cmpnt.JSPCmpnt


The first field of the JCR.EV_TYPES tables is the object type ID than can be used to identify content in the JCR.EV_ENTRY table. Based on the list below, the value 1762875877 corresponds to the ITEMCLASS column in the JCR.EV_ENTRY table.

SELECT * FROM JCR.EV_TYPES
473104548 com.ibm.workplace.wcm.services.library.Library
298371183 com.aptrix.pluto.site.Site
-161464932 com.aptrix.pluto.site.SiteArea
1494027823 com.aptrix.pluto.presentation.Template
-325197706 com.aptrix.pluto.workflow.stages.WorkflowStage
540603119 com.aptrix.pluto.workflow.Workflow
1448064964 com.aptrix.pluto.workflow.actions.PublishAction
176287587 com.aptrix.pluto.content.Content
-1290676433 com.aptrix.pluto.taxonomy.Taxonomy
-977641252 com.aptrix.pluto.taxonomy.Category
-965915661 com.aptrix.pluto.content.link.ContentLink
629030940 com.aptrix.pluto.presentation.Style
-1363088202 com.aptrix.pluto.workflow.actions.ExpireAction
858827521 com.aptrix.pluto.cmpnt.FileResourceCmpnt
-1535525020 com.aptrix.pluto.cmpnt.ImageResourceCmpnt
-1598427284 com.aptrix.pluto.cmpnt.MenuCmpnt
-1110739776 com.aptrix.pluto.cmpnt.HTMLCmpnt
538485974 com.aptrix.pluto.cmpnt.NavigatorCmpnt
1671285158 com.aptrix.pluto.cmpnt.JSPCmpnt

WebSphere Portal configuration : where are config and log files in v6.x ?

A lot's of things have changed in WebSphere Portal v6.0 and even more in 6.1.
Sometimes I spend a few minutes looking for a configuration file that has been moved to another folder and/or renamed....For those like me who are a little bit lost, here is a list of common v6.x config. files you need to work with frequently, and their correspondancy with v5.x


Basically, all the Portal and WCM config. files are now moved to : "/portal/WebSphere/wp_profile".

v6 logs file for WPS + WCM:
Now you will find most of the traces in:
/portal/WebSphere/wp_profile/logs/WebSphere_Portal/SystemOut.log

In v5, the corresponding files are :
[PortalServer root]/log/SystemOut.log
+
[PortalServer root]/log/wps_yyyy.mm.dd-hh.mm.ss.log
+
[PortalServer root]/wcm/shared/app/config/aptrixjpe.properties and connect.cfg
)


Please note that by default there are no more specific WCM log (like connect.log). Now WCM log traces output is located in SystemOut.log. (However, it is probably possible to configure the trace management system in WAS console to clearly separate WPS and WCM logs, as it was before in v5).


---------

WCM v6.x Config file (replace previous v5 aptrixjpe.properties and connect.cfg):
/portal/WebSphere/wp_profile/PortalServer/wcm/shared/app/config/
wcmservices/WCMConfigService.properties


---------

See the current fix level of the WPS application:
/portal/WebSphere/wp_profile/PortalServer/log/VersionInfo.log


---------

VMM LDAP configuration and mapping (if security is enabled):
/portal/WebSphere/wp_profile/ConfigEngine/properties/wkplc.properties

(equivalent to v5 file : [PortalServer root]/wmm/wmmLDAPServerAttributes.xml)


---------

v6.x PORTAL DATABASES configuration:
/portal/WebSphere/wp_profile/ConfigEngine/
properties/wkplc_comp.properties


---------

Hope this will help you....

Dynamic link in Spring portlet mvc

The biggest problem in portal applications written using JSR-168 and Ajax is the fact that all links to portlets within your portal must be server-side generated. This is usually achieved using the “” and/or “” tags in your JSP views or by using the Portlet API directly. These tags and the Portlet API allow you to encode arbitrary parameters that are then supplied to the target portlet. Unfortunately, if you use Ajax, these parameters are usually dynamic (e.g. an id of a row that the user has selected in a Ajaxified table widget) and are therefore unknown during server-side link generation.

This article depicts a resolution of this problem for an application that is using IBM WebSphere Portal 6.0 as it’s runtime. The application also uses Spring 2.5.6 and relies heavily on Spring Portlet MVC. The Ajax aspect was implemented using Dojo toolkit 1.2.3.

The application described here uses the following set of frameworks (only those relevant to this article listed):

* Spring 2.5.6
* Dojo 1.2.3

This is the desired end result:

1. A user is presented the initial view of the portlet (list view). This list view has an embedded dojox.grid.DataGrid dojo widget that fetches data from the server as necessary.
2. The user can select one row from the dojo grid widget. At that time a “Details” button below the widget is enabled.
3. When the user clicks the “Details” button the user is shown a different portlet view (update view) with details of the item selected in the dojo grid widget allowing the user to change something and submit the information so it can be updated in a database.
4. After submit the user is again shown the list view.

For this to work, the “Details” button needs to notify the application which item in the grid was selected. This cannot be embedded in a
since the item id is not known when this “list” view is generated on the server.

The solution uses Spring Portlet MVC, but the same idea can be applied to other situations as well.

The first thing that needs to be created is a Command class. A Spring command is a POJO that is used to pass information from a HTML FORM to a Spring MVC controller class:


1. package com.spmvc.command;
2.
3. public class MyCommand {
4. private Integer itemId;
5.
6. public Integer getItemId(){
7. return this.itemId;
8. }
9. public void setItemId(Integer id){
10. this.itemId = id;
11. }
12. }

package com.spmvc.command;

public class MyCommand {
private Integer itemId;

public Integer getItemId(){
return this.itemId;
}
public void setItemId(Integer id){
this.itemId = id;
}
}

The itemId field will be used to store the ID of the item selected in the grid. In my application, this ID represents the value of the primary key in the database table used to store the grid items. I know this value because the data that the grid widget fetches from the server includes it.

Now we need to create the button. The following is an excerpt from my list view JSP:



1. <%@page session="false" contentType="text/html; charset=UTF-8"
2. pageEncoding="UTF-8" import=""%>
3. <%@taglib uri="http://java.sun.com/portlet" prefix="portlet"%>
4. <%@taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
5. <%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
6.
7.
8.
18. ...
19.
20.
21.
22.

23. ...
24.
25.
26.
28.

29. ...



Important parts:

* 20-22 : Here we generate the link to our portlet. As you can see, we are telling the portlet API to generate us a link that will invoke the Action phase of portlet processing with one parameter named “action”. This parameter is used by Spring Portlet MVC to determine the controller that will be used to handle this action request.
* 24-28 : A small form is used to submit our request. Notice that the form has the generated link as the action attribute. There is also a hidden field that will carry the ID of the selected grid item.

The idea here is to generate a link to a specific Spring Portlet MVC controller (that is what we know during server-side processing of this JSP) and use a form to send the ID of the currently selected grid item (that is the what we don’t know during server-side processing).

The hidden form field is actually updated using a JavaScript function attached to our grid widget. The code is unimportant for this article and trivial - hence, it is not presented here.

Next, let’s see the Spring Portlet MVC controllet used for this form:


1. package com.spmvc.controller;
2.
3. import com.spmvc.command.MyCommand;
4.
5. import javax.portlet.ActionRequest;
6. import javax.portlet.ActionResponse;
7.
8. import org.springframework.validation.BindException;
9. import org.springframework.web.portlet.mvc.SimpleFormController;
10.
11. public class UpdateLinkHelperController extends SimpleFormController {
12. protected void onSubmitAction(ActionRequest request,
13. ActionResponse response,
14. Object command,
15. BindException errors) throws Exception {
16.
17. MyCommand cmd = (MyCommand)cmd;
18.
19. request.getPortletSession(true).setAttribute("itemId", cmd.getId());
20.
21. response.setRenderParameter("action", "update");
22.
23. response.setRenderParameter("form-submit", Boolean.FALSE.toString());
24. }
25. }



Important parts:

* 19 : The ID of the item that was selected and that was sent to the controller via the hidden form field is now stored in session. Obviously, this should be a small piece of information, like a single Integer in this case.
* 21 : This causes Spring Portlet MVC to use a different controller next in the chain of events. More about this a little later.
* 23 : This is a little “hack” for Spring Portlet MVC and the way it handles form submissions.

As we will show later on in Spring configuration, a request/render parameter with the name “action” is used by the Spring Portlet MVC to determine the controller to invoke for a particular request. Since Portlet requests are handled (as specified by the JSR-168 ) in two distinct phases: action and render, Spring Portlet MVC allows us to use different controllers for each of the two phases.

This is exactly what we are doing here. We use our UpdateLinkHelperController for the action phase, during which we store the ID in session, and we use a different controller for the render phase. This render phase controller is again just a simple form controller that sends us the form used by the user to input information - the only quirk here is the fact that this render phase controller uses it’s standard formBackingObject method to extract the ID from the session and prepares the command object for the form:


1. ...
2. public class UpdateController extends SimpleFormController {
3. ...
4. protected Object formBackingObject(PortletRequest request) throws Exception {
5. Integer id = (Integer) request.getPortletSession(true).getAttribute("itemId");
6. // TODO... do something with id. e.g. load data from database...
7. // Optionally, remove the id from session if not needed...
8. // And, always check if id is null just in case...
9. }
10. ...
11. }

...

Before we go on, one more thing to explain: Why do we set the “form-submit” render parameter in our controller (see line 23 in source block before last)? SimpleFormController sets this parameter to “true” just when it enters the action phase. If we don’t set it back to “false”, then our render phase controller will think that it was invoked as a render phase of a successful form submit. Technically that is true, but we want it to think like it was called in order to show the user a form used to gather user input. That is why we need to set the “form-submit” parameter to false.

The only thing left to show is the Spring portlet configuration file:


1.
2. 3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4. xsi:schemaLocation="http://www.springframework.org/schema/beans
5. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
6.
7.
8.
9.
10.
11.
12.
13.

14.
15.
16. 17. class="org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping">
18.
19.
20.
21.
22.

23.

24.
25.
26.
27.
28.
29.
30.

31.
32.
33.

34.
35.
36.

37.
38.
39.

40.

41.

42.

43.

44.




Note the following:

* 11 : This is the form that gets displayed. In this case it would be “details/Details.jsp”.
* 28 : This key must be the same as the value of the action parameter used in the actionURL tag in the JSP file (line 4 of the second code block).
* 35 : This is how Spring knows what controller to use for the render phase. See that we specify “update” for the “action” parameter in our UpdateLinkHelperController.

REFERENCES

* Dojo Toolkit
* Spring framework
* JSR-168

Tuesday, March 24, 2009

Changing Administration(wpsadmin/wpsbind) passwords in IBM WebSphere Portal 6.0

Generally we don't need to change the administration password for the portal once installed and configured properly. But there might be a situations or unavoidable circumstances when you want to change the administration passwords after installation or may be at any point of time when you need it badly. In fact I need it last week.. ;). So here are the steps to do it. These are the steps already mentioned in the websphere portal resources, I just made it easier to access...


IBM WebSphere Portal and IBM WebSphere Application Server use some user account as "Security Server ID" for the WebSphere Application Server JVM, access ID or bind ID for authenticated access to databases and LDAP servers, and WebSphere Application Server and WebSphere Portal administrative ID's.

If the password for any user ID is changed either by Websphere portal edit profile screen or through LDAP directly then the password value stored in the appropriate configuration file must be changed.
Changing the WebSphere Portal administrator password

WebSphere Portal treats wpsadmin (the administrator) as any other user, just with more permission granted. It is possible to change the wpsadmin or equivalent password through the user interface (UI), just like any other user can manage their own password through the UI. However, if the wpsadmin account is also used for more than just the administrator, then additional changes, outlined in other steps in this section, must be made to accommodate the change.

Follow these steps to change the WebSphere Portal administrator password:

1. Log in to WebSphere Portal as the administrator.
2. Click Edit My Profile.
3. Change your password in the appropriate box.
4. Click Continue.

Note: You can also change the WebSphere Portal Administrator password, like any other user password, using an LDAP editor.

Note: The WebSphere Portal configuration tasks that enable security automatically set the Security Cache Timeout to a value specified in the wpconfig.properties file. Old passwords are stored in cache for this amount of time. The default value is 600 seconds.


For the version 6.0.1

After successfully changing your password, you will need to make additional changes to the RunAsRole passwords; see WebSphere Portal requires additional changes to the RunAsRole passwords for the EJBs to support password change for WPSAdmin and WASAdmin users for information.

Changing the WebSphere Application Server administrator password using WebSphere Portal

You can change the password for the IBM WebSphere Application Server administrator user ID using the WebSphere Application Server Administrative Console.

* Confirm that the WebSphere Application Server Administrative Server and Administrative Console are running.
* Log in to the WebSphere Application Server Administrative Console as the administrator.
* Log in to WebSphere Portal as the WebSphere Application Server administrator and select Edit Profile.
* Type a new password and click OK.
* In the WebSphere Application Server Administrative Console do one of the following, depending on the type of security installation:

+ LDAP (non-realm): Click Security > Global Security > User registries > LDAP.
+ LDAP (realm): Click Security > Global Security > User registries > Custom.

Note: As we are have configured LDAP with realm support we will take that scenario for this document.

§ From the command prompt, change to the portal_server_root/config directory.

§ Enter the following appropriate command to encrypt the new password:

WPSconfig.bat -DPassword= wmm-encrypt

§ The script returns a value for the ASCII encrypted string. You can see that in your command prompt.

§ If you have a Base installation, open the portal_server_root/wmm/wmmWASAdmin.xml file with a text editor.

§ Copy the value from the ASCII encrypted string and paste it in the logonPassword field of the wmmWASAdmin.xml file.

§ Adapt the admin logon and uniqueUserid fields to the distinguished name of the new user.

* Change Server User Password to the new value using admin console for application server and save the changes.
* Stop and restart the WebSphere_Portal and server1 servers.

Note: The configuration tasks that enable security automatically set the Security Cache Timeout to a value specified in the wpconfig.properties file. Old passwords are stored in cache for this amount of time. The default value is 600 seconds.

For the version 6.0.1

After successfully changing your password, you will need to make additional changes to the RunAsRole passwords; see WebSphere Portal requires additional changes to the RunAsRole passwords for the EJBs to support password change for WPSAdmin and WASAdmin users for information.


We have successfully implemented these steps. :) If any of you find it hard on your portal environment, just drop a comment, may be I can help you.

Co-existing Installations of WPS 6.1

Requirrement : client wants to have two portal server 6.1.0.1 instances on single linux box with existing WAS.

Here is the following steps to achieve.

* Install the first portal instance on your linux box. Here is a link.
* Varify your installaton by hitting the portal URL as well as application console URL.
* Before installing second Portal Server instance make sure that all the applications on that linux box have been started so as to avoid any port conflicts.
* This second portal installation will be using an existing WebSphere directory with an existing instance of WebSphere Application Server.
* run the following command on the terminal.

./install.sh -console -W globalInstall.active=false -W was.undetectedWas="/opt/ibm/WebSphere" -W globalInstall.location=/opt/ibm/WCM -W wasLocationExistsSequence.active=false -W detectProfileAction.profileName="wcm_profile" -W detectProfileAction.profilePath=/opt/ibm/WebSphere/wcm_profile -W invalidProfileExit.active=false

Note: The directory that is specified for globalInstall.location cannot already contain an installation of Portal. If Portal exists in the desired directory, the EJPIC0054E exception occurs and a new unique directory (WCM in this case) must be used. However, even in this case, the existing installation of WebSphere Application Server can still be used with Portal. In addition, the directory specified by detectProfileAction.profilePath cannot exist prior to installation.

* Enter the appropriate values when prompted and check for the successfull installation.

Here is a technote from IBM which will help you in troubleshooting any problem you face during this procedure.

Understand HTTP Server Connection Limit

Intention
Most HTTP Servers have configuration settings to control how many simultaneous connections they can handle. Once this limit is reached, additional connections will be queued or rejected until a thread becomes ready. In this case, users experience poor response time. Therefore, to avoid HTTP Server becoming the bottleneck in your system, it is important to understand the settings which may affect the connection limit.

IBM HTTP Server includes a status monitor known as mod_status which can be accessed by browser to give a report of current active requests, like this:


One Mistake I made
As I first time experienced the mod_status, I wrongly believed the max. connection number that can be handled by web server is 50 (=1+49) which is much lower than we required. Based on this understanding, I have googled days, and all information I got is to set MaxClients (in httpd.conf )to a high number, like 600, which brings me nothing.
Understand the HTTP Server Instance and its Configuration Directives in Linux
On UNIX and Linux platforms, a running instance of IBM HTTP Server will consist of one single threaded Parent process which starts and maintains one or more multi-threaded Child processes. HTTP requests are received and processed by threads running in the Child processes. Each simultaneous request (TCP connection) consumes a thread. You need to use the appropriate configuration directives to control how many threads the server starts to handle requests and on UNIX and Linux, you can control how the threads are distributed amongst the Child processes. The relationships between them are presented in the following diagram:



Now let's have a look at the HTTP Server config directives (in httpd.conf) to know how they will affect the above HTTP components:
The affected HTTP components HTTP Config Directives (httpd.conf)
Function

Child Processes StartServer: controls how many Child Processes are started when the web server initializes
ServerLimit: the upper limit on the number of child processes.




Thread Max- or Min- SpareThread: affect how the server reacts to changes in server load. To instruct the server to automatically increase the number of Child processes when server load increases (subject to limits imposed by ServerLimit and MaxClients) and to decrease the number of Child processes when server load is low.

ThreadsPerChild: to control how many threads each Child Process starts.

ThreadLimit: upper limit of ThreadsPerChild.

MaxClients: upper limit on the number of simultaneous connections the server can handle.


For example, the following configuration tells IHS to start 2 client processes (StartServers) with each of them 25 threads(ThreadsPerChild), maintain at least 25 spares (MinSpareThreads) at any time. Which means, the the number which is displayed on mod_status is not the max connections number that HTTP Server can handle, but (StartServers * ThreadsPerChild), which is in my case 2*25 =50. When the server load is increased, IHS would add additional capacity, 25 threads at a time, until it hits 600(MaxSpareThreads).

ThreadLimit 25
ServerLimit 24
StartServers 2
MaxClients 600
MinSpareThreads 25
MaxSpareThreads 600
ThreadsPerChild 25
MaxRequestsPerChild 0

Resources

IBM HTTP Server Performance Tuning: http://publib.boulder.ibm.com/httpserv/ihsdiag/ihs_performance.html
Diagnosing Performance Problems for WebSphere Portal 5.1: http://www-1.ibm.com/support/docview.wss?uid=swg27007059

Use Portal 6.0 Advanced URL Generation Helper Class ServletURLGenerator to Generate URL of portlet

Intention
In some cases, you might want to open a single portlet in a new window in solo state (which hides the portal theme elements, like a banner, page navigation, or tool bar), for example,
This main portlet contains one link, after click the link, the PopUpTest portlet which resides on the XuTest2 page will be displayed on a new window.


The XuTest2 page has more than one portlet:

therefore, the question comes: how to generate url of the target portlet. WebSphere Portal 6.0 provides some advanced URL generation helper classes to solve this problem. I am going to demonstrate the usage of ServeletURLGenerator.generateUrlForFlyout.
Investigating the generateUrlForFlyout function
public static EngineURL generateUrlForFlyout(
String pageName, String portletName,
HttpServletRequest request,
HttpServletResponse response)*
* This is the updated version of the one provide on Portal 6.0.x Advanced URL Generation Helper classes.
This function requires four parameters where
• pageName: the unique name of the target portlet page
• portletName: the unique name of target PortletWindow
To set the unique name of page, you can use either XMLAccess or through “Manage Custom Unique Names” portlet:

To set the unique name of PortletWindow, the only way is through XMLAccess to set the unique name of the component that holds the portlet instance on the page:



About how to do it, please refer to step1-4 of URLGeneration in WebSphere Portal v5.1.x - Linking to another portlet
Restrictions
As we see from the function above, to get it work, the target portlet must be assigned to a known page, which means, this API will not work if the portlet does not map to a page.
Code to generate URL
On the MainPortletView.jsp, we use the following code to generate URL of target portlet:
<%
try {
String pageName = "co.at.profile.XuTest2";
String portletName = "xu.test.popuptest";
EngineURL targetURLStr = ServletURLGenerator.generateUrlForFlyout(
pageName, portletName, request, response);
%>



Link

Of course, to avoid the resolve exceptions, you need to include the necessary classes:
<%@page language="java" contentType="text/html"
pageEncoding="ISO-8859-1" session="false"
import="com.ibm.wps.l2.urlgeneration.helper.*,
com.ibm.portal.state.EngineURL"%>
Resources
Portal 6.0.x Advanced URL Generation Helper classes.
URLGeneration in WebSphere Portal v5.1.x - Linking to another portlet

Sunday, March 22, 2009

WebSphere Password Decoder

This utility can decode WebSphere encoded passwords.
If you have lost your password(s), use this utility to recover them.

WebSphere Password Decoder

IBM WebSphere interserver authentication: LTPA and SSL

On some applications, if you have a two layer deployment, one server for the web layer and another server for the business logic layer, you may need to enable global security and then to allow the communication between servers you need to setup LTPA between servers. On version 5.x and 6.0 just by moving the LTPA key from the business server to the application server and setting up the authentication method does the deal, and it has no need of intermediate steps to allow communication between servers.

On 6.1 version is not quite that simple, because RMI between servers runs now over SSL, and guess what if an SSL session can’t be established, the comunication is not possible.

The error message might be something like: CAUGHT_EXCEPTION_WHILE_CONFIGURING_SSL_CLIENT_SOCKET: JSSL0080E: javax.net.ssl.SSLHandshakeException - The client and server could not negotiate the desired level of security. Reason: com.ibm.jsse2.util.h: No trusted certificate found vmcid: IBM minor code: E07 completed: No]

The key lead here is the “No trusted certificate found”, which means that an SSL session could not be established do too the missing of a server certificate.

The solution: On the IBM Websphere server that needs to comunicate (in this case the server running the the web layer), execute the following steps:

1) Logon into the WAS console.

2) Goto Security -> SSL and Key Management

3) Select the NodeDefaultTrustStore and then Signer Certificates

4) Define your parameters, where the main issue is that the host must be the server you which to connect and the port is 9043.

5) Just give an alias name and press the button “Retrieve Signer Certificate”

6) Press apply and OK, and you’re done.

Try connecting again. It should work now.

Saturday, March 21, 2009

BUILDING HIGHLY INTERACTIVE PORTLETS WITH AJAX

INTRODUCTION
In today’s fiercely competitive Web space, creating a rich user interface for your Web
application is no longer an option; it's a requirement. Wherever you look on the Web,
you see highly interactive user interfaces (UI). Photo Web sites present drag and drop
upload capabilities, visual editing, as well as interactive order placement. Search sites
offer popular search results as you type. Mapping applications provide smooth scrolling
and allow you to overlay satellite photos and street maps.
What is the technology behind these highly interactive Web sites? How can you apply
this technology to portals? How natural is it for portlets to provide rich interaction? Can
you improve usability of your portlets in the same way as Web applications?
This paper introduces you to the underlying technology used by today’s Web
applications and portlets: Ajax (Asynchronous JavaScript and XML). It then shows how
you can use Ajax with your portlets to provide a highly responsive end user experience.
This paper also illustrates how you can use Ajax to contextually wire portlets, that is,
pass information from one portlet to the other.
The samples in this paper use the standards-based portlet API (JSR 168), but can easily
be applied to portlets built with any Web technology. We assume that you have a basic
understanding of Java, JSR 168 portlets, and JavaScript.
AJAX: THE TECHNOLOGY BEHIND THE SCENES
Today’s rich Web applications use a mix of JavaScript and asynchronous
communication with the application server. This mechanism is also known as Ajax:
Asynchronous JavaScript and XML. The intent of Ajax is to exchange small pieces of
data between the browser and the application server, and in doing so, use partial page
refresh instead of reloading the entire Web page.
Although Ajax does not have a strictly defined set of components, the following are the
key Ajax features:
• JavaScript: The scripting language of the browser.
o To detect user interactions, such as mouse click, mouse movements,
and typing.
o To dynamically modify the page by manipulating the Document
Object Model (DOM) tree.
• XMLHttpRequest object: The means provided by browsers to submit HTTP
requests to the server and handle the HTTP response, without a full-page
refresh.
• XML: The format of the data exchanged between the client and the server.
There is no restriction as to the data format used, though the format is usually
HTML.
HOW DOES AJAX WORK?
A traditional Web application submits the HTTP request to the Web or the application
server from the browser. An action, such as a mouse click on a hyperlink or a form
submit, initiates the request. The server generates the HTTP response, and returns the
requested page.
Ajax Web applications add a bit of seasoning to this flow. Similar to a classic Web
application, the application submits a request as a result of a user interaction. Instead of
refreshing the entire page, Ajax refreshes only part of the page.
3
An Ajax-driven application submits the HTTP request asynchronously. So, instead of
waiting for the entire page to load, the end user can continue interacting with the page.
The Ajax engine is the key player in the Ajax model. The Ajax engine is a piece of code
that is typically implemented in JavaScript, is downloaded along with the HTML page,
and runs in the browser. The Ajax engine has multiple responsibilities (Figure 1):
1. Detecting user interactions. The engine detects and reacts to user interactions as
they take place. For example, if the user hovers the mouse over a specific area,
the Ajax engine recognizes the action and triggers an HTTP request.
2. Submitting HTTP request to the server. When the pre-defined user interaction takes
place, the Ajax engine submits a request to the Web server asynchronously.
3. Handling HTTP response returned by the server. The engine handles markup
returned by the Web or application server. For example, if the response is
XML, the Ajax engine applies the XSL style sheet to it.
4. Performing partial page refresh. The engine makes the necessary changes to the
Document Object Model (DOM), which is the internal representation of the
HTML document, thus updating the rendered page. For example, the engine
can display a new layer of HTML containing the data returned from the server.
Figure 1 – Ajax Web Application Model
AJAX IN THE PORTLET WORLD
How does this model map to the world of portlets?
The Web application implementation model can be applied in the same way to portlets.
Just as in classic Web applications, the key player here is the Ajax engine. Depending on
the implementation, the Ajax engine can be part of the portal page containing the
portlet, but often it is implemented by the portlet itself.
When the Ajax engine is part of the portlet, the portlet developer and/or the page
designer need to resolve several questions, such as:
• Do the JavaScript libraries collide if multiple Ajax portlets reside on the same
page?
4
• What happens if multiple instances of the same portlet are added to the page?
In this portlet use case, the Ajax engine has very similar responsibilities to the Web
application model described in Figure 1:
1. Detecting user interactions. As the user interacts with the portlet UI, the Ajax
engine detects each action you define. For example, if the user types a
character in a text field, the Ajax engine tracks it and executes the defined
action. The value entered is then used as a parameter of the XMLHttpRequest
object.
2. Submitting HTTP request to the server. The Ajax engine creates and submits the
request to the portlet application.
3. Handling HTTP response returned by the server. When the portlet application
returns the markup, the Ajax engine must handle it. For example, if the
response is XML, the Ajax engine must apply an XSL style sheet to it.
4. Performing partial page refresh. To avoid full-page refresh, the markup must be
injected into the DOM to facilitate a partial page refresh. For example, the
result set returned by the portlet is displayed right below the text field.
Figure 2 - Ajax Portlet Model
USE CASE: INTERACTIVE PHONE BOOK PORTLET
Suppose you are required to create a new version of a phone book portlet, where end
users can enter either a full name or part of a name, and the portlet returns all matching
names. The current version of your portlet contains a text field and a Submit button. To
submit the name entered, the end user needs to click the Submit button. After the entire
page refreshes, the portlet displays the names matching the end user’s query. If the end
user misspells the name, he or she must change the entry, and then click Submit again.
Using the Ajax portlet model, the new version of the portlet contains just a text field. As
the user types in the name, the results immediately display in the portlet. The portlet
initiates a roundtrip to the back end asynchronously, passing the string entered in the
text box as a parameter. Upon return of the markup, the portlet displays the results by
5
injecting it into the DOM tree of the page. As the user continues to type, the result set
narrows down according to the entered text.
Figure 3 – Contextually Wired Ajax Portlets
BUILDING THE AJAX PHONE BOOK PORTLET
What does it take to build the interactive Ajax phone book portlet? Assuming you used
JSP to generate your portlet’s markup, the following steps show you how to build the
portlet described in the previous section.
1. Create the input field by using the following code


type="text"
size="14"
name="custName"
id="custName“
onKeyUp="assembleURL(event);"
/>
. . .

. . .

2. Catch the typing event. The onKeyUp JavaScript event is triggered when the
user hits a key on the keyboard. This part plays the “user interaction
monitoring” role of the Ajax engine. Also notice the
tag, which is
where the returned markup will be injected.
3. Construct a resource URL to the portlet application. The portlet application
contains a servlet, GetCustomerInfo, which performs the lookup
operation. The encodeURL() method creates the resource URL to the
servlet.
Note: If the portlet is accessed through Web Services for Remote Portlets
(WSRP), the resource URL ensures that the request for the
GetCustomerInfo servlet is proxied through the application server
middle tier to the portlet.