Sign In/My Account | View Cart  

advertisement

AddThis Social Bookmark Button

Listen Print

Java Enterprise Breakthroughs, Part 1
Pages: 1, 2

3. Local Interfaces for EJB Components

J2EE 1.3 supports the 2.0 version of the Enterprise JavaBeans specification. EJB 2.0 added an important new feature to EJB components: local interfaces.



Prior to EJB 2.0, client interfaces to EJBs could only be remote -- every client had to invoke remote method calls in order to obtain an EJB reference, and each business method called on the EJB reference was also a remote method call. A common architectural pattern found in enterprise Java applications, however, is for a Web component to reference an EJB component within the same application. Another common pattern is for a session EJB to utilize one or more entity EJBs on the same server, to manage persistent information. In these cases, the client of the EJB component resides in the same Java virtual machine as the EJB component itself. It would be much more efficient for these local clients to use a local (non-remote) interface to the EJB.

Local home and client interfaces are defined for session and entity EJBs in much the same way as their remote counterparts. A local interface for a ProfileServer EJB, for example, might look like the following:

  public interface ProfileServerLocal extends javax.ejb.EJBLocalObject {
   public Profile getProfile(String userName)
     throws NoSuchPersonException;
}

This EJB returns a Profile associated with a named user, through its getProfile() method. It extends the EJBLocalObject interface, which marks it as a local EJB client interface. A corresponding local home interface might look like this:

  public interface ProfileServerLocalHome extends javax.ejb.EJBLocalHome {
  public ProfileServerLocal create() throws CreateException;
}

The local home interface for an EJB extends the EJBLocalHome interface, and any create or find methods it may have will return the local client references to the EJB. In this case, the create() method on ProfileServerLocalHome returns a ProfileServerLocal interface.

A single EJB component can have both remote and local interfaces associated with it. Each home interface can be bound to separate JNDI names in the J2EE server, and a client can indicate which it requires by the JNDI lookup it performs. If the local home interface shown above is registered under the JNDI name "ejb/ProfileServerLocal", then a local client can use the local interface by making an appropriate JNDI lookup:

  Context ctx = new InitialContext();
ProfileServerLocalHome profHome =
  (ProfileServerLocalHome)ctx.lookup("java:comp/env/ejb/ProfileServerLocal");
ProfileServerLocal = profHome.create();

The local interface provides a much more efficient path for local clients to make use of the EJB component, since it avoids the overhead of constructing a remote method call with all of the corresponding marshalling/unmarshalling of method arguments and return values.

4. Asynchronous Request/Response Made Easy: JMSReplyTo Headers and Temporary Destinations

Both J2EE 1.2 and 1.3 support JMS 1.0. In J2EE 1.2, this support only included the client APIs needed to interact with a separate JMS provider. In J2EE 1.3, JMS support was extended to require that a J2EE server also provide JMS Destination and ConnectionFactory implementations that support both point-to-point and publish-subscribe messaging.

An interesting and powerful feature provided in JMS is the standard JMSReplyTo message header. This header is meant to hold a Destination to be used by the receiver to send any required response message. If we're using point-to-point messaging, for example, I might set the JMSReplyTo header on a message to a Queue, as a signal to the receiver that I want any response message to be sent to the given Queue:

  // Create a JMS session and get a Queue to be used for responses
QueueSession qSession = . . .;
Queue myQueue = . . .;
// Create a message and set its JMSReplyTo header to the Queue

TextMessage request = qSession.createTextMessage();
request.setJMSReplyTo(myQueue);

Another interesting feature provided by JMS is temporary queues. A messaging client can dynamically create temporary destinations through its Session with the JMS provider:

Queue tempQueue = qSession.createTemporaryQueue();

The combination of these two features makes it much easier to implement a request/response messaging scheme in JMS. In our example above, if I wasn't able to create a temporary destination, I would have to use some sort of administrative interface to explicitly set up a response Queue on my JMS provider before running this code. Then I'd access this specific Queue in my code through a JNDI lookup, and use it as the JMSReplyTo in my message. If I needed multiple request/response scenarios in my application, I'd have to either configure multiple Destinations for the responses, or I'd have to design some sort of message filtering scheme with a single reply-to Destination, to ensure that the proper response is picked up by each requestor.

With temporary destinations, I can dynamically create a Destination to be used as the target of the response to my message:

  Queue tempQueue = qSession.createTemporaryQueue();

TextMessage request = qSession.createTextMessage();
request.setJMSReplyTo(tempQueue);

The receiver of the message can access the JMSReplyTo Destination by simply calling the getJMSReplyTo() method on the received Message. Back on the request side, I can create a MessageConsumer for the Destination and either receive the response synchronously by calling its receive() method:

  QueueReceiver qReceiver = qSession.createReceiver(tmpQueue);
Message response = qReceiver.receive();

or I can asynchronously receive the response by registering a MessageListener with the receiver:

qReceiver.setMessageListener(new MyMessageListener(. . .));

Since the temporary destination is only accessible from this client, it effectively sets up a private request/response "channel" between the sender and receiver(s) of a message. Plus, it's a channel that's established dynamically at runtime, rather than statically through an a priori administrative step.

Summary

These are only a few of the powerful capabilities provided by the enterprise Java APIs. To see more details on these and other enterprise Java features, see the newest edition of Java Enterprise in a Nutshell. And watch for more enterprise Java tips and tricks in part 2 of this series.

Jim Farley is a technology architect, strategist and IT manager.


Return to ONJava.com.