Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Mastering Enterprise JavaBeans™ and the Java 2 Platform, Enterprise Edition - Roman E

..pdf
Скачиваний:
41
Добавлен:
24.05.2014
Размер:
6.28 Mб
Скачать

J2EE in the Real World: Combining Servlets with Enterprise JavaBeans 501

One way to perform all retrieval of these entity beans is to define specialized finder methods. For example, a method such as

findBeansMatching(String criteria, int numToReturn)

could yield at most numToReturn matches, which is highly useful for displaying discrete chunks of data. The trade-off here is overall database load. Databases are designed to handle batch operations very well. Single individual queries cannot be optimized as well. Therefore, if you need to scan through all the entity beans in the database, your overall database usage has increased.

Another question you should be asking yourself is if you really need a finder method at all. Remember that every time a finder method is called, an EJB object is constructed for every element in the returned Enumeration (or Collection in Java 2). Instead, having a session bean perform these queries for you directly at the database level may improve performance. Once you’ve found the Primary Keys for the entity beans you’re looking for, you can construct EJB objects for only those beans via a findByPrimaryKey() on the found keys.

Summary

In this chapter, we’ve finally completed our e-commerce deployment. We began the chapter by writing our e-commerce servlets, and we showed how they tied in with enterprise beans. We then executed the deployment and looked at ways to extend it. Finally, we covered some broad performance tuning tips that apply not only to this deployment, but to almost any other EJB deployment as well. If you’ve made it this far, then congratulations because you now have a realworld e-commerce deployment using EJB under your belt!

Go back to the first page for a quick link to buy this book online!

A P P E N D I C E S

Introduction to Appendices

n this final section of the book, we describe several ancillary topics to EJB pro- Igramming. Specifically:

Java Remote Method Invocation (RMI). Appendix A kicks things off by exploring Java RMI. Here you’ll gain a solid foundation in RMI, at both the conceptual and programmatic levels. You’ll also see how RMI is used in the EJB world and how it compares with CORBA.

The Java Naming and Directory Interface (JNDI). Appendix B then continues by investigating the JNDI, a standard Java extension package for performing naming and directory operations. We’ll learn the concepts, how to program with JNDI, and how JNDI relates to EJB.

The Extensible Markup Language (XML). Appendix C is a brief introduction to XML. XML is a very complementary technology to J2EE, as it provides a universal standard for structuring content in electronic documents. Several J2EE APIs depend on XML, including EJB 1.1 and Java Server Pages (JSPs).

The EJB 1.1 Specification. Appendix D surveys the new EJB 1.1 specification. EJB 1.1 increases code portability, defines the roles of EJB development more crisply, and leverages XML.

Making an EJB Purchase Decision. Appendix E is an overview of making an EJB purchase decision. It reviews common criteria that you should be taking into account when shopping for EJB products.

EJB API and Diagram Reference. Finally, Appendix F is a quick reference for programmers to use during EJB development. It includes diagrams illustrating what’s really going on in an EJB system, a guide to the core EJB API, and a transaction reference.

503

Go back to the first page for a quick link to buy this book online!

A P P E N D I XA

Understanding Java Remote

Method Invocation (RMI)

ava Remote Method Invocation (RMI) is the Java language’s native mechanism Jfor performing simple, powerful networking. RMI allows you to write distributed objects in Java, enabling objects to communicate in memory, across Java

Virtual Machines, and across physical devices.

RMI is an alternative to using CORBA, the Object Management Group’s distributed object architecture. How do the two compare? It’s becoming tougher and tougher to draw the line. In fact, neither RMI nor CORBA is clearly a superior technology.

Historically, RMI has had several distinct advantages over CORBA. For example, RMI provides almost seamless, simple, transparent integration into the Java language itself. The overhead cost of developing an application that uses RMI is very low. RMI’s strength lies in ease of use, and it has had great appeal to software developers who want to focus on the business logic of their code and leave the networking to RMI.

By way of comparison, CORBA has historically been well suited for enterprise applications. CORBA provides a cross-platform, cross-language architecture. CORBA also provides a full suite of enterprise features, such as transactions, security, and persistence. The Internet Inter-Orb Protocol (IIOP), a robust protocol for distributed object communications, is used behind the scenes in CORBA.

