Archive for June, 2011

Run explorer.exe if Remote Desktop Doesn’t Work

Monday, June 20th, 2011

If you’re using Windows for your WebCenter platform, you no doubt use Remote Desktop to RDP into the servers every now and then to run updates and diagnose issues.  Sometimes, though, you just get a blank window:

Strange right?  Well, for this particular anomaly, there’s no need to call up IT to reboot the stubborn box.  Just run explorer.exe under the “Programs” tab in the Remote Desktop Connection properties window:

Boom! – system tray is back:

Wall of Shame Rant: EBay

Saturday, June 18th, 2011

Some of you may remember Randy Pausch’s Last Lecture as an inspirational and courageous last lecture in the face of a terminal disease. I remember him as one of my professors at University of Virginia. It was the best course I ever had – CS 305 I think – called Usability something or other.

Our first assignment was to find “unusable doors”. No kidding, that was it: scour the campus, sit outside a door, and count failure rates (pushing instead of pulling, pushing the wrong side, etc.). What an eye-opening experience! We learned to observe using the things engineers like us created and quantify failure rates. We were shocked at the high failure rates in something as ridiculously simple as A DOOR. After all, Pausch said, “doors have been around for 5,000 years, and today’s engineers have yet to master them”.

[Side note: while we quantified door failure rates and submitted our reports, Randy went with a little more "soft" approach to grading, quantifying reports as "The Good, The Bad, and The Ugly". My report - creatively mentioning "the flames of Satan being visible in the door's reflection" - earned "The Ugly" distinction.]

In addition to quantifying failure rates, we learned to experiment with design before, during, and after implementing them. In the intervening years, I’ve decided to write a book on the topic. It is going to be a masterpiece called “The Ultimate Solution to Usability in Everyday Tools, Software, and Life“. But I’ve never gotten past one page. One sentence, in fact. The entire content of my book is going to be a single page, with a single sentence, with three words:

USE IT ONCE.

Recently I was trying to sell some gear on EBay. I had to verify my identity by calling a phone number. Ridiculous form of identity validation, but fine – at least they can KIND OF trace a seller to a phone number – so I played along.

So I called. And for 14 excruciating minutes I was greeted with this:

EBay FAIL

Yes, those aren’t artifacts of the recording – that was a full-on ear rape for 14 minutes of carnival music fading in and out.

Which brings me to my point: EBay has inexcusably failed the litmus test for usability: quantify your results and use it once. If any one of those support representatives had called their own support line, they would have realized that ear-raping the very clients they depend on is not a very good business practice. And making them wait on hold for 14 minutes to use their service doesn’t really cut it in this “need-it-now” world…

So, I implore any and all of you portal system admins: it’s all too easy to focus on a specific aspect of a system like keeping thing running (I find myself in this position more often than I’m comfortable with – not knowing how the system is used but just “keeping it running”). But, if we do something as simple as using it once, we may learn a thing or two about why our end users are so salty when they finally pick up the phone and call to complain.

Portal API Search Sample Code: IPTSearchRequest

Tuesday, June 14th, 2011

Today’s post is a quick code snippet from Integryst’s LockDown product (which relies heavily on search to identify objects for reporting on security configurations), and provides a pretty good sample of how to search for objects in the Plumtree / ALUI / WebCenter portal using the Search APIs. Hope you find it helpful!

See the docs for IPTSearchRequest and PT_SEARCH_SETTING for more options in developing your own search killer app.

// get the folder ID to load the grid data
string searchQuery = Request.Params["query"];

if (searchQuery == null)
return; // do nothing if there's no query

ArrayList userGroupResults = new ArrayList();
int classid, objectid;
string classname, objectname;

// get the portal session from the HTTPSession
PortalSessionManager sessionManager = PortalSessionFactory.getPortalSessionManager(Session, Request, Response);
IPTSession ptSession = sessionManager.getAPISession();

//search for users and groups that match this query
IPTSearchRequest request = ptSession.GetSearchRequest();

//turn off requests for collab/content apps
request.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_APPS, PT_SEARCH_APPS.PT_SEARCH_APPS_PORTAL);

// Restrict the search to users and groups
request.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_OBJTYPES, new int[] {PT_CLASSIDS.PT_USER_ID, PT_CLASSIDS.PT_USERGROUP_ID});

// Restrict the search to specific folders
request.SetSettings( PT_SEARCH_SETTING.PT_SEARCHSETTING_DDFOLDERS, objectFolder);
request.SetSettings( PT_SEARCH_SETTING.PT_SEARCHSETTING_INCLUDE_SUBFOLDERS, 1);

// make sure the appropriate fields are returned.
request.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_RET_PROPS, new int[] {
	PT_PROPIDS.PT_PROPID_OBJECTID,
	PT_PROPIDS.PT_PROPID_CLASSID
});

// set search order
request.SetSettings(PT_SEARCH_SETTING.PT_SEARCHSETTING_ORDERBY, PT_PROPIDS.PT_PROPID_CLASSID);
IPTSearchQuery query = request.CreateBasicQuery(searchQuery + "*", "PT" + PT_INTRINSICS.PT_PROPERTY_OBJECTNAME);

IPTSearchResponse results = request.Search(query);

UserGroupObject tempRes;
int numUsersGroupsFound = 0;

