[Previous] [Contents] [Next] [IONA Technologies]


Chapter 2
Getting Started with Java Applications


Contents

2.1 A Simple Application
2.2 Programming Steps
2.3 The IDL Specification
2.4 Compiling the IDL Interface
2.5 The Generated File Structure
2.6 The Generated Source Files
2.7 The Generated Code
2.7.1 The Client: Types Grid and _GridRef
2.7.2 The Server: Types _GridOperations, _boaimpl_Grid and _tie_Grid:
2.8 Implementing the Interface
2.9 Providing a Server
2.9.1 Error Handling: Integration with Java Exceptions
2.10 Compiling the Server
2.11 Registering the Server
2.12 Writing a Client Application
2.12.1 Error Handling: Integration with Java Exceptions
2.13 Compiling the Client Application
2.14 Running the Client Application
2.15 Possible Extensions to the Example



In this chapter, we will introduce OrbixWeb by describing a simple example. In this example, we will define an IDL interface, implement this in a Java application and develop a standalone client application.

In the next chapter, we will expand this example to illustrate how OrbixWeb applications can be integrated with Java applets. We will also introduce some of the issues which affect this integration.

At this early stage, we will explain only what is necessary to understand the example. We will avoid being slowed down by unnecessary details.

2.1 A Simple Application

The example that we will develop in this chapter is a two-dimensional grid. This will be implemented by a Java class and installed in a server: that is, as an element of the system in which OrbixWeb objects execute. We will also illustrate how Java applications can act as clients to servers that contain objects which implement the IDL definition.

The server and client can be run on different machines in the distributed system; or in different address spaces in the same machine; or indeed within the same address space.

The grid example has been chosen here because it is an abstract view of a number of commonly used components, such as a spreadsheet or a relational table. Some comments will be made at the end of this chapter to discuss how our simple application can be extended to handle added complexity that may arise in a real application.

2.2 Programming Steps

The following programming steps are typically required to write a distributed client/server system in Java, using OrbixWeb:

We will illustrate these steps in the remainder of this chapter.

A version of the sample code described in this chapter is available in the grid demonstration directory of your OrbixWeb installation. However, readers should be aware that the documented code may differ slightly from the installation example.

2.3 The IDL Specification

The first step in writing an OrbixWeb program is to define the interfaces to the application objects/components, using IDL.

The interface to our grid can be defined in IDL as follows:

The interface provides two attributes: height and width which define the size of the grid. Since these are labelled readonly they cannot be directly modified by a client.

There are also two operations:


     set()
    
which allows an element of the grid to be changed, and

     get()
    
which returns an element.

The parameters to the operations are labelled as in, which means that they are being passed from the client to the server. In other interfaces, parameters may have to be labelled as out (from the server to the client) or inout (in both directions).

2.4 Compiling the IDL Interface

The IDL specification must be compiled, both to check the specification and to map it into the target programming language.

The OrbixWeb IDL compiler can be run as follows1:

IDL compilation results in the generation of several Java data types which correspond to the IDL definition, in accordance with the OrbixWeb mapping from IDL to Java. In particular, the IDL compiler produces a set of Java data types which allow a client to access an object through the Grid interface, and another set of data types which allow a Grid object to be implemented in a server.

2.5 The Generated File Structure

The above IDL compilation produces seven Java data types (five classes and two interfaces) from the definition of interface Grid. In compliance with Java requirements, each public class or interface is located in a single source file with a .java suffix. Each source file is located in a directory which follows the Java mapping for package names to directory structures.

By default, the OrbixWeb IDL compiler creates a local java_output directory into which the generated Java directory structure is placed. An alternative target directory can be specified with the IDL compiler -jO switch.

Given the above IDL definition and compilation command, the IDL compiler produces the directory structure shown in Figure 2.1.


Figure 2.1: File structure output by the IDL compiler

2.6 The Generated Source Files

The IDL compiler produces seven Java source files (for a single IDL interface definition). Each generated file contains a Java class or interface (scoped within the package specified in the -jP switch, if any) which serves a specific role in application development:

     _GridRef
    
A Java interface; the methods of this interface define the Java client view of the IDL interface.

     Grid
    
A Java class which implements the methods defined in interface _GridRef. This class provides functionality which allows client method invocations to be forwarded to a server.

     _GridHolder
    
