How to attach a user interface to a Jini service

An in-depth look at the serviceui project from the Jini community

The serviceui project at Jini.org (see Resources) is attempting to define a recommended or standard way of attaching a user interface (UI) to a Jini service. In this month's Jiniology, I cover the serviceui project's short history and its current working proposal.

Discussing service UIs on the Jini-users mailing list

My experience with Jini service UIs began back in January, when I posted the following query to the Jini-users mailing list (see Resources):

Where will a user interface usually reside in service items? The service object itself could be an applet, the service item could have methods that put up the UI, or you could attach one or more applets as attributes. If a service has a UI that must be used every time the service is used, would you prefer to make the service object itself an applet, keep the UI separate from the service object and enter all applets as attributes, or invoke a method that puts up a UI?

Or, I suppose, will there be a preference? It seems the "community" will need to develop guidelines on how you should architect service items, and how clients should behave when presented with different types of service objects and service items.

Any ideas?

bv

The first reply to appear on the list was from Brian Jeltima of Sun Microsystems:

In my opinion, the GUI should rarely (I'd like to say never) be an integral part of the service object. I think of the service as a protocol defined via interfaces. A default user or management GUI can be attached as an attribute, but the user of the service is free to interact with the protocol directly and avoid the download of these bundled GUI objects if they are not needed.

I imagine that a preferred approach will evolve rather quickly as device manufacturers will be burning their solutions into ROM. The difficulty of changing code in consumer devices will prompt them to think through these issues early on, I would hope.

Brian

Brian's post was followed by 16 others discussing how to attach a UI to a service. I read all of these posts and then tried to summarize them on the Jini-users FAQ as an answer to the question: Where in the service item should I put the UI for my service? Here's a snippet from that answer, which describes how I think a UI object would get a reference to the Jini service object:

Your factory instantiates and returns a UI object. The [UI object] you write must accept a reference to the service object in its constructor. This reference will be stored in a local variable, so the [UI object] can use it. The [UI object] serves as an intermediary between the user and the service.

(For a complete record of this first attempt to show how to add a UI to a service, see the answer to question 14 on an

early version

of the Jini-users FAQ.)

In response to my service UI answer, Jeltima made the following comment, which describes his concern about my recommendation that a service object reference be passed to the UI object constructor:

The problem with passing the service object in the constructor is that if the implementor decides to actually provide the GUI as a serialized object in an attribute, then, when the client deserializes the GUI, the constructor won't be called.... So I think [passing a service object reference to] a separateinit() function [of the UI object] is a bit more general [than passing a service object reference to the UI object's constructor.]

I thought Brian's comment made sense, but as I was very busy with other things, my FAQ answer remained relatively unchanged for the next several months.

Discussing service UI at the Jini Community Summit

At the Jini summit last May in Aspen, CO, however, the issue of attaching a UI to a service was revisited. During his presentation called "Creating and Building New Jini Services," Jon Bostrom of Sun said that it was important that someone define a standard way of attaching a UI to a service.

Most people at the presentation agreed. I also voiced my agreement and described January's Jini-users discussion and the resulting FAQ answer. I also mentioned Jeltima's preference of using an init() method rather than a constructor to pass a service object reference to a UI object. I said, "If I do it my way and Brian does it his way, then clients will have to know about both ways to offer UIs to each of our Jini services." I also added that if no standard way of attaching a UI to a service became generally accepted, service providers would attach UIs independently and clients would need to know 500 different ways to look for a service UI.

Unfortunately, I discovered as I was writing this article that the example I gave at the Jini summit was wrong. As I myself had noted in the first FAQ proposal, the UI object was being created and returned by a factory method. A factory method is meant to hide from the client the way an object (in this case, the UI object) is instantiated. Because the factory method is responsible for initializing the new UI object, only the factory method -- not the client -- needs to worry about whether to pass a service object reference to a constructor, an init() method, or some other method. Nevertheless, the attendees of Bostrom's meeting seemed to accept my conclusion that even minor differences in the way UIs are attached to services can complicate programming Jini clients.

In the end, we all agreed that defining a standard made sense, and that the Jini community was the one to tackle the problem. Bostrom said that while he'd be happy to have his team work on the approach, he thought it would be best if someone who was not from Sun started it.

Later that day, another Sun employee slipped me this note:

Bill,

On Jini.org, we can now create "projects." This may be a possible forum for the GUI working group that we were all discussing in the "Jini Services" breakout session.

A few days later, Ken Arnold of Sun posted this message to the Jini-users mailing list:

We have added a new feature to the Jini.org Web site -- you can create collaborative projects for shared development of Jini service definitions, development utilities, clients, documentation, and so forth.

Suppose you want to work on the correct design for GUI attributes (a popular discussion among Jini users). You can go to the projects page on Jini.org and see if someone is already working on it. If not, you can create a new project....

Ken

Creating the serviceui project

I must have subconsciously taken Bostrom's and Arnold's comments as hints, because soon after this message was posted, I created a project on Jini.org called serviceui. I did this partly because the message that Sun wanted someone external to start the project had been firmly imprinted on my brain, partly because a personal experiment in chaos -- I mean, democracy -- seemed intriguing, and partly because it was so fast and easy to create a project at Jini.org that I didn't think much about it before creating it.

