A Couple Blog Matters

Mon Nov 26 18:58:02 EST 2012

I've made a couple structural changes to the blog here. Normally, I wouldn't make a fuss over things like that, but they're pertinent to the overall theme.

First off, I changed the links over on the right, adding a link to the in-progress home page of my side-project company, I Know Some Guys. We're in the market for contracts - web site projects, internal apps, and the like. I may have more about that later.

I also promoted the link to my portfolio page to its own category. Since the aforementioned side-project company isn't a full-time gig, it can't hurt to keep that and the resume visible.

Finally, the blog itself is hopping on the ever-popular Bootstrap bandwagon. For the most part, the look of the site should be the same, though some widgets here and there are an awkward mix of the two. Many of my projects lately have been Bootstrap-based, and I figured I may as well move this over too, but not just leave it at the default style. Not only is the site (somewhat) more responsive now, but it and the portfolio have been giving me practice with building controls and Themes to make the application of Bootstrap to XPages apps easier. One huge advantage of OneUI is that IBM did a lot of work theming standard controls and building excellent new ones in the Extension Library to automatically gain OneUI styling as appropriate. Fortunately, I can piggyback on that: with a bit of work with Themes and Renderers, my goal is to make it so that an app can be almost-seamlessly switched between OneUI and Bootstrap as desired. They're not perfect matches for each other (OneUI has more structural geegaws), but they're close. That'll give me some much-needed Renderer practice, too.

My Current Data-Source Musings

Mon Nov 26 18:41:48 EST 2012

Tags: mvc

My quest to find the ideal way to access data in XPages continues. Each time I make a new project, I come up with a slight variation on my previous theme, improving in one or more of the various conflicting factors involved. The problem, as always, is that the standard xp:dominoView and xp:dominoDocument data sources alone are insufficient to properly separate business logic from presentation. On the other hand, accessing view data in a way that is both efficient and flexible via just the standard Java API is a non-trivial prospect. The advantage to using xp:dominoView in particular is that IBM already did an incredible amount of work making performance passable when dealing with cases of resorting, key-lookups, FT searches, response hierarchies, and the like.

The ideal method would build upon the efficient-access and serialization work already done while retaining that Rails-like collection-fetching and relation code from my forum attempts. Accordingly, I'm trying something a bit different with my latest project: I extended xp:dominoView to be able to take another parameter, modelClass, that is the class name of the objects it should return, rather than just DominoViewEntry. In turn, the objects I'm using wrap the real DominoViewEntry and allow for transparent access to the document (as needed, e.g. when a requested field is not a column) and the usual benefits of writing Java classes: namely, I can write code to handle field-change side effects without having to care about the logic behind that in the XPage itself.

This is sort of a half-formed idea so far, and I'm not 100% comfortable with it, but I think it's promising. Ideally, there wouldn't be any data sources written into the XPage itself at all (since it should be just a View), but that's sort of a necessity given the current state of things. This should be a reasonable next-best thing, and maybe a stepping stone to a new, faster, and cleaner data-access method.

The end goal of all this is to make it so that creating a new data "type" is very straightforward but still more declarative and structured than just making a new form name in the xp:dominoDocument data source. There should be classes to go with each type, but those classes should be very simple and easy to write. The quest continues!

The Ruby Builder for XPages

Wed Nov 07 13:50:14 EST 2012

Tags: xpages ruby

After I got Ruby in XPages to the point where it's generally working enough to power this blog, I set my sights on an even-more-important goal: being able to write backing Java classes in Ruby. While replacing SSJS is quite handy, my general use of inline scripting like that has declined significantly in favor of Java classes.

Fortunately, JRuby has a language cross-"compiler" and some hooks to write Java-compatible Ruby classes. Unfortunately, I was repeatedly stymied by a couple things:

  • Having the conversion happen automatically
  • Having the resultant "compiled" classes use the right class loader, allowing them to access other classes in the app
  • Implementing Java Interfaces

The first one was the most work but also the first to be solved: I wrote an Eclipse builder. The latter two were tough until I realized yesterday that the answers were sitting under my nose the whole time. For the classloader, I was able to switch the compiled output from using the global JRuby runtime to a runtime stored in the application scope and set to use the loader from facesContext.getContextClassLoader(). For the interfaces, it turned out that JRuby already had another annotation for declaring implemented interfaces, unsurprisingly called "java_implements".

So the upshot of this is: now I can write classes in Ruby and have Designer automatically convert them to Java and then compile those classes, ready to be used like any "normal" Java class in an XPage app. For demonstration purposes, I whipped up a useless-in-reality class to implement DataObject:

