Go to the previous, next section.

Using ILU with Java

Introduction

This document is for the Java programmer who wishes to use ILU. The following sections will show how ILU is mapped into Java constructs and how both Java clients and servers are generated and built.

ILU and CORBA

Ilu is corba compatible. Compatibility is a word from the english language; in case of ILU we mean mainly two things:

1) Ilu can interoperate with other corba compatible orbs.

2) Applications which are written to use only corba compatible features can switch between ilu and other orbs without changing source code.

Sadly ILU's compatibility is not perfect. Not all corba functions are implemented. More noticable is however the fact that we do only try to achieve source compatibility; there is no binary compatibility available.

Compatibility requires the programmers help: in particular the programmer needs to leave the stubber switches appropriately (the default values generate corba compatible stubs).

javasoft's interpretation of the standard mapping: (may or may not be accurate): http://java.sun.com/products/jdk/idl/docs/idl-java.html

The standard mapping is available from OMG as PDF document: ftp://ftp.omg.org/pub/docs/orbos/97-03-01.pdf

The ISL Mapping to Java

Names

If ILU is used in standard mapping mode, its naming scheme matches the corba standard. Even resolution of naming conflicts is mostly corba compatible. However for some conflicts there might be slight differences, and, Ilu considers certain names to be conflicting which have not been mentioned in the corba standard.

In particular Ilu considers methods names used by the java.lang.Object class to be "reserved" and causing conflicts. Not doing so would generate confusing errors if a generated method would conflict with a standard method by using identical arguments.

Interface

An ISL interface is mapped to a Java package with the same name.

There is a stubber option to put a prefix to the Java package, to make it a nested package.

Avoid IDL features which are not in the scope of a idl module (= ISL Interface).

Basic Types

See the corba standard.

The "new" extended IDL types fixed is not yet supported.

128 bit floating point values are carried around as "xerox.ilu.types.float128" but no operations are available.

In case of "byte", ILU carries the bit pattern, not the numerical value.

Constant

Strings

Pickles and Typecodes

Constructed Types

Enumeration

Array

Sequence

Record

Union

Optional

ISL Optionals have no corresponding corba type. If the base type of the optional maps into a Java primitive type we will represent the optional with the corresponding Java wrapper or container class. (Boolean, Character, Double, Float, Integer, Short, Byte, or Long). The null value represents absence of the parameter.

If the base type of the optional maps into a Java object type, the optional is mapped as if it weren't optional. The null value represents absence of the parameter.

In the case of Java Strings the difference between a null String and an empty string serves this distinction perfectly.

Object Types

Surrogate and True Object Types

To request creation of an object the createTrueObject method is called. The implementation of createTrueObject is expected to call super.returnTrueObject to register the created object.

Methods, Parameters, and Exceptions

Garbage Collection and COLLECTIBLE

Access to standard ILU features

Servers and Ports

True Servers

Each object exported by an implementation must belong to a true server, an instance of the Java type IluServer which is implemented by the xerox.ilu.IluServer class.

An IluServer instance can be created by calling the function ilu.createServer([serverID]), which returns a value of type IluServer. If serverID is a string, it specifies the server ID; if it is the Java value None, a server ID will be invented automatically.

Other methods allow the specification of a daemon flags or ports for different transports or protocols, or an object table, which allows specification of a callback function for creating true instances on demand.

The first time a true server is created, it becomes the default server. The default server is used for an exported object if a server is not otherwise specified or when it is explicitly requested with the defaultServer method. If an object is exported before any servers have been created, one will be created automatically using default parameters and possibly a message to that effect will be written to System.err.

An object of type IluServer has an accessor method serverId() that returns its server ID.

Look at the Java classes IluServer and IluPort for details. In general servers may be omitted and a default server is used. IluPort as well may be ommited.

Object Tables

Object tables are defined in the class IluObjectTable. To define an object table one subclasses IluObjectTable and attached the subclasses to an IluServer when the server is created. An IluObjectTable can only be attched to one IluServer.

