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

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

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

330 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

As you’ll see, two new packages are needed when we introduce RMI over IIOP:

javax.rmi. There are differences in programming style between RMI and CORBA, such as narrowing of objects. javax.rmi addresses these issues. javax.rmi defines a unified RMI API that is portable between RMI and CORBA object implementations. As an RMI-over-IIOP programmer, you deal with the javax.rmi package directly, so it’s important to understand how it works. We’ll explain this package shortly.

javax.rmi.CORBA. This is an internal package that RMI over IIOP uses. If you ever want to define your own version of RMI over IIOP, or if you want to use another vendor’s, this package ensures portability. As an RMI-over-IIOP programmer, you don’t need to concern yourself with this package (thus we do not cover it here). Refer to the Java-to-IDL mapping specification if you want the details.

javax.rmi

The javax.rmi package is the new RMI API that you must use with RMI-IIOP. It defines one new class, called javax.rmi.PortableRemoteObject:

public abstract class javax.rmi.PortableRemoteObject { public static void exportObject(java.rmi.Remote obj); public static void unexportObject(java.rmi.Remote obj); public static java.rmi.Remote toStub(java.rmi.Remote obj);

public static Object narrow(Object narrowFrom, Class narrowTo);

public static void connect(java.rmi.Remote unconnected, java.rmi.Remote connected);

}

This class is the new alternative to java.rmi.UnicastRemoteObject, which we cover in Appendix A. While UnicastRemoteObject will work with JRMP, PortableRemoteObject will work with both the JRMP and IIOP protocols. As with UnicastRemoteObject, your remote objects can inherit from the javax.rmi

.PortableRemoteObject class, or you can call the static methods on this class to export yourself as a remote object.

Let’s take a look at the methods this class exposes:

exportObject. Call this to register your remote objects as server objects. This makes your objects available to be called remotely. Note that the default constructor for PortableRemoteObject automatically exports your remote objects for you. Thus, if your remote object extends PortableRemoteObject, by calling super() you will automatically export your object. This is the same behavior we saw with UnicastRemoteObject in Appendix A.

unexportObject. With Java RMI, your objects are cleaned up automatically if clients drop their references or if clients time out. Because your remote objects

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

CORBA and RMI-IIOP 331

are no longer automatically garbage collected, you need to manually unregister your remote objects so they will be available for garbage collection. This is accomplished via the unexportObject() method.

toStub. This method transforms a previously exported remote object into a stub. You can treat the stub as a true proxy, passing it around and invoking on it. The stub will delegate calls to the real object. Before you use the stub, however, you must call the connect() method, described next.

connect. This method makes a remote object ready for remote communication. Normally this method is automatically called for you when you pass remote objects over the network as parameters. If you manually generate a stub via the toStub() method, however, you must call connect() yourself.

narrow. As we’ve described, RMI and CORBA have different mechanisms for coercing received remote objects into user-defined objects. With RMI, when you receive a remote object over the network, you simply cast it into the desired object. With RMI-IIOP, you must call this narrow() method instead. You pass narrow() the object you’ve received and the class to which you wish to cast it. It returns the resultant object or throws an exception if the narrow is not possible.

Bootstrapping with RMI over IIOP

How do RMI-over-IIOP clients find an object over the network? Normally with Java RMI, you bind objects to an RMI registry, which serves as a registry for all your exported remote objects. Clients can then look up objects by using RMI’s Naming.lookup() facilities. Naming.lookup() knows how to contact a remote RMI registry, which is listening at a well-defined port. This is fully described in Appendix A.

Naming.lookup() has several disadvantages. For one, it does not lend itself well to enterprise deployments because you must hard-code the location of the target machines in which your remote objects live. The more serious problem is that Naming.lookup() finds RMI remote objects via the RMI registry, but it cannot find CORBA object implementations. We’d like RMI-over-IIOP clients to be able to call CORBA object implementations as well as RMI remote objects. That’s one of the goals of RMI over IIOP: to provide a standard API to access both RMI and CORBA objects.