require "java"

java_package "frostillicus"

class TestDataObject
	java_implements "com.ibm.xsp.model.DataObject"
	
	
	def initialize
		@values = {}
	end
	
	java_signature "Object getValue(Object key)"
	def [](key)
		@values[key] or "#{key.to_s} not found"
	end
	
	java_signature "void setValue(Object key, Object value)"
	def []=(key, value)
		@values[key] = value
	end
	
	java_signature "Class<?> getType(Object key)"
	def get_type(key)
		java.lang.Class.class
	end
	
	java_signature "boolean isReadOnly(Object key)"
	def read_only?(key)
		false
	end
end

Once you have that file, it gets automatically converted to Java and compiled (once you have your build path set up correctly), and then it's available for use in other Java classes, in SSJS (or Ruby-in-XPages), and as a managed bean.

As you might expect with something like this, particularly for a first draft, there are a number of caveats:

  • The implementation is ugly as sin. There's a part that actually contains Java code that writes Ruby code that writes Java. It's very much a product of a series of "I wonder if this would work..." tests.
  • I haven't tested it to look for weird conflicts or leaks, though I suspect that my use of application-specific runtimes will help head off the worst of those potential problems.
  • You can't write classes that extend other classes. While I think you can do this within JRuby itself, the resultant objects are children of RubyObject, and there's no multiple inheritance. Interfaces will work in many cases, but that still limits the applicability.
  • Since the building happens in Designer, you need to have the feature installed client-side, which is not a problem with Ruby-in-XPages.
  • All those Java annotations really harsh the buzz of writing Ruby code. In that example above, the Ruby class isn't really any cleaner than a pure-Java equivalent. However, for larger, more complex classes, the expressiveness benefits of Ruby  would start to show.
  • There's basically no IDE help to be had. I haven't written anything into the builder to highlight syntax errors yet and non-syntax errors (like implementing an Interface but not all the methods) only show up with build errors on the resultant Java class. Plus, there's no autocomplete, and you only get syntax highlighting if you specifically install Ruby syntax support (I think I got it from the Eclipse Ganymede update site). Some of those may be fixable with minor effort, but the really big stuff would go far beyond the amount of time I have to dedicate to this kind of thing.

For now, I tossed the first draft up on GitHub for the curious. It will take more work to be be considered anywhere near finished, but getting it this far means I can start using it in personal/demo apps and really start finding the rough edges in practical use.

Self-Aggrandizement for Fun and Profit

Mon Nov 05 21:38:36 EST 2012

As I alluded to in my previous post, I decided to set up a "portfolio" site to house a list of projects I've made or collaborated on and my recently-updated resume:

http://portfolio.frostillic.us

The site itself is intentionally quite simple: it's meant to house clear content, while further details are available on linked pages. Nonetheless, despite its simplicity, it's allowing me to further refine a couple things I've been tinkering with lately:

  • Bootstrap. Collaboration Today came out of the gate with a very clean implementation of a responsive Bootstrap design, and so I've been following suit by using Bootstrap for my non-data-driven sites (OneUI still feels like a better choice for complex applications in XPages). This portfolio provides a perfect testing ground for thoroughly incorporating the standard Bootstrap elements and making sure everything looks good and works properly on mobile devices.
  • Bootstrap as a Theme. This goes along with including Bootstrap generally, but I figured I'd take this occasion to start making a clean Theme to handle including the appropriate files and applying useful styles that I come across. Currently, this mostly means button styles, but I could see this expanding and potentially including renderers so that you could apply Bootstrap in much the same way that you do OneUI and standard and ExtLib components (like navigators) would adapt accordingly.
  • Cleaner URLs. I mentioned this in the aforementioned previous post, but I want to look for ways to keep XPage URLs as clean as possible. For this database, I'm taking a cautious route: using Domino web rules and giving the database a little knowledge about them, rather than exploring the possibility of running the whole site from a servlet. For a simple database, this is working well, with a basic from/to map and a simple manager bean.
  • Aggressive Open-Sourcing. Most non-work apps I've written lately have found their way to GitHub, but I decided I wanted to further drive the point home on the portfolio site. Towards this end, I included a "View page on GitHub" link in the footer of each page that links to the current master branch version of the XPage.
  • Page Controllers. I mentioned this a bit before, but I'm including my "page controller" idea in the portfolio, at least for editing documents. I created an AbstractDocumentController class that is meant to be a parent class for controllers used on pages with a single document data source. It just provides a couple convenience methods and hooks to override in type-specific cases or use directly in the basic case.
  • Another Simple View/Document Wrapper. This one isn't really anything new, but it's another example of how frequently it's useful to write a model class and manager instead of dealing entirely with the views and documents directly on the XPage with SSJS. The models make it clear what the important data is and the resultant XPage is pleasantly clean.

