Editorial Reviews
The Barnes & Noble Review
With Java 2, the Java platform offers a complete, mature set of APIs for enterprise applications. java enterprise in a nutshell brings O'Reilly's trademarked In a Nutshell format to these APIs and that's good news for anyone developing mission-critical applications with Java. The authors present fast, insightful tutorials and example-rich quick-references for each of six key technologies. You'll walk through the fundamentals of JDBC for accessing relational database systems (if you're new to this, it'll help to already know a little SQL). Next, review RMI for creating distributed computing systems; and the Java IDL for interfacing with remote CORBA objects.
Java Enterprise in a Nutshell also covers Java servlets, a great cross-platform solution for extending web servers; JNDI, a protocol-independent interface to network name and directory services systems; and finally, Enterprise JavaBeans, Sun's component model for units of business logic and business data.
You'll wonder how you got along without this book just as thousands of developers wonder how they got along with its best-selling companions, Java in a Nutshell, Third Edition and Java Foundation Classes in a Nutshell. Bill Carnada
Read an Excerpt
Chapter 4: Java IDL
4.4.3 Stringified Object References
As we've seen, Sun's implementation of Java IDL provides a nonstandard way to initialize an ORB to reference a remote Naming Service, so that one of the ORB's initial references is to the root context of the remote Naming Service. But what do you do if you want an object from a remote Naming Service, and your Java IDL implementation doesn't provide a way to directly initialize a reference to the remote service? Or, worse yet, what if the object that you want isn't stored in a Naming Service or available through any other CORBA service? How can your client get a reference to the object?
The CORBA standard comes to the rescue again. Part of the standard, called Interoperable Object References (IORs), includes a syntax for representing a remote object reference in the form of a printable string of characters. This stringified object reference includes enough information for a remote CORBA client to locate the object's home ORB and convert the string to a runtime stub reference to the object. Two methods on the ORB
interface, object_to_string()
and string_to_object()
, let you convert a CORBA object reference to string form and back again.
Example 4.9 shows how to create an instance of our server implementation of the ThisOrThatServer
interface, register it with the ORB, and generate a stringified object reference from the CORBA server object. A stringified reference to a remote object is called an Interoperable Object Reference (IOR) because it uses a format for object references that can be freely distributed between ORBs running a cross the network. In order for the IOR you generate to be acceptable to another ORB, both your ORB and the remote ORB have to be using the same inter-ORB communication protocol (IIOP, DCE-CIOP, etc.). In this example, our client and host are both running IIOP.
Example 4.9: Registering an Object/Getting Its Stringified Object Reference
import org.omg.CORBA.*; public class ServerInit { public static void main(String[] argv) { } }
The ServerInit
class contains a main()
method that is intended to be run on the server host for our remote object. The main()
method first initializes a connection to the local ORB and then creates an instance of the ThisOrThatServerImpl
class. This instance serves as the server implementation of our remote object. We create a stringified reference to the object using the object_to_string()
method on the ORB and then output the stringified reference, so that it can be copied and sent to clients. Finally, by doing a synchronous wait()
on a local object, the main()
method goes into a wait state. This wait()
is necessary to keep the ORB running so that it can respond to client requests. If we let the main()
method exit, the server object we created is destroyed, and the IOR we generated is no longer valid.
A sample client for our object is shown in Example 4.10. The client accepts a stringified object reference as a command-line argument to its main()
method. Then it initializes a local ORB reference and uses its string_to_object()
method to convert the stringified reference to a live object reference. To do this, the ORB parses the encoded information in the stringified reference, makes a connection with the remote ORB serving the object, and generates a CORBA object reference for the client.
Example 4.10: A Client Utilizing a Stringified Object Reference
import org.omg.CORBA.*; public class ServerStringClient { public static void main(String[] argv) { } }
Before we can run the client, the remote object has to be registered with its ORB, so that we can get the stringified object reference:
objhost% java ServerInit ThisOrThatServer IOR: IOR:000000000000002349444c3a6a656e2f636f7262612f546869 734f72546861745365727665723a312e30000000000001000000000000003000010000000000 0a6c6f63616c686f737400043200000018afabcafe00000002496bb469000000080000000000 000000
Somehow, you have to get this IOR to the client host. You could embed the stringified object reference within a hidden field in a HTML page, so that a Java client can access it using a URL
object. Or you could set up a simple server on a given port on your host that broadcasts the stringified object reference to whoever makes a socket connection. Or you could email the string to a colleague, and she can type the stringified reference into the startup command for her CORBA client. In any case, the client is invoked with the IOR as a command-line option:
clienthost% java ServerStringClient IOR:000000000000002349444c3a6a656e2f636f 7262612f546869734f72546861745365727665723a312e300000000000010000000000000030 000100000000000a6c6f63616c686f737400043200000018afabcafe00000002496bb4690000 00080000000000000000
The client uses the argument to reconstitute a remote reference to the server object, so that it can invoke methods on the remote object.
4.5 What If I Don't Know the Interface?
In the examples we've seen so far, we've always assumed that the Java interfaces for the remote objects are available at compile time. But what happens if they aren't? You might get a reference to a CORBA Object
from a Naming Service, for example, and not know what interface that object implements. I mentioned earlier that you can use an org.omg.CORBA.Object
reference directly to make requests and exchange data with its remote object.
The CORBA standard defines two complementary APIs for this purpose: the Dynamic Invocation Interface (DII) that a client can use to make remote method requests of a server object, and the Dynamic Skeleton Interface (DSI) that a server-side skeleton can use to forward method invocations to its server implementation object. Both of these APIs provide the same essential function: a dynamic interface to an object whose interface is not known at compile time. The DII offers this functionality to clients of CORBA objects, and the DSI provides it to the server-side skeletons that bridge the object implementation with the ORB.
The DII and DSI may seem like sidebar topics in the CORBA world, but in reality they are at the heart of CORBA and how it works. When we generate Java stubs and skeletons from IDL interfaces, the code that is generated uses the DII and DSI to execute remote method calls. The details of how this is done are shielded from you, the developer, by the Java interface you use to interact with the remote object. But it's still worthwhile to understand how CORBA objects implement their distributed nature, especially in situations where the Java interface for the remote object is not there, and you need to deal directly with these details.
In this section, we take a look at how the DII works and how you might use it in a client. We won't cover the DSI in this book, since its practical uses are even more limited for the average developer. Note, however, that the API of the DSI is analogous to that of the DII, so you shouldn't have much trouble mapping the following explanation to the DSI as well.
4.5.1 Dynamic Invocation Interface
The Dynamic Invocation Interface provides abstract representations of remote method requests and their arguments. In simple terms, this means it includes objects that represent remote method requests and parameters that are passed with these method requests. Methods on these objects allow you to set the parameters to the request, make the request, and get the results. DII's central classes are:
Request
-
A request to invoke a method on a remote object. Created by the client and issued through the ORB to the server object.
NamedValue
-
A named parameter to a method request. Conceptually, this is a name tied to an Any
value. The name of the value must match the name of the parameter as specified in the IDL interface the remote object satisfies.
NVList
-
A list of NamedValue
parameters used to represent an argument list passed into a remote method request.
Any
-
A general argument value. An Any
object can contain the Java equivalent of any basic IDL type or an Object
that can be described in IDL.
Context
-
A list of NamedValue
objects used to specify any details of the client environment that shouldn't be passed as method arguments.
Once you get an org.omg.CORBA.Object
reference to a remote object (using any of the approaches we've already covered), you can create and issue a method request to the object by building a parameter list for the method call, making a NamedValue
object to hold the result, making a Context
object and putting any useful environment values in it, and then using all of these items to create a Request
object that corresponds to a particular method on the object. Example 4.11 shows a sample DII client that gets a reference to a remote object through a Naming Service and then makes a dynamic call to its doThis()
method.
Example 4.11: Client Using DII to Make Remote Method Call
import org.omg.CORBA.*; import org.omg.CosNaming.*; public class DIISimpleClient { public static void main(String argv[]) { } }
Note that in most situations you will have the Java interface for the remote object available in your client along with its helper class, so you'll be able to narrow the Object
reference to a specific type. One exception might be if you're building some kind of software development tool, and you want to provide a dynamic execution utility for the CORBA code being developed. The previous example demonstrates how a CORBA method call can be carried out at this lower level, in case you ever find it necessary to do so. And when you're trying to fix a problem with your CORBA application, it's always better to understand what's going on under the hood, so to speak.
Read More