The client-half object pattern has been given as a means of abstracting away from particular middleware solutions, so that code not directly involved in networking is not affected by changes of middleware.
In this section, we look at the "simple ftp" problem considered earlier, and give a variety of solutions using different middleware systems
We specify the service using a Java interface.
There is a concession to lessons from RMI being adopted by a number of middleware systems:
in recognition that network errors can occur in calling remote services, the interface
extends Remote
and all methods throw RemoteException
.
This exception should not be visible "on the wire" since it is not a cross-platform
solution - for example, .NET remoting has its different equivalent
System.Runtime.Remoting.RemotingException
However, these exceptions are normally generated in the client HOPP and do not
appear on the wire. Web Services don't conform to this and the WSDL lists
remote exceptions even though they are not generated on the service side.
The client UI is independent of the network code. It just needs to know that the client
half-object implements the common interface common.FileTransfer
.
To avoid hard-coding the actual half-object
into the UI, a call is made to a factory object.
A factory object is used to generate specific client half-objects. It uses command
line parameters passed from the UI object to determine which half-object to return.
All half-objects implement the FileTransfer
interface
The socket-based solution requires a client half-object and a server talking across an
ordinary socket
This just defines strings that are common to both client and server
To run the server,
java socket.FileTransferServer
To run the client
java client.FileTransferClientUI socket localhost
Steps:
FileTransferServerHOPP.java
/home/local/jakarta-tomcat/webapps/axis
and change the extension to .jws
cp FileTransferServerHOPP.java \
/home/local/jakarta-tomcat/webapps/axis/FileTransferServerHOPP.jws
http://host:8088/axis/FileTransferServerHOPP
There are several ways of building a client HOPP. One way is to generate the WSDL
and from there generate a set of client-side classes. This is the technically
simpler but more laborious way based on constructing each function call by hand.
Note that call.invoke()
will throw a RemoteException
if an error occurs.
Download Axis from Apache.org. Copy the FileTransferClientHOPP.java
to the axis subdirectory with the .jws
extension.
Start Axis
To run the client, the classpath needs to include the Axis libraries and also the Xerces XML parser library. Then
java -classpath ... client.FileTransferClientUI webservice localhost
The file ftp.idl
contains
Generate files by
idlj -fall ftp.idl
See
http://java.sun.com/j2se/1.5.0/docs/guide/rmi-iiop/toJavaPortableUG.html
Generated files are
CORBA generates its own interfaces and classes. By specifying the module as corba
,
it generates the corba.FileTransfer
, not common.FileTransfer
.
It also introduces classes such as FileTransferPOA
which have to be used.
So introduce a "wrapper" class to translate between CORBA and our implementation.
CORBA IDL allows the application-defined exceptions. However, any remote method
call can also throw an exception. These exceptions are unchecked,
that is, they do not form part of the method signature and do not need to be caught.
However, if an unchecked exception is thrown and not caught, then it will
terminate the application. So it is better to catch them. They are all
subclasses of org.omg.CORBA.SystemException
.
A name server needs to run
tnameserv -ORBInitialPort 9876
Then you can run the server
java corba.FileTransferServer \
-ORBInitialHost localhost \
-ORBInitialPort 9876
The client is
java client.FileTransferClientU corba \
-ORBInitialHost localhost \
-ORBInitialPort 9876
Run an RMI name server
rmiregistry
Run the server
java -classpath classes \
-Djava.rmi.server.codebase=http://localhost/classes/ \
-Djava.security.policy=policy.all \
rmi.FileTransferServer
Run the client
java -classpath classes \
-Djava.security.policy=policy.all \
client.FileTransferClientUI \
rmi \
localhost
The HOPP model shows that we can change the middleware without too many problems for a decent middleware system. But we can also change the UI for any given system in the same way!
Here is a GUI based client that uses Swing and exactly the same HOPP objects
chdir
, the next time
a getdir
is requested it is to a new copy of the
service, which remembers no state changes
chdir
then the value
of the state changes for every client
chdir
is unique for each client connection