Implementing Multiple Remote GUIs With RMI
-
Upload
chirusagar -
Category
Documents
-
view
213 -
download
0
Transcript of Implementing Multiple Remote GUIs With RMI
-
8/22/2019 Implementing Multiple Remote GUIs With RMI
1/8
Implementing Multiple Remote GUIs with RMI
Copyright Gordon R. Durand, 1999-2000
Technical or typographical errors? Please email me.
You can downloadthe code for this article.
Introducing RMI
The Remote Method Invocation API allows Java objects to send messages to Java objects running in other
Java Virtual Machines anywhere on a TCP/IP network.
Declare the remote methods in an interface which extends the Remote interface
i mpor t j ava. r mi . *; publ i c i nt erf ace Hel l oI nt f extends Remot e { publ i c St r i ng get Gr eeti ng( ) t hr ows Remot eExcept i on;
}
Implement the interface in a class that extends UnicastRemoteObject
i mpor t j ava. r mi . *; i mpor t j ava. r mi . ser ver. *; i mpor t j ava. rmi . regi str y. * ;
publ i c cl ass Hel l oRmt ext ends Uni cast Remot eObj ect i mpl ements Hel l oI nt f {
publ i c Hel l oRmt ( ) t hrows Remot eExcept i on {}
publ i c St r i ng get Gr eet i ng( ) { return "Hel l o f r om Hel l oRmt ! " ;
}
publ i c st at i c voi d mai n ( St r i ng[ ] ar gs) {Hel l oRmt r emot e;
Syst em. set Secur i t yManager( new RMI Secur i t yManager( ) ) ;
t r y {
Locat eRegi st r y. cr eateRegi st r y(Regi st r y. REGI STRY_PORT) ;r emot e = new Hel l oRmt ( ) ;Nami ng. r ebi nd("Hel l oRmt ", r emot e) ;
} cat ch ( Except i on e) {
e. pr i nt St ackTr ace( ) ;}
System. out . pr i nt l n( "Hel l oRmt bound i n regi st r y" ) ;
}}
Notice that HelloRmt's constructor throws a RemoteException, but does nothing else. HelloRmt's main
method does all the work. First we install a SecurityManager. Then we create a Registry object (most RMI
examples run the registry in a separate process, but it's not necessary). Finally, we create the remote object
and bind it to a name in the Registry.
Now we need a client to test the remote object
publ i c cl ass Hel l oRMI { publ i c st at i c voi d mai n ( St r i ng[ ] ar gs) {
lementing Multiple Remote GUIs with RMI http://grdurand.com/java/rmi.html
8 12/27/2012 7:16 PM
-
8/22/2019 Implementing Multiple Remote GUIs With RMI
2/8
Hel l oI nt f r emot e = nul l ;
t r y {r emot e = ( Hel l oI nt f ) Nami ng. l ookup ( "Hel l oRmt ") ;Syst em. out . pr i nt l n( r emot e. get Gr eet i ng( ) ) ;
} cat ch ( Except i on e) {e. pr i nt St ackTr ace( ) ;
}}
}
HelloRMI never actually gets instantiated. A static main method does all the work. First it calls
Naming.lookup, which returns a reference to a Remote type. It casts that to the HelloIntf type, and call its
getGreeting method. The RMI implementation does the rest, calling the remote object's getGreeting method,
serializing the returned String, and delivering it back to HelloRMI.
Compile the classes with javac
>j avac *. j ava
Generate the stub class with rmic
>r mi c - v1. 2 Hel l oRmt
Create a text file called policy with your security policy
gr ant {/ / Al l ow ever yt hi ng f or nowper mi ssi on j ava. secur i t y. Al l Per mi ssi on;
};
Then start HelloRmt in its own window
>st ar t "Hel l oRmt " j ava - Dj ava. secur i t y. pol i cy=pol i cy Hel l oRmt
Wait until you see the "HelloRmt bound in registry" message and then start HelloRMI
>j ava Hel l oRMIHel l o f r om Hel l oRmt !
You can see that RMI can make remote objects appear to be local. RMI can also serialize objects (such as
our return String) and send them over the network as the parameters and return values of remote methods.
You Want Fries With That?
RMI can do even more. It can request the bytecodes for the classes themselves. If an RMI call returns a
reference to a class unknown to the local VM, the VM will first try to load the class from the local classpath.
Failing that, it will request the class from the remote object's codebase, typically through an HTTP GET.
This ability to ship an object's behavior along with the object itself makes RMI an extremely powerful tool
for distributed applications.
You don't even need a full scale HTTP server. With Java, you can write your own class server with just a
few lines of code.
A ClassServer would create a ServerSocket to listen on a specified port
lementing Multiple Remote GUIs with RMI http://grdurand.com/java/rmi.html
8 12/27/2012 7:16 PM
-
8/22/2019 Implementing Multiple Remote GUIs With RMI
3/8
server = new Ser ver Socket ( por t ) ;
and then wrap itself in a Thread to wait for a request
pr i vat e voi d newLi st ener( ) {( new Thread( t hi s) ) . st ar t ( ) ;
}
The heart of the ClassServer is in its run method
publ i c voi d run() {
Socket socket ;
t r y {socket = ser ver . accept ( ) ;
} catch ( I OExcept i on e) {e. pr i nt St ackTr ace( ) ;
return;}
newLi st ener ( ) ;t r y {
Dat aOut put St r eam out = new DataOut put St r eam( socket . getOut putSt r eam( ) ) ; t r y {
Buf f eredReader i n = new Buf f eredReader( new I nput St r eamReader ( socket. getI nput St r eam( ) ) ) ;
St r i ng path = get Pat h( i n) ;byt e[ ] bytecodes = get Byt es( pat h) ;Syst em. out . pr i nt l n( "Sendi ng " + socket. get I netAddr ess( ) + " " + path) ;
t r y {out . wr i t eByt es( "HTTP/ 1. 0 200 OK\ r \ n") ;out . wr i t eByt es( "Cont ent - Lengt h: " + bytecodes. l engt h + "\ r \ n") ;out . wr i t eByt es( "Cont ent - Type: appl i cat i on/ j ava\ r \ n\ r\ n" ) ;
out . wr i t e(byt ecodes) ;out . f l ush( ) ;
} cat ch ( I OExcept i on i oe) {i oe. pri nt St ackTr ace( ) ;
return; / / execut i on wi l l actual l y go t o f i nal l y bl ock f i rst}
} cat ch ( Except i on e) {out . wr i t eBytes(" HTTP/ 1. 0 400 " + e. getMessage() + " \ r \ n") ;out . wr i t eBytes(" Cont ent - Type: t ext / ht ml \ r \ n\ r \ n") ;out . f l ush() ;
}} catch ( I OExcept i on ex) {
ex. pr i nt St ackTr ace( ) ;} f i nal l y {
t r y {socket . cl ose( ) ;
} cat ch ( I OExcept i on e) {}
}}
On receiving a request, the ClassServer spins off a new Thread to continue listening, and then parses the
input stream for a GET header and a class file name. It reads the class file and send the bytecodes, along
with the appropriate header, as a response to the GET.
Skinny Client Fattens Up
Since RMI can request bytecodes when it needs them, a remote GUI only needs to know about a single
remote method. Suppose a GUIServer implements
lementing Multiple Remote GUIs with RMI http://grdurand.com/java/rmi.html
8 12/27/2012 7:16 PM
-
8/22/2019 Implementing Multiple Remote GUIs With RMI
4/8
publ i c i nt erf ace GUI Ser ver I nt f extends Remot e { publ i c Panel getGui Panel ( ) t hrows Remot eExcept i on;
}
A GUIClient only needs to request a GuiPanel and display it
Panel panel ;
t r y {
panel = ( Panel ) gui Server . get Gui Panel ( ) ;} cat ch ( RemoteExcept i on e) {
e. pr i nt St ackTr ace( ) ;}
i f ( panel ! = nul l ) {add( panel ) ;panel . set Vi si bl e( tr ue) ;
}
When GUIClient request a GUIPanel, the GUIServer instantiates the class, serializes it (and all the objects it
references), and returns a reference to GUIClient. GUIClient, finding itself with a reference to an unknown
object which itself references other unknown objects, attempts to load the bytecodes for those objects.When it fails to find them in the local classpath, it GETs them from a remote ClassServer. The beauty of this
scenario is that the GUIClient always gets fresh bytecodes in their latest revision, without the user ever
needing to update GUIClient itself.
See Diagram 1: GUI Server
Setting Up Communications
Since GUIPanel brings its own cohorts and their behavior with it, it can look up Remote objects on the
server to make calls home, and even set up a remote object on the client side to handle callbacks from the
server. A couple minor problems must be overcome.
First, because GUIPanel's constructor is actually called on the server side (prior to it being serialized and
sent to the client), you don't want to attempt to set up communications in the constructor. Rather, you need
a setup() method that the GUIClient can call once GUIPanel gets to the client side. In order to do this you'll
have to have your GUI panel extend RemoteGUI, which extends Panel
publ i c abst r act cl ass Remot eGUI ext ends Panel publ i c abst r act voi d set up( St r i ng host ) ;
GUIClient can cast the object reference to a RemoteGUI and call its setup method
t r y {panel = ( RemoteGUI ) gui Server . getGui Panel ( ) ;
} cat ch ( RemoteExcept i on e) {e. pr i nt St ackTr ace( ) ;
} i f ( panel ! = nul l ) {
panel . set up( host ) ;add( panel ) ;panel . set Vi si bl e( true) ;
}
Second, since GUIPanel extends RemoteGUI which extends Panel, it can't also extendUnicastRemoteObject, so it can't handle remote method calls itself. It might be better, anyway, to
encapsulate that functionality in another class
lementing Multiple Remote GUIs with RMI http://grdurand.com/java/rmi.html
8 12/27/2012 7:16 PM
-
8/22/2019 Implementing Multiple Remote GUIs With RMI
5/8
publ i c cl ass GUI Panel Rmt extends Uni cast Remot eObj ect i mpl ements GUI Panel I nt f { / / . . . al l the gory det ai l s here.
And have GUIPanel create GUIPanelRmt in its setup method
publ i c voi d set up( St r i ng host ) { t r y {
r mt = new GUI Panel Rmt ( thi s, name, host ) ;} catch ( RemoteExcept i on e) {
e. pr i nt St ackTr ace( ) ;}
}
Handling Multiple Clients
In order for a server to handle multiple GUIs we must first give each new instance of GUIPanel a unique
name
s tat i c i nt panel Count = 0;
publ i c Panel getGui Panel ( ) t hrows Remot eExcept i on {St r i ng name = "GUI Panel " + panel Count++;
r eturn new GUI Panel ( name) ;}
Then, in GUIPanel's setup routine, when we call GUIPanelRmt's constructor, GUIPanelRmt can register
itself in a local registry with its unique name
Nami ng. r ebi nd( name, t hi s) ;
and then call a remote method on the server side
St r i ng l ocal Host = ( I net Addr ess. get Local Host ( ) ) . get Host Addr ess( ) ;gui Ser ver . addGUI ( l ocal Host + "/ " + name) ;
which will add its remote reference to a Vector of remote references
pr i vat e Vect or gui s;
publ i c voi d addGUI ( St r i ng name) t hr ows Remot eExcept i on { t r y {Obj ect gui = Nami ng. l ookup ( " rmi : / / " + name) ;gui s. add( gui ) ;
} catch ( Except i on e) {e. pr i nt St ackTr ace( ) ;
}}
Finally, whenever the server side object's state changes, it broadcasts a message to all registered GUIs
publ i c voi d updat eGUI s( i nt l en) {GUI Panel I nt f gui ;
I t erator i = gui s . i t erator ( ) ;
whi l e ( i . hasNext ( ) ) {gui = ( GUI Panel I nt f ) i . next ( ) ;
t r y {
lementing Multiple Remote GUIs with RMI http://grdurand.com/java/rmi.html
8 12/27/2012 7:16 PM
-
8/22/2019 Implementing Multiple Remote GUIs With RMI
6/8
gui . updat eGUI ( l en) ;} cat ch ( RemoteExcept i on e) {
i . r emove( ) ;}
}}
Notice that if we get an exception in the broadcasting loop, we simply remove that reference from our
Vector, as a quick-and-dirty way of handling GUI termination without implementing a removeGUI method.
See Diagram 2: Multiple Remote GUIs
A Complete Demonstration
You can download the code for a complete demonstration of a GUIServer/GUIClient which supports
multiple remote GUIs. On the server side we have a GUIServer and a ClassServer. On the client side we
start with a simple GUIClient. The server side has a JBoard object which interacts with remote JBoardGUls.
The adapter classes which actually handle the RMI methods are JBoardRmt on the server side and
JBoardGUIRmt on the client side.
The GUI has a slider which adjusts a value in a text box. Changing the value in the JBoardGUI panel sendssetLength messages via JBoardGUIRmt to JBoardRmt, which passes it on to JBoard. JBoard then sends a
updateGUls message to JBoardRmt, which broadcasts updateLength messages to all GUIs.
See Diagram 3: Remote GUI Classes
Notes
The java commands to start up GUIServer and GUIClient require some additional options. To simplify
things, we put these commands into DOS batch files. To simplify further, we can create a shortcut to the
batch files.
Building the GUIServer and GUIClient class files involves a number of steps, including running the javac
compiler, copying files, and running the rmic stub compiler. To simplify things, we put these commands into
a batch file.
If calls to Naming take longer than one or two seconds, it's not Java, it's a DNS lookup timeout problem.
Edit your \winnt\system32\drivers\etc\hosts file to specify IP addresses for each machine involved.
Diagrams
Diagram 1: GUI Server return to text
lementing Multiple Remote GUIs with RMI http://grdurand.com/java/rmi.html
8 12/27/2012 7:16 PM
-
8/22/2019 Implementing Multiple Remote GUIs With RMI
7/8
Diagram 2: Multiple Remote GUIs return to text
Diagram 3: Remote GUI Classes return to text
lementing Multiple Remote GUIs with RMI http://grdurand.com/java/rmi.html
8 12/27/2012 7:16 PM
-
8/22/2019 Implementing Multiple Remote GUIs With RMI
8/8
lementing Multiple Remote GUIs with RMI http://grdurand.com/java/rmi.html