Thanks, Bruce

Wed Oct 02 10:55:21 EDT 2013

Tags: thanksbruce

Though I'm not as eloquent on the matter as the many others who have shared their appreciation for what Bruce Elgort has done for the community, I wanted to be sure to pitch in as well. I have been active in this community for a relatively short amount of time, but even before that Bruce's was one of the names I knew looking in from outside, from his personal contributions to the Taking Notes podcast and to his leadership of OpenNTF. And since I started being actively involved in the community, all of my interactions with him have been not only pleasant, but encouraging and inspirational.

So: thanks, Bruce!

URLs in XPages

Tue Oct 01 20:28:59 EDT 2013

Tags: urls xpages

The topic of URLs came up today in a chat and in the most recent NotesIn9, and I think this is an area that deserves some particular attention. When designing any web app, it's easy to fall into some traps with URLs, and writing XPages code juggles things around a bit - some things are much easier than usual, some are insidiously harder.

At a base level, there are four main types of URLs you'll use when writing a web app, distinguished by how they begin (don't quote me on the names, or even whether or not they're technically called "URLs"):

  • Full-protocol URLs beginning with a protocol followed by a colon, such as https://frostillic.us/f.nsf/Home.xsp
  • Protocol-relative URLs beginning with a double-forward-slash, such as //frostillic.us/f.nsf/home.xsp (these are fairly rare)
  • Server-relative URLs beginning with a forward-slash, such as /f.nsf/home.xsp
  • Page-relative URLs beginning with basically anything else, such as home.xsp

As a general rule, page-relative URLs are only a good idea if you are absolutely certain of the structure of your app relative to the URL the browser is using. The tricky part here is that it's very easy to write such a URL that works when you test it (say, pointing from one XPage to another with a URL like <xp:link value="otherXPage.xsp" text="Click me"/>), but fails in other situations. For example, see how such a URL would work when visiting each of these URLs, which all point to the same XPage:

Yes, the last one is legal - you can get to the stuff after the ".xsp" via facesContext.getExternalContext().getRequest().getPathInfo().

Fortunately, the XPage environment provides a nice solution to this problem: when using XSP elements, it converts the third type (server-relative URLs) from being relative to the server to be relative to the app. This is almost always1 what you want. So if I write a link as <xp:link value="/otherXPage.xsp" text="Click me"/>, it will work correctly in all of those situations.

Note the opening caveat: you have to be using XSP elements. Fortunately, this covers all WYSIWYG use and pretty much everything you're going to do elsewhere. It's rare that you actually want a stock-HTML <a/> instead of an <xp:link/>, and this includes resource URLs in an XPage, custom control, or theme. So, as a rule, you should almost always preface your in-app links with a forward slash to piggyback on this feature.

There are two cases that need special treatment: when you want to link out of your app from an XPage element and when you want to link into your app from a non-XPage element. Fortunately, there are two bits of non-obvious code that will do these jobs easily and reliably:

  • To break out of the app-relative "jail" in an XPage element, prefix your URL with "/.ibmxspres/domino/". For an explanation as to what this stands for and a list of similar prefix URLs, read Mastering XPages. For now, just know that that prefix means "get me out of here". So to link to, say, the directory, you could write a link like <xp:link value="/.ibmxspres/domino/names.nsf" text="Domain's Directory"/>.
  • To reliably reference the current app from a non-XPage link, use this bizarre EL formulation: ${facesContext.externalContext.requestContextPath}. What that gets you is basically like @WebDbName prefixed with a slash. So, for example, if you wanted to reference a video attached as a file resource, you could do something like <video src="${facesContext.externalContext.requestContextPath}/someVideo.mp4" />.

Keep in mind that the special XPage behavior applies only to when you're writing XSP markup (or otherwise pulling URLs into XPage elements); it doesn't apply to, for example, rich text or other HTML brought into the page.

And on a final, self-aggrandizing note, the "mentoring" offer in that NotesIn9 applies to me and my company. Feel free to contact us or get in touch with me directly if you're ever in need.

1. Except when writing CSS files. In CSS, URLs are relative to the location of the CSS file. This is usually just fine, since you, not the browser, control the URLs you use to refrence the CSS file. It gets tricky when you use resource aggregation, though.

Domino Wishlist, September 2013

Fri Sep 20 13:06:48 EDT 2013

