Sponsored Link •
|
Advertisement
|
On Thursday, March 8, 2001, I had the privilege to visit the Jini team at Sun Burlington and discuss the Place API in the room with white board walls and bean bag chairs. Our discussions didn't dip down to the level of classes and interfaces and method names, but hovered instead at a higher, more conceptual level. The Jini team asked me questions about the basic approaches taken by the Place API. In this document I attempt to summarize the questions I was asked and the answers I gave (or should have given -- in many cases I have been able to come up with better answers after a week of reflection.).
One of the basic thrusts of the questioning challenged me to justify the need for a standard
way to provide the functionality of the Place API in a Jini service proxy.
"Why can't each UI that a human uses simply provide the functionality itself?" I was asked.
In other words, couldn't Service UIs
use proprietary Link
-like objects, which wouldn't need to be known to the underlying service proxy
or standardized?
I'll begin answering this question by stating and attempting to justify my basic design philosophy for Jini service UIs. I feel that, to the extent it is practical, the complete functionality of a Jini service should be embodied in the interface of the service proxy. A service UI should just provide users access to functionality present in the service proxy interface, and not add extra functionality. I admit that sometimes functionality exists that only makes sense for users, and in that case it can be overkill to try and force that functionality down into the service proxy interface. But in general my design sensibilities push me to attempt to capture as much of the functionality of a service as possible in the interface of the service proxy, even if the service is only intended to be used with a service UI.
One advantage of embodying service functionality in the service proxy is that the functionality can be
accessed both by software agents and users. Software agents can access the functionality directly by invoking
methods on the proxy interface. Human users can access the functionality indirectly via client UIs and/or service UIs.
The Jini team was certainly aware of this advantage, but pressed me to give them examples in which I thought
software agents would in practice need to follow Link
s. I'll address that question later in this document.
The other main justification for my separate the UI and functionality philosophy involves software project management. Were I a manager of a development team responsible for a Jini service and its UIs, I would encourage my team to separate UI and functionality so that the functionality code just exists in one object. As a manager, I'd want to avoid replicating functionality code in each UI, so that when functionality needs to be updated, only one object need be updated. It is true that my team could model the functionality in an object whose code is just included in the JAR file for each UI, but if that object represents the functionality of the service, it should likely be the service proxy.
Moreover, one advantage of the service UI architecture that I often cite is because UI and functionality are kept separate, it is easier to evolve the UI without breaking the functionality, and vice versa. Both UI and functionality code evolve over time, but often UI code evolves at a greater rate. Good UIs are hard to design. They usually require a lot of iterations and user testing. When UI and functionality are intermingled, it raises the risk of improving the user experience of the functionality. When programmers go in to change the look and feel, say, they can end up creating bugs in the intermingled functionality code.
On the other hand, the question Bob posed was why there needs to be a standard way to do Link
s.
In the absence of a standard Place API, could I as a project manager not move the functionality of the link
activations to the service proxy using my own proprietary interfaces? I could indeed. Nevertheless, I feel a standard API is
justified because of:
Place
services directly.
One of the opportunities I try to sieze in the Place API is raising the level of abstraction
of the URL. Whereas a URL is data, a Link
is an object, a bundle of behavior. I can send you
a URL across the network, but to use that URL you need to understand the protocol. In addition, I need
to know the host and port name where a server is running. You have to be able to get to that server.
I can only specify one server and port, and the I must be able to express any other information about
how to retrieve the resource in the filename portion of the URL. If I send you a Link
across
the network, by contrast, all you need to know is that by invoking its activate
method, the Link
will retrieve the service for you. The responsibility for knowing how to retrieve the service belongs
to the Link
object itself, not the client that receives the Link
object.
I claim that this "raises the level of abstraction" of the URL because the contract between
a Link
recipient and the Link
provider is more abstract than the contract
between a URL recipient and a URL provider. In the case of URLs, the contract involves the bits and
bytes of protocols, assumes the provider knows a host and port number, assumes there is only one host
and port number, and assumes that any other information can be embodied in the filename portion. In
the case of Link
s, the contract involves abstract behavior-oriented semantics of the
activate
method, which says simply, "Retrieve this service."
The more abstract contract of Link
makes it much easier to send innovative and new kinds
of links across the network, including many kinds of things I can imagine doing with Jini lookup
services. A Link
could, for example, do discovery, perform lookups by type and attributes,
and sort through multiple matches of those lookups using an algorithm that was sent across the network
as part of the Link
object's class. That would be hard indeed to express in a URL.
One difficulty with giving the Link
object responsibility for retrieving a service,
however, is that in practice the Link
can't do anything it wants to retrieve the service.
The Link
can only do things allowed by the client side security policy. Because of this,
I believe we need some standard implementations of the Link
interface sitting on the client
already, implementations which are trusted by the client. (In the current incarnation of the Place API,
three such trusted implementations exist: UnicastDiscoveryLink
, MulticastDiscoveryLink
,
and URLLink
, all of which are declared final
.) In addition, we need a standard way
to ask the client to present a service. This
shows up in the Place API as the ServicePresenter
interface. When the user indicates to a Place
service UI
that a Link
should be activated, the service UI would in general delegate that job to the
ServicePresenter
by invoking its presentService
method, passing in the Link
object to be activated. The presentService
method would ultimately activate the Link
by invoking
the Link
's activate method. But if the Link
is an instance of any of the trusted
Link
implementations, the presentService
would wrap the Link
activation
in a doPrivileged
invocation, so that stack inspection stops before reaching the potentially
untrusted code of the service UI initiating the activation. If the Link
object is not an
instance of any trusted implementation, the presentService
method just invokes activate
and the Link
will only be allowed to do things permitted by normal stack inspection.
Another aspect of security that I've put into the presentService
method is that it returns
void
. A service UI that invokes presentService
not only doesn't get back
the resulting ServiceItem
, it can't find out if the activation succeeded or not. The user,
however, will know. The ServicePresenter
, if the activation is successful, will present
the service to the user, likely via a service UI. If the activation fails or is aborted by the user,
the ServicePresenter
can indicate that status to the user. The user knows the results and
gets the service, but untrusted service UI code that initially invoked presentService
does not.
In short, the realities of client side security policies call for a standard client-side API that enables
untrusted code to ask the client to present a service to the user. This shows up in the Place API (which in
my world-view will be installed at the client on top of the J2SE, Jini, and Service UI APIs) as the
ServicePresenter
's presentService
method, which takes one parameter, a
Link
. Thus a standard Link
interface is needed, as well as a handful of
useful trusted implementations of Link
, such as UnicastDiscoveryLink
,
MulticastDiscoveryLink
, and URLLink
.
Link
and present the resulting service
to the user. First of all, the Service UI architecture requires that UI providers describe their UIs,
clients decide which UI to use. Thus, only the client
knows how to determine which UI is most appropriate. Network mobile code for a Place
service would
not be able to select a UI from a list of UIDescriptor
s without the client's help. So at a minimum a
service or service UI, were it
to successfully activate a Link
itself and receive a ServiceItem
, would need some way
to ask the client to select an appropriate UI among all the UIDescriptor
s appearing in that
ServiceItem
.
At one point during the review, I was asked why the client couldn't pass in some data indicating what kind of UI it wanted. This approach was discussed during the course of the service UI project. It was rejected in favor of letting the client decide, primarily because we felt it was easier for a UI provider to provide information describing what a particular UI is than it would be for a client to provide information describing what kind of UI they want. Imagine you sit down at a restaurant, and instead of a menu the waiter brings you a long form to fill out. On the form you indicate what kinds of food you like and don't like, what things you are allergic too, and so on. The waiter then takes the form back to the kitchen and the cook decides for you what kind of meal you want. I would expect that kind of system to produce fewer happy customers than the traditional approach where the waiter brings menu of meal descriptions, and the customer who must ultimately eat the meal sorts through the descriptions and makes the decision. But what's really the crux of the problem with the fill-in-a-form approach is figuring out what questions to ask on the form. I think it's easier to describe actual meal choices than it is to describe customer preferences for meals. The best kind of "data," therefore, with which a client can express its UI preferences are bytecodes that sort through descriptions of actual available UIs.
Another problem, aside from the need for clients to select the most appropriate UI, involves the desire by
client providers to give their users a uniform experience of network-delivered services.
A "UI selector" method in a standard API could conceivably enable a service UI to pass in an array
of UIDescriptor
s. The implementation of that UI selector method (the client) could sort
through those UIDescriptor
s, select one, and return that selection to the service UI.
(Actually, now that I think of it, we may want to add such a method to ServicePresenter
.)
The trouble is that unless the service UI is going to embed the selected UI in itself, it doesn't really
know what to do with that UI. For example, in the Montage browser, a UI either pops up into its own frame,
or appears kind of like a web page in an existing browser frame. An arbitrary service UI can't really know
how a client presents UIs to the user -- only the client itself knows. By enabling the service UI to delegate
the job of presenting a service UI to the user, the client is able to provide the user with a more seamless
experience. For example, Montage is able to overlay service UIs in the same browser window, or pop them
up into their own frame, depending upon the kinds of UIDescriptor
s found in the ServiceItem
.
A standard API that defines a standard way to ask the client to present a service is required to
enable clients to give their users such a seamless experience of using network-delivered services.
The third justification for having a standard Place API is that it enables code to interact with Place
service functionality directly. Three kinds of code I can imagine using Place
services directly
are client UIs, third party service UIs, and software agents.
When I mentioned client UIs, I was challenged to come up with some compelling examples of
client UIs for Place
services. Bob Scheifler commented that
a Place
service is basically an unordered collection of
Link
s. "Most web pages aren't just unordered collections of links," he said. The point was
that a web page that provided solely an unordered collection of links probably wouldn't be very useful,
and neither would a client UI of a Place
service.
Jim Waldo also wanted to pin me down on whether I wanted Place
services to be used by
client UIs or service UIs, but I was slippery. "Both," I said. Jim pointed out that this issue really
goes back to the old question of who gets to decide how to present network-delivered content. In the early
days of the web, the thinking was that the client would decide how to present the content, but the content
providers complained. Content providers wanted to control presentation, saying that "the presentation of
the content is part of the content."
Unfortunately, when I was put on the spot in the design review, I couldn't think of many examples of
client UIs. Since then,
however, I have thought of several. For example, one kind of browser I have wanted to
eventually build has a tree view on the left and a service UI on the right.
The tree view on the left provides a hierarchical
view of the "objects" and "places" the user has navigated through, starting with his "first place," much as the tree
view in Windows Explorer provides a hierarchical view of files and directories.
The tree view provides an easy to navigate history of places and objects the user has visited, plus a way to hop to new
places. At any time, only one link can be selected in the tree view. When a link is selected, the link is activated
and the resulting service UI is displayed in the right hand window.
Although the right hand window would display service UIs, the tree view to the left is in effect a client
UI of the Place
services the user has visited.
Another potential use for a client UI of Place
services is a "Save Object" dialog box, which lets
users navigate their own hierarchy of modifiable places, searching for just the right place to put a Link
to a particular object. This example points out that although a Place
service does provide an
unordered collection of Link
s, that doesn't mean a Place
service
won't have a more orderly presentation by
the time the user sees it. A Save Object dialog box could, for example, arrange the Link
s in alphabetical
order. A Lifestreams style client UI could arrange Link
s by order of last-modified date. And in addition
to order or other presentation context layered on by UI objects, subtypes of the existing collection types in the API
could yield up order at the API level.
Another possible client UI is a speech-enabled UI for the dashboard of your car that could read
out a list of Link
s at a Place
and let you activate one by voice command. Peter Korn (Sun
accessibility team) would
say that when you drive your car you have a "situational disability" in that you can't use your eyes or hands
to operate a software service. Many people, of course, live with such disabilities all the time. Client UIs
could be used to grant people with disabilities, be they situational or permanent, access to Place
services.
Besides client UIs, another way that the Place API could be used is by third-party UIs
registered with UIDescriptor
s in existing services. If service providers all use non-standard
APIs for Link
functionality, life is more difficult for developers wishing to create third
party UIs. Given a standard Place API, third party UI developers can developer their UIs to that one
standard. Such third-party UIs could address accessibility needs, or simply user preferences. If a user
likes ZoomWorlds, for example, she could purchase a ZoomWorlds service UI and register its UIDescriptor
in her Place
services. (ZoomWorlds, a UI metaphor described by Jef Raskin in his book The Humane
Interface, positions services at the same X and Y location on a two-dimensional surface on which users
can move around, and zoom in and out, to locate desired services.)
Lastly, a standard Place API enables Place
services to be used directly by software agents
in the absence of a user. The example I offered here was search engine spiders following Link
s
and collecting information about the resulting service. Bob Scheifler asked me, "Are search engine spiders
the only way you can imagine software directly using a Place
service?" The general feeling seemed to be
that spiders were not a compelling example, because one could imagine a spider collecting information about services
using other mechanisms, such as by traversing a federation of lookup services.
Or one could imagine better ways to solve the search problem in general, such
as a publish and subscribe scheme. I myself am interested in exploring more spontaneous search approaches such
as that used by GNUtella, and my interested is piqued by the suggestion of a publish/subscribe approach.
Nevertheless, I would claim that enabling search agents to follow links is useful, because it is how people
find things today on the web, and I want people to be able to find Jini services that way too.
I did ultimately admit to Jim Waldo that I expected that most of the time, people would use service UIs
for Place
services, so I fall more on the side of "letting the content provider control the presentation." But I insisted that
I still think it's important that people can use client UIs if they want.
By defining a Place
API standard, both client UIs and (primary or third-party) service UIs are possible,
as well as direct use by software agents such as search engine spiders. One last point I would make is that
technologies are always used in ways their designers never imagine. If we define a standard Place API, people
will use it in ways they find
valuable, but which we never imagined or expected.
Link
activation a UI instead of a ServiceItem
?
One of the fundamental questions that Bob Scheifler asked was "Why not just have long term relationship to a UI?"
The Link
interface has
just one method in it, activate
. The activate
method is reponsible for retrieving
a service. The client that invokes activate
must pass in an ActivationClient
through which the Link
, if the activation is successful, sends the client a ServiceItem
.
This question basically asks why the result of a Link
activation is a service UI
rather than a ServiceItem
.
I can think of three justifications that Link
activation results in a ServiceItem
:
Link
code doesn't know which UIDescriptor
to pick, though as described
previously this could be solved by having a standard method Link
code could call to ask the
client to pick a best-fit service UI.
ServiceItem
opens up the possibility that software agents can activate
Link
s and either use the service proxy directly, collect information about the service,
or present the service to a user via a client UI.
I elaborated on all three reasons in the previous answer.
I addressed this question in my first answer. In short:
Most often, I expect people to use service UIs for Place
services, but I expect that sometimes
they will want to use client UIs.
link
just be used by a UI?
I answered this question in my first answer as well, but I wanted to add one more point. A service UI
could activate a Link
itself. (I.e., not delegate the activation to the ServicePresenter
.)
If the security manager allows it, the service UI would receive a ServiceItem
. The service UI
could then potentially select a UI that matches its own selection criteria, and then embed that UI inside of itself.
This possibility is why I realized that perhaps it would be good to have a method in ServicePresenter
that selects a best-fit UIDescriptor
from a passed array. Such a method could help the service
UI decide which UI to embed inside itself.
LinkItem
?This was a good question. I believe Jim Waldo said the existence of localizable info in the Place API gave him a funny feeling, and frankly it does me too. One of the first decisions we made in the service UI project is that UI should not be mixed in with the service proxy, UI should be a separate object. And here we are putting localizable information in a service API. So why is it there?
The reason is that I can imagine many situations in which it is useful to have localizable information
associated with the Link
itself. First of all, this kind of information would likely be used by many
service UIs, so one might be inclined to to factor this information out into the proxy used by those UIs.
If a user changes the name associated with a Link
in her home Place
, that new name
will appear in all UIs with which she accesses her home place from then on.
In addition, client UIs would want some basic information about the service to present the service to
the user. This information could be retrieved by following the Link
and getting it out of the
ServiceItem
(i.e., from a LinkEntry
), but that would require a lot more network traffic and
user wait time. One way to think about the localizable information, therefore, is that
it is a client-side cache of a certain amount of information about the linked-to service.
One other reason for including localizable information with a Link
is that I want users
to be able to move Link
s from one Place
service to other (modifiable)
Place
services.
If Swing service UIs are representing Place
, then a drag and drop approach could be used.
But because we can't assume that UIs will always be Swing, we can't assume that drag and drop will always
be available. Thus, I think
the ability to move Link
s from one Place
to another needs to be possible at
the Place API level, so that it can be supported irrespective of the UI type. When a Link
moves, some amount of localizable information about that Link
should move too.
Bob Scheifler posed this question, and frankly the answer is, "I don't know." I believe people will want to access their services from many different geographic locations and that likely they'll want to access them from an assortment of different devices. It is an assumption that underlies this whole effort, but it is a guess.
One other relevant experience I had while in the bean bag room was seeing a Sun Ray for the first time, a kind of network appliance that you can plug your card into and get your "session" as you last left it. Perhaps what people really want to go to initially is their current session, not their first place. I want to think about that.
Jim Waldo questioned our dropping of referential integrity, which the Jini team worked very hard to get,
by defining Link
s that could be broken. One answer I had to this question is that referential
integrity is most important for spontaneous networking. If I'm looking for a printer, I only want to know
about printers that aren't on fire. But if I'm looking for my email service, a service with which I have
a long term relationship, I don't want any old email service. If my email service has moved and didn't tell
me, and my Link
to it doesn't work anymore, I don't want a different email service. I want
my Link
to not work, which would tell me that I need to go find out where it went.
But on the other hand what I really want is a self-healing network of Link
s. That when my email
service moved, that my Link
to it was automatically updated. There is nothing in
the API currently to address this, but one could imagine some approaches. For example, there could be an interface
optionally implemented by Link
s that enables a Place
server to register as interested
in being notified when a Link
needs to be updated. Or, a Place
server could occasionally
poll, follow the Link
s to make sure they are still valid. Or, a Place
service proxy could
implement an interface that allows it to be notified when a Link
activation results in a
redirect. We probably need to define a kind of "redirect," in which a replacement Link
can be
sent in lieu of the actual service.
I want to again thank the Jini team for making time to discuss the Place API.
It had been about one year since I first spent time in the bean
bag room during the Service UI design review.
It was great to see everyone in Burlington again.
The visit was very stimulating and productive.
I was asked a lot of hard questions which made me think and gave me
ideas for further exploration. If this document has stimulated ideas or questions in your mind, please
post them to the cyberspace@jini.org
mailing list.
Sponsored Links
|