A Java class which defines a Holder type for class Grid. This is required for passing Grid objects as inout or out parameters to and from IDL operations.

     _GridOperations
    
A Java interface which maps the attributes and operations of the IDL definition to Java methods. These methods must be implemented by a class in the server.

     _boaimpl_Grid
    
An abstract Java class which allows server-side developers to implement the Grid interface using one of two techniques available in OrbixWeb; this technique is called the BOAImpl approach to interface implementation and will be described in later chapters of this guide.

     _tie_Grid
    
A Java class which allows server-side developers to implement the Grid interface using one of two techniques available in OrbixWeb; this technique is called the TIE approach to interface implementation and will be described later in this chapter.

     _dispatcher_Grid
    
A Java class used internally by OrbixWeb to dispatch incoming server requests to implementation objects. Application developers do not require an understanding of this class.

The class _GridHolder is not relevant to the programs developed in this chapter.

It is important to note that by default all IDL generated Java classes are defined in the global package, which may be useful for small test programs but has the potential of introducing name clashes. In the examples which we will develop in this chapter, we use the IDL compiler -jP switch to specify a package name into which all generated Java classes are placed. This can be done as follows:

2.7 The Generated Code

The relationships between the Java types produced by the IDL compiler can be illustrated by a brief examination of the generated source code.

2.7.1 The Client: Types Grid and _GridRef

To support client application development, the OrbixWeb IDL compiler maps the IDL interface Grid to a Java interface and a corresponding Java class which implements that interface. The code described here was not compiled with the IDL -jP switch, so the Java types are not scoped within a package name.

The _GridRef.java file produced by the IDL compiler contains the following Java interface definition:

This Java interface defines an OrbixWeb client view of the IDL interface defined in grid.idl. It is implemented by the Java class Grid in the file Grid.java:

The primary role of this Java class is to transparently forward client invocations on Grid operations to the appropriate Grid implementation object.

The IDL compiler generates both a Java interface and a class which implements that interface in order to allow the mapping of IDL multiple interface inheritance to Java (which supports multiple inheritance of interfaces, but not multiple inheritance of classes). This issue is covered in detail in Chapter 13, "Inheritance".

Let us now consider the mapping of the operations set() and get(). The mapping to Java is very straightforward: each IDL operation is mapped to a Java method. The parameters, which were IDL basic types in the IDL definition, are mapped to roughly equivalent Java basic types. For example, the IDL type long (a 32 bit integer type) maps to the Java type int (also a 32 bit integer type).

The two readonly attributes have been mapped to with Java methods (get_height() and get_width()). Since the server and client might not be in the same address space, there would be no point in mapping attributes with Java public member variables.

All the Java methods generated by the IDL compiler include a throws clause, which specifies that they can throw the OrbixWeb system exception type SystemException. Class SystemException is defined in the OrbixWeb package IE.Iona.Orbix2.CORBA and is the base class for all OrbixWeb system exceptions. OrbixWeb system exceptions allow clients to handle errors raised during manipulation of or communication with objects in the distributed system.

2.7.2 The Server: Types _GridOperations, _boaimpl_Grid and _tie_Grid:

The generated Java interface _GridOperations defines the Java methods which a server class must implement in order to support the IDL interface Grid. The file _GridOperations.java contains the following:

In OrbixWeb servers, Java classes are used to implement IDL interfaces. There are two alternative approaches used to indicate that a Java class implements an IDL interface: the BOAImpl approach and the TIE approach. To provide support for each approach, the IDL compiler generates code for two Java classes. In our example, these classes are class _boaimpl_Grid and class _tie_Grid.

For reasons which will be discussed in Chapter 6, "Programming OrbixWeb using Java", the TIE approach is often the preferred strategy for IDL interface implementation in OrbixWeb servers; we will focus on this approach in this chapter.

Programmers who wish to implement IDL interfaces using the TIE approach do not need to understand the full details of class _tie_Grid. However, it is useful to be aware that an object of type _tie_Grid stores a reference to a user-supplied implementation object, to which it simply delegates incoming method invocations. For example, the source code generated in file _tie_Grid.java can be outlined as follows:

2.8 Implementing the Interface

