"Java Remote Method Invocation (Java RMI) enables the programmer to create distributed Java technology-based to Java technology-based applications, in which the methods of remote Java objects can be invoked from other Java virtual machines*, possibly on different hosts. "[Oracle] In the current post a java client will send a java class to the server that will analyze a DNA sequence fetched from the NCBI, using the RMI technology.
Files and directoriesI In this example, my files are structured as defined below:
./sandbox/client/FirstBases.java ./sandbox/client/GCPercent.java ./sandbox/client/SequenceAnalyzerClient.java ./sandbox/server/SequenceAnalyzerServiceImpl.java ./sandbox/shared/SequenceAnalyzerService.java ./sandbox/shared/SequenceAnalyzer.java ./client.policy ./server.policy
The Service: SequenceAnalyzerService.javaThe remote service provided by the server is defined as an interface named SequenceAnalyzerService: it fetches a DNA sequence for a given NCBI-gi, processes the sequence with an instance of SequenceAnalyzer (see below) and returns a serializable value (that is to say, we can transmit this value through the network).
Extract a value from a DNA sequence : SequenceAnalyzerThe interface SequenceAnalyzer defines how the remote service should parse a sequence. A SAX Parser will be used by the 'SequenceAnalyzerService' to process a TinySeq-XML document from the NCBI. The method characters is called each time a chunck of sequence is found. At the end, the remote server will return the value calculated from getResult:
Server side : an implementation of SequenceAnalyzerServiceThe class SequenceAnalyzerServiceImpl is an implementation of the service SequenceAnalyzerService. In the method analyse, a SAXParser is created and the given 'gi' sequence is downloaded from the NCBI. The instance of SequenceAnalyzer received from the client is invoked for each chunck of DNA. At the end, the "value" calculated by the instance of SequenceAnalyzer is returned to the client through the network. The 'main' method contains the code to bind this service to the RMI registry:
Client sideOn the client side, we're going to connect to the SequenceAnalyzerService and send two distinct implementations of SequenceAnalyzer. What's interesting here: the server doesn't know anything about those implementations of SequenceAnalyzer. The client's java compiled classes have to be sent to the service.
GCPercent.javaA first implementation of 'SequenceAnalyzer' computes the GC% of a sequence:
FirstBasesThe second implementation of 'SequenceAnalyzer' retrieves the first bases of a sequence.
The ClientAnd here is the java code for the client. The client connects to the RMI server and invokes 'analyse' with the two instances of SequenceAnalyzer for some NCBI-gi:
A note about securityAs the server/client doesn't want to receive some malicious code, we have to use some policy files:
Compiling and Running
Compiling the client
javac -cp . sandbox/client/SequenceAnalyzerClient.java
Compiling the server
javac -cp . sandbox/server/SequenceAnalyzerServiceImpl.java
Starting the RMI registry
Starting the SequenceAnalyzerServiceImpl
$ java \ -Djava.security.policy=server.policy \ -Djava.rmserver.codebase=file:///path/to/RMI/ \ -cp . sandbox.server.SequenceAnalyzerServiceImpl SequenceAnalyzerService bound.
Running the client
$ java \ -Djava.rmi.server.codebase=file:///path/to/RMI/ \ -Djava.security.policy=client.policy \ -cp . sandbox.client.SequenceAnalyzerClient localhost gi=25 gc%=2.1530612244897958 gi=25 start=TAGTTATTC gi=26 gc%=2.1443298969072164 gi=26 start=TAGTTATTAA gi=27 gc%=2.3022222222222224 gi=27 start=AACCAGTATTA gi=28 gc%=2.376543209876543 gi=28 start=TCGTA gi=29 gc%=2.2014742014742015 gi=29 start=TCTTTGThat's it, Pierre