RMI-IIOP in the enterprise

来源:互联网 发布:ipad旧版本软件 编辑:程序博客网 时间:2024/05/15 15:32

RMI-IIOP in the enterprise

An introduction to running RMI over IIOP


Level: Intermediate

Damian Hagge (Hagge@uk.ibm.com), Software Engineer, IBM

12 Mar 2002

RMIand CORBA are often seen as competing technologies, since both providetransparent access to remotely distributed objects. But the twotechnologies are actually complementary, in that each one has strengthsthat can address the weaknesses of the other. The marriage of RMI andCORBA has resulted in RMI-IIOP, a cornerstone of server-side Javadevelopment for the enterprise. In this article, Java developer DamianHagge offers a brief introduction to RMI-IIOP, then shows you how tobuild and run a simple, Java-based RMI-IIOP client/server application.See for yourself how well RMI works over IIOP.

IBM and Sun Microsystems launched a joint initiative in 1997 to promote the advancement ofJava as an enterprise-development technology. In particular, the two companies focused on how Java could be used as a server-side language, producing enterprise-level code that could be incorporated into existing architectures. What was needed was a remote transport technology that combined the small footprint of Java's RMI(Remote Method Invocation) and the sturdiness of the more mature CORBA (Common ObjectRequest Broker Architecture) technology. Out of this need was born RMI-IIOP, whichhas helped propel the Java language into its current position as the leadinglanguage for server-side enterprise development.

Inthis article, I'll provide a basic introduction to RMI-IIOP, with thegoal of getting you started using the technology in your enterprisedevelopment solutions. In order to explain what RMI-IIOP really is Ithink it's important to presentinformation about CORBA and RMI that you might not find in your typicalintroduction to either technology. If you're unfamiliar with the basicsof eitherCORBA or RMI, I suggest you go through some introductory informationbefore you proceed. See Resources for a selectionof articles and tutorials.

Before I talk specifically about RMI-IIOP, we'll take a look at the mechanisms thatCORBA and RMI use to marshall requests. CORBA will be our primary example, because RMI-IIOPmarshalling is based on the CORBA transport protocol (IIOP). We'll go over the basic functions of the transport protocol and ORB (object request broker) in sending a request, locating a remote object, and transporting that objectover a network.

Remote object transport

When a CORBA request is marshalled, it is done using the IIOP protocol. Simply put,IIOP represents the elements of any IDL (Interface Definition Language)construct in a standardized format as a series of bytes. So, assume that a Javaclient is dispatching a CORBA request to a C++ server. The client applicationhas a reference to the remote object in the form of a Java interface, and itinvokes an operation on that interface. Under the hood, the interface invokesits corresponding implementation of the operation, which will be in the stub(which you will have generated from IDL using idlj).

The stub dispatches the method call down into the ORB, which consists of two parts: theclient ORB and the server ORB. The client ORB's job is to marshall requests onto the network destined for a specific location. The server ORB's job is to listen for requests coming off the network and to convert them into method calls that a language implementation canunderstand. For a more in-depth discussion of the role of a CORBA ORB, refer to the Resources section.

After the stub dispatches the method call, the client ORB converts the request, including all parameters, into a standardized byte format, in this case IIOP. The request isthen sent out on the wire to the server ORB, which should be listening for the incoming request. The server-side ORB will read in the bytes of data and convert the request to something meaningful to a C++ server implementation. The C++ server method will do its thing (that is, invoke the requested method) and return the result to the client over IIOP, using the same mechanism.

RMI handles requests similarly, but uses JRMP (Java Remote Messaging Protocol) as its transport protocol. And, of course, RMI transport involves the serialization of Java objects.

Differences between CORBA and RMI
  • CORBA runs over the IIOP protocol; RMI uses JRMP.
  • CORBA is language independent; RMI is purely Java-to-Java.
  • RMI uses JNDI to locate remote objects; CORBA uses CosNaming.
  • RMI serializes objects; CORBA does not.

Remote object location

CORBA uses the CosNaming naming service to locate remote objects. CosNaming provides a framework for a name server to hold bindings (or references) to CORBA server processes. When a CORBA client sends a CosNaming request to the name service for a server process of a givenname, the name service returns an interoperable object reference (IOR) forthat process. The client then uses that IOR to communicate directly with theserver process.