Shortly after creating the serviceui project, however, I had a minor panic attack. What business did I have starting this project? Shouldn't I have at least posted a query to the Jini-users list to build a consensus before acting like some trigger-happy cowboy? Time, however, calmed my anxieties. Over the next few weeks, many people joined the project and an interesting and fruitful discussion commenced on the serviceui mailing list.

So far, the project felt like a group of engineers sitting in a virtual conference room, discussing a design problem, and homing in on a solution. I have served as scribe, attempting to capture the consensus in writing. (Our current proposal forms the bulk of this article.)

I believe that in general the serviceui experiment has been successful. Our main problem has simply been that because no one is getting paid and we are all busy, our work has gone slowly. Nevertheless, we have made quite a bit of progress. Hopefully, our work will be timely enough to do some good. One of your most important goals when trying to establish a de facto standard is to define it as early as possible, before people invest too heavily in other approaches.

I hope to get a solid proposal by the next Jini summit, to be held in Annapolis, MD, in October (see Resources.) Someone from the project, perhaps myself, will present the proposal at the summit.

I'll now give you the serviceui project's current working proposal. Any feedback you have is welcome. You can submit comments to my usual discussion forum at Artima.com. Or you can join the serviceui project at Jini.org and post comments to its mailing list.

How to add a UI to a Jini service

As a general rule, you should not make a Jini service object extend a class from a user interface library, such as Panel or JPanel. Think of the service object as the way clients interact with a service through the well-known Java interfaces that the service object implements. To associate a UI with a service, use attributes.

You can associate many UIs with a service by placing entries for the UIs in the service item's attributes. One reason to keep the UI separate from the service object is that services may be used in devices that don't have user interface libraries available. If you attach a UI to a service item as attributes, those clients who have user interface libraries can retrieve your UI and display it. Clients who don't have them can just use your service object directly.

Each UI is represented by one UI object, which may or may not represent a graphical UI component. A UI object could represent a voice-only interface, a text interface, a combination of voice and graphics, a 3D-immersible world, and so on. Each distinct kind of UI, including a 3D-immersible world with voice and a virtual-text display, would be represented in the attributes by one UI object.

Figure 1. Client code talks to a service through the Jini interface

Think of a service UI object as a type of "human adapter" -- an object that sits between the Java interface offered by the service object and a human who wants to use the service. Often a client program looks up a Jini service by Jini interface type. As shown in Figure 1, such client programs can use the service object directly by invoking methods in the service object's Jini interface. The service object's Java interface must provide access to all the service's functionality. Thus, a UI object merely serves as a go-between. As shown in Figure 2, a UI object gives a human user access to the service functionality via the Jini service interface.

Figure 2. A user interacts with a service via a UI object

The current working proposal gives four steps for adding a UI to a service. The user will:

  1. Define a factory object
  2. Pass the service object to the UI
  3. Place the UIFactory in an Entry
  4. Have the service object implement Identifiable (optional)

Step 1. Define a factory object

To add a UI as an attribute, create a factory object with a method that instantiates and returns a new UI object. This approach lets you make UI objects available without requiring that they get serialized and stored in the lookup service. You only need to serialize and store the factory-object attribute and its enclosing entry in the service.

The UIFactory interface

The factory object will need to implement a well-known UI factory interface (and the serviceui project should propose one). Here's an example of what the interface might look like:

// In file UIFactory.java package org.jini.ui;

public interface UIFactory extends java.io.Serializable {

Object getUI(Object serviceObject) throws UICreationException; }

Note that the package prefix org.jini.ui is used here to represent whatever package prefix the community eventually decides upon. Please do not use this package prefix. The org.jini package space is controlled by the Jini community, which hasn't given anyone permission to use org.jini.ui.

Exceptions thrown by getUI()

A factory object's getUI() method may throw the following two exceptions: InvalidServiceClassException andUICreationException. The unchecked InvalidServiceClassException will be thrown by getUI() if it cannot cast the passed reference to the expected service object class.

// In file InvalidServiceClassException.java package org.jini.ui;

public class InvalidServiceClassException extends RuntimeException {

public InvalidServiceClassException() { }

public InvalidServiceClassException(String msg) { super(msg); } }

The checked UICreationException will be thrown by getUI() if the factory cannot produce the UI object. If an exception thrown by the UI object's constructor detects this problem, a reference to that exception should be passed to the constructor of UICreationException. This enables clients to retrieve the original exception by invoking getThrownException() on the caught UICreationException.

// In file UICreationException.java package org.jini.ui;

public class UICreationException extends Exception {

private Exception thrownException;

public UICreationException() { }

public UICreationException(String msg) { super(msg); }

public UICreationException(Exception e) { thrownException = e; }

public Exception getThrownException() { return thrownException; } }

Defining a concrete factory class

To add a UI to a service, you must create a concrete class that implements the UIFactory interface, such as:

1 2 3 Page 1
Page 1 of 3