Turns out Partial Execute is handy

Sun Aug 22 22:53:00 EDT 2010

My main "spare time" project involves working on a lineup editor for raids in WoW. Basically, each player can have one or more characters, each of which can perform one or two roles (out of "Tank", "Healer", or "DPS"), and the UI should allow the person setting it up to pick which character that player will bring and which role they will perform. The setup is a table, with each row looking like:

The checkbox indicates whether or not the player is going on the run, then there's the player name, the currently-selected character (the icon denotes the character's current specialization), then how they originally signed up and their desired role, then three checkboxes for the role, and then their skill/gear rank.

Originally, I had the lineup set up as a Server-Side JavaScript array with ad-hoc objects with fields for each column. This worked out alright at first, but not only stepped all over MVC separation, since the controls had to "know" about the nature of the data they were working with, but made the necessary event-handler code really tangled.

What clinched the deal was the side effects of switching a character or role - not every character can fill every role, so switching a character or role could easily switch the other. Case in point - if I switch my lineup line there to my hunter Elegabal, the role has to change as well:

With a JavaScript array and event handlers, every change meant code attached to the control itself that looked up the current character in the database, the roles they can fill, if they're eligible for the selected role, then either what roles they CAN fill (if a character was picked) or what character is available to fill the selected role. Not impossible, but VERY hairy.

So I switched over to Java objects on the back-end. While the Java code itself is less expressive than JavaScript, the organization is significantly cleaner and more logical. The Lineup is a class that descends from Vector to provide the overall table, and each element is a LineupLine object with getters and setters for each important element. That way, rather than each role radio button having to have code to sanity-check the character, they're just bound to "#{line.role}" and the LineupLine.setRole(String) method handles all the particulars.

Early on, though, I started running into some oddities - I'd pick a different role, the table would refresh, and then my role selection would go back to its previous state. I added in some System.out.print() lines in the Java objects to make sure setRole() was being called and, sure enough, it was - I could see that it was called with the right new value, yet it kept switching back to the old one. Upon further investigation, I found the problem: while the new role was being set, the server was also getting a setCharacter() call with the existing character value. So the role would be switched, then the character would be set, and, since that character couldn't do the new role, it'd naturally switch the character back.

The solution I found was to enable Partial Execution on the input controls. I can only assume that this means that, rather than sending the server the entire contents of the row as the new data to process, it sends only the control's (i.e. the drop-down's or the radio button's) data, which limits the method calls to only the one that actually changed. Presumably, this has the side effect of being slightly faster, since less data is sent to the server to be processed.

Notes 8.5.1's new LotusScript Editor

Thu Oct 15 23:22:43 EDT 2009

Tags: notes

So Notes 8.5.1 is out, and it's not bad as far as Notes clients go. My show-stopping bug is fixed, there's a slew of nifty user features, and, most importantly, they're taking concrete steps to improve the process of actually writing code for their platform.

As I'm sure you know if you've programmed in Notes, the LotusScript editor can be charitably described as "beta quality" and had, from all appearances, not been touched in any way since the addition of LotusScript in R4. Rather than list all of its horrible qualities, I'll try to leave it at this: the editor, from time to time, easts code. As far as I'm concerned, there's nothing worse that a code editor (or any editor, really) can do than destroy code, yet I can't tell you how many times Designer deleted an "End Sub" statement when trying to highlight an error somewhere in the body of the code, creating a nightmarish cascade of syntax errors and automatic code rearrangement. It's really bad.

So the addition of a proper editor for LotusScript (for agents and script libraries, at least) is HUGE; if I had had my choice about what made it into 8.5.0, I'd have picked this over XPages any day. Just the customization is a huge boost. For reference, here's the programming environment I use when I'm enjoying life:

TextMate

And here's the old LotusScript editor:

Old Editor

Right. You can change it around a bit, picking your font (but not font style) and the text color (but not background color), but that's about it. This isn't even showing any of the behavioral problems like the handling of class definitions, the many bugs, or the paucity of useful features found in other editors like mass-indenting, code templates, and the like.

Now that it's a proper Eclipse editor, I can change it around more to my liking (we'll see if I stick with it exactly like this, but it shows the options):

Eclipse Editor