The IOR contains information about the server process, such asits location. One of the downsides of the CosNaming service isthat an IOR is illegible to humans -- at least those of us whodon't have cyborg brains! RMI, on the other hand, is a bit more user friendly.It locates remote objects using a registry (much like a naming service) running on top of JNDI. The RMI registry uses the Java Reference object, which is composed of RefAddr objects, to identify and locate remote objects. These Java objects are more user friendly than an IOR.

COBRA has fairly recently incorporated the Interoperable Naming Service (INS)into its object-location scheme. INS runs over CosNaming, using human-readable URLsas its object locations. INS doesn't make use of a naming service; instead, it sends invocations directly to the specified URL. See Resources to learn more about INS.



Back to top

RMI versus CORBA

So, which is better: CORBA or RMI? The answer depends on what youwant to do. CORBA is a big tried-and-tested architecture running over anindustry-standard third- or fourth-generation protocol. When you take into accountall the add-ons CORBA offers (such as transaction processing, interceptors for security, eventchannels, and more), CORBA seems to be the answer for enterprise applications. The big drawback with CORBA is that it's complicated. Developers generally havea steep training curve to reach CORBA fluency.

RMI, on the other hand, is fairly easy to learn. It's quite simple to create a client/server implementation, bind to a registry and remote object, and invoke and/or receive a request using RMI. RMI also has amuch smaller footprint than CORBA, since JRMP is a considerably less costlyprotocol than IIOP. But RMI lacks CORBA's industrial-strength add-ons,and is a purely Java-based mechanism. So, what we really want isthe flexibility and ease-of-use of RMI coupled with the enterprise-readiness ofCORBA, right? Enter RMI-IIOP.

Why RMI-IIOP?
  • RMI-IIOP combines the strength of CORBA with the flexibility of RMI.
  • RMI-IIOP is easy for developers to use and integrates easily into most corporate infrastructures.

Overview of RMI-IIOP

RMI-IIOP lets you run RMI invocations over IIOP with very little modification. WithRMI-IIOP you can write straightforward Java code and also use the rich suite of enterprise features that CORBA has to offer. Furthermore,the code is flexible enough to run over either RMI or IIOP. This means yourcode can run in a pure Java environment when a small footprint and flexibility are key or integrate into an existing CORBA infrastructure with minimal code changes.

One of the very powerful features of RMI-IIOP is that it lets youwrite pure-Java client/server implementationswithout losing the flexibility of RMI class serialization. RMI-IIOPaccomplishes this by overriding Java serialization and converting the Javaclasses to IIOP on the wire. On the other side, the Java class is read off thewire as IIOP and a new instance of the class is created (using reflection) withall its member's values intact -- and voila: Java serialization overIIOP!