I joined in a tweet from Paul Hannan earlier about desired Domino features (that's a very worthwhile thread to read - lots of great ideas from others) and it's had me thinking about more on my list. Fortunately, I have a blog for this kind of thing! I'm leaving off a couple big-ticket items like Eclipse-4.x-based Designer on the Mac because IBM may not be required for that.

  1. Make $WSIS not trigger crummy SSL behavior (really, first-class support for proxies in front of Domino, not just IHS/Windows)
  2. Direct access to note item data via Java
  3. Newer JRE
  4. Direct creation/update of NSFs from git server-side
  5. New XSP model-object framework
  6. New views, though that may be our job
  7. Aggressive, small-company-friendly licensing to compete with OSS stacks
  8. NSF-based SSL keychains
  9. NSF-based jvm/lib/ext distribution
  10. "Sensible defaults" mode for clean-install servers to get appropriate memory/cache/performance settings on modern setups without learning dozens of secret notes.ini settings
  11. apt-get-based distribution and updates for Domino on Debian/Ubuntu
  12. Improved XPages file-upload and -download controls to handle modern file uploading and provide better hooks for non-dominoDocument bindings
  13. Bootstrap theme for XPages. Done - thanks!
  14. Built-in default support for authentication fields in LDAP
  15. init.d startup script installed with Domino, because seriously, who ships server software without one?
  16. OS X build of Domino 64-bit
  17. Built-in Firefox sync server, because that would be a nice overture to general open-source use
  18. Support for HTTP authentication filters in Java
  19. Built-in beer database to compete with Couchbase's substantial lead in the area
  20. Easier configuration of multiple TCP/IP adapters on a server and assignment of services to bind to them
  21. Full control over URL routing inside a database (e.g. "no legacy" mode where a Java class can map requests to resources)
  22. Keep up the ODS improvements - 8.x was a great set of releases on this front
  23. CalDAV and CardDAV support - Domino should be a close-to-drop-in replacement for Gmail on OS X and iOS
  24. Along the lines of #7, a general push to establish Domino as a top-flight NoSQL database and app-dev platform, not just "your old company's mail system"
  25. A real focus on standard-API performance, with less XSP-specific cheating

I'm sure this list is not exhaustive.

Progress on the org.openntf.domino Design API

Fri Sep 06 18:57:39 EDT 2013

Tags: java openntf

The primary focus of my recent work with the OpenNTF Domino API has been the implementation of a fleshed-out design API. I've done a lot of work in my Domino-programming career manipulating design elements, usually via DXL (such as with my Forms 'n' Views app), and my aim is to codify all of that into the API itself, eventually growing it to cover almost every design element that Designer does (we'll see about Navigators, Composite Apps, and the like).

One of the big hurdles in recent years when manipulating design elements has been dealing with XPages-related elements - XPages themselves, Java design elements, Jars, faces-config.xml, etc.. Though XPages by their nature have a very nice XML representation, that doesn't carry over to DXL - all of those elements are dumped out in the "raw" data format that DXL uses when it doesn't have a better idea of how to handle what you're trying to export. And more specifically, though the XSP markup and the compiled Java code are present in the result, attempts to actually manipulate that were stymied by a "checksum" block of bits at the start of the data - you couldn't just drop the Java bytecode into the doc and expect it to work.

Fortunately, it turns out that those bits aren't a weird "checksum" at all: the data is just stored as Composite Data, the internal format of rich text in Domino. Specifically, all of those elements share the same internal representation as File Resources and Style Sheets, being composed of a CDFILEHEADER and list of CDFILESEGMENTs. When DXL uses the "raw" format, it exports that data as an array of Base64-encoded bytes directly. After discovering this, I wrote the start of a CD implementation in the API and got it to work: the API is now able to read/write the attached data of any one of those file types. Now, there are a few steps that would have to be implemented between this and "write a new XPage with a few lines of code", but this is a step in that direction (and you could theoretically modify your faces-config.xml, xsp.properties, etc. on the fly now, though I haven't tested much).

More immediately, it's also a huge step in the direction of interesting read-focused uses. One of these uses in particular has caught my fancy: loading and using XSP-related Java classes in other contexts. To go along with my work, I wrote a DatabaseClassLoader that gives you access to all of those class types from anywhere using the API (including Jar design elements). The possibilities for this have made me giddy: re-using data-model objects in external scheduled tasks, sharing classes with Java agents (...with the caveat that you have to use reflection or a scripting language), "loading" other XPage apps from inside another, treating NSFs as replicating, access-controlled Jars, and so on. I have my own notions for some practical uses I may want to explore, and I'm very interested in seeing what kind of things this lets others do as well.