All in all, this has proven to be a good exercise in writing a focused, simple XPages app with an eye towards extreme cleanliness.

Taking a Swing at the URL Problem

Sun Nov 04 19:20:03 EST 2012

Tags: xpages urls

In the new portfolio web site I'm setting up for myself, I've decided to see what I can do about Domino's, and XPages' specifically, tendency towards ungainly URLs. An XPage URL, particularly an auto-generated one from, say, a view panel, can quickly become filled with undesirable elements - namely, ".nsf", ".xsp", "$$OpenDocument", "action=", and "documentId=". They all make sense and serve important purposes for the server, and to a certain extent URLs other than the main one don't matter, but I want a clean address bar, dang it.

The approach I'm trying now involves creating a managed bean named "url" that implements Map<String, String>. Its get() method takes a normal URL of the kind that you would usually write for a page and returns a cleaned-up version if it can find it, and the original URL otherwise. So a link to, say, the contact page looks like this:

<xp:link text="Contact" value="${url['/Contact.xsp']}"/>

I also set up a "link" custom control to act as a drop-in replacement so I don't have to do that EL bit everywhere. The code itself generates an internal map based on a view of simple From/To "Alias" documents in the DB, though I'm considering having it peek into names.nsf to find any applicable Web Rules more dynamically. The net effect is that I can use that bit of EL or the custom control and hand it a "normal"-style database-relative XPage URL and it'll clean it up if it can or, worst case, pass it through directly.

I can imagine some improvements, beyond the switch to looking at names.nsf instead. For one, I should make it handle "partial" replacements, so that I could map, say "/whatever.nsf/Posts/postid" to just "/posts/postid". I could go beyond that, too, making it do regular expressions to allow it to translate arbitrarily-complex routes beyond what just checking Web Rules could do.

I'm not certain that this is necessarily the best way (the REALLY best way would be to hook into whatever code handles all URL generation in the app), but it has a nice simplicity to it and I figure it's worth a shot.

Improving My Development Process: Source Control

Mon Oct 22 16:50:00 EDT 2012

I think it's fair to say that most professional programmers know that they should use source control, but, unless you work for a company that mandates it, you treat it like flossing or going to the gym. However, unlike your personal health and well-being, using source control is very important and can improve your life noticeably.

I'm a recent convert, in part due to Domino's historic hostility to proper source control. However, since 8.5.3 and its inclusion of the surprisingly good Source Control Enablement, there's no more excuse to slack. If you haven't already, read/watch the following things (and shame on you):

But beyond the basics of "make sure to check in changes with useful notes", I want to figure out the best way to do Domino development in this brave new source-controlled world. Mainly, I think I'm going to try to adopt a model similar to a shipping application: longstanding "write once" branches for significant versions, lengthy but temporary branches for development of the next version, throwaway branches for pie-in-the-sky ideas (like whenever I want to try to re-do my forum app's data access layer), and deployment via Source Control Enablement's "New Database From..." functionality.

That last part is huge, especially now that it's so easy to point an XPage app to a different database for its data access. I'm going to try more of an app/data separation in the future - I'm not sure I'll stick with it, but I think it could be very useful in deploying a new just-about-live version of an app alongside the "real" live one.

Regardless of the specific form my development process takes, I'm aiming to integrate source control thoroughly, to the point where NOT using source control feels "dirty", the same way that modifying a production app directly does. Fortunately, it doesn't take much to reach that point - just one instance of a client asking "is there any way we can go back to how it was working at the start of the week?" and being able to do it and you'll never look back.

A Couple Things I've Been Trying Out Lately

Tue Oct 16 09:22:18 EDT 2012

Tags: xpages

I'm always trying to figure out new tricks and (groan) patterns for my XPages development, and I've had a couple trends and experiments lately that I think are worth mentioning.

First off, I've been doing a lot of source control stuff lately, but that's a topic for another post, currently in crummy-draft form.