For RMI-IIOP to achieve transparent object location, ORB vendorshave historically used the Java CosNaming service provider (or plug-in inlayman's terms). The plug-in acts beneath the JNDI API to access the CORBA namingservice. Although I do not have the space to go into the reasons here, this naming solution isn't ideal. As a result, numerous vendors -- particularly application servervendors -- have developed proprietary object location mechanisms for RMI-IIOP.

RMI-IIOPalso supports INS as an extension to the Java CosNaming service.Because I believe that INS will set the direction of object location inthe future, the code example we'll work with in this article uses INS.

Note: Because Sun has not yet fully complied with the OMG INS standard and has not exposed register_initial_reference on the org.omg.CORBA.ORBinterface, the source code presented in this article will not work withthe Sun JDK. You will need to use the IBM Developer Kit for Javatechnology, version 1.3.1 or greater. I have, however, created aSun-compatible example that uses a naming service, which you candownload from the Resources section.



Back to top

Do-it-yourself RMI-IIOP

Enough talk, let's code! In the following sections we'll build a simple, Java-basedclient/server RMI-IIOP application. This application consists of three parts: the RMI interface, the server application, and the client application. The example features Java serialization over IIOP, so you can see how a Java class can be instantiated by the client, passed to the server, altered by the server, and passed back to the client with the alterations intact.



Back to top

Part 1: Define the interface

Under RMI-IIOP we can choose to define our interface using RMI or IDL. Because we wantto see how RMI runs over IIOP, we'll define the example interface using RMI.Listing 1 is the RMI interface for our simple example:


Listing 1. RMIInterface.java
/*
* Remote interface
*/
public interface RMIInterface extends java.rmi.Remote {
public String hello() throws java.rmi.RemoteException;
public SerClass alterClass(SerClass classObject)
throws java.rmi.RemoteException;
}

The RMIInterface defines a hello() method and an alterClass(SerClass) method. This methodtakes SerClass, a Javaclass that implements Serializable, and returns a class of the same type. SerClass is a simple class with a few membersand corresponding getter methods. The methods are shown in Listing 2:


Listing 2. SerClass.java
/**
* This class is intended to be serialized over RMI-IIOP.
*/
public class SerClass implements java.io.Serializable {
// members
private int x;
private String myString;

// constructor
public SerClass(int x, String myString)
throws java.rmi.RemoteException {
this.x=x;
this.myString=myString;
}

// some accessor methods
public int getX() { return x;}
public void setX(int x) { this.x=x; }
public String getString() { return myString; }
public void setString(String str) { myString=str; }
}

That's all there is to our simple interface. Now let's check out theserver class.



Back to top

Part 2: Build the server

We'll use a server class (Server.java) that both actsas the RMIInterface implementation class and contains the main method tostart our service. Server.java extends javax.rmi.PortableRemoteObject. In this way, it containsall the functionality it needs to bind itself as a Remote interface to the ORB and begin listening forrequests. Listing 3 is the code for the server:


Listing 3. Server.java
/*
* Simple server
*/
import java.util.*;
import java.rmi.Remote;
import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;
import javax.rmi.CORBA.Tie;
import javax.rmi.CORBA.Util;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.*;
import org.omg.PortableServer.Servant;
import org.omg.CORBA.ORB;

public class Server extends PortableRemoteObject
implements RMIInterface {
// must explicitly create default constructor
// to throw RemoteException
public Server() throws RemoteException {
}

// implementation of RMIInterface methods
public String hello() throws RemoteException {
return "Hello there!";
}

public SerClass alterClass(SerClass classObject)
throws RemoteException {
// change the values of SerClass and return it.
// add 5 to X
classObject.setX(
classObject.getX() + 5 );
// alter the string
classObject.setString(
classObject.getString() + " : I've altered you" );
return classObject;
}

public static void main(String[] args) {
try {
// create the ORB passing in the port to listen on
Properties props = new Properties();
props.put("com.ibm.CORBA.ListenerPort","8080");
ORB orb = ORB.init(args, props);

// instantiate the Server
// this will automatically call exportObject(this)
Server s = new Server();

// now get the Stub for our server object -
// this will be both
// a remote interface and an org.omg.CORBA.Object
Remote r=PortableRemoteObject.toStub(s);

// register the process under the name
// by which it can be found
((com.ibm.CORBA.iiop.ORB)orb).
register_initial_reference("OurLittleClient",
(org.omg.CORBA.Object)r);

System.out.println("Hello Server waiting...");
// it's that easy -
// we're registered and listening for incoming requests
orb.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}

Er, what's happening here?

The server application is code heavy, so let's break it down. First of all, aspreviously mentioned, the Server class implementsRMIInterface and provides implementations for all ofits methods. You can see the implementations of the RMIInterface's hello() and alterClass(SerClass) methods at the beginning of the code.The hello() method simply returns the String "Hellothere!" The alterClass(SerClass) method takes aSerClass object, alters the member values, andreturns the new object -- all using RMI-IIOP.

Server.java's main method initializes an ORB. It passes in the com.ibm.CORBA.ListenerPort property set to 8080 as a parameter. This willcause the ORB to listen for incoming requests on port 8080. Note that com.ibm.CORBA.ListenerPortis a proprietary IBM property. If you want to run this code on another vendor'sORB you should refer to that vendor's documentation for the appropriate property. (Sun usescom.sun.CORBA.POA.ORBPersistentServerPort, but it only works ifyou're using POA (portable object adapter) servants.)

With the ORB initialized, the main method moves on to instantiate a Server object. Because the server object isalso a PortableRemoteObject, the default constructorautomatically makes a call to exportObject(this). The object is now ready to receive remote calls.

Next, we need to register the object with a call to ORB.register_initial_reference(String,orb.omg.CORBA.Object).For this, we need to have a reference to our server objectas an org.omg.CORBA.Object. The call PortableRemoteObject.toStub(s) accomplishes this, becausethe returned object implements both java.rmi.Remote and org.omg.CORBA.Object.

The returned org.omg.CORBA.Object object is then registered with the server-side ORB as "OurLittleClient". To ensure that an INS request can locate the object, we use the registration call register_initial_reference. When an INS call comes into an ORB, the ORB will look for an object that has been registered under the name being requested. Since we registered the object as "OurLittleClient", we'll know what object the client is looking for when an INS callcomes into our server ORB for "OurLittleClient".

Finally, I'm sure that you've noticed that we cast the ORBto a com.ibm.CORBA.iiop.ORB. Because Sunhas not yet exposed register_initial_reference onthe org.omg.CORBA.ORB interface, the IBM SDK cannot expose it either. Therefore we must cast our ORB into an IBM ORB. Future versions (post 1.4.0) of the JDK will probably not require this cast, as Sun's compliance with the OMG evolves.

And that's it! Easy-peasy -- well, sort of. Our server is nowawaiting incoming client INS requests. But what about that client?



Back to top

Part 3: Build the client

The code for the client application is shown in Listing 4:


Listing 4. Client.java
/*
* Client application
*/
import javax.rmi.PortableRemoteObject;
import org.omg.CORBA.ORB;

public class Client {
public static void main(String[] args) {
try {
ORB orb = ORB.init(args, null);

// here's the URL for the local host
String INSUrl =
"corbaloc:iiop:1.2@localhost:8080/OurLittleClient";

// get the reference to the remote process
org.omg.CORBA.Object objRef=orb.string_to_object(INSUrl);
// narrow it into our RMIInterface
RMIInterface ri =
(RMIInterface)PortableRemoteObject.narrow(objRef, RMIInterface.class);

// call the hello method
System.out.println("received from server: "+ri.hello()+"/n");

// try RMI serialization
SerClass se = new SerClass(5, "Client string! ");
// pass the class to be altered on the server
// of course behind the scenes this class is being
// serialized over IIOP
se = ri.alterClass(se);
// now let's see the result
System.out.println("Serialization results :/n"+
"Integer was 5 now is "+se.getX()+"/n"+
"String was /"Client String! /"
now is /""+se.getString()+"/"");
} catch (Exception e) {
e.printStackTrace();
}
}
}

How the client code breaks down

The client code is somewhat simpler than the server code. We initialize an ORB andmake a call to string_to_object(String), where thestring is our INS URL. Constructing the INS URL is relatively simple: first we specifythat we're using a corbaloc URL (see Resources) andthe IIOP protocol version 1.2. Next we add in the host name (www.whatever.com) and the porton which to connect. And, finally, we specify the name of the service we're looking for. The resulting INS URL is corbaloc:iiop:1.2@localhost:8080/OurLittleClient.

When we pass this URL into ORB.string_to_object(String) the ORB will dispatch a request to the specified server for the requested service.Assuming that everything is working as it should, the ORB will receive back an object reference (really an IOR) for the service. We then narrow the object reference into something we can use, namely an RMIInterface, and we're ready to start callingmethods.

After we've called the simple hello method (which should require no explanation),we can begin exploring RMI-IIOP's serialization feature. First, we create a SerClass, a serializable Java class, and initialize its member variables. Next, we pass this class into our method, which writes it out over IIOP to the server. The server reads the class in and re-creates it as a server-side Java object, alters its member values, and returns it (using IIOP) as the return value of our method. When we receive the re-created object after the remote method call, we see thatits members have indeed been changed by the server. And it's that simple:Java serialization over IIOP.



Back to top

Part 4: Run the example

Note that the example we've created here must be run with an IBMDeveloper Kit for Java technology, version 1.3.1 or greater. If youprefer to use a Sun JDK please download the Sun-specific source code,which should be run with a Sun 1.4.0 JDK or greater. This source codeincludes a readme.txt file that explains the differences between theIBM SDK and the Sun JDK versions. If you don't have an IBM DeveloperKit for Java technology (and you want one) download one now; they're free.

Here's how to run the example:

  1. Download the source file.

  2. javac all the files by typing javac *.java.

  3. Run rmic on the server class with the IIOP flag: rmic -iiop Server.

  4. Start the server: on Windows, type start java Server.

  5. Start the client: on Windows, type start java Client.



Back to top

A note about RMI-IIOP and EJB components

The EJB 2.0 specification states that EJB components must be ableto run over both RMI and RMI-IIOP. The addition of RMI-IIOP as an on-the-wireprotocol for EJB components has greatly assisted the integration of the J2EE environment into existing corporate infrastructures, most of which are quiteCORBA intensive. But it also poses some problems.

The short version is that integrating custom-built components and EJB components requires you (the developer) to deal with the plumbing, which would otherwise beabstracted for you by the EJB architecture. As of yet, there is no simple solution to this problem, and there may never be. The solution could come fromevolving technologies such as Web services, but that is as yet unknown.



Back to top

Conclusion: Where to go from here

It is my hope that this article has shown you how easy it is to build and run RMI-IIOPclient/server applications. You can play around with the example we used by replacingthe client or server with pure CORBA, though doing so would cutJava serialization out of your application.

If you're thinking of using RMI-IIOP in aCORBA environment it would be worthwhile to see how IDL maps into Java and vice versa. If you're thinking of deploying RMI-IIOP in an insecureenvironment (that is, not your own PC) it would be a good idea to look intoCORBA security features such as interceptors and the CORBA security model, aswell as other CORBA enterprise features such as transaction processing. All of CORBA's rich features are available to you when you run RMI-IIOP.



Resources

  • Download the IBM-compatible source for this article.



  • Download the Sun-compatible source for this article.



  • The IIOP protocol is defined by the Object Management Group (OMG),which also develops and maintains the CORBA specification.



  • To learn more about CORBA, visit the OMG's CORBA Web site.



  • To learn more about RMI, visit the RMI homepage.



  • The Java Developer Connection offers an INS tutorial that also provides a general introduction to the naming services, the CosNaming service, and thecorbaloc URL format.



  • Want to expand your Java technology options? See the complete listing of IBM Developer Kits for Java technology.



  • For a further introduction to programming with RMI and CORBA, take the tutorial, "Java distributed objects: Using RMI and CORBA" (developerWorks, November 2002).



  • If you're new to programming with EJB components, you might want to take the tutorial,"Getting started with Enterprise JavaBeans technology" (developerWorks, April 2003).



  • To learn more about the relationship between EJB technology and CORBA, see Ken Nordby's"Deploying and using Enterprise JavaBeans components" -- Part 3 in a three-part introduction to EJB technology (developerWorks, July 2000).



  • RMI-IIOP's lead architect offers his perspective on the technology inthe JavaWorld article, "RMI over IIOP"(JavaWorld, December 1999).



  • For a well-rounded perspective on RMI-IIOP, see the ServerSide.com article "RMI/IIOP, nice idea but the reality is turning out to be different," which focuseson what RMI-IIOP doesn't deliver (TheServerside.com).



  • You'll find hundreds of articles about every aspect of Java programming inthe developerWorks Java technology zone.


About the author


Damian Hagge works at IBM's HursleyDevelopment Laboratories. Although he currently lives in the UK, he originated five hours counterclockwise from his present location just above the forty-ninth parallel (that's Canada for those whose geography isn't up to scratch). Aside from working as a developer on the IBM Java ORB team and writing long articles on obscure subject matter, Damian is a veritable encyclopedia of useless facts; for instance, did you know that Iceland supports a self-sustaining banana-growing industry? Damian also does some normal stuff like power lifting (if you call that normal!). You can contact him at Hagge@uk.ibm.com.


From: http://www.ibm.com/developerworks/library/j-rmi-iiop/
原创粉丝点击