A Slick Alternative to pt:standard.openerlink

For one reason or another your bosses (we all have more than one, don’t we?) have told you that the look-n-feel of the common object opener in ALUI just doesn’t cut it. Even though it’s powerful, scalable and pretty nice-looking and it includes a myriad of options (e.g search, browse, single vs. multi-select, set previously selected, etc.), they just want something different. Perhaps they don’t want a pop-up window. Perhaps they don’t like how many clicks it takes to get down to an object. Perhaps they’re just being difficult.

Regardless, you’ve been asked to come up with a clean, fast, in-place object selector that still shows a hierarchical view. (For the purposes of this discussion, I’m going to use the example of communities from here on out instead of just talking about “objects.”) So naturally, as a portlet developer, you turn to the IDK. Unfortunately, if you want to get portal metadata, you have to use the PRC/SOAP server. There goes fast. So maybe you can write it in native code or using database calls. There goes clean.

Your best bet here — and really the only good way to accomplish this — is to develop a custom taglib. Custom taglibs are quickly becoming my favorite new feature in G6. (BTW, if you aren’t on G6, upgrade ASAP — it’s worth the effort.) So, for your benefit, I decided to try my hand at writing a taglib to present a nice hierarchy of communities. Here’s what I discovered.

First off, let’s talk about the HTML I want to display in my custom tag for a moment. Whoever came up with the concept of select boxes and optgroup elements was a complete goofball. Why develop something that’s naturally suited for a hierarchy and then limit the hierarchy to a depth of one?

Here’s an example:

So I had to throw my initial idea of using nested option elements out the window simply because you can’t nest an optgroup within an option. Bummer.

So here’s the display I settled on:

There’s still a hierarchy here, it’s just flattened and there’s essentially a “breadcrumb” for each community. In the example I have, bdg is a top level community and services is a subcommunity of bdg. Consulting, development, integration and training are all subcommunities of services.

Alrighty then, so how to you construct this nice select box? And BTW, make it easy, clean and fast. Here you go:

package com.bdgportal.alui.taglib

import com.plumtree.openlog.OpenLogService;
import com.plumtree.openlog.OpenLogger;
import com.plumtree.portaluiinfrastructure.tags.*;
import com.plumtree.portaluiinfrastructure.tags.metadata.*;
import com.plumtree.xpshared.htmlelements.*;
import com.plumtree.server.*;

