Things I Rarely Use: sessionScope

Thu Jul 03 20:20:06 EDT 2014

Tags: xpages
  1. Jul 03 2014 - Things I Rarely Use: sessionScope

As this post's title implies, I'm considering making this a series on XPages anti-patterns, but no promises there.

In any event, this is a topic that's been stewing in my brain for a little while: my antipathy towards the session scope in XPages. Now, don't get me wrong: other than the "not reset on logout" thing that may be fixed by now, I have no technical qualms with sessionScope; it does what it says on the tin. However, I've often found that many people use it very frequently, whereas I have found fewer and fewer uses over time where it is appropriate.

To set the stage, I use the various scopes in roughly this order by descending frequency:

  1. viewScope
  2. applicationScope
  3. flashScope
  4. requestScope
  5. sessionScope

The main things that I use sessionScope for are things that truly make sense only for the current browser session, such as the current date range to view in a log-viewing app. Other than that, I generally don't use it for:

Caches

Though it's not wrong, per se, to use the session for this, I've found it better overall to use the applicationScope, either directly (applicationScope.put("someCachedValue", whatever)) or by putting a Map keyed by username in there. The latter gets the same user-specific cache benefits of sessionScope (and more reliable, too, due to the potential for switched authentication) while also having the benefit of keeping the cache if the user logs in from another device. This is particularly potent with Anonymous. This is not a hard-and-fast rule, though - you may decide otherwise for cache-size or other reasons.

Primary Navigation or Context

Unlike the previous one, this is a hard-and-fast rule: do not use sessionScope for important page context. The worst would be something like having an "open document" button that puts the desired document UNID (or, worse, note ID) in sessionScope and then navigates to the page. Never do this! Though XPage URLs are a continuing problem, they're still the correct place for target-document information. The rule of thumb is that you should be able to copy the URL any time, paste it into another browser, and be in basically the same place.

Secondary Context

By this I mean things like the active linksbar category for the current page. I've seen things like having a navigation bar link that sends the user to a certain page while also setting a sessionScope variable to indicate the active menu bar. This is a huge problem for a number of reasons: it's a maintenance nightmare (having to code every link to do this), it's just asking for bugs (links setting the wrong or no value), and it breaks completely when the user bookmarks the page or comes back after session expiration. It's technically better than the previous crime, but only barely. The correct place for this information is handled somewhere in the page structure, though the specifics get murky. I generally take a page from the Extension Library example DB and use a "navigationPath" properly on my layout control to define a slash-delimited hierarchy of navigation context.

Page-to-Page Context

I'm thinking of things like a task-tracking system where you're looking at a Client document and want to add a Task to them, providing the Client document's ID for context. This is another area where the URL is the correct choice: ending up with a URL like "/task.xsp?clientId=whatever" makes the intent ("create a new task for client with ID 'whatever'") clear and stable across visits.


Overall, I think of sessionScope as the Petyr Baelish of XPage features: there are some cases where you have to deal with it, but you should generally consider it extremely unreliable and untrustworthy.

XPages Data Caching and a Dive Into Java

Wed Jul 02 16:39:54 EDT 2014

Tags: java

One of the most common idioms I run into when writing an app is the desire to cache some expensive-to-compute data in the view or application scope on first fetch, and then use the cached version from then on. It usually takes a form like this:

public Date getCachedTime() {
	Map<String, Object> applicationScope = ExtLibUtil.getApplicationScope();
	if(!applicationScope.containsKey("cachedTime")) {
		// Some actual expensive operation goes here
		applicationScope.put("cachedTime", new Date());
	}
	return (Date)applicationScope.get("cachedTime");
}

That works well, but it bothered me that I had to write the same boilerplate code every time, and I wondered if I could come up with a better way. The short answer is "no, not really". But the longer answer is "sort of!". And though the solution I came up with is kinda pathological and is generally unsuitable for normal humans and not worth the thin advantages, it does provide a good example of a couple of more-advanced Java concepts that you're likely to run across the more you get into the language. So here's the cache function in question, plus a "shorthand" version and an example:

@SuppressWarnings("unchecked")
public static <T> T cache(final String cacheKey, final String scope, final Callable<T> callable) throws Exception {
	Map<String, Object> cacheScope = (Map<String, Object>) ExtLibUtil.resolveVariable(FacesContext.getCurrentInstance(), scope + "Scope");
	if (!cacheScope.containsKey("cacheMap")) {
		cacheScope.put("cacheMap", new HashMap());
	}
	Map<String, Object> cacheMap = (Map<String, Object>) cacheScope.get("cacheMap");
	if (!cacheMap.containsKey(cacheKey)) {
		cacheMap.put(cacheKey, callable.call());
	}
	return (T) cacheMap.get(cacheKey);
}

public static <T> T cache(final String cacheKey, final Callable<T> callable) throws Exception {
	return cache(cacheKey, "application", callable);
}

public Date getFetchedTime() throws Exception {
	return cache("fetchedTime", new Callable<Date>() {
		public Date call() throws Exception {
			return new Date();
		}
	});
}

This code begs a question: what in the name of all that is good and holy is going on? There are a number of Java concepts at work here, some of which you've likely already seen:

  • Generics. Generics are the class names in angle brackets, like Map<String, Object> and Callable<Date>. They're Java's way of taking a container or producer class and making it usable with any class types without having to cast everything from Object.
  • Overriding methods. This is a small one: you can declare the same method name with different parameter types, which is often useful for "shorthand" versions of methods that allow for default values after a fashion. In this case, the short version of "cache" defaults to using the application scope by name.
  • The Callable interface. This is an interface in the java.util.concurrent package and is meant as a utility for multithreading purposes, but it also serves our needs here. Basically, it's an interface that means "this contains code that can be executed by using the call method with no arguments".
  • Anonymous classes. This is that business with "new Callable...". Java calls those anonymous classes and what they are are classes declared and instantiated inline with the code, without having a "proper" class declaration somewhere else. They're called "anonymous" because they have no name of their own - just the interface or class they implement/extend. In this case, I'm saying "make a new object that implements Callable and is used for this purpose only". I could make a standalone class, but there's no need. If you're familiar with closures from good languages, anonymous classes can be used like a really crappy version of those.
  • Generic return value declarations. The "<T> T" and "Callable<T>" bits build on normal generic use for when declaring a method. The first one, is brackets, basically says "okay Java, rather than returning a known object type, I'm going to let the user use anything, and for this purpose we're going to call it T". So from then on, an occurrence of T in that method body refers to whatever the programmer using the method intends. You can see in the getFetchedTime that I'm using a Callable<Date>; Java picks up on that "Date" name and conceptually substitutes it for all the Ts in the method. I'm essentially saying "I'm going to use the cache method, and I want it to accept and return Dates". Another call to the method could be to cache a List<String> or a SomeUserClass, while the method itself would remain the same.

So is all this worth it for the task at hand? Probably not. There are SOME advantages, in that it's easy to change the default caching scope, and in practice I also used a map that auto-expires its entries over time, but for normal use the first idiom is fine. But hey, it sure provided a whole torrent of Java concepts, so that's worth something.

Another Round of URL Fiddling

Thu Jun 19 17:59:51 EDT 2014

Tags: domino urls

I was working on another installment of "Be a Better Programmer", but the result isn't where I want it to be yet, so it'll have to wait. Instead, I'll share a bit about my latest futzing around when it comes to improving the URLs used in an XPages app. This has been a long-running saga, with the latest installment seeing me stumbling across a capability that had been right under my nose: the ViewHandler's ability to manipulate the URLs generated for a page. That method worked, but had the limitation that it didn't affect navigation between pages.

As it turns out, there's a slightly-better option that covers everything I've tried other than navigation rules specified in faces-config.xml (but who uses those in XPages anyway?): the RequestCustomizerFactory. This is one of the various classes buried in the Extensibility API and present in the XSP Starter Kit, but otherwise little-used. In the Starter Kit stub (and in a similar commented-out stub in the ExtLib), it can be used to add resources to a page without needing to specify them in code - say, for a plugin to add JS or CSS libraries without being specified in a theme.

However, there are other methods in the RequestParameters object that would appear to let you shim in all sorts of settings on a per-request basis - different Dojo implementations, different theme IDs, whatever "debugAgent" is, and so forth. The one that interests me at the moment is the UrlProcessor. This is aptly named: when a URL is generated by the XPage, it is passed through this processor before being sent to the browser. This appears to cover everything other than the aforementioned stock-JSF-style navigation rules: link value properties, form actions, normal navigation rules, view panel generated links, etc..