Materials From MWLUG 2013

Sun Aug 25 12:54:32 EDT 2013

Tags: mwlug

I gave two presentations at MWLUG 2013 in Indianapolis, and here are the slide decks and resources for those:

AD110: Write Cleaner, More-Manageable XPages Applications With Java

AD108: The org.openntf.domino API: Modernized Domino Programming for Java and XPages

Expanding your use of EL (Part 2)

Wed Jul 24 12:37:12 EDT 2013

Tags: el java
  1. Jul 23 2013 - Expanding your use of EL (Part 1)
  2. Jul 24 2013 - Expanding your use of EL (Part 2)

Last time, I said that my next post would delve into operations and comparisons in EL, but I figured first it would be good to have a real-use example of what I talked about last time.

In several of my apps lately, I've taken to using properties files to store app configuration, primarily the server and file paths for the databases that store the actual data. The standard way of doing this is to use the platform's built-in bundle-handling abilities. However, that'd leave me stuck with either putting the bundle reference in the XSP markup somewhere or in a theme - the former would muddy things up and the latter is not available at page-load time. So instead, I wrote a quick class to use as an application-scoped bean, making it available everywhere via EL and Java:

package config;

import java.io.IOException;
import java.io.Serializable;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
import com.ibm.xsp.application.ApplicationEx;
import com.ibm.xsp.model.DataObject;

public class AppConfig implements Serializable, DataObject {
	private static final long serialVersionUID = -5125445506949601097L;

	private transient ResourceBundle config;

	public Class<?> getType(final Object keyObject) {
		return String.class;
	}

	public Object getValue(final Object keyObject) {
		if(!(keyObject instanceof String)) { throw new IllegalArgumentException(); }
		return getConfig().getString((String)keyObject);
	}

	public boolean isReadOnly(final Object keyObject) { return true; }

	public void setValue(final Object keyObject, final Object value) { }

	private ResourceBundle getConfig() {
		if (config == null) {
			try {
				ApplicationEx app = (ApplicationEx) FacesContext.getCurrentInstance().getApplication();
				config = app.getResourceBundle("config", Locale.getDefault());
			} catch (IOException ioe) {
				ioe.printStackTrace();
			}
		}
		return config;
	}
}

This is an example of a simple read-only DataObject implementation. There are only four methods to implement: getType, which returns the class of the value for the key; getValue, which returns the actual value; isReadOnly, which determines whether a given key is settable (always false here); and setValue, which would set the value for the key if I wasn't making it read-only.

It's pretty straightforward to take this idea and apply it to any of your Map-like objects to ease their use in EL without having to implement or stub-out the dozen or so methods demanded by the actual Map interface.

Expanding your use of EL (Part 1)

Tue Jul 23 13:07:43 EDT 2013

Tags: el java
  1. Jul 23 2013 - Expanding your use of EL (Part 1)
  2. Jul 24 2013 - Expanding your use of EL (Part 2)

One of the main aspects to cleaning up the code of an XPage is the heavy use of Expression Language (EL), which is XPages/JSF's shorthand language for binding properties to values and methods. The most common kind you'll run across is the kind you get for "free" when working with document data sources:

<xp:inputText value="#{doc.FirstName}"/>

This is the essence of EL in a nutshell: the actual code behind the scenes can be pretty complex, but EL handles that for you. It goes far beyond this, though, in two important ways: accessing custom and non-Domino data sources and writing complex operations.

Accessing Custom Data Sources

In addition to accessing "built-in" data types like Domino documents and the scope variables, EL is generic enough to deal with several kinds of data access (technically, it ONLY does these, and the standard bindings are examples of it):

  • Lists (and probably arrays). EL can use bracketed-subscript notation to reference individual elements of a Java list/array, e.g. #{names[3]}. I've found this to be the rarest use, but it could be useful if repeating over two parallel lists.
  • Maps. This is how EL accesses the scope variables (requestScope, viewScope, etc.). It translates code like #{sessionScope.cart} to sessionScope.get("cart") and sessionScope.put("cart", ...).
  • DataObjects. This is basically a "Map-lite" interface from IBM that is meant for making generic key/value objects easily-accessible via EL - this is what Domino document objects implement. It translates code like #{doc.FirstName} to doc.getValue("FirstName") and doc.setValue("FirstName", ...).
  • Generic bean-style methods. If (and only if) your object doesn't implement any of the above interfaces, EL falls back to seeking out bean-style getters and setters. For example, if you have a class that implements no special interfaces, EL will attempt to match #{myObject.foo} to myObject.getFoo() (or myObject.isFoo()) and myObject.setFoo(...).

