Anyone who's ever done a major Plumtree/ALUI deployment knows of this problem: You create a portlet or community (or any other object) in Dev and then you migrate it to Test and on to Production. The problem is that you've also written some code in your navigation portlet or in another portlet that depends on an ObjectID
(e.g. you've used a pt:standard:opener
tag) and now, in each environment, your ObjectID
has changed and you're basically hosed.
Pre-G6, I came up with a solution described (somewhat hastily) in this post, but it requires a lot of leg work and -- worse yet -- manual configuration in each environment.
Enter G6 and the magic of taglibs. (Am I beginning to sound like a broken record? Yes, I know, you can't fix every problem with a taglib, just 95% of them, right?) With this new taglib I wrote today, I extend AOpenerLinkTag
and simply convert a UUID
to an ObjectID
and ClassID
so that you can use the same taglib invocation in every environment. I don't want to toot my own horn too much here, but honestly, this is pretty much the most useful taglib I've ever encountered, and once again, it took under 30 minutes to write.
Before I dive into the source, let me back up and say that I had to bend the rules a bit. OOTB, there are two subclasses of ATagAttribute
: RequiredTagAttribute
and OptionalTagAttribute
. I added a third: MutableTagAttribute
. It looks and smells like a tag attribute, but under the covers it's not. Instead of grabbing its value out of the tag invocation, it allows you to set/change the value at runtime inside the taglib code. Granted, this is a little weird, but it's what I needed to do in order to subclass AOpenerLinkTag
and keep it happy dappy.
MutableTagAttribute.java:
package com.bdgportal.alui.taglibs;import com.plumtree.portaluiinfrastructure.tags.metadata.*;
public class MutableTagAttribute extends ATagAttribute {
private String value;
public MutableTagAttribute(String name, String desc, AttributeType type) {
super(name, desc, type);
}public String GetDefaultValue() {
return value;
}public void SetDefaultValue(String value) {
this.value = value;
}public boolean GetIsRequired() {
return false;
}
}
Now that we have a tag attribute that we can change on-the-fly, writing the taglib was a snap.
UUIDObjectOpener.java:
package com.bdgportal.alui.taglibs;import com.plumtree.portaluiinfrastructure.tags.*;
import com.plumtree.portaluiinfrastructure.tags.metadata.*;
import com.plumtree.xpshared.htmlelements.*;
import com.plumtree.taglib.standard.basetags.*;
import com.plumtree.server.*;public class UUIDObjectOpener extends AOpenerLinkTag
{
public static final RequiredTagAttribute UUID;
private MutableTagAttribute OBJECT_ID;
private MutableTagAttribute CLASS_ID;public UUIDObjectOpener() {
OBJECT_ID = new MutableTagAttribute("objectid", "Not used -- do not set a value for this!", AttributeType.INT);
CLASS_ID = new MutableTagAttribute("classid", "Not used -- do not set a value for this!", AttributeType.INT);
}public ATagAttribute GetObjectIDAttribute()
{
return OBJECT_ID;
}public ATagAttribute GetClassIDAttribute()
{
return CLASS_ID;
}public static final ITagMetaData TAG;
static
{
TAG = new TagMetaData("uuidobjectopener", "Opens an object based on its UUID.");
UUID = new RequiredTagAttribute("uuid", "The UUID for the object you want to open.", AttributeType.STRING);
}public HTMLElement DisplayTag()
{
Object[] objectAndClassId = ((IPTMigrationManager)(((IPTSession)GetEnvironment().GetUserSession()).OpenGlobalObject(PT_GLOBALOBJECTS.PT_GLOBAL_MIGRATION_MANAGER,
false))).UUIDToObjectID(GetTagAttributeAsString(UUID));OBJECT_ID.SetDefaultValue(objectAndClassId[PT_MIGRATION_OBJECT_COLS.PT_MOC_OBJECTID].toString());
CLASS_ID.SetDefaultValue(objectAndClassId[PT_MIGRATION_OBJECT_COLS.PT_MOC_CLASSID].toString());
return super.DisplayTag();
}public ATag Create()
{
return new UUIDObjectOpener();
}
}
To deploy this code, see the excellent section on edocs about creating custom Adaptive Tags.
To use this code in a portlet, do the following.
myportlet.htm:
<span xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/'>
<pt:mytaglibns.uuidobjectopener pt:uuid="{00000-0000-0000-000000}" pt:mode="2">Open My
Object</pt:mytablibns.uuidobjectopener>
</span>
I did actually test this taglib and it worked swimmingly. Of course you need to substitute a real UUID for all those Os.
In closing, here's a little shameless plug: I've been asked by BEA to give a short, 20-minute talk at BEA World on my favorite subject (duh, taglibs) at the ALUI Developer User Group on Monday, September 18th in Moscone Center, San Francisco. It will happen some time between 1 and 5:30 PM. The ALUI User Groups are free for conference attendees. I hope to see you there or at the bdg booth. Please come on up and introduce yourself -- I always like to meet members of this great community in person.
Enjoy!
Comments are listed in date ascending order (oldest first)
select objectid, classid from ptmigration where uuid = ?)
which should be a pretty darn fast query, especially since there's probably an index on uuid. The portal is making database calls left and right when you're displaying a portal page, so making one more database call to generate an opener link shouldn't really be a performance factor. Nonetheless, it's definitely something to think about and I'm glad you brought it up.
One gotcha is that you need to pass mode=2 if you want to open the object in view mode because the default is edit mode, e.g.: /portal/server.pt?uuID={46514C0F-0187-4340-AA24-84E41C00C60F}&mode=2