|[ Team LiB ]|
Early and Late Binding Models
When you use jCOM to enable a COM client to access your Java objects, it is jCOM's job to make sure that your Java objects look exactly like any other COM component to that client. Remember: One of the main goals here is transparency.
To that end, you'll choose between an early- or late-bound method of object binding directly in support of COM's early and late binding models.
From a COM perspective, when a client program initiates a call to a COM component, the methods and properties of the component referred to by the calling program must be verified to see whether they actually exist and have been specified correctly. This process is known as binding. The verification itself can occur in one of two ways. One approach uses what is called early binding: At compile time, an object's properties and methods are exposed through a virtual method table (VTBL). In late binding, information about the object being called is available only at runtime through the IDispatch interface.
The choice to use early or late binding is predicated on the particular needs of the individual application and the overall environment in which that application resides. With that in mind, we'll next look at each of these modes of object awareness in greater detail while keeping our focus on the advantages and disadvantages found in each. A summary of our findings is listed in Table 33.1.
Probably the most compelling reason to opt for the early binding mode of serving up your Java objects is the age-old need for speed. Early binding is without a doubt faster and here's why: With this mode, all the binding procedures are over with before your program is even run. Because syntax and data types are detectable, they can be verified beforehand along with object references, which can be resolved and compiled. With the quality control aspects out of the way, we render code devoid of the inherent overhead associated with the binding process. This dramatically reduces the time required to access property values of an object.
Now, for jCOM to support an early binding model, it requires some extra effort on your part to make sure that the information required for type checking is available at compile time in the form of type libraries. Wrappers for the server objects must be generated as well, making it—for some—an even more complex proposition. The client requires a type library, and wrappers are required on the server. If the client and server are running on separate machines, the type library and wrappers must be generated on the same machine and then copied to the systems where they're required.
Although more complex, early binding winds up being more reliable in the long run. The syntax and type checking done at compile time cause programming mistakes to show up earlier. In this way, simple errors such as type mismatches can be caught and dealt with earlier in the process. The calling program's code itself becomes clearer because object variable declarations can specifically match the types of objects being called. The objects being used by a procedure are then more clearly represented by the variables that refer to those objects.
From a pure programming standpoint, the static nature of early binding allows some IDEs to show the Java objects for which you have generated type libraries. Through the type library, a developer can readily check out what properties and methods are available for a particular object while coding simply by looking them up in an object browser.
The downside to statically mapping object elements is that if any changes are made to the underlying component, corresponding changes must be made to the type libraries and wrappers associated with that component as well. This might result in less flexible code that can't adapt to shifting interfaces.
The reason for this degradation, as you might recall, is found in the extensive overhead incurred when performing the object verifications we spoke of earlier.
Because the IDispatch interface is a dynamic mapping between objects, it forces objects to describe themselves at runtime, much in the same way that reflection does in Java. Here the compiler takes for granted that all references made to the called object are in good order. It is at runtime that errors become evident. They can then be trapped and handled accordingly, but this necessitates that a constant interrogation take place to verify the validity of each individual call. Calling programs must dynamically locate remote objects and verify the methods and attributes of those objects for each invocation. You can just imagine the overhead this begins to incur.
The IDispatch interface requires that calls going between clients and servers marshal their arguments into a consistent form understandable by both. Types must map correctly between objects. This translation, which is done in real-time, not only slows things down but also can limit the data types that can be passed using this technique.
Overall, the dynamic type mapping found in late binding tends to be a more flexible solution because changes in the underlying components don't require the regeneration of any wrappers or type libraries. However, without compile-time syntax checking, more runtime failures are likely to occur because they will not have been caught up front by the compiler.
|[ Team LiB ]|