The first important thing to remember is that EL applies these rules to your own and third-party objects just as much as it does to IBM's stock objects. If your code is just #{doc.foo}, you can switch "doc" from a Domino document to a HashMap, a custom DataObject class, a bean with getFoo, or an entirely-different third-party data source that implements one of those and it will continue to work smoothly. If you instead wrote it as #{javascript:doc.getItemValueString('foo')}, your experience would be... a bit rougher.

The second important thing to remember is EL's equivalence between dot and bracket notations. What I mean by this is that these three are all equivalent (assuming "barHolder" is a variable on the page containing the string "bar"):

  • #{foo.bar}
  • #{foo['bar']} or #{foo["bar"]}
  • #{foo[barHolder]}

Note that those are equivalent for every supported object type, including generic beans (okay, but not Lists, because #{foo.1} is illegal). This equivalence allows you to use EL to reference keys that would not be legal in dot notation (e.g. #{someProperties['us.iksg.setting']}) and to use other EL expressions to determine the field name. Say you're keeping some user-specific info in the application scope; you could end up with a chain like this to access it via EL:

<xp:text value="#{applicationScope.userCache[context.user.name].ticketCount}"/>

The more you understand the different ways of accessing your objects via EL, the more you can remove SSJS from your XPage markup and make your apps cleaner, (probably) faster, and more portable.

In my next post, I will cover the second major topic: complex operations and comparisons in EL.

Couchbase Followup and a Github Repository

Tue Jun 18 15:27:33 EDT 2013

Since my initial tinkering with Couchbase, I've been idly thinking about improvements to the data sources and potential uses I may have for it.

As for the latter, I think I may give a shot to implementing IKSG's new project-tracking system in it. I'll lose out on reader and author fields, but otherwise it'd be a pretty direct translation between NSF or Couchbase data stores.

For the former, I decided to drop my development code in a Github repository and start tracking my to-dos there:

https://github.com/jesse-gallagher/Couchbase-Data-for-XPages

The test database stored in that repository is the same as the one from my previous post with two main exceptions:

  1. I added a new parameter to XSPCouchbaseConnection to specify whether or not it should, when acting as a DataObject, treat the bucket as a document store. Since "documents" in Couchbase are just keys with JSON strings as their values, it's a tricky matter to detect intent... thus, I decided I may as well just make it a config option.
  2. I added a second example connection in faces-config.xml: clusterScope. Since the Java API automatically serializes and deserializes objects to store in the bucket, it makes for a perfect backing store for a clustered XPage app's persistent clusterScope.

I can't say how much time I'll have to dedicate to the improvements I want to make in the short term, but I think even the current form should be enough for me to build apps upon. I'm very interested to see if I can come up with tricks to use that are more difficult or are very inefficient in an NSF.

Couchbase Data Sources for XPages

Sun Jun 16 23:25:51 EDT 2013

The other day, I attended a Couchbase Developer Day in Philly. If you're not familiar with Couchbase, it's one of the young crop of NoSQL databases, and more specifically a document database and a conceptual cousin to Domino by way of Damien Katz. It's this similarity that makes it so interesting to me - Couchbase's still-living predecessor CouchDB started life as Notes built from the ground up for the web and the heritage is clear. Couchbase itself ends up being like if you melted down the cores of NSF/NIF and poured the result on top of a speedy key-value store.

That all makes Couchbase a perfect candidate for some XPage tinkering. Ignoring the foundational key-value aspects of Couchbase, the JSON document storage and views in 2.0 make for perfect analogues to the Domino data sources in XPages. To wit:

<xp:this.data>
    <cb:couchbaseView var="beersView" connectionName="couchbasePelias"
        designDoc="beer" viewName="by_name" />
    <cb:couchbaseDocument var="beer" connectionName="couchbasePelias"
        documentId="${param.documentId}"/>
</xp:this.data>

I've set up a demo app on one of my test servers (don't be surprised if that link is periodically unavailable). It demonstrates one of the views in the beer sample database that comes with Couchbase (it's like fakenames.nsf, but more intoxicating), with each row providing a link to edit the document in the DB, though editing is disabled for Anonymous users. The app also contains pages to show the applicable Java classes and support elements. The sources are nowhere near complete works - the view source lacks any knowledge of keys, grouping, etc., while the document source doesn't allow for the creation of new documents, nor is there any representation of non-document values.

Pretty much every concept you work with in Couchbase has a corresponding concept in Domino, but with a bit of slant, like a different dialect (for example, they call it a Royale with Cheese). A table may suit this explanation best:

 

Domino Couchbase Notes
Server Node + Cluster Couchbase has a strong focus on splitting up the job of housing databases into many servers for reliability and scalability reasons. Where Domino's clustering is RAID 1, Couchbase's is more like RAID 5.
Replication XDCR Unlike Domino's replication, Couchbase uses a set of rules to determine which of two conflicting documents lives and which dies unceremoniously.
Database Bucket The Couchbase name is a bit more evocative.
View Design Doc + View Unlike Domino1, Couchbase stores multiple views per design document, and it appears to be a sort of arbitrary art to decide how you want to split your views up among multiple design documents.

 

I'm tempted to find an excuse to build something using Couchbase as a back-end, just to see how its performance stacks up. It seems like my years of built-up NSF habits would serve me well, as many of the programming models and tradeoffs are similar, except that Couchbase views are probably consistently fast without having to cheat.

If I come back to the data sources, I'll probably flesh them out to support creating new documents, properly handle dynamically-computed properties, provide some control over view parameters (maybe including the geoboxing stuff built in), support Couchbase's document-save-conflict detection, and add a data source for basic key/value pairs. And if I do, that could provide a good excuse for me to package them up as a proper OSGi plugin, which I've so far avoided bothering with. We shall see.

1. This is a lie. The Couchbase way is actually very similar to Domino: Domino view design notes contain one or more collations, which correspond to the main index and any click-to-sort column directions. However, each of Couchbase's views inside its design document can produce wildly different data, not just resorts of the same selection, and so the fact that they're similar technically isn't very useful.

The "final" Keyword in Java

Sun Jun 16 14:45:24 EDT 2013

Yesterday, I suggested that everyone enable finalizing parameters in their code cleanups and, better, to do the same in their Java save actions; later, I set Eclipse loose on the org.openntf.domino API to implement it there. Adding final keywords to method parameters (and elsewhere where possible) is one of the habits I picked up from reading Effective Java a bit ago, but it's kind of a subtle thing and the benefits aren't immediately obvious.

If you're not at all familiar with the final keyword, it has a couple meanings in Java - in the context of variable and parameter declarations, it means that you can't reassign the value of the variable after it's been assigned the first time. So, for example, this is illegal and will generate a compile error:

final int i = 1;
i = 2;

In that example, it seems like a "why the heck would I do that?" sort of thing, but it's not too much of a stretch to picture a block of code involving something like this:

void doSomething(Document doc) {
	System.out.println("doc is " + doc.getUniversalID());
	
	// a bunch of code
	doc = database.getDocumentByID("FFFF0002");
	// a bunch more code
	
	System.out.println("doc is " + doc.getUniversalID());
}

That will WORK and it won't damage the original doc that was passed in, but it'll get confusing, particularly the more lines of code or eyeballs involved. Functioning or not, it's poor code style, and changing the method signature to doSomething(final Document doc) means that the compiler will enforce good style.

In addition to being good style, final has some technical benefits. First off, it might be faster. Secondly, if you ever use anonymous classes, final variables are a necessity for accessing information in the surrounding block. If you get into the habit of finalizing your variables, you'll already be ready by the time you have a need for anonymous classes.

final is a component of a larger and more important topic: immutability. I should probably write a lengthy post on immutability in the future, but for now there's an important thing to remember: final does not make your objects immutable. It only prevents assignment - it doesn't prevent calling methods on an object that change the object's value (in fact, Java lacks any language construct or cultural convention for immutability). So even if your Document variable is declared final, you (or any code you pass it to) can still call doc.replaceItemValue("Form", "Ha ha"); with impunity.