Let's talk about exceptions ...
How do you handle exceptions? Do you think upfront about the type of exceptions that you want to catch or do you just let the outside world handle it?

-- Jeroen van Bergen in JW Blogs

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

Objects versus documents for server-client interaction, Part 2

Determining the best approach when there is no client-side user

In Part 1 of this series, I demonstrated two approaches to defining the interaction between a client and a newsfeed server: using documents and protocols and using objects and interfaces. Now I'd like to compare their relative merits. I'll discuss the advantages of objects as compared to documents, then the disadvantages.

TEXTBOX: TEXTBOX_HEAD: Using objects versus documents for server-client interaction: Read the whole series!

The advantages of objects

In the following sections, I will identify a few advantages of using objects for client-server interaction.

Raising the level of abstraction

One obvious difference between the object and document approaches is that developing newsfeed protocols involves network handshake and data-model design, whereas developing the newsfeed API requires object-oriented design. The object approach enables client and server programmers to work at a higher level of abstraction. To explain, I'll relate a story about Bjarne Stroustrup, creator of C++.

I first learned C++ in early 1992 from Borland's World of C++ videotape, which includes a short introduction by Stroustrup. He begins by saying the main goal of C++ was to raise the level of abstraction in programming. As I watched the tape, I was able to grasp the object-oriented concepts and C++ syntax, but I was puzzled by Stroustrup's comment. I was unsure of what he meant by "raising the level of abstraction" and why he found it desirable.

In April 1999, I attended a small C++/Java conference in Oxford, England, at which Stroustrup gave a keynote. In the speech, he cited two ideals for programming: keep independent things independent, and work at the highest level of abstraction you can afford.

Afterwards, I asked Stroustrup why working at the highest possible level of abstraction was a fundamental programming ideal. He said it allows details to be hidden, which makes code shorter. "The more details, the more mistakes," he said. Code size also impacts maintainability: the more code you have, the more difficult it is to maintain. Stroustrup also said that at higher levels of abstraction, code is more amenable to tools that analyze and optimize. He summed up by saying that code written at a higher level of abstraction is easier to understand, write, and maintain.

I believe the object approach is bolstered by the programming benefits, outlined above by Stroustrup, of working at a higher level of abstraction. To a great extent, programmers who switch from procedural to object-oriented programming reap the same benefits. When you write a client program that interacts with a server via an object sent across the network, the advantage of using object-oriented programming in your distributed system is obvious.

Protocols become implementation

Object-oriented programming cleanly separates interface and implementation. One of the main strengths of Jini's architecture is that communication between a Jini service object and a server is part of that object's implementation. Although a client and server must agree on a network protocol in order to send the first object from server to client, client/server communication can take place via object interfaces once the first object is in place.

Unlike an object, a document cannot make a socket connection back across the network. Thus, for clients to interact with documents received from a server, the client and server must agree on the document's data model as well as a protocol. For example, if a user fills out a form contained in an HTML document and presses Submit, the Web browser opens a socket to the Web server and most likely issues an HTTP POST command containing that information. The Web server processes this POST and returns another HTML document. If a client program wishes to interact with the server via documents instead of just silently consuming documents, the client and server must agree on protocols beyond the initial protocol that gets the document to the client.

Once a Jini service object has been downloaded into a client, the client and server need only agree on that object's interface. The network protocol, which is part of the service object's implementation, can vary by service vendor and change over time. (Because the service object is sent across the network from the service provider to the client, it will always be up to date, be compatible with the service provider, and speak the correct network protocol.) The network is one of the fussiest and most dynamic parts of the hardware being programmed, so having the ability to choose the most appropriate protocol for each situation is important.

Evolving the contract

Another basic difference between the object and document approaches is the nature of the client/server contract. For network-mobile documents, the protocol (including the data models of any documents) forms the contract. For network-mobile objects, the object's interface forms the contract. One important advantage of objects is the ease of changing their contracts over time.

Coming up with a good design, whether for an API or a DTD, is difficult. Figuring out, agreeing upon, and communicating the design requirements is often a significant challenge. So is determining the best way to model the functionality (for an API) or information (for a DTD) that the requirements demand. And then there is perhaps the most daunting task of all: predicting the future.

Requirements evolve over time. Consequently, a design's ability to gracefully accommodate future changes is usually an important quality. But how do you achieve this when you don't know what changes will occur? Mark Johnson, JavaWorld's XML columnist, discussed the difficulty of anticipating evolution in XML DTD designs:

It's difficult to get a DTD right because it's difficult to get a data model right, and a DTD is a data model. The hardest thing about getting a data model right is that data models evolve. There's "right" for today, and "right" for tomorrow. But you don't know what's "right" for tomorrow up front, so you have to guess. Data modeling is, in part, the art of including enough generality to anticipate future schema changes without kicking the model up to such a high level of abstraction that it's inefficient or incomprehensible.


Fortunately for API designers, Java pays close attention to the need to improve contracts. The seldom-read "Chapter 13: Binary Compatibility" of the Java Language Specification describes how a Java class or interface can change without breaking binary compatibility with client code compiled by an earlier version. Similarly, the Java Object Serialization specification provides mechanisms that enable the exchange of serialized objects between parties familiar with different versions of the objects' classes. Java's support for versioning of classes, interfaces, and objects helps to evolve requirements over time. XML, by contrast, does not offer much help with evolving requirements. On the topic of evolving DTDs, Rusty Harold, author of XML: Extensible Markup Language and creator of Cafe con Leche, an XML developer Website, (see Resources for a link) said:

XML does not provide any explicit versioning support. You have to do it all yourself. However, [if you write a DTD in 2000 that validates year 2000 tax return XML documents,] it is fairly easy to write a new DTD in 2001 that will validate both 2000 tax returns and 2001 tax returns. Writing that DTD in 2000 or 1999 is a little harder.


Data-model designers typically allow for change by specifying in the initial data model some abstraction that can be ignored if not recognized. For example, the Java class-file format (a data model for defining Java types) includes a data entity called an attribute. Each attribute's name indicates its structure and semantics. The original Java Virtual Machine (JVM) specification defined the structure and meaning of several named attributes, and identified attributes that JVMs are required to recognize and use. The specification also stated that:

  • The use of any other attributes is optional
  • Any party can define new attributes, as long as those attributes don't affect the semantics of the class or interface described by the class file
  • New attributes defined by anyone other than Sun must be named via a reverse domain name convention to prevent name conflicts
  • JVM implementations must silently ignore attributes they don't recognize


The attribute abstraction of the Java class-file format enables the class-file data model to evolve in such a manner that class files containing new attributes can remain backward compatible with old virtual-machine implementations that don't recognize the new attributes. Designers of an XML DTD or other data model can incorporate a similar abstraction to accommodate future changes in requirements.

Dealing with evolving requirements can be challenging when working on a monolithic application, and even more so on a distributed system. In a monolithic application, you can adopt a new contract that is incompatible with the old and update the old contract to understand the new one. For example, in a monolithic Java application, you can break an interface's contract by changing the name of a method in that interface. If you recompile the entire application, however, the compiler will find all the code broken by your change. If you update those areas of the code to use the new method name, your application will compile.

Resources