In Appendix B, we detail the Java Naming and Directory Interface (JNDI) as a mechanism for binding, and later finding, resources on a network. Appendix B shows how JNDI is a generic lookup service for any kind of resource, such as a printer or a computer. JNDI provides a standard API, with several “service providers” plugging into a Service Provider Interface (SPI). These service providers could be LDAP providers, Novell NDS providers, or others.

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

332 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

Of particular importance to RMI over IIOP is the RMI Registry service provider. The RMI Registry service provider allows you to reference RMI remote objects through JNDI (see Appendix B for a hands-on example of this). JNDI is a much better solution for bootstrapping than the normal RMI’s Naming.lookup() convention because clients are not hard-coding the addresses of machines. Rather, you bind your remote object locations to a well-known directory tree, such as an LDAP server.

Recall from earlier in this chapter that CORBA has its own built-in naming service, called the CORBA Naming Service (or COS Naming). COS Naming is the standard way CORBA clients look up remote CORBA objects. But again, this is simply looking up an arbitrary resource over the network—the resource just happens to be CORBA objects rather than printers or RMI objects. Therefore, COS Naming is a perfect fit for JNDI. JNDI has a CORBA Naming Service provider, called the COS Naming service provider. The COS Naming service provider allows you to look up CORBA objects over the network using JNDI.

JNDI is thus a perfect fit for RMI over IIOP. RMI-over-IIOP clients need to be able to access both CORBA object implementations and RMI remote objects using the same API, so that we no longer have two different camps for network computing in Java. We can unite these camps by providing a standard way to look up either CORBA or RMI objects using JNDI as follows:

■■RMI over IIOP clients cannot use RMI’s Naming.lookup() facility. Clients must use JNDI. This unified lookup API gives us a single interface to both RMI remote objects and CORBA object implementations.

■■By plugging in JNDI’s CORBA Naming Service service provider, our RMI- over-IIOP clients will be able to access CORBA object implementations.

■■By plugging in JNDI’s RMI Registry service provider, our RMI-over-IIOP clients will be able to access RMI remote objects.

This last bit finally gets us exactly what we want—being able to mix CORBA clients and server objects with RMI clients and server objects, without recompiling code. The good news for you is that your EJB server should abstract most of this away from you, and that it can handle the steps of generating the appropriate stubs, skeletons, and IDL. Most likely, though, if you are writing client code that uses JNDI, you will be responsible for choosing the correct JNDI service provider.

The Big Picture: CORBA and EJB Together

In this section, we’ll assume you’ve understood how RMI-IIOP bridges RMI and CORBA, and we’ll apply these concepts to EJB. Before we get into the technical

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

CORBA and RMI-IIOP 333

details, you should note how EJB and CORBA re being positioned relative to one another.

As you know, EJB is useful for server-side component development, sporting features such as networking, threading, transactions, persistence, security, and a well-defined server-side component model. CORBA, on the other hand, is more of the enabling technology that resides beneath the EJB level. Most serious EJB server vendors will be layering their EJB products on top of an existing CORBA infrastructure, and RMI-IIOP allows just this to happen.

So if anyone tells you that CORBA is dying, they’re simply wrong—CORBA is really the physical basis for EJB. CORBA ORBs are a natural fit for brokering method requests across the network. CORBA’s persistent Interoperable Object References (IORs) make a great foundation for EJB object handles. And in the future, CORBA OTS and IIOP will hopefully be used as well to guarantee on- the-wire transaction interoperability.

Benefits of CORBA/EJB Interoperability

Although CORBA/EJB interoperability is still in its infancy, the vision is solid, and there are several benefits that we hope will come from it. For one, CORBA clients written in any language (that OMG IDL maps to) should be able to call your enterprise beans. This can happen only if everyone agrees to use RMI-IIOP. Sun Microsystems has realized this, and has defined RMI-IIOP as the de-facto communications API in EJB 1.1 (see Appendix D). This means vendors will no longer be able to use other communications APIs, such as the vanilla RMI API we’ve seen throughout this book with BEA’s WebLogic. Thus, when vendors ship their EJB 1.1 products, you should be able to connect an RMI-IIOP client and a CORBA client to the same enterprise bean. We’ll demonstrate how to do this shortly.