Because the Object Tables calls are made with internal ILU locks held, it must not do recursive calls into ILU.

Threading and Event Loops

ILU uses Java threads. There is no event loop option.

It is possible to change thread priorities by setting properties at start up of the application. This is however not recommended.

Custom Records

Record types can be subclassed. The subclass can register itself with the original (stub) class.

"Custom Records" class assign their own class to a (protected) java.lang.Class variable of the original stub class for the record. Whenever ILU needs to allocate an instance of such a record it will allocate a an instance of the subclass instead.

Custom Surrogates

Surrogate creation can be intercepted. To do so one registers either a Java class, or, a factory object with the stub class implementing a object type. See the methods IluClassRep.setSurrClass or IluClassRep.setSurrFactory for details.

String Binding Handle Formation

The class xerox.ilu.IluSBH provides methods for both scanning and composing string binding handles.

Simple Binding

An object may be published using the simple binding service by calling the method
xerox.ilu.IluSimpleBinding.publish().

An object may be unpublished by calling the method xerox.ilu.IluSimpleBinding.withdraw().

A published ILU object may be obtained by calling xerox.ilu.IluSimpleBinding.lookup(sid, ih, cl), where sid is object's server's server ID, ih is the object's instance handle, and cl is its class.

Principal Identities and Passports

Passport are represented in the class IluPassport. Identities are represented by the class IluIdentity. The class IluIdentityType represents the type of an identity. A passport can carry at most one IluIdentity of each IluIdentityType.

Client generated passports are mutable and stay alive until garbage collected. Clients tell ILU about their passports via the current thread which must be a subclass of IluServiceThread. The methods IluServiceThread.setMyStubPassport and IluServiceThread.setStubPassport can be used to set passports. For security reasons passports of other threads can not be set. (We need to rethink the possible threats). However it is possible to clear the passport of any thread (as this is only a denial of service attack).

Ilu generated passports are immutable and can be used only while the call for which it has been constructed is ongoing. If used afterwards, an exception will be raised. For a client to access an Ilu generated passports, the method IluPassport.getSkeletonPassport is used.

These passport features are carried around fully, but since the api to create identities and identity type features are still missing, usefullness of passports is grossly limited.

Building Java/ILU Applications

Please read the introductory section on "Java Administrativia Without ILU" first.

Java Administrivia Without ILU

This section will be required knowledge when we explain how to do Java administrativia WITH ILU later.

The first time you see any of the standard Java tree structures you are bound to be overwhelmed. However, it is not that bad if you know some of the reasoning. If you have a good understanding of the Java system building concepts without ILU, you will tolerate Java with ILU much better.

The Java compiler takes Java sources and creates binaries, typically called class files. (Never mind, that the word "class" has as a meaning in the source domain as well).

The Java compiler conceptually copes with 4 file hierarchies.

  1. Where it takes its source input from.
  2. Where it takes its takes binaries of pre-compiled imported sources.
  3. Where it stores compiled binaries.
  4. Where it loads itself from.

