May 20, 2005

Jini, Indigo and the "Highlander Fallacy"

In Craig McMurty's blog entry that stirred up discussion of Indigo and Jini, he mentions a piece by Don Box, in which "the four fundamental tenets" of service-oriented development are laid down. Craig further asserted that 'The "services" that one can construct with Jini do not conform to any of those four tenets'. Really? Well, given how badly Craig seems to have misunderstood Jini, I decided to go back to the source and see what the good Mr. Box has to say for himself.

So what exactly are Don's four fundamental tenets?

  1. Boundaries are explicit

  2. Services are autonomous

  3. Services share schema and contract, not class

  4. Service compatibility is determined based on policy

Plausible? Well, the first two are unexceptional, and describe Jini services quite nicely. I suspect the devil may be in the details. The third seems unduly coupled to a particular technology and language; if we replace "schema" with "interface" and "class" with "implementation", it feels OK - and describes Jini very well. And the fourth? I have no idea what it means, but on the surface it seems to conflict with the second (autonomy) and to overlap with the third. Perhaps we can resolve these conflicts later on. Let's dig into each of these ideas.

  1. Boundaries are explicit: Back in the early days of distributed computing, it was considered a good idea to hide the boundaries, to make remote resources look just like local ones. This is what gave us remote file systems and early RPC schemes; in extremis it gave us things like Locus. Over time the wisdom of folks like Peter Deutch and Jim Waldo cured us of this. These days we all believe in explicit boundaries.

    Box, however, introduces what seems to me like a non-sequitur: "Because each cross-boundary communication is potentially costly, service-orientation is based on a model of explicit message passing rather than implicit method invocation." Now this is bizarre. He's saying that because an interaction may be expensive, we have to describe it explicitly at the lowest level. Even if one is performing a higher-level pattern, such as a method invocation, one is required to unpack it by describing the individual message patterns and how they are correlated. While sometimes this may be appropriate, it hardly seems fundamental. For a start, it conflicts with the notion of autonomy. Why should a client and service, mutually consenting adults, be required to describe their interaction in such detail in advance? Why could they not negotiate a mechanism on the fly, using available resources?

    Box goes on to say, "the fact that a given interaction may be implemented as a method call is a private implementation detail that is not visible outside the service boundary". But this is disingenuous. How detailed, how explicit is the message description? Either we give up on type (or schema) based notions of compatibility, or every interface requires a detailed description of request and response messages which will make the "private implementation detail" instantly public (and will significantly constrains the ways client and service can interact).

    A final thought on boundaries: while they may be explicit, they are not necessarily static. Refactoring is a fact of life. In practice this means that software components will be constructed in such a way that potential boundaries are declared as such (using, for instance, the remote interface in Java), and services will be assembled and composed in terms of such interfaces. Describing a service in terms of a low-level message exchange pattern then becomes one technique among many for defining service boundaries, and one that is generally effected by a design tool of some kind. It's an implementation artefact, not a design principle.

  2. Services are autonomous: Box's account of service autonomy is excellent. He discusses version skew, the dynamic nature of the aggregations that comprise a system, the effects of unintended usage, partial failure, and security. (He could also have said something about dynamic discovery, self-healing, the use of patterns such as broker and facade, and the use of techniques such as introspection to perform dynamic adaptation.) There is nothing here that a Jini enthusiast would disagree with.

  3. Services share schema and contract, not class: Earlier I wondered if this referred simply to a separation between interface and implementation. This understates Box's position. He writes, "services interact based solely on schemas (for structures) and contracts (for behaviors). Every service advertises a contract that describes the structure of messages it can send and/or receive as well as some degree of ordering constraints over those messages." And he also says that "the contract and schema used in service-oriented designs tend to have more flexibility than traditional object-oriented interfaces. It is common for services to use features such as XML element wildcards (like xsd:any) and optional SOAP header blocks to evolve a service in ways that do not break already deployed code". So what we are dealing with here are relatively simple interfaces, evolving slowly, with weak consistency and ad hoc extensions.

    Now there are plenty of situations where this kind of approach is just fine. As Box notes earlier, it's the kind of thing that made Amazon.com's services the success that they are today. But for other applications, this kind of thing is hopelessly inefficient or inflexible. For the vast majority of intranet services, for instance, the most common way to invoke a service isn't going to be by parsing its description and constructing a new client stub ab initio: it's going to be by invoking a copy of the stub code generated when the service was created. And if you're going to do that, why not take advantage of it - not just at compile time, but dynamically, so that the interactions with the service can reflect the characteristics of the deployed service? As for the suggestion that one needs more flexibility than "traditional object-oriented interfaces", mechanisms like introspection allow for powerful and robust run-time flexibility, without sacrificing type safety.

    It seems to me that the fundamental principle involved here is the one I alluded to earlier: establishing a clear separation between interface and implementation. How we do that seems to depend on the application and context; there is no reason to believe that one size fits all.

  4. Service compatibility is determined based on policy: It turns out that what Box is talking about here is the distinction between structural compatibility and semantic compatibility. The latter is familiar and unremarkable: XML schemas, class signatures, on-the-wire encodings, that kind of thing. But what Box is interested in is "[s]emantic compatibility... based on explicit statements of capabilities and requirements in the form of policy". He gives a few hints about what he's thinking of, but at this stage I think it's safe to say that he raises more questions than answers. Suffice it to say that this whole area is in its infancy, and it's not an immediately important issue. By the time we figure out exactly how to express such things (OWL-S?), how and when services get to " apply simple propositional logic to determine service compatibility", and exactly what customers want to use this for, our initial expectations are likely to change significantly. There's certainly nothing here that is incompatible with Jini.

