Java 1.2 extends Java's distributed object capabilities

Find out what RMI and Java IDL, Java 1.2's seemingly similar distributed object technologies, have to offer you

Welcome to JavaWorld's new bimonthly Distributed Objects column! The purpose of this column is to discuss distributed object technology and products as they apply to Java developers. Over the course of the next 12 months, we'll be focusing on such technologies as RMI, CORBA, and DCOM, as well as on tool and product offerings that will be of interest to enterprise-scale Java developers. As is the case with all JavaWorld columns, you're encouraged to contact me if you have topics you would like to see addressed in this forum.

If the whole idea of distributed object computing is new to you, I suggest you take some time to review two articles on this topic previously published in JavaWorld. The first of these articles, "CORBA meets Java," provides an introduction to CORBA development in Java. The second article, "Applied CORBA: Integrating legacy code with the Web," discusses the use of CORBA to allow Java developers to access legacy code as remote objects. The latter article deals specifically with calling remote objects written in C++ from a Java applet or application.

Without further ado, let's begin what hopefully will be an informative and enlightening undertaking!

Surveying the field

With the release of the Java 1.2 platform, portions of the Java Enterprise specification begin to make the transition from documents and specifications (that is, vaporware) to actual working code. Although the Java 1.1 release gave Java developers the ability to create distributed pure-Java applications from scratch, Java 1.2 extends these capabilities with Java IDL. To quote the JDK 1.2 documentation:

Java IDL adds CORBA (Common Object Request Broker Architecture) capability to Java, providing standards-based interoperability and connectivity. Java IDL enables distributed Web-enabled Java applications to transparently invoke operations on remote network services using the industry standard OMG IDL (Object Management Group Interface Definition Language) and IIOP (Internet Inter-ORB Protocol) defined by the Object Management Group. Runtime components include a fully-compliant Java ORB for distributed computing using IIOP communication.

In other words, Java 1.2 ships with a 100% Pure Java object request broker (ORB) that can interoperate with any CORBA 2.0-compliant ORB, including IONA Technologies Orbix, Visigenic Software's VisiBroker, and IBM's ComponentBroker. This addition eliminates the requirement for licensing and distributing third-party Java ORBs and will greatly improve download times for CORBA applets as Java 1.2 Web browsers become available. Unfortunately, the major Web browsers (Microsoft Internet Explorer 4.0 and Netscape Navigator 4.0) continue to struggle to provide implementations of Java 1.1. Therefore, it may be late 1998 before valid Java 1.2 browser implementations appear on the market.

More importantly, with IDL JavaSoft's "enterprise" vision for Java begins to take shape, because Java IDL will allow Java developers to take advantage of CORBA transaction, naming, and messaging services. In fact, Java IDL actually ships with a CORBA-compliant naming service known as the Java IDL naming service, which allows objects to be accessed on servers using a standardized set of interfaces. Despite these advances, confusion still abounds among three camps of Java developers:

Camp 1: CORBA veterans (been there, done that!)

This first camp of developers have been developing CORBA applications for some time. When Java came along, they immediately saw its promise and some even began retrofitting existing CORBA applications with Java clients and Java ORBs. To these hearty souls who have braved the changing winds of time and managed to successfully build and field applications using CORBA as their architecture, all of the promised pieces are finally falling into place. Highly visible vendors such as Netscape and Oracle are adding CORBA components to their product offerings, and Java promises to take CORBA to places once thought impossible. With all of these positive goings on, RMI becomes a purely extraneous technology (almost a distraction) that should be ignored in hopes that it will eventually die from neglect.

Camp 2: Java purists (Java, Java everywhere!)

Members of this camp believe that all new applications should be completely written in Java and, for good measure, most old applications should be rewritten for purity's sake. CORBA sounds great in a theoretical sense, but who cares about legacy code integration when all components are written in Java? JavaSoft promises several important Java services (transaction, directory, among others) over the coming years so, in time, the Java platform will match CORBA feature for feature. Because the client and server are written in Java, there's no need for any messy IDL code and all objects are first-class Java citizens.

Camp 3: Everyone else (Hey... I just want something that works!)

Developers in this camp have never built a production application using distributed objects but can see the advantage to this architecture in certain situations. For someone starting an application completely from scratch (no legacy code required), a 100 percent Java solution will probably be on the short list of options. This type of development project will require analysis of the capabilities of Java RMI and Java IDL and decisions based on need.

A brief technology comparison

I won't even attempt to estimate the number of developers that fall into each camp, but I will venture a guess that 90 percent of you fall into Camp 3 and simply want a robust technology that actually does what it says it will do. With just about all comparable technologies, you can rest assured that each technology will have some advantages and disadvantages when compared with the competition. This is especially true when comparing RMI and CORBA. (Note that in this comparison, CORBA and Java IDL are used somewhat interchangeably. This is due to the fact that CORBA is an open specification "owned" by the OMG, and Java IDL is an implementation of this specification.)

To some, RMI's biggest advantage is the fact that it was designed from the ground up to be an all-Java solution. This means that building RMI applications is quite simple, and all remote objects have the same features as local objects (that is, you can typecast and subclass them). Of course, RMI's biggest advantage is also its biggest disadvantage: it was designed from the ground up to be an all-Java solution -- a very exclusive club!

CORBA, meanwhile, benefits from the fact that it is a language-independent solution, but that adds significant complexity to the development cycle and also precludes using Java's garbage collection features and RMI's pass-by-copy parameter passing. While there is currently a formal request for proposals (RFP) out on CORBA pass-by-copy, it will never be at a level supported by RMI, due to the complexities of morphing objects from one language to another.

