Sponsored Link •
Traditionally, desktop applications are designed with a built-in user interface (UI). The code for the application's UI is often highly coupled to the code that implements the application's functionality. Over time, tentacles of UI code may burrow deep into functionality code, and tentacles of functionality code may burrow back into UI code. In the traditional desktop application, therefore, the UI code and functionality code are usually inseparable, married for all eternity.
Jini's service proxy architecture encourages you to think differently about UI and functionality:
A Jini service proxy should represent the service's pure functionality, expressed via the methods of its object interface. For example, the service proxy interface for a toaster service should express or model the conceptual toaster service's functionality -- the interface should say "what it means to be a toaster." The service proxy should not supply human access to the toaster service; a separate UI object should provide such access.
One reason for excluding the UI from the service proxy is to enable client programs (clients) to access the service without human intervention or supervision. Clients written by programmers who knew about a particular service proxy's (potentially well-known or standard) interface can interact with a service directly. As Figure 1 shows, client code can interact directly with a service by invoking the methods in the service proxy interface. Such a client is called a direct-use client, because its programmers, based on their knowledge of the service proxy interface, can write code that uses the service directly via that interface.
Direct-use clients need not be completely devoid of a user. For example, a user could operate a device that acts as a direct-use client in certain cases. If the user requested that the device save some data in a file, the device could acquire a storage service proxy and directly invoke methods on that object to save data in a file, without further user intervention. In this case, the user-operated device acts as a direct-use client of storage services, because the device's programmers had prior knowledge of the storage service proxy interface and used that knowledge to program the device to use those services directly.
On the other hand, direct-use clients can also function independently of human supervision or intervention. Such clients act as autonomous agents, which decide for themselves when to enlist a service's help. When an autonomous agent uses a service, it invokes the methods offered by the service proxy interface directly. Thus, an autonomous agent's programmers must have prior knowledge of the service proxy interfaces their agent uses. (Although the human programmer actually has the prior knowledge when he or she writes the client code, in this document the code itself will often be said to have prior knowledge.)
When you design a Jini service, you should attempt to capture the service's entire functionality in the service proxy interface. To access any aspect of your service, a direct-use client should only need a reference to the service proxy. The service proxy should not include any code that defines a user interface to the service, just code that provides the service functionality at the method invocation level.
To provide a user interface for the service, you should encapsulate the user interface code in a separate UI object. As Figure 2 shows, a UI object grants a user access to some aspect of a Jini service. Think of a service UI object as a user adapter -- an object that adapts a service proxy interface that a human user cannot interact with directly into one a human user can interact with directly. Sitting between the service proxy interface and a human user, a UI object can grant the user access to a service.
A UI object can represent a graphical UI component, such as an AWT
Frame or Swing
but doesn't necessarily need to be graphical. A UI object could also represent
a speech interface, a text interface, a speech and graphic combination, or a
3D-immersive world. (The UI object is called UI object, rather than GUI
object or view object, because the object represents UI components
in general, not just graphical UI components.) Any kind of Jini Service UI,
including a 3D-immersible world with speech and virtual text display, should be
represented by a UI object, which is distinct from the service proxy.
One advantage of this architecture, in which UI and functionality are separated, is that you can associate multiple UIs with the same service. Associating multiple UIs with one service lets you tailor different UIs for clients that have particular UI capabilities, such as Swing or speech. Clients can then choose the UI that best fits their user interface capabilities. In addition, you may want to associate different UIs that serve different purposes, such as a main UI or an administration UI, with a service. Often, you may need to associate multiple UIs with one Jini service, where each UI has a particular purpose and targets a particular set of client capabilities.
This specification standardizes how UI providers associate a UI (user adapter) object with a Jini service, and shows how client programs can find the best-fit UI among multiple UIs associated with the same service. To associate a UI with a Jini service, UI providers (primarily service providers, but also possibly third parties) must supply three items:
A UI factory is an object that has one or more
factory methods that produce and return a UI object. A UI descriptor, an
serves as a container for the UI factory and other objects that describe the UI produced by the factory.
you can include a
in a Jini service item's attribute sets array, thereby associating the UI with
the service. A UI descriptor contains four public fields:
factory: A reference to a
java.rmi.MarshalledObjectthat contains the UI factory object in marshalled form
java.util.Setof attribute objects that describe the factory-produced UI
Stringthat names the main package of the UI toolkit the UI requires
Stringthat gives the fully qualified name of a Java interface type that represents the UI's role
fields' purpose is to describe the UI produced by the marshalled UI factory.
Using these fields, clients can choose from multiple UIs associated with a
service. Once they select a UI object, clients can use the other field,
create the object.
To associate a UI with a Jini service, the UI provider must first fill a UI
descriptor with a role
an attribute set, and a marshalled UI factory. The UI provider must then place
the UI descriptor in the attribute sets of the Jini service's service item.
A UI's role indicates both its purpose and its role-related semantics. Each
UI role is defined as a Java interface type, which UI objects playing that role
field references a
whose value is the role interface type's fully qualified name. For example, a
role UI provides general access to a service. A
UI enables a user to administer a service. Although most UI object semantics of
interest to the client program are defined by the UI factory's return type,
some semantics may be tied to the role. For example, for a role that represents
a user dialog, the role interface might include methods that let the client
determine the dialog's result.
The UI descriptor's
field holds a reference to a
java.util.Set of serializable objects that contain
information about the UI the descriptor represents. These objects can be of any
class, so long as they are serializable. Clients can search through the
attributes set for attribute types about which they have prior knowledge. The
objects can then help the client decide whether or not to use the
descriptor-represented UI. Several attribute classes, defined in the
package, are described later in this document.
field facilitates matching when querying the Jini lookup service. For example,
if a client seeks all services that have main UIs working with the Swing
toolkit, it could form a
array includes a UI descriptor template. If the UI descriptor template's
fields are set to
field is set to
field is set to
the lookup would only return services that have at least one main UI for Swing.
field contains the UI factory object inside a
MarshalledObject so that you
can place the class files for the factory and the UI it produces in a different
codebase than the service item containing the UI descriptor. By placing the
class files for UI factories and UI objects in separate codebases than that of
the service item, clients can download a service item without downloading all
the JAR files containing those class files, most or all of which the client may
never use. Only if the client attempts to use a UI will it need to unmarshal
the UI factory; this would trigger the downloading of the JAR file containing
the factory class files, and possibly the class files for the factory-generated
To use a UI, a client program must have prior knowledge of both the UI factory type (including, of course, the UI object type returned by its factory methods) and the UI role type. These types define the UI object semantics, which client programmers must understand before they can write code to interact properly with the UI. A client doesn't need prior knowledge of all the attributes types that appear in the attributes set. To the extent the client has prior knowledge of the attribute types, it can use that knowledge to select an appropriate UI from multiple UIs associated with a service.