Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples

Head First EJB

How to Talk About Jini, J2EE, and Web Services at a Cocktail Party

by Kathy Sierra and Bert Bates, authors of Head First Java, 2nd Edition

Editor's note: Kathy Sierra and Bert Bates, the brains behind O'Reilly's Head First series, first wrote this article in 2003 at the time of the release of Head First Java. It was hugely popular and we are still receiving requests for more like it, so much so that we decided to bring it back again now that Head First Java, 2nd Edition has released. So, if you didn't catch this piece the first time around, let Kathy and Bert show you how to hold your own in conversation with Java geeks.

It's all so predictable. There you are at a dinner party, sipping a second martini, when the conversation turns, inevitably, to distributed programming. What to do? Relax, because here we'll tackle three of the most interesting distributed technologies, complete with all the napkin-ready drawings you can use to up your whuffie. (Don't know about whuffie either? Read Richard Koman's interview with Cory Doctorow.)

But first, in case you're actually at a party right now, we'll start with a few quick phrases that you can use even if you don't know Java. After that, for those who do know some Java, we'll dig a little deeper.

"What's dynamic discovery? It just means that clients and services find each other, you know, dynamically, over the network, without any prior knowledge of one another. It's all based on IP multicast."

"What's an automatic self-healing network? It means the Jini network is always reflecting the current status of all the available services -- like, 'OK, this one's up and this one's not ...' without any human administration!"

Related Reading

Head First Java
By Kathy Sierra, Bert Bates

"Of course, most routers have IP multicast disabled, so you aren't going to use Jini on the web. But Jini was designed to work for local networks, or collections of local networks, so that's not so much of a problem."

"The cool things about J2EE are vendor-independence and that you get to focus on your business logic and leave all the big plumbing/heavy lifting to the server vendor. You work on the rules for your particular business, and leave the security, transactions, concurrency, persistence, and even the networking code implementations up to the server. And you have to learn only one API, and you can redeploy your J2EE apps to any vendor's J2EE-compliant server, so now the vendors have to kiss up to you instead of the way it used to be, where you were locked in and had to beg the vendor to add some new capability or fix bugs ..."

"The cool thing about Web services is ... well, OK, so maybe in its current state there isn't anything really cool about Web services. But that could change. Sometime in the future. When all the standards are worked out, and the tools mature, and ..."

"But if Web services were cool, it would be because you can take the business apps you already have, even legacy apps, and expose them on the Web using XML as the interface. A client sends an XML message (in a format called, cutely, SOAP) to a service in an interoperable way."

"Security and transactions are the two glaring holes in Web services right now, which means everybody has to roll their own solutions. There's no big ol' transaction manager sitting out there on the Web, and the only security you've got is HTTPS for mutual authentication.

"Jini and J2EE are both Java technologies. With J2EE, it's like the spec is saying, 'Oh, don't you worry your little developer head about all these big, hard, things. The vendor will take care of all those messy things so you can pay attention to your own domain-specific needs (like, how to sell more lingerie).' But with Jini, it's like the spec is saying, 'You are so out there on your own with this. Don't expect anybody to come to your rescue with a bunch of big infrastructure. This is lean and mean, baby, but you can do the most amazing and elegant things. And check out JavaSpaces while you're here.'"

"Web services is not a Java-specific technology, but Java can sure make it a gazillion times easier to do, especially if you switch to J2EE 1.4. No, you're right, J2EE 1.4 isn't out yet, but it will be before the end of the year. You'll probably see some solid vendor support in early 2004."