The following table attempts to summarize many of the features supported by the two architectures. Following this table, we will begin development of two simple Java applications using RMI and Java IDL. Remember, Java IDL is simply an implementation (albeit a subset) of the CORBA specification, therefore Java IDL and CORBA can be compared interchangeably in many areas.

Comparison Of RMI and CORBA Features
CapabilityCORBARMI
Server CallbacksYesYes
Pass-By-ValueNoYes
Dynamic DiscoveryYesNo
Dynamic InvocationsYesYes
Multiple Transport SupportYesYes
URL NamingNo (ORB-dependent)Yes
Firewall ProxyNo (ORB-dependent)Yes
Language-IndependentYesNo
Language-Neutral Wire ProtocolYes (via IIOP)No (Future IIOP?!?)
Persistent NamingYesNo
Wire-level SecurityYes (via CORBASecurity)Yes (via SSL)
Wire-level TransactionYes (via CORBA OTS)Yes (via JTS)

MortgageCalc 1.0 -- one app, two technologies

To highlight the similarities and differences between RMI and Java IDL, I deemed it best to build two versions of the same application -- MortgageCalc 1.0 -- one for each of the technologies (see

Resources

for the complete source for these two apps). Each application will be comprised of a client and server component used to calculate and display mortgage payments based on a number of initial conditions (length of loan, interest rates, taxes, insurance, and down-payment amount). Because the number-crunching portion of these two applications will be identical, we can encapsulate that calculation code within a single Java class to be shared by both. This will allow us to focus on the specific steps involved in building an application using RMI and Java IDL.

Before we begin, I'll briefly explain the formula we'll be using to perform the calculations. Note: These calculations use the mortgage formula for U.S. mortgages. Other countries, such as Canada, compound interest semi-annually, resulting in a different calculation.

The monthly payment (PMT) represents the principal plus the interest you owe the bank each month. In addition to this payment, your total payment (TOTPMT) will also include city/county taxes (TAX) and home-owner's insurance (INS). In other words, your monthly payment can be represented by the following formula:

TOTPMT = PMT + TAX + INS

The TAX and INS values are simple to calculate (TotalAmounts/12), but PMT proves to be more difficult. Without going into detail, the formula used to calculate this value is as follows:

PMT = BAL * (INT / (1 - (1 + INT) ** -MON))

BAL is the initial amount of the loan, INT is the monthly interest, and MON is the number of months over which the loan is amortized (Years * 12).

The PaymentCalc class

To avoid duplicating the calculation code in both our RMI and Java IDL examples, we will build a simple Java class,

PaymentCalc

, that can be reused in both applications. If these financial applications were to grow in complexity, we could easily extend the

PaymentCalc

class without continually duplicating changes to two sets of code. For now,

PaymentCalc

contains two methods --

PI()

and

PITI()

. The

PI()

method calculates a payment consisting of principal and interest, while the

PITI()

method calculates a payment consisting of principal, interest, taxes, and insurance.

class PaymentCalc { /* PI calculates only the principal and interest payment */ double PI(double Balance, double AnnualInterestRate, int YearsLength) { double BAL = Balance; double INT = (AnnualInterestRate / 12); double MON = (YearsLength * 12);

double PMT = BAL * (INT / (1 - java.lang.Math.pow(1 + INT, -MON)));

return PMT; }

/* PITI calculates the total payment, including insurance and taxes */ double PITI(double Balance, double AnnualInterestRate, int YearsLength, int AnnualInsurance, int AnnualTaxes) { double BAL = Balance; double INT = (AnnualInterestRate / 12); double MON = (YearsLength * 12);

double PMT = BAL * (INT / (1 - java.lang.Math.pow(1 + INT, -MON))); double INS = (AnnualInsurance / 12); double TAX = (AnnualTaxes / 12); double TOTPMT = PMT + INS + TAX;

return TOTPMT; } }

The server portions of the RMI and Java IDL applications will utilize the PaymentCalc class to perform calculations for a variety of term lengths and principals and will return an array of payment options to the client.

The RMI-based MortgageCalc app

Developing an RMI application consists of the following steps:

  1. Define a remote interface
  2. Implement the remote interface by building an implementation class (server app)
  3. Generate client stubs and server skeletons using rmic
  4. Start the RMI registry and register remote objects
  5. Build the client application
  6. Start client application and connect to the server

Note that these steps look vaguely similar to those required when we built our CORBA examples several months ago. The major difference lies in the first step. Using RMI, we can define the remote interface using the Java programming language as opposed to IDL.

Step 1: Define a remote interface

The first step requires us to define the operations we would like to be performed by our server. An extremely simple application could calculate a single payment based on principal, interest, and length, but we'll take this a step further. Instead of calculating a single payment, let's allow our server to calculate a variety of payments based on options such as amount of down-payment (5%, 10%, or 20%) and length of loan (15 year or 30 year). These options will allow us to examine the passing of data types from client and server. In the RMI case, we will return a Vector object to return a list of objects containing the calculated data.

The Calculate interface will be implemented by our server application.

public interface Calculate extends java.rmi.Remote
{
  public java.util.Vector calcPI(int HousePrice, 
                  double InterestRate) throws java.rmi.RemoteException;
  public java.util.Vector calcPITI(int HousePrice, double InterestRate, 
                  int Insurance, int Taxes) throws java.rmi.RemoteException;
}
1 2 3 4 Page 1
Page 1 of 4