Following my previous desire, I want to make it so that all links inside my task-tracking app Milo use the "/m/*" substitution rule I set up for the server. The method for doing that via a UrlCustomizer is pretty similar to the ViewHandler:

package config;

import java.util.regex.Pattern;

import javax.faces.context.FacesContext;

import com.ibm.xsp.context.RequestCustomizerFactory;
import com.ibm.xsp.context.RequestParameters;

public class ConfigRequestCustomizerFactory extends RequestCustomizerFactory {

	@Override
	public void initializeParameters(final FacesContext facesContext, final RequestParameters parameters) {
		parameters.setUrlProcessor(ConfigUrlProcessor.instance);
	}

	public static class ConfigUrlProcessor implements RequestParameters.UrlProcessor {
		public static ConfigUrlProcessor instance = new ConfigUrlProcessor();

		public String processActionUrl(final String url) {
			String contextPath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
			String pathPattern = "^" + Pattern.quote(contextPath);
			return url.replaceAll(pathPattern, "/m");
		}

		public String processGlobalUrl(final String url) {
			return url;
		}

		public String processResourceUrl(final String url) {
			String contextPath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
			String pathPattern = "^" + Pattern.quote(contextPath);
			return url.replaceAll(pathPattern, "/m");
		}

	}
}

The method of adding this customizer to your app directly is, however, different: instead of being in the faces-config file, this is added as a "service", as mentioned in this handy list. For an in-NSF service, you accomplish this by adding a folder called "META-INF/services" to your app's classpath (you can add it in Code/Java) and a file in there named "com.ibm.xsp.RequestParameters":

In this file, you type the full name of your class, such as "config.ConfigRequestCustomizerFactory" from my example. You'll likely have to Clean your project after doing this to have it take effect (and possibly in between each change to the code).

Now, my current use is very limited; the UrlProcessor has free reign for its transformations and is passed every URL generated by the XPage (except hard-coded HTML, unsurprisingly) - you could change URLs like "/post.xsp?documentId=foo" to "/blog/posts/foo" without having to code that explicitly in your XPage. You could write a customizer that looks up all Substitution rules for the current Web Site from names.nsf and automatically transforms URLs to match. You could go further than that, trapping external links to process in some way in the "processGlobalUrl" method. The possibilities with the other methods of the customizer go much further (and are largely undocumented, to make them more fun), but for now just fiddling with the URLs is a nice boon.

The frostillic.us Framework

Mon Jun 09 15:40:17 EDT 2014

Tags: framework

For a while now, I've maintained a project called XPages Scaffolding on OpenNTF and GitHub. This project is the NTF that I use when creating a new XPages application and acts as a storehouse for my "bag of tricks", things like my model framework, controller classes, and various goodies I've picked up over the years, like a JSFUtil class and a flashScope. For a while, I've figured that, once this stuff is in proper shape, I'd extract it into an OSGi plugin and get it out of the NSF. Last week, I decided to take the plunge.

Something surprised me about the process: not only did I gain the benefits of a cleaner NSF and a nicer environment for editing the code, but it really solidified my focus for what I want it to be and gave it a real sense of purpose. The newly-dubbed Framework is geared towards turning an NSF app into two main things: a data-access API available via Java and REST and an XPages front-end that is first-among-equals for accessing that API and follows defined structural conventions.

The Model Framework

The model framework is the newest part of the project and the REST API in particular is only days old, but it's rapidly becoming the most important aspect and is likely to be the spiritual core. By providing a way to define models in a way that is simple, consistent, and (theoretically) storage-agnostic, a large part of the work of creating a new application is made significantly easier to write and understand. The models provide numerous characteristics built-in that would previously have been implemented as a series of script libraries, XAgents, and UI components:

  • Collection access. The Manager classes let the XPage care only about getting a collection of "my Tasks", rather than "the 'Tasks by Assignee' view filtered to just the category of @UserName()".
  • Property control and side effect handling. Model objects allow handling side effects where they belong, so setting, for example, the Client field to a new value needing to reset Project to blank is done there, not on every XPage implementing those fields.
  • Validation. I'm currently trying out integrating Hibernate Validator into the framework to allow for declarative constraints on a model's properties. It shouldn't have to be the XPage's job (solely) to know how to validate an email address or ensure that a username is at least N characters long. By declaring it at the model level, it frees up code elsewhere while also allowing to constraints to function when accessing models programmatically.
  • REST API. This is the new golden child that has brought this clarity of purpose to the framework. Having "for free" REST access to the model objects in an app removes a ton of potential work from the programmer and also opens up tremendous opportunity for integration. Previously, allowing access to an app's data meant rewriting all of the business logic, either in the foreign app (accessing the data via DAS or legacy Domino APIs) or in XAgents designed to serve up JSON. Now, when you write the business rules for your XPages app, you're also writing a method for external access. Things like a JS-based or mobile app move from "possible with lots of work" to "may as well". It also means you don't have to choose between having either an XPages app or an interoperable API.