// iterate the results
for (int x = 0; x < results.GetResultsReturned(); x++)
{
	objectname = results.GetFieldsAsString(x, PT_INTRINSICS.PT_PROPERTY_OBJECTNAME);
	objectid = results.GetFieldsAsInt(x, PT_INTRINSICS.PT_PROPERTY_OBJECTID);
	classid = results.GetFieldsAsInt(x, PT_INTRINSICS.PT_PROPERTY_CLASSID);
	classname = GenericObject.getClassNameFromID(classid);

	// search filter doesn't seem to work; make sure the classid is user or group
	if ((classid == PT_CLASSIDS.PT_USER_ID) || (classid == PT_CLASSIDS.PT_USERGROUP_ID))
	{
		// do stuff
	}
}

Cool Tools 21: IE Developer Tools

Friday, June 10th, 2011

At Integryst, we do a lot of Plumtree / ALUI / WCI diagnostics. We’ve featured IEWatch, IE Web Developer, and discussed FireBug as fantastic tools to diagnose what’s really going on in the portal from the perspective of the web browser.

Today’s Cool Tool is yet another one you already have but probably didn’t know it: Internet Explorer’s Developer Tools. In an IE8 or IE9 browsing session, just hit F12 to bring it up, and you’ll have virtually all of the functionality offered by those tools other tools – DOM analysis, Javascript debugging, and HTTP traffic monitoring.

Happy Debugging!

There’s a WCI App For That 8: SMTP2Collab

Tuesday, June 7th, 2011

WebCenter Collaboration Server has a decent feature that allows end users to email documents directly to Collaboration Server by using a dedicated SMTP address for each folder:

Properly configured, attachments (but not message text) on any email coming in to that address are created as documents in the Collab Folder. But what if you want to capture the text of that email? And what if the user doesn’t have an account in Collab? Also, wouldn’t it be nice if inbound documents to the few folders you care about allowing (possibly anonymous) document submissions could have “vanity email addresses” like rrrgm8ty@mycompany.com for the pirates in your organization?

That’s exactly what SMTP2Collab does. Like Collab, it sets up an inbound SMTP server. Any mail delivered to it – whether the user has an account in the portal or not – gets created as a document in the specified folder, and a linked discussion is also created containing the text of the email. Oh, and you can create any vanity aliases you want for the folders:

Wanna see it in action? You know the drill.

Cool Tools 20: New Relic

Saturday, June 4th, 2011

Every once in a while, a wicked cool app comes along that you look at and say “holy cow, that’s AMAZING!”.

Such is the case with New Relic, a code-level monitoring tool provided as a service. It supports Java, .NET, PHP, Rails, and others through the use of client-side agents that report to New Relic servers, which provide an unprecedented level of diagnostic reporting for your monitoring needs. Unlike most monitoring services, New Relic actually instruments your code (or even out-of-the-box applications) with diagnostic capabilities that not only tell you if your app is performing slowly, but exactly where in the code it’s taking the most time:

And that’s just scratching the surface – here’s a chart showing that, for our Atlassian Confluence installation, response time stays flat as load increases (indicating that we’ve got good scalability built into our system):

Bug Blog 12: ALUI Publisher Doesn’t Work in IE9

Wednesday, June 1st, 2011

Now that we’ve picked on Plumtree Studio for a while, let’s direct our attention back to WCI Publisher for a moment, shall we?

If you are one of the 2.9% of the general population (as of April, IE9′s first full month on the market) that use Internet Explorer 9, and also use AquaLogic Publisher – a product that dates back to the Plumtree days and is in dire need of another upgrade – you’ve no doubt noticed it no longer works in IE9:

HTTP Status 404 – /ptcs/
——————————————————————————–
type Status report
message /ptcs/
description The requested resource (/ptcs/) is not available.
——————————————————————————–
Apache Tomcat/5.0.30

Why? Hell if I know. Seriously, I have no idea. Publisher’s Javascript code is some of the most convoluted I’ve seen in a while.

But, all is not lost! I spent (way) too much time with Internet Explorer’s Developer Tools, comparing IE8 and IE9 URLs and stepping through Javascript on each to tease out what the difference was between the two of them. I found that when IE9 breaks, the URL doesn’t have a CID – it shows something like:

http://portal.integryst.com/ site/integryst.i/gateway /PTARGS_0_200_347_0_0_43 /http%3B/localhost%3B7087 /ptcs/navigate.jsp

… instead of:

http://portal.integryst.com/ site/integryst.i/gateway /PTARGS_0_200_347_0_0_43 /http%3B/localhost%3B7087 /ptcs/navigate.jsp? cid=e35977c1-2df0-417d-abd9-3c3f5f56657b&fbr=1306030533426

But, the problem seems to occur in JavaScript way before the URL is actually generated in Javascript. Specifically, I kept seeing this exception when stepping through the Publisher script:

While I don’t profess to have delved into the depths that is Publisher Javascript insanity, it was clear that this line caused the page to mis-fire and show the above error.

The fix? Open up \imageserver\imageserver\plumtree\content\private\js\hablador.js and change this:

SessionVars.prototype.toString = function() {
	return this.staticVars.toString();
}

… to this:

SessionVars.prototype.toString = function() {
	try {
		return this.staticVars.toString();
	}
	catch (err) {}
}

That way, whatever crazy error it is that happens in this third level of hell doesn’t burn the rest of the code that generates the proper URL. Net result: Plumtree Publisher lives for another day in Internet Explorer 9.