Another benefit of CORBA/EJB interoperability is at the transaction level. Clients should be able to mix calls to both CORBA objects and enterprise beans under the hood of the same transaction. Similarly, you should be able to construct a distributed transaction that spans heterogeneous EJB servers. For this to happen, vendors not only need to agree to use IIOP, but they also need to agree on how to propagate transaction contexts across the network, and CORBA’s Object Transaction Service specifies exactly this. To answer this need, Sun Microsystems has promised to release a new standard called EJB/IIOP which will yield on-the-wire transaction interoperability. This will hopefully be part of EJB 2.0, due out well into the year 2000.

What You Don’t Get from Corba-ejb Interoperability

Lastly, I want to make it clear that there is one benefit that you do not get out of EJB-CORBA interoperability. CORBA-EJB interoperability is for connecting a

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

334 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

CORBA client to an enterprise bean written in Java. You cannot write your enterprise beans in any language but Java. If you want to write your server-side components using another language, you have four choices:

1.Write your components in the language of your choice, and wrap them in an EJB layer. This works very well for existing investments. Your enterprise beans should use CORBA APIs to delegate to your non-Java code. Note that you cannot use the Java Native Interface (JNI), as native methods are banned from EJB.

2.If you have a fairly hairy existing investment with its own middleware issues, you could write a J2EE Connector (see Chapter 1) to bridge this investment into the EJB world. But you’ll have to wait until Sun finalizes the Connector specification in EJB 2.0.

3.Use Microsoft’s COM+ architecture, a language-neutral standard for distributed server-side components. If you do this you’ll be completely departing from EJB. COM+ has its own ups and downs, and is a completely separate debate (a debate, by the way, in which I’ve participated. See the book’s accompanying Web site at www.wiley.com/compbooks/roman for a transcript).

4.Wait and see what happens with the CORBA Components specification.

CORBA/EJB Interoperability Scenarios

Now that we’ve whetted your appetite, let’s illustrate how to tie together CORBA clients with EJB systems. There are two types of Enterprise JavaBeans clients: Java RMI-IIOP based clients and CORBA-based clients. There are also two types of EJB servers: CORBA-based EJB servers and proprietary EJB servers. Both of these servers use the RMI-IIOP API. The real difference is the communications they use beneath the API.

ACORBA-based EJB server ships with a CORBA Object Request Broker (ORB). The server exposes its objects, such as EJB objects and home objects, as CORBA objects. It accomplishes this by generating RMI-IIOP skeletons for all server-side objects. Thus you can write client code using either the CORBA API or the RMI-IIOP API. The ORBs deployed on the clients and servers communicate via IIOP. This is shown in Figures 11.6 and 11.7.

A proprietary EJB server does not ship with a CORBA ORB. Rather, it has its own proprietary communications architecture. The proprietary EJB server must still allow clients to call methods using RMI-IIOP API, because that is mandated as of EJB 1.1. However, the implementation of RMI-IIOP does not use an ORB, and IIOP is not used as the transport protocol, which means CORBA clients cannot call your enterprise beans. This is shown in Figure 11.8.

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

CORBA and RMI-IIOP 335

CORBA-based EJB Container/Server

RMI-IIOP Client

EJB Object

Implementation

EJB Remote Interface

RMI-IIOP Stub

RMI-IIOP

Skeleton

ORB

 

ORB

 

 

 

Network

via IIOP

Figure 11.6 Java RMI-IIOP client with a CORBA-based EJB server.

Example Code

Now let’s write some sample code to illustrate both RMI-IIOP EJB clients and CORBA EJB clients. These examples have been tested with an early access release of Inprise Corporation’s Inprise Application Server. The key thing to notice about both these examples is that we’ll access the exact same enterprise bean from both RMI-IIOP and CORBA without modifying the bean.

