| Sign In/My Account | View Cart |
Java Enterprise Breakthroughs, Part 1
Pages: 1, 2
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.
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.
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.