Sad to say, Sun's documentation is not conceptually clean. The functionality is different when directories are specified as command line options or with environment variables.

  1. Java sources can be thought of as tree structured in the package domain. You may or may not assume that sources are stored in a similar directory nesting as the package nesting. This is not an important issue because the Java compiler lets users specify source files explicitly. (Unless you are working with very explicit make files, I recommend compiling multiple sources with one single compile command and letting the Java compiler worry about dependencies.)
  2. Precompiled binaries or jar files can be found using the -classpath command line switch or the CLASSPATH environment variable. The semantics are different! The -classpath command line switch must be complete (including system binaries), but if the CLASSPATH environment variable is used, the standard binaries are automatically accessed. You can work either way, if you know the difference.

    Some experiments suggest that the compiler may also on the fly generate binaries when needed... We don't rely on this.

  3. The most important `monkey wrench' to know about is where the compiled binaries are stored. The -d option allows one to specify a directory. In the absence of the -d option the compiler uses the working directory. With the -d option binaries are stored hierarchically in the destination directory, according to their package structure. Without the -d option binaries are stored directly in the curent working directory. Recommendation: Always use the -d option. If the -d option is not used some Java tools will not find the binaries... Don't get confused that "Hello World" programs can be compiled without -d option; real programs can't.
  4. The compiler itself loads its own binaries from the CLASSPATH environment variable. Be warned, that is the same environment variable used to locate pre-compiled input sources.

To make matters worse:

Packages

What package to use ? Java ILU is deeply committed to give the choice to the application. (That is why the prefix package is optional).

An application programmer will face the decision whether the implementation for true object should be in the package designated for stubs, or in a package of its own. Both choices do make sense; ILU will work either way and doesn't make that decision for you. In general we expect most applications to prefer working in one single package. However we can imagine scenarios where for security reasons a stub could be trusted but a server object might not be trusted, or they'd be signed independently by different entities.

But please: Don't ever write Java code which is not in a package at all. You will end up putting it in a package later anyway. It will be much more work to do that later than to, at the very beginning, set up all your commands and files to work with a package.

Summary

We recommend a compiler usage by which the input, independent of its structure, is compiled into a hierarchical file structure depending from a directory called `./classes'.

We also recommend putting the `./classes' directory into the CLASSPATH so that the Java loader finds the compiled binaries. The ILU runtime is in the Java package xerox.ilu. The primary interface is the class Ilu.

Stub Generation

To generate Java stubs from an ISL file, use the program java-stubber. Since the stubber creates a surprisingly large number of Java files, these files must be directed to a designated stub directory. For the same reason a file with a list of generated Java files is generated.

The stubber recognizes the following options or switches:

All command line options (unless if documented otherwise) have a second variant with a suffix "1". If the command line option with suffix is used, an extra argument for the name of an interface is read, and the option only affects that interface. The un-suffixed command line options affect all interfaces. Suffixed command line options override un-suffixed command line options. Option processing is from left to right.

The stubber can be run without arguments to generate a usage message.

Problems and Solutions

Java Compilation

Unless you are using make files, we recommend stubbing into empty directories. This allows the Java compiler to compile all Java files with an asterisk syntax. Always use the -d option with the Java compiler!!!

In unix, the report file can be used to generate the list of files to be compiled. It can be used directly with a back-quote cat report-file back-quote syntax.

Execution

At execution time the loader needs to find
  1. Your application and its regular imports (binaries; resp. classes). This is normal Java usage. Use the CLASSPATH environment variable.
  2. Java binaries (classes) from generated stubs. There is nothing special here. Compile the stubs into whatever directory you want (e.g. `./classes/') and put that directory on the CLASSPATH environment variable.
  3. Java binaries (classes) from ILU runtime support. The classes binaries from the ILU runtime support are compiled into the jar file `ILUHOME/lib/ilu.jar'; put this file on your CLASSPATH environment variable.

    If your java system does not support jar files, the classes are compiled into `ILUHOME/lib/javaclasses/'. The reason for this non-standard place is the fact that some ILU developers believe the subdirectory `./classes/' should be reserved for some other purpose.

  4. C binaries (object files) from ILU runtime support and kernel. The C binaries (object files) are accessed using the LD_LIBRARY_PATH. The path must have an entry pointing into the ILU Java runtime directory.

Debugging

Use of the standard ILU debugging environment variable ILU_DEBUG is recommended; please section Debugging ILU Programs.

Java ILU listens to a large number of Java command line switches. The simplest one is to set the -D command line option (e.g. -Dilu.debug.default=4). For more specialized command line switches look at the xerox.ilu.IluDebug.java file.

Note that the -D option of the Java interpreter has no relationship whatsoever to the -d option of the Java compiler.

When using dbx or gdb: The standard Java binaries (classes) are found automaticly (without specification on the CLASSPATH environment variable) when not debugging. When debugging, those classes must be specified on the CLASSPATH. We don't understand this difference.

Implementing an ILU module in Java