Just as the previous screenshot doesn't convey the bugs, this one doesn't convey the overall feel of the editor. For lack of a better description, I'll say that it now feels like the text editor was designed with the expectation that a programmer might actually use it. I'm sure it'll have its own share of irritants (like having to manually delete the stub parameters when accepting a method auto-completion), but it's already made my job significantly less of a hassle.

Playing sound in the Lotus Notes client

Thu Oct 15 22:47:17 EDT 2009

Tags: notes

From time to time, mostly for fun, I've wanted to figure out how to play arbitrary sound clips in the Notes client. From what I can tell, the "proper" way to do that is to use NotesUIWorkspace.PlayTune(), which, as with so many aspects of Notes, falls far short of what I want. I don't want to do any filesystem or network access (both because that's ugly and also because it should be cross-platform and not depend on being in the office), and so that just won't work.

A while ago, I came up with a method that kind of worked, using Java's "sun.audio.AudioPlayer" class and feeding it data pulled from an HTTP connection. However, this had a couple problems - the audio player returns control as soon as it starts, resulting in the code ending and closing the stream, so I had to either cache the data first or add in a loop to wait for it to finish. More problematically, though, it caused weird problems with the web server wherein the connections didn't properly close, bogging it down to unresponsiveness over time. So... scratch that idea.

Eventually, I came up with something that worked: access the sound files as NotesDocuments (I do it as file resources showing up in a $FormulaClass-modified view, but it should work as attachments to normal documents too), export the docs as DXL, pull out the Base64-encoded sound file data, translate that back, and feed it to the audio player.

I ran into some trouble instantiating some of the objects in a pure-LotusScript implementation, so the library is broken up into two parts: a LotusScript script library with a function that pulls an audio file from the storage DB by name and calls a Java method, and a Java library to do the dirty work of playing the audio. The LotusScript, cleaned slightly, is:

Uselsx "*javacon"
Use "Java Audio"
	
Sub PlayByName(fileName As String)
	Dim jsession As New JavaSession, session As New NotesSession
	Dim storagedb As New NotesDatabase(session.CurrentDatabase.Server, "storagedb.nsf")
		
	If Not storagedb.IsOpen Then Exit Sub
		
	Dim soundEffects As NotesView, effect As NotesDocument
	Set soundEffects = storagedb.GetView("Sound Effects")
	soundEffects.AutoUpdate = False
	Set effect = soundEffects.GetDocumentByKey(fileName, True)
		
	If Not (effect Is Nothing) Then
		Dim exporter As NotesDXLExporter, dxl As String, fileData As String
		Set exporter = session.CreateDXLExporter
		dxl = exporter.Export(effect)
		fileData = Strleftback(Strright(dxl, {<filedata>
}), {
</filedata>})
		Dim audioPlayer As JAVACLASS
		Set audioPlayer = jsession.GetClass("JAudioPlayer")
		Call audioPlayer.play(fileData)
	End If
End Sub

The Java code isn't much worse:

public class JAudioPlayer {
	public static String play(String base64data) {
		AudioStream audioStream;
		try {
			byte[] audioBuffer = new BASE64Decoder().decodeBuffer(base64data);
			ByteArrayInputStream inputStream = new ByteArrayInputStream(audioBuffer);
			
			audioStream = new AudioStream(inputStream);
			AudioPlayer.player.start(audioStream);
		} catch(Exception e) {
			String stackTrace = "";
			for(StackTraceElement element : e.getStackTrace()) {
				stackTrace += element.toString() + "\n";
			}
			return stackTrace;
		}
		return "Success";
	}
	
	public static void stop(AudioStream audioStream) {
		try {
			AudioPlayer.player.stop(audioStream);
		} catch(Exception e) { }
	}
}

Naturally, there's other stuff to worry about, like making the DB, setting up the way you want it stored (if you use normal documents with file attachments, the DXL-searching bit would have to be slightly different), etc., but this is the meat of it.

All in all, this has been working out pretty well. It's not perfect (exporting as DXL would have a lot of waiting time if the audio file is big or the network slow), but it works in Windows and OS X, hasn't caused any server troubles (always a plus), and, since the audio player returns control immediately, the UI doesn't lock up while the file is playing.

Tivoli

Fri Feb 13 00:40:04 EST 2009

Tags: domino

My company is currently dealing with a client that wants us to look into Single-Sign-On options to integrate with their portal. Since this client has a lot of money, I've been doing just that lately. The keywords are straightforward: they want single-sign-on using SAML. Gotcha!

Step one: search for the keywords. There are a couple promising links:

The first one is an overview article that has two followups, but the only one that mentioned SAML is the first, and only in passing. Right. The second one is a notes.net forum posting asking if it's possible to use SAML to authenticate with a Domino server. No replies.

My further searching led me to Tivoli Federated Identity Manager. I've known of Tivoli primarily as that "other" group of files when I go to download something on IBM's site, part of the sea of giant "IBM Application Services for Application Server Version 6.1, for IBM Application Services 6.1 Enterprise for e-business for Windows XP, Windows 2003 Multilingual (1 of 3)" names.

But the page I found, part of a help DB for the program, contained a kernel of promise: Domino is listed as one of the usable directory stores. Now, I'm not sure if that means this thing will allow you to sign INTO Domino, or if it will just let you sign into OTHER stuff using names FROM Domino, but it's worth investigating, right?

So skip ahead a while and I'm looking at an installer for Tivoli Access Manager. Well, I THINK I'm looking at an installer. I'm also looking at a bunch of other potential installers:

Installers?

So I take a stab at it. "install_ammgr.exe" must stand for "Install Access", uh, "Mmanager", right? Double-click and... nothing. I try some of the others. Double-click and... nothing.

So I put it aside for now. I find some other downloads, such as one that seems to be what I was originally looking for, the Federated Identity Manager. I had a horrifying time with this, including a foray into WebSphere, before I decided to come back and take a whack at Access Manager again. I found the problem this time! You see, since IBM decided that useful file names are for wusses, their downloads are named things like "C1AV9ML", and I, as I always do with Domino, renamed it something useful, "Tivoli Access Manager Base - C1AW2ML", and extracted it into a folder of the same name.

If you're familiar with IBM, or if you have arrived at the present day via a time machine from circa 1990, you may see the problem immediately: the spaces. I mean, sure, Windows has had spaces-in-the-filename support since at least 1995, so not accounting for them was an amateur mistake fourteen years ago, but here we are. I renamed the folder, clearing out spaces, and voila! The installer launched!

It was very promising, too, asking me what directory I wanted, what the Domino server name was, and everything. But when I installed it, it failed, telling me only that it failed and that I should probably check a log file (which I guess it was unable to do itself). When I did, I noticed this suspicious text:

HPDHZ0021E   This file could not be found:  M:\Desktop\IBM\SAML\TAM-Base-C1AV9ML\windows\TivSecUtl\Disk

Oh god. What is in the "TivSecUtl" folder, exactly? Surprise surprise:

Disk Images

Excuse me? There's a folder in the directory tree that was in the zip file that IBM made that it simply can't use because they don't know how to escape spaces? Let me reiterate:

IBM's installer can't work out of the box.

There's already the whole issue that they use these horrible Java-based installers for their "Enterprise" apps. When the main problem is how weird it is that Lotus Notes uses a platform-native installer while Lotus Domino uses something that looks like it was mugged by X11, it's just weird. But when the JVM initialization takes up as much time as the entire rest of the installation, and you have to sit through it half a dozen times because you keep having to make more changes to the installer script, it's like IBM is punching you in the face.

The only theory I can come up with is that IBM doesn't actually want you to use their software. What other explanation is there for an installer package that simply doesn't work? It's not a OS version issue, or a weirdo setup issue, it just doesn't work.

This is even beneath the callous explanation that they do it so they can charge for support contracts. The RIGHT way to lock customers in to painful support is to at least make the program INSTALL and provide a basic level of functionality that is ALMOST what people want, but then make getting from there to the goal like wading through an ocean of steel briars. Like Notes, for example. At least that shows a basic level of respect, not just letting the programmer zip up whatever in-development folder he had and uploading it to the software catalog.

Bah!

It makes all the stupid crap like mysterious line breaks in rich text on the web seem almost user-friendly.

Lotus Notes

Thu Feb 12 23:55:57 EST 2009

Tags: notes

I generally do a lot of ranting about Lotus Notes, so I figure it's only fitting that I make a blog about it.