Client callbacks

What’s the best way to broadcast a message from an entity bean to many clients?

Q: I need to have an entity bean to which many clients can connect. When a client sends a message to the bean, the bean should broadcast that message to all of the clients. I tried doing this by having each client send the entity bean an instance of itself (the clients are serializable). At that time the entity bean stores that instance in a vector. When the entity bean gets the message to broadcast, it just calls a method in each of the clients in the vector that prints a string to the command line. This string gets printed in the command line of the server, so obviously this doesn’t work the way I want it to. My questions are:

  1. Can this be done using J2EE?
  2. What is happening in the instance that I describe (i.e., why is the message printing on the server)?
  3. Is JMS the solution I am looking for?

To clarify, a simple example of the exact architecture that I described above would be a chat server with a chat client. Clients send messages to the server and the server broadcasts each message to everyone connected to it.

A: As an example, let’s look at Mr. Happy Object in Figure 1.

Figure 1. Mr. Happy Object

Mr. Happy Object is the client from your question. As in your question, Happy is serializable.

The client and entity bean live in different process spaces, as seen in Figure 2.

Figure 2. The client/server environment

These spaces can be on the same machine or on different machines, though it doesn’t really matter much. Each space will need to communicate with the other over the network.

In Figure 3 we see that there is something wrong. Happy begins to feel weird. We see that the Serializer (the java.io.ObjectOutputStream, for the humor impaired) is sucking Happy over the network.

Figure 3. The Serializer

The ObjectOutputStream takes an object as input and sends it over its associated java.io.OutputStream. The stream achieves this feat by utilizing the object’s writeObject() method. This method knows how to write the object out to the stream.

We see in Figure 4 that after being sent down the stream, Happy is reconstituted on the other side by the Unserializer. (Again, we all know the Unserializer as the java.io.ObjectInputStream.)

Figure 4. The Unserializer

The ObjectInputStream achieves this feat by calling the object’s readObject() method. This method knows how to read itself from the stream.

However, you’ll note that there are now two Mr. Happy Objects and that the entity bean only has reference to the Happy that was transported to its environment. This isn’t Star Trek, so when we beam an object from one environment to another, we don’t move the original object. Instead, the process is much closer to cloning (in fact, you can write a very slow object cloner using serialization). Be aware that transient information is lost during serialization.

So, when your entity bean makes a call on Happy, it isn’t the Happy that you think it is. Instead, it is a copy of the original client.

Now, on to questions 1 and 3. The answers are “yes” and “maybe,” respectively.

It is possible to have an entity bean call back into its clients. Whether or not you use JMS is up to you. You could also use the CORBA event service or roll your own solution. Regardless of the protocol you choose, your solution should look like the form in Figure 5.

Figure 5. A possible solution

In my proposal, there are three pieces: the clients, the server, and a registrar (or proxy). Upon startup, the clients need to register themselves with the proxy. When the client wishes to send a message, it sends the message to the server as before. Now, instead of the server sending the message to the clients directly, it obtains a reference to the proxy and forwards the message to the proxy instance, not the clients. It is then up to the proxy to forward the message to each client. Both JMS and CORBA supply such a proxy-based service. For more information read up on the Proxy pattern (see Resources).

Be careful. I would not register a client directly with an entity bean. Because of the nature of entity beans, a given entity bean is not guaranteed to always be available. A specific instance may be passivated or returned to its object pool at any time. Remember, you never have a reference to a specific entity instance. Instead, all instances are hidden behind the EJB’s remote interface. So, relying on a specific instance (such as one that you are registered with) might not be such a great idea.

Tony Sintes is a principal consultant at BroadVision. Tony, a Sun-certified Java 1.1 programmer and Java 2 developer, has worked with Java since 1997.

Source: www.infoworld.com