Daniel Lipton is a consultant with Random Walk Computing in New York City. He develops Java,
CORBA, and XML-based applications for the financial industry. He can be contacted
at [email protected].
CODE-REUSE HAS been a promising and often elusive goal of developers. Too often, reuse
simply means snipping code out of one program and jamming it into another. This has been
problematic, to say the least, and inefficient. Object-oriented software methodology promised
much and arguably delivered less. Now there's a new way to save time and effort: CORBA.
My company recently developed a suite of CORBA services for a client that delivers often-used
functionality. Some of these CORBA services are client-specific but others are not. The idea
is simple: If you are going to do the same thing over and over again, do it once, do it right,
and wrap it in a CORBA service. Then you can re-use that functionality on virtually any
platform and with any language. The client part of the service can be wrapped as either a
JavaBean for use in IDEs, such as Symantec's Café or wrapped as an ActiveX control.
As we finished our project, I thought of other things that we often use in our programs.
Email, in particular, stood out. Quite frequently, it is desirable for applications to be able
to send email. For example, if an enterprise application throws an exception indicating that
there's a bug, notification could be sent directly to support staff. Alternatively, if a program
takes an action and needs to notify a group of people, it can be sent automatically via email.
There are many uses for such a service.
WHY NOT JUST DO IT
IN THE CLIENT?
Let's review another way of sending email from an application. A module could be programmed in
the client program's language. First, a library must be found to send email. If one can't be
found, it will have to be written from scratch. The next time email functionality is needed
in a program it will have to be written in the exact same language and on the same platform.
Next comes the issue of what kind of platform it will need to run on. The program probably is going
to be distributed on a number of machines with an unknown environment. The machines might have Sendmail
or some other SMTP program but might not. If an SMTP host (or POP, IMAP, etc.) is specified, then that
machine's name or address will have to be hardwired into the client program. Then, if the mail host
goes down or moves, the email functionality will not work correctly.
If the program is written as a CORBA service, client applications can take advantage of the email
functions in it without many of the headaches that come from writing it from scratch. The reason
is that the object semantics are already implemented and encapsulated in the server object. This
is a common idea in object-oriented programming. If a class already implements what you need,
then there's no reason to write it again. CORBA allows you to easily present that object to
other programs on the network. That's the idea behind setting up the email-sending capability
as a CORBA service. The developer of the client just wants to send email. He or she doesn't
necessarily want to know how the email system works or the support policies or network
practices behind it.
WRITING THE SERVICE
The first step in writing the email service is deciding on an interface. CORBA interfaces are written
in a language called CORBA IDL. I leaned toward simplicity when designing the interface
(see Listing 1).
There is only one operation, send, defined by the interface. It sends an email and may raise an exception.
When the service cannot send the message, the exception provides an explanation of why the service couldn't
send it. I used the typedef facility to declare
StringList as a sequence of Strings (an IDL sequence is similar to a
Java array). I named the module RWEMail after my company. I could have
added much more, but I didn't want to unnecessarily complicate the interface.
In writing the code for this article, I used Inprise's Visigenic for Java CORBA Object Request Broker (ORB).
If you are using another vendor's product (like Iona) then you may need to change some of the example code.
Later, I discuss some of the issues of portability between ORBs.
After writing the interface, it must be compiled into stubs and skeletons for the client and server,
respectively. First, let's look at the client
(see Listing 2).
The most important pieces are the send and the bindToService methods.
The bindToService method finds a service object and binds to it.
In other words, the client object gains what appears to be a regular object reference. The client may
call methods on the server object just like it would on any other. CORBA works the magic behind the
scenes, such as marshaling and unmarshaling parameters and sending data across the network. This is
the most vendor-specific part of the program. Again, if you are writing this yourself, you may need
to check your CORBA vendor's manual to see how they locate and bind to the service object.
After an application creates an RWEMailClient object, it just calls
the send method with the recipients, the subject, and the email's text. The recipients are provided as
an array of strings in the to and cc
fields (see Listing 3).
Applications don't need to use the RWEMailClient class. They can
bind directly to the service using ORB APIs. If you are writing a client application in another language,
then you will need to compile the interface into the stubs in that language.
The service implementation is broken into two parts. The first is RWEMailServer
(see Listing 4),
which is the entry point and scaffolding for the service. It delegates the responsibility of implementing
the RWEMailInterface to RWEMailImpl
(see Listing 5).
The server creates an instance of the service implementation and then uses the services of the BOA
(basic object adapter) to register the implementation with the ORB and enable it to receive incoming
requests. This is another part you might have to change if you are using a different vendor's CORBA
product. The server also registers the service with Visigenic's locator service.
For the implementation, I used the new JavaMail API. It provides another level of abstraction between
your program and the platform's email system. The JavaMail API provides a set of classes and interfaces
to send and receive email independent of the underlying protocol. It provides access to SMTP, IMAP,
and soon POP. This implementation uses SMTP.
For this service implementation to work, you'll need to download the JavaMail 1.1 jar and the Java
Activation Framework, which is used by JavaMail. The server this runs on will also need an SMTP server.
That may seem like a great deal, but that's exactly the point. If you're going to go through all of
the trouble of downloading, installing, and configuring the necessary third-party modules and services,
then you might as well do it once on the server instead of on every client.
The service doesn't have to be implemented in Java. It can be written in any language that the CORBA
vendor supports (such as C++). The interface must be compiled into skeleton classes and then extended
in the implementation. You can also send email via any application protocol and through any API or
system call, custom or otherwise; the JavaMail API is a matter of convenience. For instance, you can
connect to a POP server and send the email or you could write your own SMTP server.
WHAT ARE THE OTHER ADVANTAGES?
CORBA provides quite a bit of useful functionality to the service. For example, many vendors sell an SSL
pack that provides data encryption. If that's important to you, then CORBA easily supports it. A CORBA
service can also do load-balancing or automatic fail-over. If one mail server fails, then CORBA can
automatically route to a backup mail server. This can be very powerful but could be non-trivial to
implement on your own. I recommend that you go to vendors' Web sites for more information.
Another advantage to sending email through a CORBA service is that all processing goes through a set of
known machines. If mail can only come from a set of pre-defined machines (e.g., destined to go through
a firewall), then the addresses of the hosts sending email are known in advance. The email service can
also incorporate other services. For example, an auditing service can log all email transmissions. The
service can also authenticate from whom the email is
HOW CAN I USE THIS?
For many readers, this code can be used as-is as long as you have the proper libraries
(Visibroker for Java 3.2, JavaMail 1.1, JAF, and JDK 1.1.x). If you are using another vendor's CORBA
implementation other than Inprise, then you may need to rewrite certain parts of the example code.
The server may need to be configured for your specific machine as well. When I was running the service,
I had to move it from a Windows NT machine to Solaris because Windows NT Workstation doesn't provide
an SMTP server.
You may want to add more functionality to the service if you have specific needs for your company, such
as a proprietary email protocol that needs more information for the header. You can also add more methods
to the interface, such as an asynchronous callback mechanism to let the client know that the email was
delivered. Perhaps you want authentication before you allow a program to use the service. My only
suggestion is that you keep it as generic as possible so that any application you may write can easily use it.
Perhaps in your job you will see things which you use in your programs quite often. There may be common
functionality that would be useful if it was available over your network to other programs. Chances are
that it could benefit from becoming a CORBA service. As the example I've presented here shows, it's probably
simpler than you think, and it will save you time in the long run.
Quantity reprints of this article can be purchased by phone: 717.560.2001, ext.39 or by email: [email protected].