In order to implement the Grid interface, the programmer must write a Java class which implements the methods listed in the Java interface _GridOperations. The programmer must also indicate that this class implements the interface Grid using either the BOAImpl or TIE approach. In this section, we will illustrate how to achieve this using the TIE method.

In the example server and client applications, we will assume that the IDL file described above was compiled with the following command:

All the application data types will then be placed within the gridtest package.

We will call our implementation class GridImplementation (in file GridImplementation.java), and we will ensure that it implements the attributes and operations defined in IDL type Grid by implementing Java interface _GridOperations, as follows:

Interface _GridOperations is automatically produced by the IDL compiler and defines the Java methods which our implementation class must provide in order to support IDL type Grid.

Class GridImplementation will implement each of the methods get_width(), get_height(), get() and set(); and it will also add some member data and a constructor:

2.9 Providing a Server

In order to service client requests on the Grid interface, we need to write a server application in which we can instantiate a Grid implementation object (of type GridImplementation). We then indicate to OrbixWeb that this object can be accessed through IDL interface Grid by passing it to the constructor of a _tie_Grid object.

Conceptually, the simple Java class illustrated below demonstrates how this could be achieved. However, this Java class will not compile without the addition of error handling code as described in section 2.9.1.

This server program creates a GridImplementation object, giving it an initial size. It then creates a TIE object which stores a reference to the GridImplementation object and indicates to OrbixWeb that the server's initialisation has completed, by calling impl_is_ready().

The parameter to impl_is_ready() is the name of the server as registered in the Implementation Repository (see section 2.11). _CORBA.Orbix is an object which is used to communicate directly with OrbixWeb. As used here, impl_is_ready() is a blocking call that returns only when OrbixWeb times-out the idle server. Hence the call to impl_is_ready() will not return for some time.

2.9.1 Error Handling: Integration with Java Exceptions

If an error occurs during an OrbixWeb method invocation, the method may raise a Java exception to indicate this. Therefore, it is necessary to enclose such calls within Java try statements. Exceptions thrown by OrbixWeb method invocations can then be handled by subsequent Java catch clauses.

All OrbixWeb system exceptions inherit from type SystemException (defined in package IE.Iona.Orbix2.CORBA), so it is possible to handle all possible system exceptions by passing this type to a catch clause. This can be done as follows:

or as follows:

For example, the server class described above could be coded as follows:

The code in the catch clauses simply displays details of possible system exceptions raised by OrbixWeb. It achieves this by printing the result of the SystemException.toString() method to the Java System.out print stream.

In this example, it is particularly important to note that the constructor for the IDL generated _tie_Grid type may raise a system exception; so the instantiation of the TIE object should be enclosed in a try statement.

2.10 Compiling the Server

The exact details of application compilation are specific to the Java development environment in use. However, it is possible to describe the general requirements and we will illustrate these with examples for Sun Microsystems' Java Developer's Kit, which is the development environment used by the OrbixWeb demonstration make files.

To compile the server (or any OrbixWeb application), it is first necessary to ensure that the Java compiler can access the following:

The IE.Iona.Orbix2 package is normally installed in the OrbixWeb classes directory.

For example, if using the javac compiler to build the grid client application, the location of Java API classes and that of the IE.Iona.Orbix2 package should be added to the CLASSPATH environment variable or specified in the -classpath switch as follows:

The server application can be compiled by invoking the Java compiler on all the associated Java source files. In the grid server example, the necessary source files are:

The OrbixWeb grid demonstration directory provides a makefile which invokes the javac compiler as required. In this directory, it is simply necessary to type (on Unix):

or (on Windows 95 or Windows NT):

2.11 Registering the Server