The XPages Components

The XPages side of the framework is still something of a grab bag, filled with the aforementioned small utilities, controllers, my dying-on-the-vine messaging framework, support classes for writing in-NSF servlets, and a number of useful converters. In the process of plugin-ifying these, I've made some refinements, such as turning the converters into real JSF components, redubbing "JSFUtil" as "FrameworkUtils" and making it work in a non-Faces OSGi environment, and integrating my @ManagedBean implementation.

The transition has also given me the freedom to be a bit more brash about changes, making backwards-incompatible tweaks that I've been meaning to do for years, making the different parts of the framework a bit more integrated, and a number of other things I have in mind to try out.

But though this side is less integrated than the model side, it still represents a consistent way to write XPages applications: model objects for data access, controllers for primary logic, servlets instead of XAgents when appropriate, SSJS relegated to glue code in Custom Controls, and a consistent, simple naming scheme for Java classes favoring simple "local" package names like "controller" or "model" over fully-qualified ones like "com.somecompany.appdev.domino.xpages.apps.someapp.controllers" when appropriate.


All in all, I'm pretty excited about the changes I've been making. For as long as I've been working with XPages, I've been searching for the "right" way to write them, and I feel like I'm finally approaching an answer I can feel comfortable with.

And not only does my XSP code feel better and less cluttered, but it makes the platform as a whole feel better. It's always been the case that server-based app-dev lets you use whatever environment you want, though modern web development has modified that situation somewhat. It's still true that your framework doesn't necessarily matter, but it should be able to adhere to common contracts to function in an interoperable world. Much like other things I want the platform to do, the model framework in particular brings Domino into a role where the NSF-based app is the central dispatch point for a multi-platform environment. Don't want to use NSF for data storage? Plug in a different back end. Don't want to use XPages for the UI? Use the REST API and get the same transparent data access.

I think there's good potential with this setup.

REST Services for my Model Framework

Fri Jun 06 09:55:01 EDT 2014

Tags: framework

Recently, I've been refactoring out my framework code from XPages Scaffolding into an OSGi plugin. Part of this is just to help with code reuse and versioning: having a whole bunch of framework classes in each NSF is a drag, both from a perspective of having a bunch of extra stuff in the NSF and for having to worry about keeping them up to date (a template would work, but eh...). But another part is that it lets me work on some new features I've been itching to try.

One of those is adding REST services for model objects. Having access to your data via REST+JSON is pretty important, whether you're using Angular.JS, iOS, or miscellaneous. The Data service in the ExtLib does a great job of exposing document and view data directly, but it runs into the same problem that the standard data sources in XPages do: it doesn't have any provisions for your specific domain models. On the XPage side, I've solved this for myself by making a model framework that has done a fine job so far of covering my needs for accessing and collecting data in a pretty friendly way, and now I'm working on building REST APIs "for free".

Using the DAS as an inspiration (both in a vague sense and in a "using the code" sense), I'm working on Wink services to provide access to the model objects defined in each DB in a way that uses all of the same getters/setters with almost no changes to the code. The only change required (at least so far) is an optional annotation to define which fields should be included when accessing the object via REST. I'm aiming to match the data formats used by DAS as much as makes sense, since they're well-thought-out for representing Domino-friendly data, though the URLs will be pretty different due to the nature of my model manager objects.

This has been going well so far, and I'm looking forward to having it fully fleshed out. It should allow me to continue defining my model objects the same way I have been for use in XPages/Java, but then also be able to access the data just as well from other front-end technologies - potentially having NSFs that contain just a set of model definitions to act as a headless API app for use with other clients. And hey, if I get around to adding non-Domino backends to the model framework, the NSF would turn into a platform-agnostic gateway for data access.

Be a Better Programmer, Part 3

Thu Jun 05 11:06:03 EDT 2014