RMI-IIOP EJB Client Example

First, let’s see how to write an RMI-IIOP client to access an EJB system. This example uses the “Hello, World!” session bean we developed in Chapter 4. We’ll use the following:

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

336 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

CORBA-based EJB Container/Server

CORBA Client

EJB Object

Implementation

EJB Remote Interface

CORBA Stub

RMI-IIOP

Skeleton

ORB

 

ORB

 

 

 

Network

via IIOP

Figure 11.7 A CORBA client with a CORBA-based EJB server.

■■JNDI to look up the home object

■■JTA to demarcate transaction boundaries

Source 11.1 shows the code, which is relatively self-documenting.

The key thing to notice in Source 11.1 is we’re using the RMI-IIOP PortableRemoteObject.narrow() method to help cast returned remote objects.

CORBA EJB Client Example

Next, let’s take that exact same “Hello, World!” session bean and access it from a CORBA client. We’ll use the following:

■■ COS Naming to look up the home object

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

CORBA and RMI-IIOP 337

Proprietary EJB Container/Server

RMI-IIOP Client

EJB Object

Implementation

EJB Remote

Interface

Proprietary

 

Proprietary

Stub

 

Skeleton

 

 

 

Network via proprietary

protocol

Figure 11.8 A Java RMI-IIOP client with a proprietary EJB server.

■■OTS to demarcate transaction boundaries

■■The Java language to write our CORBA client

Source 11.2 shows the implementation.

package com.wiley.compBooks.roman.corba.helloworld;

import javax.ejb.*; import javax.naming.*; import javax.rmi.*;

import java.util.Properties;

import javax.transaction.UserTransaction;

/**

*This class is an example of client code that invokes

*methods on a simple stateless session bean.

*/

public class RMIClient {

Source 11.1 Example RMI-IIOP EJB client (continues)

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

338 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

public static void main(String[] args) {

try { /*

* Get System properties for JNDI initialization */

Properties props = System.getProperties();

/*

* Use JNDI to look up the home object */

Context ctx = new InitialContext(props);

HelloHome home = (HelloHome)

javax.rmi.PortableRemoteObject.narrow(

ctx.lookup("HelloHome"),

HelloHome.class);

/*

*Use JNDI to look up the JTA

*UserTransaction interface

*/

UserTransaction userTran = (UserTransaction) ctx.lookup("javax.transaction.UserTransaction");

/*

* Start the transaction */

userTran.begin();

/*

* Use the home object to create the Hello EJB Object */

Hello hello = home.create();

/*

* Call the hello() method, and print it */

System.out.println(hello.hello());

/*

* Done with EJB Object, so remove it */

hello.remove();

/*

* Commit the transaction */

userTran.commit();

Source 11.1 Example RMI-IIOP EJB client (continues)

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

CORBA and RMI-IIOP 339

} catch (Exception e) {

e.printStackTrace();

}

}

}

Source 11.1 Example RMI-IIOP EJB client (continued).

package com.wiley.compBooks.roman.corba.helloworld;

import java.util.*;

import org.omg.CosNaming.*; import org.omg.CosTransactions.*;

public class CORBAClient {

public static void main(String[] args) throws Exception {

/*

*Initialize the ORB.

*A more portable way to do this is:

*Properties p = new Properties();

*p.put("org.omg.CORBA.ORBClass", <..ORB class..>);

*org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, p);

*/

org.omg.CORBA.ORB orb = com.inprise.ejb.Global.orb();

/*

* Get a reference to a naming context */

NamingContext context = NamingContextHelper.narrow (orb.resolve_initial_references("NameService"));

/*

* Look up the home object using COS Naming */

NameComponent[] names = { new NameComponent("HelloHome", "") }; HelloHome helloHome = HelloHomeHelper.narrow

(context.resolve(names));

/*

*Get the CORBA OTS Current interface for

*controlling transactions

*/

Source 11.2 Example CORBA EJB client (continues).

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