So what's the verdict? Was Craig correct to claim that Jini doesn't conform to Box's "tenets"? Unambiguously not: Jini absolutely conforms to every aspect of Box's "autonomy" tenet. How about the others? Well, it all depends on whether you read the interface or the implementation: whether you concentrate on the broad principle, or how Box chooses to implement it. Jini is entirely compatible with the broad principles, but not surprisingly it's not going to conform to Box's Procrustean Bed of message-based service patterns. But why should it? Box gives us no reason to believe that this technology is the only way to realize the principles. It's just the way Microsoft chose.

I've already discussed why Microsoft took this path, but it's important to recognize that it's not the only - or even the best - approach. There are more powerful, elegant, and efficient models for realizing the principles of service-oriented distributed computing, and Java and Jini represent such a model. For Box and McMurty to argue that only one technology fulfills these principles is self-serving, not to mention ahistorical. The wide range of problems to be solved, the variety of contexts in which the solutions must operate, and the kinds of constraints and requirements that must be met, are such that multiple technologies will clearly be needed. As Jim Waldo pointed out, the "Highlander Principle" ("there can be 'only one'") is a fallacy.


Posted by geoff2 at 06:02 PM | Comments (2)

April 26, 2005

Thread convergence: Formula 1 and Jini

Regular readers will have noted that two of my greatest enthusiasms are for Formula 1 motor racing and Sun's Jini™ distributed computing technology. So one item in today's quarterly "customer wins" press release from Sun is particularly sweet:

"Magneti Marelli Holding (Italy) -- Sun designed, for Magneti Marelli Racing Department, a new system to manage telemetry data for Formula 1 teams in real time, using Java and Jini(TM)/Rio technology with the aim of achieving the required performance, to support multiple platforms, such as Linux and Windows, and to provide high availability and location transparency of components."

I don't think I'm supposed to identify individual teams, but every time you see a car with this logo, think Jini. MM logo

Posted by geoff2 at 09:03 AM | Comments (0)

March 25, 2005

Tim, Rio, Jini, Rob

Over in ongoing · Java, the Grid, and Rio, Tim was "thinking about how you’d run a big distributed Java system as a service across a whole lot of networked computers". Dan Templeton pointed him at Rio, and I followed up with a link to the papers from last December's Jini Community Meeting in London. And I remembered a comment by Rob Gingell, adapting Santayana: "Those who do not use Jini are doomed to reinvent it."

Posted by geoff2 at 12:27 PM | Comments (0)

January 11, 2005

More Java cores than you know what to do with

After publishing a skeptical and rather petulant piece about Azul last October, El Reg decided to give Azul's CMO, Shahin Khan, his own soapbox this week. He certainly waxed lyrical "If you could count CPUs the same way that you count memory, some problems would simply become uninteresting and others would transform in a qualitative way. And completely new possibilities would emerge. [...] No need to plan capacity for each individual application. Let all of your users share a huge compute pool and plan capacity across many applications."

Well, maybe. Remember that Azul is planning to ship up to 1,200 cores in a single rack, but these core will be specialized Java™ engines. Now I'd love to see Java take over the world and remove the need for any other kind of operating environment, but for the next few years, while we're waiting for this brave new world, systems like Azul's are going to have to coexist with mundane Solaris and Linux boxes. In other words, it's a co-processor, an "applications accelerator". And ever since the days of "intelligent Ethernet cards" (anyone remember the 3C505?) I've observed that such co-processors are doomed to be overtaken by general-purpose processors. The only obvious exception is in the area of graphics. Not only are the specialized processors not that much faster than their general-purpose brethren; the cost and complexity of the software needed to manage the co-processor usually eats up all of the savings. In the case of the 3C505, I remember that the host driver to manage the on-board TCP/IP stack was roughly as complex as a TCP/IP stack!

Don't get me wrong - I think that multiple core are absolutely the way to go. Various companies - Sun, IBM, even Intel - are realizing that the best way forward is to simplify their pipelines to reduce the size and complexity of their cores so that they can stuff more cores on a chip. Designing around Java byte-codes rather than RISC ops doesn't save all that much.

Will Azul prove me wrong? I'm not holding my breath....

Posted by geoff2 at 04:27 PM | Comments (0)