Beyond that, I think I'll just start a list:

  1. The joys of ExtLibUtil. Historically, I've had a general "JSFUtil" class (with the name and original code copied from here), but I've stopped copying that around from DB to DB and instead have started only copying the methods I really need, instead looking first at the ExtLibUtil class. If you, like me, were slow to hear about this bundle of magic, I suggest you take a look.
  2. Using the DominoDocument class in a bean. This one I'm not sure of, but I figured I'd give it a shot. DominoDocument is one of the classes that the XPages environment uses to wrap a lotus.domino.Document object and make it more or less persist across serialization. I decided to try using this (and maybe the View equivalent later) directly on the theory that it might be a bit easier to use and maybe even faster. So far, it's been a bit of a hassle, but I do enjoy having the various DataObject methods available for passthrough for my bean for EL use.
  3. Dynamic form generation. This is along the lines of something I was discussing in a chat the other day - the notion of having some more default "scaffolding" for XPages, where it could pick up more of the existing database elements without having to actually write the form XPage (or drag the fields over). For a simple data-driven app, having an XPage that generates type-appropriate fields (including keyword values from drop-downs and the like) could save a lot of time up front.
  4. "Controller" classes to back XPages. I've started more often making classes meant to have a bit of knowledge about a specific XPage (say, Document.xsp paired with DocumentController.java) and putting almost all code in there. So, instead of having a bit of SSJS on the save button to handle saving the document, putting a confirmation in the flashScope, and handling a redirection (ideally by returning a string), I do something like <xp:eventHandler ... action="#{documentController.save}"/> and write all the code in Java. This is still slightly awkward, but it's another way to move code out of the XPage itself, aiming to go EL-only as much as possible.

Most little tweaks like these aren't huge on their own, but they all combine to make significant quality-of-life improvements. It's a great feeling to see my XSP markup getting leaner and easier to read day by day.

Forms 'n' Views

Mon Sep 10 19:33:03 EDT 2012

One of my (many) for-fun projects lately has been a design-element editor named "Forms 'n' Views". Though it's not really release-quality, it's been coming together enough to toss it up on GitHub and make a post about it. Basically, it's meant to serve a couple purposes:

  • Help mitigate the "Windows problem" - when all you want to do is make a quick change to a legacy design element (say, a stylesheet), but doing so would mean firing up a Windows VM, launching Designer, and opening the DB. For quick edits, the amount of time that takes wildly eclipses (heh) the time spent actually coding.
  • Experiment with a data-focused way to edit forms and views. The legacy editors are geared towards a Notes client target, dedicating most of their space to aspects that have no meaning when the design element is intended just for backing an XPage.
  • Eventually, provide a way to grant "sudo"-style access to other users to modify certain design elements without granting full designer/manager access, setting up WebDAV, or exposing a poor web designer to Designer.
  • Let me experiment with a different setup for an XPages app - Forms 'n' Views consists of a Dojo BorderContainer- and TabContainer-based UI on a single XPage, which loads up tabs containing custom controls on the fly. None of it is unexplored territory, but it's good to write different kinds of apps sometimes.
  • Let me try out some more backing-class architectures. Each editor is backed by a DOM representation of the exported DXL, which is manipulated through wrapper classes and then re-imported back directly. Things like getting lists of columns are done via XPath queries without storing the data redundantly.

In its current incarnation, it's taken on the pale complexion of Dojo's "claro" theme - I've been going back and forth between that and the Notes-like "soria" theme:

Forms 'n' Views

It should do for now, but I'll likely fiddle with it more to make it look better.

In any event, this has been a fun project so far, and hopefully it'll shape up into a useful tool.

Building XPages servlets with FacesContext access

Thu Sep 06 10:05:00 EDT 2012

I have a confession to make: I'm not crazy about XAgents. Don't get me wrong - they do everything they're supposed to and do it well. However, it's always kind of bothered me that you take a visual design element like an XPage and turn off all the higher levels to get back down to the core servlet. Plus, it muddies the list of XPages in the DB - some are actual XPages, some are just wrappers for scripts. So my objection is essentially pedantry.

However, the fact that my objection is wildly exaggerated has never stopped me from sinking a lot of time into finding the "right" answer before, and it hasn't stopped me now. When what I want to build is, say, an Excel exporter for a particular type of document in a reporting DB, what I really want is a basic servlet that exists only in the database and has access to the surrounding XSP environment and custom classes. Fortunately, between a post by Sven Hasselbach, the referenced Chinese-language developerWorks article, the XSP Starter Kit, and a bit about facesContext.release() on a JSF-focused article and reinforced by the FacesContextServlet class from the ExtLib, I made it work.

The developerWorks article covers the bulk of the work - creating the Factory, setting up the file in META-INF, etc.. After that, you can set up your servlets by extending (using the Starter Kit method) DesignerFacesServlet. It turns out that the important thing to remember is to close out your context when you're done - I ran into a lot of trouble from not doing this, which would break XPages visited after the servlet. As an example, here's the test class I ended up building while figuring out how to make it not blow up my application:

import java.io.*;
import java.util.*;
import com.ibm.commons.util.StringUtil;
import com.ibm.xsp.webapp.DesignerFacesServlet;
import javax.faces.context.FacesContext;
import javax.servlet.*;
import javax.servlet.http.*;

public class TestServlet extends DesignerFacesServlet implements Serializable {
	private static final long serialVersionUID = -1152176824225969420L;

	@SuppressWarnings("unchecked")
	@Override
	public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
		// Set up handy environment variables
		HttpServletRequest req = (HttpServletRequest)servletRequest;
		HttpServletResponse res = (HttpServletResponse)servletResponse;
		ServletOutputStream out = res.getOutputStream();
		FacesContext facesContext = this.getFacesContext(req, res);

		try {
			res.setContentType("text/plain");

			out.println("start");

			// The sessionScope is available via the ExternalContext. Resolving the variable
			//	would work as well
			Map<Object, Object> sessionScope = facesContext.getExternalContext().getSessionMap();
			sessionScope.put("counter", sessionScope.containsKey("counter") ? (Integer)sessionScope.get("counter") + 1 : 1);
			out.println("Counter: " + sessionScope.get("counter"));

			// A query string map is available via the request. This method, as opposed to
			// 	getting the "param" variable, returns arrays of strings, allowing things like
			//	"?foo=bar&foo=baz" properly
			Map<String, String[]> param = req.getParameterMap();
			for(String key : param.keySet()) {
				out.println(key + " => " + StringUtil.concatStrings(param.get(key), ';', false));
			}

			out.println("done");

		} catch(Exception e) {
			e.printStackTrace(new PrintStream(out));
		} finally {
			out.close();

			// It shouldn't be null if things are going well, but a check never hurt
			if(facesContext != null) {
				facesContext.responseComplete();
				facesContext.release();
			}
		}
	}
}

I set up my ServletFactory to use this one for "/test", and so it's available via a URL like "/database.nsf/xsp/test?foo=bar". As with an XPage, you can also chain more path bits on after the servlet name, like "/database.nsf/xsp/test/some/other/stuff" and get to that via req.getPathInfo() - though with the caveat that, unlike with an XPage, the servlet path is included in the path info, so it would return "/xsp/test/some/other/stuff".

So long as I don't run into any other app-exploding problems, I plan to go this route for non-UI requests like exports and actions. When I have a use for it, I'll also go down the related path of writing custom services, for which the ExtLib provides an extensive foundation.

A Custom Control for dojox.widget.Toaster

Wed Sep 05 09:27:00 EDT 2012

Tags: xpages dojo

Update: Looks like Chris Toohey beat me to this by a couple months: http://www.dominoguru.com/pages/04092012113950.html

Marky Roden did a presentation at MWLUG that included, among other things, a demonstration of Pines Notify, a jQuery plugin that provides Growl-style notifications - something that could come in tremendously handy in a lot of situations.

I wanted to use something like this, but I decided to check to see if there's an equivalent in Dojo already, so I don't have to start including jQuery as well. Fortunately, there is... ish. dojox.widget.Toaster serves a similar purpose, though it takes its design cues from the little "toaster" notifications common on Windows. However, their default appearance is the worst thing in the entire world:

GAH MY EYES

Fortunately, that can be cleaned up with a little CSS to be a crummy version of Growl:

A little better

With a bit more work and attention to detail, it could end up pretty classy. I think it's still not as featureful as Pines Notify (no "clickthrough" options, its handling of multiple messages with different timeouts is not nuanced, etc.), but it's serviceable.

The API to use this widget is actually pretty straightforward: you run a bit of code at page load to create a toaster object to listen to a specific channel name (e.g. "/save/success") and then publish messages whenever you want something to appear. The code for sending a message is pretty simple, and there are two forms, depending on whether or not you want to include additional parameters:

dojo.publish("/test/channel", ["This is message one, lasting five seconds"])
dojo.publish("/test/channel", [{ message: "This is message two, lasting 10 seconds", duration: 10000 }])

I decided to wrap the instantiation and required resources up into a custom control and make another demo DB:

http://frostillic.us/tests/djToaster.nsf

The "toaster.css" page is the CSS I wrote to override the standard behavior. The margins are intended for the top-right positioning, but could be changed readily to equivalents for other corners.

The control exposes five properties: messageTopic (the channel name, required), defaultType ("message", "error", etc.), duration (in milliseconds), positionDirection (the position and slide direction, defaulting to up from the bottom right), and separator (the text that appears between two simultaneous messages).