Note that both these trade-offs are historical. The differences between RMI and CORBA are beginning to disappear because both RMI and CORBA are learning from each other. Many of the services specific to CORBA are becoming available with RMI coupled with the Java 2 Platform, Enterprise Edition. Similarly,

505

Go back to the first page for a quick link to buy this book online!

506 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

the ease of use of RMI is becoming available in CORBA. In essence, the two camps are converging. We’ll look at exactly how later in this appendix and also in Chapter 11.

This appendix examines the benefits and drawbacks of RMI and details the architecture and logic behind it. We also compare RMI with CORBA, and we examine how RMI and EJB relate. After reading this, you will be able to write your own distributed object applications based on the RMI standard.

Remote Method Invocations

A remote procedure call (RPC) is a procedural invocation from a process on one machine to a process on another machine. RPCs enable traditional procedures to reside on multiple machines, yet still remain in communication. They are a simple way to perform cross-process or cross-machine networking.

A remote method invocation in Java takes the RPC concept one step further and allows for distributed object communications. RMI allows you to invoke methods on objects remotely, not merely procedures. You can build your networked code as full objects. This yields the benefits of an object-oriented programming, such as inheritance, encapsulation, and polymorphism.

Remote method invocations are by no means simple. Below are just some of the issues that arise:

Marshalling and unmarshalling. Remote method invocations (as well as RPCs) allow you to pass parameters, including Java primitives and Java objects, over the network. But what if the target machine represents data differently than the way you represent data? For example, what happens if one machine uses a different binary standard to represent numbers? The problem becomes even more apparent when you start talking about objects. What happens if you send an object reference over the wire? That pointer is not usable on the other machine because that machine’s memory layout is completely different from yours. Marshalling and unmarshalling is the process of massaging parameters so that they are usable on the machine being invoked on remotely. It is the packaging and unpackaging of parameters so that they are usable in two heterogeneous environments. As we shall see, this is taken care of for you by Java and RMI.

Parameter passing conventions. There are two major ways to pass parameters when calling a method: pass-by-value and pass-by-reference, as shown in Figure A.1. When you pass by value, you pass a copy of your data so that the target method is using a copy, rather than the original data. Any changes to the argument are reflected only in the copy, not the original. Pass-by-reference,

Go back to the first page for a quick link to buy this book online!

Understanding Java Remote Method Invocation (RMI) 507

RMI Client Address Space

 

RMI Server Address Space

 

 

 

 

 

 

 

 

Object A

 

Pass-by-Value

 

Object A

 

 

 

 

 

 

 

 

When performing remote invocations with pass-by-value, a new copy of Object A is instantiated on the remote host. When the remote host modifies Object A, the new value, A', does not affect the local host's data.

Return

Object A

Modify Object A

Object A'

Object A

Pass-by-

Reference

With pass-by-reference, the remote host receives a remote reference to the original Object A, rather than a copy of Object A. Any modifications to Object A are reflected in the original data.

Reference back to Object A

Modify Object A

Object A'

Return

Reference back to

modified Object A'

 

 

 

 

 

Figure A.1 Pass-by-value versus pass-by-reference.

on the other hand, does not make a copy. With pass-by-reference, any modifications to parameters made by the remote host affect the original data. The flexibility of both the pass-by-reference and pass-by-value models are advantageous to have, and RMI supports both. We’ll see how in the pages to come.

Distributed garbage collection. The Java language itself has built-in garbage collection of objects. Garbage collection allows users to create objects at will,

Go back to the first page for a quick link to buy this book online!

508 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

and it leaves the destruction of objects to the underlying Java Virtual Machine. But in a distributed object system, things become more complicated. An object residing on a remote host might have a reference (called a remote reference) to a local object. Thus, the remote host has a reference that actually refers to an object across the network, rather than a local object. But how does garbage collection work then? After all, a JVM’s garbage collector runs within that JVM and does not take into account object references from remote hosts. Because of this, a distributed garbage collector is needed to track remote hosts that reference local objects.