Tags: performance
  1. May 15 2014 - Be a Better Programmer, Part 1
  2. May 22 2014 - Be a Better Programmer, Part 2
  3. Jun 05 2014 - Be a Better Programmer, Part 3
  4. Aug 14 2014 - Be a Better Programmer, Part 4
  5. Jan 30 2015 - Be a Better Programmer, Part 5

After a break last week, this week's entry returns a bit to practical concepts. Specifically:

Develop a Working Knowledge of Relative Speeds

Performance of an app depends on almost-countless factors, but I've found that you mostly just need to know a few general ideas and rules of thumb to avoid the real pitfalls.

Big O Notation

The first thing to have a general working knowledge of is the naively-named Big O notation. This is one of the core concepts in a Computer Science curriculum and is often one of the more "mathy" subjects when you learn it. However, for the level of programming we do, it mostly serves as a warning to not loop too much. Specifically, avoid this sort of thing when possible:

for(int i = 0; i < someLength; i++) {
	for(int j = 0; j < someLength; j++) {
		// some stuff here
	}
}

That's O(n²): the amount of times that the inner loop runs grows quadratically with the size of "someLength", and it's among the worst things you can do. I recommend looking around for some basic introductions to the concept, such as this article. One thing to remember with Big O notation is that it's a general guide, not a hard-and-fast rule: an O(n²) algorithm may be faster than an O(1) if what the latter is actually doing is really slow in some other way.

I/O Overhead

Another key thing to keep in mind is that the difference between "levels" of activity - in-memory, DB access, etc. - is often so great that it completely dwarfs any other complexity. For example, it's usually going to be significantly faster to sort/search/mangle a data structure in memory many times over than to access a database even once. As with Big O, this is sort of a fuzzy rule, but I tend to keep a couple order-of-magnitude levels in mind:

  1. In-memory structure access
  2. Efficient database access (open connection, in-memory)
  3. Filesystem access
  4. Remote database/service access (e.g. web services)

#2 and #3 probably go back and forth in performance in different contexts, but any filesystem use is "dirty" enough conceptually that I downgrade it just for that.

This is why caching and minimizing database access is so important. The Domino programming environment makes it feel like the database is there "for free", but it has all the same pitfalls. Say you have a basic List of Maps in Java and the same data stored in a view in Domino, and you want to do what amounts to a keyed lookup. Even though the algorithm for doing a lookup by key in Domino is (presumably) very efficient from a Big O perspective, even a linear search through the List in memory is going to run laps around it.

There are, naturally, limits: some database operations are particularly fast and some in-memory algorithms are particularly slow.

Platform Knowledge

And in addition to the rules of thumb, sometimes it's best to just know a lot about the platform you're working with. Sometimes this comes with a knowledge of the general type of platform (e.g. key/value lookup in a document DB is fast, "relational" activity is not), and sometimes it just takes hands-on experience.

Fortunately, this becomes self-reinforcing as you learn it. Once you run across severe pitfalls (say, db.Search or using @Now in a view), you develop sort of a visceral revulsion to using it again except when it's the only option. Eventually, you build up enough working knowledge and callouses that it becomes second nature.


Once you have a good grasp of what is and isn't quick, it can really help you structure your programs more effectively. Not only does it help you write faster-executing code, but it also helps you understand when it does and does not matter: if you have code that will only execute once, you can intentionally forgo a faster-but-harder-to-maintain algorithm in favor of a clear-but-moderately-slower one as long as you know you're not falling off a performance cliff. That balance between writing for the computer and writing for other programmers is one of the crucial things to strive for.

Swift

Wed Jun 04 20:52:28 EDT 2014

Tags: swift

This is a topic that doesn't really fit my usual bailiwick of Domino programming, nor is it something I'm particularly qualified to comment on, since the most Objective-C programming I've ever done was some putzing around years and years ago with a weird idea for a pseudo-database that didn't even involve Cocoa, but I'm going to talk about it anyway.

I'm really excited about Swift.

In case you don't follow Apple circles, Swift was one of the fire hose of announcements at WWDC on Monday. It's a new programming language designated to replace Objective-C, billed as "Objective-C without the C", and can be thought of as Apple's Go.

So why am I so excited about it? Part of it is that I've been flirting with the notion of diving into Cocoa development proper, and this provides a perfect impetus. But beyond that, it tickles my programmer brain in a great many ways.