(Before we go further, some disclaimers: First, if you have any problem with the high-level nature of this article, re-read the title. We're taking huge bartender license with the content. We won't tell you anything that's not true, but you aren't getting the whole story, either. Each of these topics requires a book of its own. (And darned if we're not just about to come out with one, Head First EJB. What are the odds?) Let's just say the cocktail view of a topic probably isn't what you want driving your next architecture. (We know you know this, but for that one disturbed person who will somehow mistake this for a Serious Technical White Paper, we felt compelled to cover our a**es).)

So now it's time to dive down a level. We'll start with a look at what it means to have a service, and, most importantly, how you expose yourself to others. In other words, how you tell potential clients about your service.

With Jini, J2EE, and Web services, the goal is for a client to access a service. What's a service? Pretty much anything you can do as the result of a message sent from one piece of software to another (which may or may not involve human direction). You might have a service that does huge calculations for genetic matching. Or a service that plays a mean game of Go. Or a service that lets you buy concert tickets. Or books an exotic tropical cruise. Or even sends your text to a high-volume printer. In other words, a service is anything that starts as software, but the result doesn't necessarily stay in software.

You might have a service that moves a video camera, prints to a printer, dials a phone. Doesn't matter. Or at least it shouldn't matter. One of the main goals, as it always with OO, is have the least amount of coupling — in this case, between the client and server. In other words, we want the players (the clients and services) to know as little about one another as possible.

But let's say you've got a service ... now what? How do clients find you? And if they find you, how do they know what your service can do? In other words, how do they know the methods they can call on your service? Somehow, you have to expose yourself to clients, and it's a little different for each of the three technologies we're looking at. Regardless of whether you've talking Jini, J2EE, or Web services, though, there's always an interface in there somewhere. That interface declares what you can do.

Service Interfaces

As a service developer, you have to tell folks what your service can do. In other words, you have to declare your service's methods. That includes declaring what the client can pass to your methods (the arguments) and what the service will return to the client (the return types).

The interface above is for a service called Advice. It has one method, getAdvice(). You call the method and you get back a String of stunningly useful, randomly chosen advice. (We've chosen to not show the return types in our little fake UML-ish things. It was a really small napkin.)

For Jini and EJB (Enterprise JavaBeans — the heart and soul of J2EE), that interface is usually Remote. A Remote interface means the service developer writes a Java interface that extends java.rmi.Remote. Oh yeah, the Remote methods (meaning all of the methods in the Remote interface) have to declare a java.rmi.RemoteException — a checked exception that says to the client, "Things can go horribly wrong, so be prepared."

For Web services, the interface is defined in a WSDL (pronounced "wizdle," rhymes with "fizdle") — a special type of XML document. So, to summarize, here's another little phrase you can drop in casual conversation:

"In other words, with Jini and EJB you expose yourself with a Java interface, but with Web services, you expose yourself with an XML interface."

(Actually, if you're a Java developer, you create the WSDL by first writing a Java interface, and then pushing a magic red button on your development tool that turns your Java interface into an XML WSDL, but that is, as they say, beyond the scope of cocktail party conversation.)

OK, so now we've got a service, and we have an interface that exposes our service. Now what? How do clients know about the interface? How do they actually get the interface and whatever else they need to talk to your service? That depends on the type of service. And it's different for each of the three types. You'll access Jini, J2EE, and Web services each a little differently, and the rest of this article looks at some of the details and key differences.

First, we'll start with a little background with Java's Remote Method Invocation (RMI). It's the backbone of most of Java's distributed technologies, and Jini and EJB depend on it. In fact, since virtually all distributed technologies work on something that is conceptually like RMI, anything you get here will help make sense of the whole distributed world, Java or non-Java.

With RMI, you write your service and you make it a Remote object. It's a piece of cake to make it Remote — write a Remote interface, then create a Remote class that implements it.

To Make a Remote Interface:

  1. Extend java.rmi.Remote

  2. Declare a java.rmi.RemoteException for each method:

    public interface Advice 
    extends java.rmi.Remote {
       String getAdvice() throws 

To Make a Remote Class:

  1. Implement your Remote interface

  2. Write the actual business logic for the interface methods:

    public class AdviceImplementation implements Advice {
       public String getAdvice() {
       // monumentally important 
        business logic here

(OK, so code is maybe a bit much for a cocktail party, but we're all geeks here ...)

The Key to Everything: The Stub

Once you're got your interface and your class, you run your class through the RMI Compiler (rmic) that ships with J2SE. (If you've got javac, you've got rmic.) That process creates what you'll find in nearly all modern distributed programming models — the stub. The stub is just a helper on the client, which acts like the Remote object (the service) by implementing the Remote interface just as the service does. But really, the stub is just a little object that takes the method call, packages it up, and sends it over the wire to the real one true Remote Object. In other words, the stub knows how to phone home and ask the real service to do the real work.

The stub's methods are fake. Well, they are methods and they do have a lot of code, including all the networking and I/O stuff needed to contact the service. But they aren't the actual business methods. So for the Advice service, the stub has a getAdvice() method, but that method simply passes the client's request to the real AdviceImplementation on the server.

That way, the client gets to pretend that he's making calls on the Remote object, but of course we know that can't really happen, since the Remote object (i.e., the service) is in a different JVM heap.

(Yes, there is also something on the server side that accepts the Socket connection from the client and unpacks the method call, packages and ships the return values, etc., but we're not talking about that in this article. It's a more trivial process, because you don't have to worry about delivering that functionality to the client. So yes, there's a companion to the stub's functionality on the server, but no, you probably won't have to worry about it.)

RMI Basic Architecture

With RMI, the Remote Object Is the Service

RMI Exposure

If you're a client and you want something from a Remote service (in other words, a Remote object), you have to have the Remote service interface (at both compile time and runtime), and you have to get the stub object (runtime). It's the stub, remember, that actually knows how to send your method call to the Remote object (and give you back the return value), so you're dead without it. Chances are, you'll get both the interface and the stub .class file from the service developer.

(There is, however, a much cooler way to get the stub class just in time, without having it prior to runtime, through a process called dynamic code downloading. It's one of the most powerful things you can do in Java, and not very hard, either. But, you can of course always do it the wimpy way and just have the developer email you the stub class file, or carry it down the hall to your cube.)

Finding the Service (i.e., Getting Hold of the Stub So That You Can Call Business Methods on the Service)

In RMI, you look up the stub using the RMI Registry (which ships with J2SE). The RMI Registry is like a little white pages phone book; you look up the name and you get back the stub. Remember, when the stub object comes over, it's serialized. That means it has to be deserialized when it gets to the client, and for that to work, the stub class has to either be on the current classpath, or be findable using dynamic code downloading. That's just basic Java -- an instance can't be deserialized without its class!

Finding the Lookup Service (RMI Registry)

With RMI, you must know where the stub is located. That means you have to know the IP address and TCP port number for the RMI Registry. (Which also happens to be the server where the Remote object/service itself lives.) Actually you probably don't have to know the port number, since there's a default, but if the service deployer changes it, you'll need to know. The client does a simple one-line lookup, using a static method (java.rmi.Naming.lookup()), and then a miracle occurs and it has a freshly deserialized, live, stub. An object that knows how to phone home.

Now that we've looked at RMI, this part'll make more sense. Jini is like extreme RMI. And we use the word extreme here in the sporting sense, not the XP way.

Dynamic Discovery: How Services and Lookup Services Find One Another

This is where plain RMI and Jini differ most. In RMI, the client has to know a lot, and the service has to be explicitly registered (under a logical name) with the RMI Registry, and the registry must be on the same machine with the service!

But with Jini, everything is just... out there. Somewhere. And nobody knows much of anything except interfaces. Here's a quote about it, which we've found especially helpful to drop at strategic moments in a conversation:

"With Jini, services are always trying to discover lookup services, clients are always trying to discover lookup services, and lookup services are always trying to let services and clients know that they (the lookup services) are out there. And it's all automatic!"

The basic Jini architecture uses RMI, although in Jini you can also send the client the whole service itself, rather than having the service be a 100 percent Remote object on the server. When the client asks for a reference to a service, it might get a stub to a Remote object (if the service is implemented as a Remote object), or it might get the whole darn service shipped over, on which it can make plain old local calls. In fact, with Jini, the client might even get a hybrid or "smart-proxy" (drop that phrase at the bar for extra credit) -- that is, a non-Remote Java object that contains a stub to a Remote object (like, in an instance variable). That way, the client makes local calls directly to the service, but the service itself might turn around and make Remote calls to something else. A smart-proxy can help performance on both the client and service by having some of the work done on the client.

Jini Architecture

Another key difference between Jini and all of the others (plain RMI, EJB, and Web services) is that Jini uses distributed leasing to help create a self-healing network. If a Jini service is Remote, for example, it gives the client a "lease" and says, "Here's your lease. If you don't keep renewing it, I'll assume you've gone away and I'll stop using any resources over here on your behalf." How up to date the network stays depends on the length of those leases. For example, a two-hour lease would mean the client could have been gone nearly two hours and you (the service) wouldn't know. What a waste! On the other hand, a one-second lease means a really up-to-date network ... except everybody's spending all of their cycles and bandwidth renewing leases! So there's a tradeoff, and it really depends on the type of service and other quality-of-service issues.

Another cool thing about the self-healing network is that, since even the Jini lookup service is a Jini service, the lookup service gives the Jini service a lease. So in this case, the Jini service is a client to the Jini lookup service. That way, when a normal client (in other words, a client that isn't itself a Jini service, but rather someone who just wants to use a Jini service) comes to look for a service, like a printer, the client won't see a service as "available" if the service hasn't been renewing its lease with the lookup service. Again, the shorter the lease times, the more current the network snapshot, and the less likely it'll be that a client selects a service that's no longer available.

Jini Exposure

If you're a client and you want something from a Jini service, you must have the interface for the service. Unlike RMI, Jini's a lot more flexible, because you don't have to know anything else but the interface. You don't have to know the name it's registered under or the location of the service. As long as you know the interface and you're on a network that can discover a lookup service, you're in business.

Today, chances are that a developer gave you this interface. But there are a few interfaces floating around that have become kind of, sort of, standards, including Bill Venners' infamous ServiceUI.

Finding the Service Class

Unlike RMI, with Jini you don't have a choice about dynamic code downloading. You're pretty much forced to use it. (Well, you can get away without it, but it defeats the main purpose of Jini.) With Jini, you aren't required to know where something is on the network, and you aren't necessarily supposed to know who built the service. Remember, all you have is the interface and in many cases, all you care about it that you get something that implements the service interface (could be a stub, could be the real service, or a combination ...).

Remember, with RMI, the class you need on the client is always the stub class, not the service itself. With Jini, the thing you call methods on might be a stub, if the service is implemented as a Remote object, or it might be the real service — i.e., a class that implements the service interface and actually does the real work, right there locally on the client.

Looking Up the Service

With Jini, you use a Jini lookup service, rather than RMI Registry. A Jini lookup service is a lot more flexible and powerful, and it can give you information as well as service objects, which, again, may or may not be Remote object stubs, depending on whether the service is a Remote object that stays on the server or a non-Remote service that gets shipped to the client. Best of all, you don't have to know where the lookup service is! With RMI, you must know the IP address and port for the Remote service in order to find the RMI Registry where the service's stub lives. But with Jini, you know only that somewhere, there's one or more lookup services sitting out there on the network, reachable through IP multicast.

So that's Jini. But if Jini is the wild frontier, where nobody knows anything and you're really on your own model, J2EE is pretty much the opposite.

The main idea behind J2EE is that the server (via the containers) gives you a bunch of additional services that you might otherwise have to write yourself, or cobble together from different pieces, or purchase from a proprietary vendor. We're talking Big, Huge, Gravel-Hauling Services, like transaction management, concurrency management, security, resource/lifecycle management, lookup services, persistence, messaging services, and more.

That way, you get to focus on your own business rules instead of reinventing such a big frickin' wheel. (Or, as many have discovered, instead of reinventing a flat tire.) Other app servers have been around for quite a while — things like CICS and TUXEDO are the classic examples. But with those, you had to learn a proprietary API, and you were locked in with the vendor. J2EE is a standard for the enterprise business middle tier, so you learn just a single API, regardless of which server you choose. Best of all, you can deploy your app to any vendor's J2EE-compliant server, so you can kiss vendor lock-in goodbye.

Of course, in reality, it's not that easy to redeploy a J2EE app into a different server, for a variety of reasons. But you can. And if you've got the money to dump your current vendor and switch, isn't it nice to know you can? Better yet, isn't it nice to know that the vendor knows you can?

First, a clarification about the difference between J2EE and EJB: J2EE is a specification for a server that must be able to run Enterprise JavaBeans (EJB). But a J2EE server also has to support servlets and JSPs. You can think of J2EE as almost a meta-server — something that binds together a servlet and JSP-capable web server and an EJB server. In J2EE land, we call those sub-servers containers. So you have a web container and an EJB container living within a J2EE server. We'll focus on the EJB side here, since beans are a little more exotic than servlets and JSPs, and in the EJB world, the service is the bean.

One really cool thing about EJB is that it's a component-based development model. You build reusable components that can even be customized at deploy time without touching the Java code. A component is a little more coarse-grained than just a Java class, so it's the next level of reuse. And since your components (i.e., beans) are deployed using an XML document that describes how the server should handle the bean, you can configure things like security, transactions, resource use, etc. all declaratively, in XML, just by pushing a few buttons in a deployment tool. (You can hack the XML directly, if you really really want to, but these days the tools are good enough that you usually don't have to.)

J2EE Architecture

A key difference between J2EE and plain RMI is that the server has to step in between the client's call and the service (i.e., the bean) actually getting the call. If a client makes a remote method call to one of the bean's exposed methods, the server has to jump in and protect the reclusive, pampered bean from direct contact with the client. For example, suppose the client called getAddress() on a bean that represents a specific customer. First, the server has to verify that this client is even authorized to call this method, but assuming the client makes it past the security checkpoint, now the server has to do other things to get the bean ready to handle the call. If the bean returns the customer's address, for example, the bean might need to be freshly loaded up with the database record for this customer. And this might need to be part of a transaction. And another client might already be using this customer. And ... on it goes.

The J2EE solution is to make the bean a non-Remote object, protected by a Remote object. So although the bean really is the service (in other words, it has the business logic functionality for the service methods the client wants to call), the bean itself is not Remote in the RMI way. But the client still interacts with an RMI stub and Remote object; it's just that with EJB, the Remote object is more like the bean's bodyguard. The Remote object (called the EJBObject in J2EE) receives the client's Remote call (i.e., the call the client made on the stub), and then the server gets involved to decide how, when, and even if the call should make it to the bean.

J2EE Exposure

With EJB, there's another layer added to the RMI picture (besides the server). The EJBObject is the Remote object, but unlike with RMI, the EJBObject isn't actually the service. So it's like there are now two helpers for the service, instead of just the one (the stub) for plain RMI. Your service interface is still a Remote interface, but instead of implementing java.rmi.Remote directly, your service interface implements EJBObject — an interface that itself extends java.rmi.Remote. Notice how the bean doesn't extend the service interface (Advice) even though the bean does have the same methods. (Don't be squeamish; most EJB-aware development tools can make sure that the bean and the service interface match.)

Finding the Service Interface

With J2EE, you're probably working within a single enterprise, so you can just email the client developer the interface, or maybe you even publish it in some sort of internal OO repository. Whatever. The point is that, just as with RMI and Jini, the client must have the interface at the client application's compile time.

And once again, for the stub class, you have a choice of giving it to the client in advance, or using dynamic code downloading. But in this case, dynamic code downloading might not be possible, depending on your particular J2EE server, so you might be stuck with having to personally deliver the stub classes to the client. Most J2EE servers prepare a nice little client JAR for you when you deploy a bean.

Finding the Service

Warning: we're exceeding cocktail party knowledge limits in this section, so this is the part where some people say, "Whoa! I was with you just fine until you got here ..." It's not your fault, it's ours. So it's here if you want it, but you could skip right to Web services now and nobody would really know. Still, if you're single and looking, this might be the very part that gets you that phone number ...

This works a lot like RMI, except the lookup service is now JNDI instead of an RMI Registry or a Jini lookup service. JNDI is an interface that sits in front of a range of Naming and Directory services, and it's a requirement for J2EE. The client does a lookup on the bean's logical name, just like with RMI, and gets back a stub.

There's just one little thing we forgot to mention.

With EJB, the client can't directly ask JNDI for the stub to the Remote object (the EJBObject). In other words, the client can't find the stub with the service methods in JNDI. In JNDI, the client can get only the bean's Home. The Home is just a factory for the bean; its main purpose in life is to hand out references to EJBObjects. In other words, the Home gives you the EJBObject stub — the thing you can call service methods on. But the Home is itself a Remote object, so when the client wants to call service methods on a bean, it has to jump through a couple of extra hoops it didn't have with straight RMI.

  1. Do a JNDI lookup on the bean's logical name (whatever the bean deployer called it).

  2. This gets the client a stub to a Remote Home object.

  3. The client calls a Remote method on the Home stub, to ask for a stub to the service itself. OK, well, it can't have a reference to the real service — the bean — but the client can get the next closest thing: a stub to the bean's bodyguard, the EJBObject -- the Remote object that implements the bean's service interface.

(A disclaimer on the whole EJB picture — as of EJB 2.0 (which is part of J2EE 1.3, the current version), not all client interfaces have to be Remote. In other words, the Home and EJBObject objects can be local to the client instead of RMI Remote objects. That means both the client and the bean are running in the same JVM! Doesn't sound too distributed, does it? No, it's not, because you lose one of the most valuable benefits — location independence. If you "co-locate" the client and the bean, you do get some performance gain, since you're eliminating the whole stub-to-Remote object process, but you're giving up the chance to move pieces of your so-called distributed app to other nodes on your network. There is a compelling, even mandatory, reason to use local Home and EJBObjects, but it has to do with persistent Entity beans, so you should consider it only a Very Special Case. For now, anyway. When you're a J2EE designer, you can worry about the subtleties on your own time.)

Now that you've got RMI, Jini, and J2EE all figured out, let's just say that these are the nice, happy, clean, well-lighted, crisp, technologies when compared to Web services. In fact, we won't say much about Web services, because it's all so wild and wooly out there on the Web services frontier. But we'll say enough to get you through one drink.

Java RMI, Jini, J2EE, and EJB are all Java technologies. Web services is not. Web services is about taking your existing apps (although some folks are creating new apps specifically to deploy as Web services, but this is rare), and exposing them on the Web. Most of the time, that means an intranet. It's pretty unlikely today that you'll find Web services just sitting out there on the Web for all the public to access, although Amazon and Google do offer Web services you can play with to add more Googleability and Amazonity to your own site. We'll put those down as Special Cases.

Today, most folks are using Web services for integration among their own business applications. But the ideal vision is that one day there will be tons of Web services happily playing together in a B2B and C2B way (Business-to-Business and Consumer-to-Business), without anyone having a lot of prior knowledge about the other application other than the business domain.

For example, the classic* example is: you're on a multi-city publicity tour for your latest bestseller, "It's Not About the Kilt. " But there's a massive power outage in what was to have been your next stop, and now your whole schedule is toast. So you make a few clicks in a little app on your laptop and it takes care of everything else. It changes and extends air tickets, hotel reservations, and rental cars. Sure, you could have done it by going to all the various web sites and painstakingly making the changes yourself, to each service in turn, but remember, you're in an Internet cafe with dial-up, and you have better things to do.

(* It's just oxymoronic to call anything about Web Services "classic," but there you go. And we've modified it somewhat. I think it's supposed to be a traveling salesman.)

The big problem with Web services is that it's really hard to approach it the way you would a traditional enterprise app, because transactions and security are basically roll-your-own on the open Web. There's no Transaction Manager out there on the Web, the way there is inside of your J2EE server. There's nobody out there managing all of the security, either. And everything gets tough when the whole idea is that you don't know who — or what — will access your Web service. There is a way to expose Web services in such a way that those services aren't tightly coupled to the client (and/or dependent on both the client and the service using the same programming language, for example).

In some ways, the promise of Web services is that some aspects of it can be like Jini, with a certain level of dynamic discovery. In reality, that's both really hard to work out, and rarely done. But this stuff is changing on a daily basis. Remember, this is Internet time, baby.

Web Services Architecture

This picture is a lot higher-level than the previous ones, so there can be all kinds of other players in here, including stubs of various kinds (Web services can have their own kind of stubs), more interfaces, and many more things doing XML processing.

One key difference between the RMI-driven technologies and Web services is that the others are mostly based on real Java method calls. A call to a stub is still a Java method call. Sure, the stub makes a socket and a stream and uses a particular protocol to transmit the method call (usually RMI-IIOP, another impressive acronym), but once it gets over to the server where the service is running, it turns back into a regular method call, invoked on the Remote service object.

With Web services, the messages are sent using XML, using the SOAP protocol. SOAP is more or less just an envelope for a message, and the message isn't much more than just the actual "method" call the client wants the Web service to perform. (And we use the word "method" loosely here, although when we're talking Web services in Java, it does translate to a actual method call on a real live Java object, complete with arguments and return values.)

Most of the heavy runtime work with Web services is that there're all kinds of XML processing going on all over the place and, well, parsing XML is slooooooooow. Which means performance is an issue (which you can add to the other Web services problems like no transaction support, and very little security.) Then again, the beauty of XML is that it doesn't care about the platform, the programming language, or anything else. It's pretty much just text with tags. So the potential for interoperability and integration of anything and everything is possible with Web services.

You expose RMI, Jini, and EJB services through a regular old Java service interface. You expose Web services through an XML interface known as the WSDL (say it with me again: "wizdle"). The WSDL describes the service, and even tells the client where to find the service. But how the WSDL itself is exposed can really vary.

For example, there is a kind of registry/lookup service for Web services called UDDI, where you can publish, among other things, the WSDL. But since most Web services are being done on internal intranets, there isn't as much use of UDDI, but if (it's more like when) Web services start getting out there, that will probably change.

So a huge difference between Web services and the other Java distributed technologies is that with Web services (if they're to be interoperable, anyway), the client doesn't have to retrieve references to real objects. If you've got the WSDL, you've probably got enough information to make yourself a SOAP message and fire it off to the Web service described in the WSDL.

Remember, with Jini and EJB, it's often only the stub that knows the IP address and TCP port of the Remote service. The Java interface itself is just for declaring the methods, not the location of the service. But with a WSDL, it's different. A WSDL is more like a Java interface on steroids, except without the Java. The WSDL includes not just the method descriptions (name, arguments, return types, etc.) but also the network location of the service.

J2EE 1.4 and Web Services

J2EE 1.4, due out before the end of 2003, adds Web services capabilities, and should make it a lot easier for developers who're already using J2EE to turn a J2EE application into a Web service endpoint (for today, think of the endpoint as the real service). With J2EE 1.4, you shouldn't have to write XML for the WSDL, and best of all, you don't have to translate the incoming XML messages (SOAP) into Java calls, and vice versa. You can do that already, using the JAXP (part of J2EE 1.3) and JAX-RPC (available, but not yet part of J2EE until 1.4 ships) APIs, but with J2EE 1.4, it will all be built into the system, and the deployment tools will make it way more seamless than it is now, trying to cobble together all of the various Web-services-related APIs on your own.

Snapshot for Today

OK, let's face it: Jini is just not the buzzword it once was, with J2EE and Web services all the rage. Except that J2EE really works, with transactions and security, and all the rest, while Web services are still largely an uphill struggle. The word "bleeding" comes to mind. But Jini is out there, used by some of the world's largest banking organizations and even the U.S. military.

Bottom line: for big, serious enterprise-scale apps, J2EE is extremely popular in the marketplace. Web services are painfully immature but potentially very important, and next year we'll see what happens when J2EE embraces and integrates Web services. But Jini is just ... so much cooler. After all, this is about cocktail party conversation, not your next PowerPoint presentation.

Kathy Sierra has been a master Java trainer for Sun Microsystems, teaching Sun's instructors how to teach the latest Java technologies. She is also the founder of one of the largest java community websites in the world, javaranch.com.

Bert Bates is a 20-year software developer, a Java instructor, and a co-developer of Sun's upcoming EJB exam (Sun Certified Business Component Developer).

Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.