Network or machine instability. With a single JVM application, a crash of the JVM brings the entire application down. But consider a distributed object application, which has many JVMs working together to solve a business problem. In this scenario, a crash of a single JVM should not cause the distributed object system to grind to a halt. To enforce this, remote method invocations need a standardized way of handling a JVM crash, a machine crash, or network instability. When some code performs a remote invocation, the code should be informed of any problems encountered during the operation. RMI performs this for you, abstracting out any JVM, machine, or network problems from your code.

Downloadable implementations. Remote method invocations allow you to pass whole Java objects as parameters to methods invoked over the network. This means, for example, that you can pass a java.lang.String over the network as a parameter to a method. If you pass an entire Java object to a target machine, what you’re really passing is that object’s data to the target machine. In our String example, this could be the String’s character buffer. But objects also contain code, and that code might not be available on the target machine. For example, String objects have a method called length()that returns the length of the String. This logic, as well as the other logic surrounding objects, is stored in .class files in Java. The target machine needs those class files so that it can construct the code portion of the objects you send as parameters to methods over the network. RMI allows for these class files to be automatically downloaded behind the scenes, relieving you of this dogmatic chore. This also means RMI is a very dynamic system, allowing for different object implementations to come in over the wire.

Security. We mentioned that RMI contains built-in dynamic class loading. This allows object implementations to arrive from remote, and possibly hostile, sources. Java applets are perfect examples because they are downloaded on the fly and could be malicious. A security mechanism needs be in place to restrict possibly hostile implementations and grant system-level access only to authenticated implementations. RMI has such support.

Activation. You’d like to be able to invoke methods on remote objects, even if they are not in memory yet. If you invoke a method on a remote object that is

Go back to the first page for a quick link to buy this book online!

Understanding Java Remote Method Invocation (RMI) 509

not in memory yet, RMI contains measures to automatically fault the object into memory so that it can service method calls. This is called remote object activation.

As you can see, there’s a lot involved in performing remote method invocations. RMI contains measures to handle many of these nasty networking issues for you. This reduces the total time spent dealing with the distribution of your application, allowing you to focus on the core functionality.

RMI is the Java language’s native remote method invocation service. It ships with the Java 2 platform, and it is required for any 1.1-compatible Java Runtime Environment. It is built entirely in Java and is therefore highly cross-platform. This is a big win for RMI—you can write your networking code once and run it in any recent Java Runtime Environment. Contrast this with proprietary, platformdependent RPC libraries, and you can see some real value in RMI.

Java RMI has historically not been supported by Microsoft. If you wanted to use Microsoft’s Java environment, you needed to download an RMI add-on, available at ftp://ftp.microsoft.com/developr/msdn/unsup-ed/rmi.zip. A recent court order, however, has required Microsoft to support Java RMI in future versions of its product. Make sure the environment you’re developing with does indeed support RMI.

RMI Architecture

In RMI, any object whose methods can be invoked from another Java VM is called a remote object. Remote objects are networked objects, which expose methods that can be invoked by remote clients. The physical locations of remote objects and the clients that invoke them are not important. For example, it’s possible for a client running in the same address space as a remote object to invoke a method on that object. It’s also possible for a client across the Internet to do the same thing. To the remote object, both invocations appear to be the same.

RMI and Interface versus Implementation

In Chapter 1, we discussed one of object-oriented design’s great programming practices—the separation of the interface of code from its implementation.

The interface defines the exposed information about an object, such as the names of its methods and what parameters those methods take. It’s what the client works with. The interface masks the implementation from the viewpoint of clients of the object, so clients deal only with the end result: the methods the object exposes.

Go back to the first page for a quick link to buy this book online!

510 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

The implementation is the core programming logic that an object provides. It has some very specific algorithms, logic, and data.

By separating interface from implementation, you can vary an object’s proprietary logic without changing any client code. For example, you can plug in a different algorithm that performs the same task more efficiently.

RMI makes extensive use of this concept. All networking code you write is applied to interfaces, not implementations. In fact, you must use this paradigm in RMI—you do not have a choice. It is impossible to perform a remote invocation directly on an object implementation. You can operate solely on the interface to that object’s class.