public class CommunitySelector extends ATag
   private static OpenLogger log = OpenLogService.GetLogger(

 public static final ITagMetaData TAG;
 public static final RequiredTagAttribute SELECT_ID;
 public static final RequiredTagAttribute SELECT_NAME;
 public static final OptionalTagAttribute SELECT_CLASS;
 public static final RequiredTagAttribute ROOT_FOLDER_ID;

  TAG = new TagMetaData("communityselector",
    "Displays a community selector.");

  SELECT_ID = new RequiredTagAttribute("id",
    "The id of the select box.",

  SELECT_NAME = new RequiredTagAttribute("name",
    "The name of the select box.",
  ROOT_FOLDER_ID = new RequiredTagAttribute("rootfolderid",
    "The root folder. All communities in this folder and below " +
    "will be displayed.",

  SELECT_CLASS = new OptionalTagAttribute("class",
    "The CSS class of the select box.",
    AttributeType.STRING, "objectText");

 public HTMLElement DisplayTag()
  HTMLSelect comms = new HTMLSelect(

   .GetCommunities(), ((IPTSession)GetEnvironment()
   .GetUserSession()).GetAdminCatalog(), comms,
   GetTagAttributeAsInt(ROOT_FOLDER_ID), "");
  return comms;

 public ATag Create()
  return new CommunitySelector();

 public TagType GetTagType() {
  return TagType.NO_BODY;
 private void recursiveAddComms(IPTObjectManager commObjMgr,
  IPTAdminCatalog adminCatalog, HTMLSelect comms,
  int folderId, String prefix) {
  //CAB: add the communities at this level, if any
  IPTQueryResult commsToAdd = commObjMgr.SimpleQuery(folderId,
  for (int i = 0; i < commsToAdd.RowCount(); ++i) {
   comms.AddOption(new HTMLOption(
    Integer.toString(commsToAdd.ItemAsInt(i, PT_PROPIDS.PT_PROPID_OBJECTID)),
    prefix.substring(0, prefix.length() - 3)));
  IPTAdminFolder adminFolder = adminCatalog.OpenAdminFolder(folderId, false);
  if (0 == adminFolder.QuerySubfoldersCount()) {
   return; //CAB: base case
  } else {
   IPTQueryResult subFolders = adminFolder.QuerySubfolders(
   //CAB: recurse into each subfolder
   for (int i = 0; i < subFolders.RowCount(); ++i) {
    recursiveAddComms(commObjMgr, adminCatalog, comms,
     subFolders.ItemAsInt(i, PT_PROPIDS.PT_PROPID_OBJECTID),
     prefix + subFolders.ItemAsString(i, PT_PROPIDS.PT_PROPID_NAME)
     + " : ");

I think the code pretty much speaks for itself, but if you want further explanation, let me know by posting a comment.


Comments are listed in date ascending order (oldest first)

  • Iiiinteresting. This is very cool, Chris. I might be forced to highjack this and turn it into a pt:data tag 🙂 You have any thoughts on how / where you might approach caching with this? Have you seen the EOD sample tag?

    Posted by: ewwhitley on August 31, 2006 at 9:41 AM

  • Hmmm . . . caching. It’s so fast OOTB that I didn’t think about caching it. 🙂 Plus, I used it on a project where we have fewer than 100 communities, so I didn’t have any problems. I mean, we’re not using the PRC, right? I guess if you wanted to cache it you could doink around with the shared variables in the tag library (session scope), but you’ve got to worry about clearing the cache after a fixed interval of time.

    Posted by: bucchere on August 31, 2006 at 10:31 AM

  • Awesome! Thanks Chris. I just spent about 2 hours last night trying to do almost the exact same thing. This is great!

    Posted by: jturmelle on May 17, 2007 at 7:48 AM

Washington DC Area ALUI (Plumtree) Training

bdg plans to offer a 5-day AquaLogic (Plumtree) Training Course in the Washington DC Metro Area starting on October 16th. We’re combining our two most popular courses into one jam-packed week. The first three days will cover Plumtree Administration followed by two days of Portlet Development with the IDK. The course will be given in Herndon, VA about 10 minutes from Dulles Airport. All course materials have been updated for the G6 version of ALUI.

If you’re interested, you may download the complete syllabi from our web site.

There are no pre-requisites for the Plumtree Administration course other than a basic understanding of Web applications. The Portlet Development course requires strong programming skills in either Java or .NET including Web programming concepts such as posting forms, retrieving parameters from the querystring and working with basic Javascript for form validation.

The price for this course is $500/day. You may attend the 3-day segment, the 2-day segment or the entire week.

There is a limit of 10 participants. You must sign up by Friday, October 6th and bdg must receive payment by Friday, October 13th. We now accept VISA/MC payments in addition to corporate checks and money orders.

To sign up, please send an e-mail to [email protected]. If you have any questions, please send us an e-mail or call us at 703 234 7910.

Searching Intrinsic ALI Properties Using the PRC

There’s a problem with the IDK PRC API for search that’s tripped up users in the dev2dev forums and that stymied me for the first time today while coding up a custom search application for one of our customers.

The problem is that there’s a hardcoded limitation in the IDK that prevents you from calling PortalField.forID if the passed in object ID is less than 100. This prevents you from searching on some really useful properties, including e-mail address! For the life of me, I can’t figure out why this limitation was imposed.

The good news is that I found a workaround. It involves a quick two-file IDK patch that entails subclassing two classes. The only catch is that you need to put the child classes in the same package as the IDK (because the parent classes have package-private constructors).

Here’s the source code that does the trick.


package com.plumtree.remote.prc.search;

import com.plumtree.remote.prc.search.PortalField;
import com.plumtree.remote.prc.search.xp.*;

public class IntrinsicPortalField extends PortalField {
  private IntrinsicPortalField(IntrinsicXPPortalField xpField) {

  public static final IntrinsicPortalField EMAIL_ADDRESS;

  static {
    EMAIL_ADDRESS = new IntrinsicPortalField(IntrinsicXPPortalField.forID(26));


package com.plumtree.remote.prc.search.xp;

import com.plumtree.openfoundation.util.XPIllegalArgumentException;

public class IntrinsicXPPortalField extends XPPortalField {

  private IntrinsicXPPortalField(String name, boolean isSearchable, boolean isRetrievable) {
    super(name, isSearchable, isRetrievable);

  public static IntrinsicXPPortalField forID(int propertyId) throws XPIllegalArgumentException {
    return new IntrinsicXPPortalField("ptportal.propertyid." + propertyId, true, true);

I used e-mail address (ID = 26) as an example, but you can put any properties in there that you want. Then, when you’re setting up your search filter, just use IntrinsicPortalField instead of PortalField. For example:

IFilterClause filter = searchFactory.createOrFilterClause();
filter.addStatement(IntrinsicPortalField.EMAIL_ADDRESS, Operator.Contains, searchQuery);

Since IntrinsicPortalField is a subclass of PortalField, the PRC has no problem with it. I’ve tested this with e-mail address and it works flawlessly. I’m sure other properties will work perfectly well too.



Comments are listed in date ascending order (oldest first)

  • Thank you, Chris 🙂 Now that Chris has kindly posted a workaround, any possibility of having this put into an IDK hotfix?

    Posted by: ewwhitley on August 27, 2006 at 2:39 PM

  • I second Eric’s opinion. Can you guys just remove the artificial restriction of 100 from the IDK in the next release? Seems to work fine without it and it would obviate the need for my silly patch.

    Posted by: bucchere on August 30, 2006 at 2:31 PM

  • Here is an e-mail I received from a person who attempted to use my patch:


    I found your blog because I am having the same problem you describe with searching Intrinsic properties. However, I am now having trouble actually “patching” the IDK. How exactly would I go about repackaging everything with these new java files included? Thank you very much for your time and help.

    Here was my response:

    Thanks for your note. Assuming that you’re building a Java web application, all you need to do is compile the patch along with all your other application code. You can put the class files for the patch in WEB-INF/classes or you can make a jar (e.g. myapp.jar) and put the class files for the IDK patch there and then drop the jar in WEB-INF/lib. You can then put everything into a .war or .ear (or not).

    The magic of the Java classloader is that all the .class files in WEB-INF/classes and all your .class files inside jars in WEB-INF/lib all end up loaded into the same memory. That means that if you have two class files in two different jars, but they’re both in the com.plumtree.remote.portlet package (meaning you have the line package com.plumtree.remote.portlet; at the top of your source files and your .java files live in com/plumtree/remote/portlet), then they’ll act like they’re in the same package. This means that you’ll have access to all package private member methods, which the patch needs in order to compile.

    Posted by: bucchere on August 30, 2006 at 7:23 PM

  • Hi mate, I think this is very helpfull but I was wondering where can I find corresponding ID’s for all standart and custom user properties, when I’m using

    forID(26) method? Thanks in advance!

    Posted by: ggeorgiev on September 19, 2006 at 1:16 AM

  • This gets you the standard (intrinsic) ones:
    select objectid, name from plumdbuser.ptproperties order by objectid where objectid < 200;
    1 Name
    2 Description
    3 Object Created
    4 Object Last Modified
    5 Open Document URL
    6 Content Type ID
    7 Plumtree Document Image UUID
    8 Content Language
    9 Content Tag
    26 Email Address
    50 Full Text Content
    60 Document Submit Content Source
    61 Document Upload Repository Server
    62 Document Upload DocID
    71 Related Communities
    72 Related Folders
    73 Related Portlets
    74 Related Experts
    75 Related Content Managers
    80 Snapshot Query Reference
    101 Keywords
    102 Subject
    103 Author
    104 Created
    105 Document Title
    106 URL
    107 Category
    112 Modified
    152 Phone Number
    153 Title
    154 Department
    155 Manager
    156 Company
    157 Address
    158 Postal Code
    159 State or Province
    160 Country
    161 Employee ID
    162 City
    163 Address 2

    For the custom ones, change the where clause to >= 200.

    Posted by: bucchere on September 23, 2006 at 6:53 PM

Everyone likes a friendly URL

As part of our BEA World strategy for this year, we’re revamping our corporate web site, http://www.bdg-online.com. You should expect an unveiling in the upcoming weeks.

While there will be some revised and some additional content, this is primarily an infrastructure upgrade, including moving to more powerful virtual hosts and upgrading the backend from ASP to ASP.NET (yes, I know, it’s about time).

One of things that really bugs me about ASP and ASP.NET is the failure to include built-in support for friendly URLs. By friendly I mean something that doesn’t end in .asp, .htm, .aspx or some other extension and naturally also doesn’t have a querystring (?foo=bar&boo=moo . . . etc.). For example, http://www.bdg-online.com/customers is a lot more friendly than http://www.bdg-online.com/customers.asp and definitely more friendly than something like http://www.bdg-online.com/content.aspx?p=/customers.

Java provides a nice facility for this in the form of servlet mappings. Since a lot of people are using MVC these days, you are probably going to set up servlet mappings anyway. Here’s an example from a sample web.xml file:



But what about ASP or ASP.NET? No one cares about ASP any more, so I didn’t bother to research that. But for .NET, I came up with a simple and elegant solution to the friendly URL problem. All you need to do is add the following code (or something like it) to your Global.asax.cs file:

protected void Application_BeginRequest(Object sender, EventArgs e)
 if (!Request.RawUrl.EndsWith("htm") &&
     !Request.RawUrl.EndsWith("css") &&
     !Request.RawUrl.EndsWith("ico") &&
     !Request.RawUrl.EndsWith("jpg") &&
     !Request.RawUrl.EndsWith("js") &&
   if ("".Equals(Request.RawUrl) || "/".Equals(Request.RawUrl))
     Context.Server.Transfer(Request.RawUrl + ".aspx");

You’ll note that I forward requests to the corresponding aspx page, as long as the request isn’t for static content (images, css, etc.).

Of course you also need to do two things:

  1. Configure an .aspx page for every friendly URL you want resolved
  2. Add a wildcard mapping in IIS for * (files without extensions) to the asp.net ISAPI filter

The process for #2 is a little involved. It’s also different for IIS 5 (XP) and IIS 6 (2003). I don’t feel like posting screen shots right now, but if anyone wants to give this a trial run and can’t figure out how to do #2, just e-mail me and I’ll walk you through it.

I just came up with this a couple of hours ago and I haven’t put it through much testing, so YMMV.

More adventures in desktop linux

Everything I do in linux seems to be an adventure. That couldn’t be more true for Oracle 10g. After fighting with the installer, monkeying around with the ALUI database scripts and editing the start-up script, I got the database to start, but it would only shut down immediately afterword. Drats!

This morning, I deleted every trace of Oracle 10g from my system and attempted an install of Oracle 9i. The adventure begins . . . .

First off, Oracle 9i requires JRE 1.3.1, which Sun is planning to retire very soon (as soon as Java 6 comes out). Damn, I remember working on Java 1.0 — am I getting old?

JRE 1.3.1 doesn’t install cleanly on Fedora Core 5. Then again, does anything? Java is closed-source — meaning you can’t build it yourself — so once again I was in a linux bind. When I tried to unpack the 1.3.1 JRE I downloaded from Sun, it gave me this:

tail: `-1' option is obsolete; use `-n 1' since this will be removed in the future
tail: cannot open `+486' for reading: No such file or directory
1 The download file appears to be corrupted. [etc]

I downloaded the file again a few times to make sure it really wasn’t corrupted. Of course it wasn’t.

Then I found this great blog post that explained exactly what was going wrong and offered an easy fix. Easy, that is, if you’re a developer. (I’m becoming more and more convinced every day that linux is not at all poised to take over the desktop unless the entire earth’s population goes out and gets a CS degree.)

Alas, the antiquated JRE was really to roll and now it was time to run the Oracle installer. Of course, that didn’t run either. Instead, it spat out JRE errors;

Error occurred during initialization of VM
Unable to load native library: /tmp/OraInstall2006-08-19_11-59-35AM/jre/lib/i386/libjava.so: symbol __libc_wait, version GLIBC_2.0 not defined in file libc.so.6 with link time reference

Nice. Back to Google.

The fix this time came (ironically) from IBM’s web site. No problem, just make a change to libcwait.c, recompile it as a shared object and then set the LD_PRELOAD variable. I’m sure my mom could do that, right?

Then of course I had the standard “this only works under X” problem, but I had already figured that one out. Here’s the error:

Xlib: connection to ":0.0" refused by server
Xlib: No protocol specified
Exception in thread "main" java.lang.InternalError: Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at sun.awt.X11GraphicsEnvironment.(X11GraphicsEnvironment.java:59)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:120)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:58)
at java.awt.Window.(Window.java:188)
at java.awt.Frame.(Frame.java:315)
at java.awt.Frame.(Frame.java:262)
at oracle.sysman.oii.oiic.OiicInstaller.main(OiicInstaller.java:593)

And the fix (as root):

%>xhost +
%>xterm &
%>su - oracle
%>/tmp/Disk1/runInstaller &

And finally, the Oracle 9i installer launched. Now of course it’s totally hung at 18% on “Linking Oracle Net Required Support Files” and it’s been stuck there since before I started writing this blog post.

Gotta love it.

Handy Startup Script for ALUI G6 on *nix

I just wrote a nice little startup script for ALUI G6 on *nix. If you want to use it, place a file in /etc/init.d called “plumtree” with the following contents:


. /opt/plumtree/pthome.sh

case "$1" in
   $PT_HOME/ptportal/6.0/bin/automationserverd.sh start
   $PT_HOME/ptws/6.0/bin/apiserviced.sh start
   $PT_HOME/ptdr/6.0/bin/drserverd.sh start
   $PT_HOME/ptsearchserver/6.0/bin/searchserverd.sh start
   $PT_HOME/ptupload/6.0/bin/plumtreefileuploadd.sh start
   /opt/httpd/bin/apachectl.pt start

   $PT_HOME/ptportal/6.0/bin/automationserverd.sh stop
   $PT_HOME/ptws/6.0/bin/apiserviced.sh stop
   $PT_HOME/ptdr/6.0/bin/drserverd.sh stop
   $PT_HOME/ptsearchserver/6.0/bin/searchserverd.sh stop
   $PT_HOME/ptupload/6.0/bin/plumtreefileuploadd.sh stop
   /opt/httpd/bin/apachectl.pt stop

Now make the script executable:

%>chmod +x /etc/init.d/plumtree

To run all the ALUI components, type:

/etc/init.d/plumtree start

To stop them, use

/etc/init.d/plumtree stop

If you want to start ALUI automatically when the server comes up, do this (assuming you want ALUI to start at run level 3):

ln -s /etc/init.d/plumtree /etc/rc3.d/S50plumtree

Of course you need to make sure that Oracle is started first if you go this route. If you’re not running all the ALUI services on the same machine (not a recommended configuration, but good for development), you’ll need to edit the script above to start and stop only the components you have installed on each server. Enjoy!

ALI Install Issues on Fedora Core 5

Note: I don’t think this is officially supported, so YMMV.

I encountered a problem installing ALUI G6 on Fedora Core 5. Just for the record, it’s not a problem with ALUI — it’s a problem with InstallAnywhere, the software that BEA uses to install ALUI.

Here are the errors I got:

[[email protected]]# ./PlumtreeFoundation_v6-0
Preparing to install...
Extracting the JRE from the installer archive...
Unpacking the JRE...
Extracting the installation resources from the installer archive...
Configuring the installer for this system's environment...
awk: error while loading shared libraries: libdl.so.2:
cannot open shared object file: No such file or directory
dirname: error while loading shared libraries: libc.so.6:
cannot open shared object file: No such file or directory
/bin/ls: error while loading shared libraries: librt.so.1:
cannot open shared object file: No such file or directory
basename: error while loading shared libraries: libc.so.6:
cannot open shared object file: No such file or directory
dirname: error while loading shared libraries: libc.so.6:
cannot open shared object file: No such file or directory
basename: error while loading shared libraries: libc.so.6:
cannot open shared object file: No such file or directory
hostname: error while loading shared libraries: libc.so.6:
cannot open shared object file: No such file or directory

Launching installer...

grep: error while loading shared libraries: libc.so.6:
cannot open shared object file: No such file or directory
/tmp/install.dir.17585/Linux/resource/jre/bin/java: error while loading
shared libraries: libpthread.so.0: cannot open shared object file:
No such file or directory

I resolved these errors by doing the following:

[[email protected]]# cat PlumtreeFoundation_v6-0 | sed

[[email protected]]# chmod a+x PlumtreeFoundation_v6-0.new

[[email protected]]# ./PlumtreeFoundation_v6-0.new

This may work to get ALUI installed on other unsupported flavors of *nix, although I’ve never tried it, so again, YMMV.


Comments are listed in date ascending order (oldest first)

  • once you got it installed how did it run on core 5?

    Posted by: phil- on April 13, 2007 at 12:30 PM

  • It ran pretty well aside from the occasional JVM segfault, which I could have probably fixed by upgrading to the latest 1.4.2 JVM and plugging that into Tomcat 5, rather than running the OOTB bundled Tomcat/JVM supplied by BEA.

    Instead, I’ve switched to Ubuntu (with Oracle XE), which is a great platform because, for the most part, it just takes care of itself. It’s like having RHEL with a lifetime subscription to RHN, but without actually paying for it! 😉

    Posted by: bucchere on April 14, 2007 at 6:17 AM

Time to switch search keywords?

The data below are from overture.com. They state how many times the following terms are currently being used in search queries. (I’m not sure if the data collected are only from Google or if they include multiple search engines.)

680 plumtree
67 plumtree software
46 plumtree portal

305 aqualogic
31 aqualogic bea

According to these data, which show that more than twice as many people are searching for “plumtree” than for “aqualogic,” it’s not quite time to insert AquaLogic keywords into bdg-online.com and/or re-brand the bdg Plumtree blog as the bdg AquaLogic blog.

Adoption of the new names takes time, but we’re getting closer.

Fedora Core 5 Support for Intel Pro Wireless (Centrino)

I bought a new Gateway MP6954 Laptop yesterday and decided to give Linux another go. This time I told myself: I’m not even going to attempt to run any Windows applications using Crossover Office or anything else. I’m just going to go with what works best: httpd, Tomcat, Java, PHP, Perl, Ruby, Oracle, MySQL, etc.

I installed Fedora Core 5 again (kernel build 2.6.15-1.2054_FC5smp) from the same CDs I used last time and it installed and came up cleanly, but with no wireless support. There is very little documentation about running Linux on my particular laptop model, but the wireless hardware (Intel Centrino/Pro Wireless ipw3945) is fairly commonplace and, according to the many sources I referenced, it’s “well supported” by Linux. Intel even offers a driver for it, but it’s a source-only distribution.

According to the install guide for the driver, I first needed to download and compile the IEEE 80211 subsystem. I later found out that in most cases, doing so is a bad idea. Compiling the subsystem (version 1.1.14) and then the driver (version 1.1.0) led to runtime incompatibilities — “Invalid Module Format” was the exact error. However, against the 80211 module included with the 2.6.15 kernel source, the driver wouldn’t even compile. So I was in a bind.

I needed to find an IEEE 80211 subsystem that was compatible with the 1.1.0 version of the driver. The answer was actually more simple than I thought. All I needed to do was upgrade to the latest FC5 kernel 2.6.17, install the latest kernel sources (yum install kernel-devel) and then build the driver from there. These are the instructions I followed.

And just like that, I had wireless support for my new laptop under FC5. Now only if I could get the sound card working . . . .