A Java program which wants to implement a object type T from interface I needs to create a class which implements the stubber-generated Java interface I. Objects of this class then are registered with the ILU runtime either implicitly or explicitly, or with an object table.

Explicit registration allows specification of additional parameters, like the string binding handle, the server, and more. Explicit registration done by calling the stubber generated method I.T_stub.registerTrueObject(). As an alternative, if the programmer is willing to specify the class, he can also use the method xerox.ilu.Ilu.registerTrueObject directly.

Objects are implicitly registered with ILU if they are returned as a result value from a method call that returns an object type or has an object type as an INOUT or OUT parameter or if they are published using the Simple Binding mechanism.

Hints about implicit registration

If objects are not registered but get auto-registered on use only there are two pitfalls to watch out for.

  1. The ILU type must be unique. If no type is given ILU will look at the Java type and make its best possible guess about the ILU type.
  2. The ILU type must be loaded. Unless the ILU type is loaded the registrar will never find that type. If there is any doubt about whether a stub implementing an ILU type is loaded or not, it might be useful to actually load the class. The xerox.basics.Environment class can be used to load a class from external commands. The stubber also generates a special class whose sole purpose is to help load whatever is necessary for the registrar to not miss a class.

Implementation Inheritance

Exporting Objects

Using an ILU module in Java

A client program may obtain a reference to an ILU object in one of the following ways:

  1. True instance creation.
    The application may create an true instance of a class.
  2. objectFromSBH()
    Knowing the string binding handle sbh and class (or superclass) cl of an object, call xerox.ilu.Ilu.objectFromSBH(sbh, cl) which returns an instance of that class. For example, to obtain an instance of ISL type square from INTERFACE shapes, which has a string binding handle sbh, one would call xerox.ilu.Ilu.objectFromSBH(sbh, shapes.square).
  3. ILU Simple Binding.
    Knowing the object ID (sid, ih) and class cl of an object that has been published using the simple binding service, call xerox.ilu.IluSimpleBinding.lookup(sid, ih, cl) which returns an instance of that class (or raises an exception if the lookup fails).
  4. Return result or parameter.
    An instance may be received as a result value from a method call that returns an object type or has an object type as an INOUT or OUT parameter.

Notes for Java on Windows

Please see the "Java" subsection of "Building ILU" in the chapter section Using ILU with Microsoft Windows.

Java/ILU API Reference

The interface is rather large. This section will cover the most important classes but reading the standard javadoc documentation or reading the source will be more complete.

javadoc documentation

javadoc is about the worst documentation package I have encountered sofar. Nevertheless, ILU java code contains javadoc tags. We think however that reading the source code might be easier then reading the javadoc output.

javadoc documentation: http://java.sun.com/products/jdk/javadoc/index.html

Bugs

The javadoc index is empty. For some reason javasoft prefers to document this bug instead of fixing it.

javadoc documents features which are not to be used by applications. This is an ILU problem as ILU declares many features public simply to make them available to stubs.

It would be nice if javadoc documentation would have links to the source code.

Build of the javadoc documentation

You need to manually create an images subdirectory and copy the images. (Ask javasoft why). Since I don't know how to make the ilu build find the images, the build does not do the javadoc step automatically.

Another reason to not automatically build the javadoc documentation is that different users might want to or not include -package and -private features. The third reason for manual build is that some users might want to include standard packages into the same documentation build.

# create a javadocs directory
# we recommend using ILUHOME/doc/javadocs
# (When making links, they might point to that directory)
mkdir javadocs

# build the javadoc documentation into the javadocs directory
# cd ILUSOURCE/runtime/java
javadoc -d javadocs xerox.basics xerox.ilu xerox.ilu.types xerox.ilu.tools org.omg.CORBA *java

# copy the javadoc images into the proper place
# (Substitute the source as you most likely have the images somewhere else...) 
cd javadocs; mkdir images; cd images; cp /project/java/jdk-1.1.3-sgi/images/* .

Go to the previous, next section.