To avoid running the server through the Java interpreter manually, the server should be registered in the Implementation Repository. The Implementation Repository is a server `database' which maintains a mapping from the server name to the name of the Java bytecode that implements that server. If the server is registered, it will be automatically run through the Java interpreter when a client uses our Grid object.

To register the server, use the putit command on your local machine:

The first parameter to putit is the server's name which we have chosen as GridSrv. This was also the name of the server passed to impl_is_ready() in section 2.9.

The second parameter is the name of the class which contains the server main() method, that is the name of the class which should be interpreted by the Java interpreter. Finally, the third parameter indicates the class path for the server classes.

Note that the client and server in this example will not work unless the server is registered using putit. If the server were not registered, minor modifications to the client and server code, or a special OrbixWeb daemon setting would be required.

Chapter 11, "Registration and Activation of Servers" provides a full specification of the putit command.

2.12 Writing a Client Application

We have now outlined how to define and compile IDL interfaces, how to implement these interfaces and how to provide an OrbixWeb server which instantiates implementation objects. In this section, we will demonstrate how Java clients can be written which access implementation objects through IDL interfaces.

The most simple form of client application could be written as illustrated below. However, this Java class will not compile. Error handling code must be added to this class and a fully developed version will be described in section 2.12.1.

Class Client defines a member variable of type _GridRef. The client calls the static method _bind() on class Grid to create an instance of Grid which can be accessed via the _GridRef Java interface. This object acts as a proxy for an object that implements IDL interface Grid in the OrbixWeb server. A proxy is a local Java object which acts as a representative for a remote object; its purpose is to transparently forward Java method invocations to the remote object.

The _bind() method creates a proxy object of type Grid and binds it to an implementation object, running in the GridSrv server. The first parameter to _bind() is a string of the form:

It names the object and the server in which the object is running. In the example, the object is not named so OrbixWeb is free to choose any Grid object in the specified server. The server name, GridSrv, is the name of the server as registered in the Implementation Repository on the server host (as described in section 2.11).

The second parameter to _bind() specifies the host name for the target server. In this example application, the host name is taken from a command line argument.

2.12.1 Error Handling: Integration with Java Exceptions

A valid OrbixWeb client must check for and handle errors. In particular, the call to _bind() or to any of the Grid operations could fail, especially if the call is to a remote machine. Such calls should be enclosed within Java try blocks which will allow any exceptions thrown by method invocations within the block to be handled by the subsequent catch clauses. Thus, the previous example could be rewritten in a valid form as shown below.

2.13 Compiling the Client Application

Section 2.10 describes the general requirements for compiling OrbixWeb servers and similar requirements apply for OrbixWeb clients.

It is necessary to ensure that the Java compiler can access the Java API packages, the OrbixWeb IE.Iona.Orbix2 package, and all application-specific classes. The compiler should then be invoked on all the Java source files for the application. In this example, the required files are gridtest/Grid.java, gridtest/_GridRef.java, and gridtest/Client.java.

The OrbixWeb grid demonstration directory provides a makefile which invokes the javac compiler as required. In this directory, it is simply necessary to type (on UNIX):

or (on Windows 95 or Windows NT):

2.14 Running the Client Application

Running a Java application involves the invocation of a Java interpreter on the bytecode (.class files) produced in the compilation. When running an OrbixWeb client application, it is necessary to ensure that the interpreter can load the following:

Again using Sun Microsystems' JDK, this can be done by setting the CLASSPATH environment variable to include the location of Java API classes, the location of the IE.Iona.Orbix2 package, and the directory into which the application bytecode files were output in the compilation stage. For an OrbixWeb demonstration, the output files are typically redirected to the classes directory.

The gridtest/Client.class bytecode can then be run through the Java interpreter, for example by typing:

The makefile in the OrbixWeb grid demonstration directory generates a script which implements these steps. This script is named javaclient1 and can be run as follows:

2.15 Possible Extensions to the Example

A number of extensions can be made to our example in order to make it more realistic. For example:

Many more sophisticated architectures can also be supported, such as the use of multiple servers, multiple clients, and the passing of object references as operation parameters.

In the next chapter, we will demonstrate how OrbixWeb functionality can be integrated with Java applets.



1 Before running the IDL compiler you must ensure that OrbixWeb can find its configuration file, Orbix.cfg. On Unix, if this file has been installed in the /etc directory, it will be automatically located. If not, or if OrbixWeb is installed on Windows 95 or Windows NT, the environment variable IT_CONFIG_PATH must be set as described in Chapter 2, "Compilation of IDL and Java" of the OrbixWeb Reference Guide.



[Roadmap] [Introduction] [GS: Applications] [GS: Applets]
[IDL] [Mapping] [Programming OrbixWeb] [Publishing Objects] [Retrieving Objects] [IIOP]
[Running Clients] [Running Servers] [Exceptions] [Inheritance] [Callbacks] [Contexts]
[API Configuration] [TypeCode] [Any] [DII] [IR] [Filters] [Smart Proxies] [Loaders] [Locators]
[Index]