Low level + dynamic

The primary thing that piques my interest is the way it blends the best of what in olden days were referred to as "systems" and "scripting" languages. It's not the first language to do so, but it'll be among the few to get widespread adoption. It's C without pointers (mostly); it's functional programming without the Lisp; it's Objective-C without the brackets and @s; it's Ruby/Python without the speed loss; it's ML/Haskell/etc. without the "what the hell is this?".

What this means in practice is that it doesn't shy away from syntactic sugar. It's extremely common to want to make literal arrays and maps (Dictionaries in Cocoa parlance), and so Swift has clean syntax for those. They want to really emphasize closures, so the syntax gets cleaner the simpler the task is. They want strong typing, so they use type inference to get the result without all the "oh, come on, you know what I mean!" feeling you get from writing Java.

Good for programmers and compilers

It's striking just how many of the syntactic sugar bits and the defaults of the language are geared both towards improving programmers' lives (with easier code and bug prevention) and improving compiler optimization. It seems like it's a product of the modern state of compilers: whereas C was made during the infancy of computing and is designed to allow the programmer to really turn the screws in tons of crazy ways (see: pointer arithmetic), Swift is designed to take advantage of the fact that the bounds for what makes a good program are now well-known, and by restricting "dangerous" operations, the code is not only safer but also much more predictable.

One example of this is something that most current languages have adopted: for-all loops. In languages without them, it's contingent on the programmer to write the looping logic themselves. In pre–for-all Java, for example, this meant either using array indexes or Enumerators/Iterators. Those ranged from sort of a pain and potentially inefficient (indexes) to probably fast but horrendously ugly (the others). But for-all loops fix that: not only is the syntax much easier to type and is much clearer in intent, but now the compiler can choose the most appropriate method of iteration.

Swift is full of this, from its focus on immutability to its use of the "override" keyword to its integration of functional-programming idioms.

Type inference

I mentioned this already, but it deserves its own section. I've long had a very conflicted view on type systems. On the one hand, I appreciate the values of a Java-style strict type system - the consistency, the prevention of errors, the self-documentating nature - but good lord is Java a huge PITA to actually write sometimes. I can't even count how many times I've written a line like this:

List<Map<String, Object>> someListOfMaps = new ArrayList<Map<String, Object>>();