To designate that your object can be invoked on remotely, your class must implement the interface java.rmi.Remote. You must perform this by creating your own custom interface extending java.rmi.Remote. That interface should have within it a copy of each method your remote object exposes.

For example, the following code snippet is a valid remote interface:

public interface IMyRemoteInterface extends java.rmi.Remote {

public void foo() throws java.rmi.RemoteException;

}

Your remote object implementation (that is, the networked object) implements this interface. Client code that wants to call methods on your remote object must operate on IMyRemoteInterface.

An additional restriction of RMI is that each method must also throw a java.rmi

.RemoteException. A java.rmi.RemoteException is thrown when there is a problem with the network, such as a machine crashing or the network dying. Your remote objects can throw their own regular exceptions in addition to the required java.rmi.RemoteException.

Stubs and Skeletons

One of the benefits of RMI is an almost illusionary, transparent networking. You can invoke methods on remote objects just as you would invoke a method on any other Java object. In fact, RMI completely masks whether the object you’re invoking on is local or remote. This is called local/remote transparency.

But local/remote transparency is not as easy as it sounds. To mask the fact that you’re invoking on an object residing on a remote host, RMI needs to somehow simulate a local object that you can invoke on. This local object is called a stub, and it is responsible for accepting method calls locally and delegating those

Go back to the first page for a quick link to buy this book online!

Understanding Java Remote Method Invocation (RMI) 511

method calls to their actual object implementations, which are possibly located across the network. This effectively makes every remote invocation appear to be a local invocation. You can think of a stub as a placeholder for an object that knows how to look over the network for the real object. Because you invoke on local stubs, all the nasty networking issues are hidden behind the scenes.

Stubs are only half of the picture. We’d like the remote objects themselves— the objects that are being invoked on from remote hosts—to not worry about networking issues as well. Just as a client invokes on a stub that is local to that client, your remote object needs to accept calls from a skeleton that is local to that remote object. Skeletons are responsible for receiving calls over the network (perhaps from a stub) and delegating that call to the remote object implementation. This is shown in Figure A.2.

One of the more interesting responsibilities of stubs and skeletons is the marshalling and unmarshalling of parameters. RMI relies on a technology called object serialization to assist with this, which we’ll learn about a bit later.

Client

 

Remote Object

 

 

 

Remote Interface

Stub

 

Skeleton

 

 

 

Network

Figure A.2 Stubs and skeletons.

Go back to the first page for a quick link to buy this book online!

512 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

Bootstrapping and the RMI Registry

For a client and a server to start talking, they need some way to connect. Acquiring this connection is known as bootstrapping. How does RMI accomplish bootstrapping?

RMI provides an entity known as the RMI Registry for this purpose. When you want to make an object remotely accessible, you register it with the registry. You give the registry a name for the object during this registration. From then on, the Registry will route all incoming requests for that name to your object. You can think of the RMI Registry as a giant hashtable that maps names to objects.

The RMI Registry accomplishes this task by sitting at a well-known network port and listening for incoming connections. When a remote client wants to access an object registered with a particular registry, the client issues a request over the network to the registry. The Registry reads the request, looks up the name of the remote object requested, and returns the stub for that remote object to the client. This is shown in Figure A.3.

You can have as many RMI registries as you want on a machine, but only one Registry per VM. And, of course, only one Registry can be bound to a specific port. There are thousands of ports for you to choose from, though, so that’s no problem. If you don’t specify a port, RMI uses port 1099 by default. Remember that both your client and server must agree on which port the Registry sits at, or they will never find each other.

There are two ways to start the RMI Registry. You can launch it as a stand-alone program by typing

rmiregistry

from a command prompt. You can also start a registry from inside your Java program by accessing the java.rmi.Registry class.

RMI URLs

An RMI URL is a Java String that is used to locate a remote object on another Java Virtual Machine. It looks very similar to other types of URLs, such as http:// www.java.sun.com or ftp://ftp.microsoft.com. RMI enforces the following conventions for URLs:

1.The URL must begin with the text rmi://.

2.Next, you may specify the target machine where the Java Virtual Machine is located—for example, rmi://foobar.baz.com/. If you don’t specify a target machine, RMI defaults to the local host.

Go back to the first page for a quick link to buy this book online!