Gahhhhh. Every time! Never versions of Java have improved on this (though we as Domino programmers likely won't see that for a while), but it's still a drag. Moving to a strongly-typed-but-declaration-free language like Ruby is such a breath of fresh air. Not because I specifically want to assign objects of different types to the same variable, but because I don't have to fight the compiler over nuts-and-bolts of getting the right class name down.

The kind of type inference Swift uses makes Java-style strictness palatable. You get all the benefits of strict typing, both to you and to the compiler, without having to write "Map" five hundred times per source-code file.

LLVM as .NET or the JVM

LLVM is the just-above-the-metal virtual machine that Apple uses on its devices, and this sort of marks its coming-out party as a multi-language platform in the vein of .NET or the JVM. Swift files compile down to the same object types as Objective-C, so you can mix and match them in the runtime, much as you could mix and match multiple .NET languages or Java and Scala. In practice, this means that diving into it in an existing Cocoa app is much easier than having to rewrite the whole thing, while it also means that someone like me who isn't well-versed in the framework can still make use of the decades of Objective-C knowledge online.

Conclusion

So in conclusion: I'm just real excited. This looks fun! It's like a best-of setlist from all modern languages built on top of a giant framework that lets you build apps immediately. You should give it a look too - at the very least, watch the end of the WWDC keynote, where it was introduced.

Coaxing Enums Into XPage Combo Boxes

Wed May 28 19:07:12 EDT 2014

Tags: java xpages

I've been reworking Forms 'n' Views over the last couple days to use it as a development companion for the OpenNTF Design API, and one of the minor hurdles I ran across was presenting a getter/setter pair that expects a Java Enum to an XPages control (a combo box in this case, but it would be the same with other similar controls). I had assumed at first that it would simply not work - that the runtime would entirely balk at the conversion. However, it turned out that XPages does half the job for you: for displaying existing values, it will properly coax between the string form and the Enum constant. However, it breaks when actually going to set the value.

This whetted my appetite enough that I decided to try to see if I could write a small converter to finish the job in a properly generic way, and it turns out I could. To cut to the chase, I wrote this class:

package converter;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.el.ValueBinding;

public class EnumBindingConverter implements Converter {

	@SuppressWarnings("unchecked")
	public Object getAsObject(final FacesContext facesContext, final UIComponent component, final String value) {
		ValueBinding binding = component.getValueBinding("value");
		Class<? extends Enum> enumType = binding.getType(facesContext);

		return Enum.valueOf(enumType, value);
	}

	public String getAsString(final FacesContext facesContext, final UIComponent component, final Object value) {
		return String.valueOf(value);
	}

}

The getAsString method is your standard "I don't care about this" near-passthrough, but the getAsObject portion does the work necessary. Because I'm binding to a Java bean with getters/setters expecting the appropriate Enum type (this would presumably also work with a DataObject with a thoroughly-implemented getType method), the ValueBinding class is able to look up and provide back the expected Enum class. I then use the standard Enum.valueOf method to let Java do the work of actually finding the appropriate Enum constant.

Using this, I'm able to write a control like this:

<xp:comboBox value="#{columnNode.sortOrder}">
	<xp:this.converter><xp:converter converterId="enumBindingConverter"/></xp:this.converter>
	<xp:selectItem itemLabel="None" itemValue="${javascript:org.openntf.domino.design.DesignColumn.SortOrder.NONE}" />
	<xp:selectItem itemLabel="Ascending" itemValue="${javascript:org.openntf.domino.design.DesignColumn.SortOrder.ASCENDING}"/>
	<xp:selectItem itemLabel="Descending" itemValue="${javascript:org.openntf.domino.design.DesignColumn.SortOrder.DESCENDING}"/>
</xp:comboBox>

And it works! That allows you to bind to a getter/setter pair that expects an Enum without having to write in a shim to convert it to a String value beyond the generic converter.

You probably noticed the same thing I did, though: that's ugly as sin. Not only that, but it's a lot of redundant code when what you usually want to do is provide a selection of all available constants for the given Enum. To save myself a bit of future hassle and prettify my code a bit (at the expense of UI, but who cares about that? (I kid)). I wrote this DataObject bean to accept an Enum class name and return a list suitable for use in a control:

package bean;

import java.io.Serializable;
import java.util.*;

import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import org.openntf.domino.utils.Strings;

import com.ibm.xsp.model.DataObject;

import frostillicus.bean.*;

@ManagedBean(name="enumItems")
@ApplicationScoped
public class EnumSelectItems implements Serializable, DataObject {
	private static final long serialVersionUID = 1L;

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

	@SuppressWarnings("unchecked")
	public List<SelectItem> getValue(final Object key) {
		if(key == null) {
			throw new NullPointerException("key cannot be null.");
		}

		String className = String.valueOf(key);

		try {
			Class<? extends Enum> enumClass = (Class<? extends Enum>)FacesContext.getCurrentInstance().getContextClassLoader().loadClass(className);

			Enum[] vals = enumClass.getEnumConstants();
			List<SelectItem> result = new ArrayList<SelectItem>(vals.length);
			for(Enum val : vals) {
				SelectItem item = new SelectItem();
				item.setLabel(Strings.toProperCase(val.name()));
				item.setValue(val);
				result.add(item);
			}

			return result;
		} catch(Throwable t) {
			throw new RuntimeException(t);
		}
	}

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

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

It uses the @ManagedBean implementation that I cobbled together a while back, but you could just as easily use the normal faces-config route. The way you use this is to pass in the class name of the Enum you want in a selectItems component:

<xp:comboBox value="#{columnNode.sortOrder}" onchange="fnv_mark_dirty('#{id:viewPane}')">
	<xp:this.converter><xp:converter converterId="enumBindingConverter"/></xp:this.converter>
	<xp:selectItems value="${enumItems['org.openntf.domino.design.DesignColumn$SortOrder']}"/>
</xp:comboBox>

Though it only saves a few line in this case, it'd pay off more with larger Enums. It has the down side of being pretty naive about its conversions: it just does a basic first-character proper-casing of the Enum constant name, but there's no reason you couldn't add better human-friendly-ifying to it.

I'm not sure if I'll be able to satisfy all of my Java preferences when it comes to multi-value Enums, though. Java's generic type erasure means that runtime code wouldn't have a way to inspect the getters/setters to figure out the appropriate Enum type. Perhaps I can inspect the select items attached to the control to find the appropriate class.

Code for Tim: LESS CSS for XPages

Sun May 25 16:39:10 EDT 2014

When OpenNTF announced the "Code for Tim" initiative, I browsed Tim's GitHub repository list and one stuck out to me: the "xspless" stub repository for adding LESS CSS support to XPages. I'd latently wished for this sort of feature for a while, but hadn't yet set out down the path. It seems Tim had had the same desire, and had taken at least one more step than me.

I've decided to try my hand at making this desire a reality, and it's borne some fruit so far. I've created a fork of his project to house my attempts:

https://github.com/jesse-gallagher/xspless

So far, I've made functional drafts of two tacks:

  • A servlet plugin for Domino, in the "org.openntf.xsp.less" and ".feature" projects. This servlet is available at "/xspless" within each database (behavior outside of a database is not handled) and it processes the named file (can be a Stylesheet resource, File Resource, or file in WebContent) just-in-time and delivers the result as normal CSS
  • A builder plugin for Designer, in the "org.openntf.xsp.less.builder" and ".feature" projects. This builder adds a new Eclipse Nature to Designer (activated per-project by right-clicking the app and choosing "Add/Remove LESS CSS Nature") that compiles Stylesheet resources named in the form of "foo.less.css" (Designer automatically appends the ".css") and other File or WebContent resources named in the form of "foo.less" and stores the compiled results in the NSF

My ideal goal would be the ability to write .less files in Designer without any plugins and have the server treat them as normal CSS files with pre-processing, including them in resource-aggregation chains. Since I don't currently know how to have files processed on the fly and also included in aggregation, I created the two routes, with the latter being the likely-preferred route. Though it requires installing a plugin on each developer's system, it has the distinct advantage of the resultant files working perfectly with the normal resource aggregation pipleline of the server.

In their current state, these plugins seem to do their job. If I find out a way to hook into the resource chain on the server transparently, I'll look to improve the server plugin, but for now the Designer plugin seems promising. I plan to give a shot to using it for normal development; it will likely be a refreshing change of pace to be able to use LESS to write cleaner CSS. After a bit of testing, I'll likely create a project on OpenNTF.

Be a Better Programmer, Part 2

Thu May 22 12:38:32 EDT 2014

Tags: philosophy
  1. May 15 2014 - Be a Better Programmer, Part 1
  2. May 22 2014 - Be a Better Programmer, Part 2
  3. Jun 05 2014 - Be a Better Programmer, Part 3
  4. Aug 14 2014 - Be a Better Programmer, Part 4
  5. Jan 30 2015 - Be a Better Programmer, Part 5

For this week's installment, I'd like to cover a more abstract topic than last time:

Develop a Philosophy of Programming

By this grandiose title I don't mean that your outlook on programming has to be an answer to life, the universe, and everything (though tell me if it is), but more that it's useful to know why you do what you do. Why are you a programmer? I'm assuming it's not because of a particular love for "delivering" "enterprise" "workflow" "solutions".

In my case, it's because I find the act of programming to immensely joyful (even when it's a pain). The best times are when I'm working on something and my brain is just saying "This is awesome" - whether the actual end product remains awesome is largely immaterial; it's more the act of creating it. Good thing, too, since another part of the joy is figuring out why the stuff I did before is awful in light of a new idea I've had.

The most influential thing I've read on the notion of programmer identity is Paul Graham's Hackers and Painters. His numerous other essays are also generally worth a read, but that one has stuck with me. The crucial aspect is that he aligns programmers' personalities with those of artists (over-reduced to "painters") rather than the scientists and mathematicians that Computer Science grew up with. Over the years, I've spent a lot of time thinking about where programming fits in the pantheon of professions, and I think the essay is mostly right. Certainly, programmers share a lot of traits with mathematicians (pedantry, for one), but otherwise the math/science basis of programming is something of an implementation detail. The real beating heart of programming is the joy of creating - or even just the joy of tinkering and trying, of discovering the contours of the medium.

Deciding on your philosophy of programming, whether it matches mine or takes a different path, isn't something that directly assists your day-to-day work, but I think it informs the whole. Having this sense of identity gives me a solid feeling of why I'm doing what I'm doing and an intrinsic motivation to do it properly. It helps push me to elevate my code past "the first thing that works" and into an intentionally-crafted product. Far from being a flighty academic exercise, thinking this sort of thing through has bolstered my consistent drive to improve.