Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Learning JavaFX Script, Part 2: Remote Communication Using RMI

 
By Robert Eckstein, August 2007  

Articles Index

Part 1 of this series introduced the syntax and semantics of the JavaFX Script programming language to the Java technology programmer. This article will draw on your knowledge of JavaFX Script, invoking the Java platform's Remote Method Invocation (Java RMI) libraries to allow a JavaFX graphical user interface (GUI) to communicate remotely. Using RMI with JavaFX Script is very straightforward, and it provides a quick and easy way to demonstrate and test client-server functionality with JavaFX Script technology.

Creating a JavaFX Script Project in the NetBeans IDE

First, you will create a JavaFX Script project in the NetBeans integrated development environment (IDE) 5.5.1. If you have never done this before, be sure to read this excellent article, Getting Started With the JavaFX Script Language (for Swing Programmers), for a detailed description. However, if you know your way around the NetBeans IDE and have already downloaded and installed the JavaFX technology modules from the NetBeans Beta Update Center, you will find the important points summarized here.

  1. From the NetBeans IDE main menu, go to the File menu and select New Project.
  2. In the New Project wizard, select General in the Categories pane and Java Application in the Projects pane. Click Next.
  3. Type JavaFXClient in the Project Name field.
  4. In the Project Location, click Browse, and specify the location in which to store the project.
  5. Deselect both the Set as Main Project and Create Main Class check boxes, and click Finish.

Now, use the IDE to create a JavaFX Script file called HelloServer.

  1. Under the Projects tab, right-click the JavaFXClient > Source Packages node, and select New > File/Folder.
  2. In the Categories pane, choose Other, and in the File Types pane, choose JavaFX File. Then click Next.
    The JavaFX file type should now appear in the list of available file types when you invoke New from the main project node or Source Packages node in the Projects window.
  3. In the Name and Location page of the New JavaFX File wizard, type MyClient in the File Name field and src/client in the Folder field. Notice that the new file name now appears in the Created File field.
  4. Click Finish to create the project.
  5. From the Projects window, right-click the JavaFXClient node, and select Properties.
  6. In the Categories pane of the Properties dialog box, select Run.
  7. Enter the name of the script, client.MyClient, in the Arguments field, and click OK.

This will create an empty JavaFX Script file called MyClient.fx inside the client directory of the project JavaFXClient. At this point, leave the file empty, and set this project aside -- you will return to it after you set up the RMI server.

Client-Server Communication With Remote Method Invocation (RMI)

The Java Remote Method Invocation API (Java RMI) is a Java application programming interface (API) for performing the object equivalent of remote procedure calls. Developing distributed applications in RMI is simpler than developing with sockets because the developer need not design a protocol, which is often a time-consuming and error-prone task.

In RMI, the developer has the illusion of calling a local method from a local class file, when in fact the arguments are shipped to the remote target and interpreted, and the results are sent back to the callers. Because JavaFX Script technology can call Java objects, RMI is a tool to quickly and easily allow JavaFX clients to communicate remotely.

Developing a distributed JavaFX Script application using RMI involves the following five steps:

  1. Define a remote interface.
  2. Implement the remote interface.
  3. Develop the server.
  4. Develop a Java technology-based connection helper for JavaFX script.
  5. Create the JavaFX Script client that calls upon the connection helper.

The author of this article has condensed the first three steps from Qusay Mahmoud's excellent article Distributed Java Programming With RMI and CORBA, because they do not differ from a traditional Java technology implementation of RMI. The final two steps are altered for use with JavaFX Script technology. However, before you delve into each of these steps, you will need to create a new NetBeans IDE project for your server.

Within the NetBeans IDE, do the following:

  1. From the File menu, select New Project. You should see a dialog box similar to Figure 1.

  2. Customizing the New Project in the NetBeans
IDE
    Figure 1. Creating a New Project in the NetBeans IDE 5.5.1
     
  3. In the Categories list, choose General. In the Projects list, choose Java Application. Click Next. You should see a dialog box similar to Figure 2.

  4. Customizing the New Project in the NetBeans IDE
    Figure 2. Customizing the New Project in the NetBeans IDE
     
  5. For the Project name, type JavaRMIServer. Choose the appropriate folder, and deselect Set as Main Project. Finally, click the Finish button. This creates a new Java project called JavaRMIServer.
Define a Remote Interface

Now, create a Java technology interface called ServerInterface in the package server, as shown in Code Example 1. The interface ServerInterface provides one method, ping(), which takes a String argument and returns that argument with the word Hello prepended to it.

Code Example 1
package server;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface ServerInterface extends Remote {

    public String ping(String fileName) throws
        RemoteException;

}
 

As with any RMI application, ServerInterface must do the following:

  • It must extend the Remote interface.
  • It must be declared public, in order for clients to be able to load remote objects that implement the Remote interface.
  • Each method in the interface -- this example contains only one method -- must throw a java.rmi.RemoteException.
Implement the Remote Interface

The next step is to create a class that implements ServerInterface. A sample implementation is shown in Code Example 2. Note that in addition to implementing the ServerInterface, the ServerImpl class extends UnicastRemoteObject. This indicates that the ServerImpl class is used to create a single, nonreplicated, remote object that uses RMI's default TCP-based transport for communication. This may be all you will ever need for using RMI.

Code Example 2
package server;

import java.io.*;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;

public class ServerImpl extends UnicastRemoteObject
    implements ServerInterface {

    private String name;

    public ServerImpl() throws RemoteException{
        super();
    }

    public String ping(String s){
        return "Hello " + s;
    }

}
 
Develop the Server

The third step is to develop a server. This class will also constitute the entry point for your server application, because it has a main() method. The server must do three things:

  1. Create the RMI registry.
  2. Create an instance of the remote object -- in this case, ServerImpl.
  3. Register the object created with the RMI registry.

A sample implementation is shown in Code Example 3.

Code Example 3
package server;

import java.rmi.*;
import java.rmi.registry.LocateRegistry;

public class ServerMain {

    public static void main(String argv[]) {

        try {

            LocateRegistry.createRegistry(1099);

            ServerInterface s = new ServerImpl();
            Naming.rebind("//127.0.0.1/Server", s);

        } catch(Exception e) {
            System.out.println("Server: "+e.getMessage());
            e.printStackTrace();
        }
    }
}
 

The statement Naming.rebind("//127.0.0.1/Server", s) assumes that the RMI registry is running on the default port number, which Code Example 3 defines in the LocateRegistry.createRegistry() statement as port 1099. However, if you run the RMI registry on a different port number -- for example, by changing the registry creation statement to LocateRegistry.createRegistry(4500) -- then you must change the binding statement accordingly:

Naming.rebind("//127.0.0.1:4500/Server", s)
 

Also, it is important to note here that the address 127.0.0.1 is a special localhost address that assumes that the RMI registry and the server are running on the same machine. If they are not, then simply change the address in the rebind() method to match the RMI registry's IP address.

Develop a Java Technology-Based Connection Helper for JavaFX Script

The next step takes place in the JavaFXClient project, and it differs from a traditional RMI application: You must now create a Java technology-based connection helper. This connection helper remotely invokes any methods specified in the remote interface -- ServerInterface -- and returns the result to the JavaFX Script that invoked it. To do so, however, the connection helper must first obtain a reference to the remote object from the RMI registry. Once a reference is obtained, the appropriate method can be invoked.

The implementation is shown in Code Example 4. Note that this is simply a static method that JavaFX Script technology can use to obtain a stub for the remote ServerInterface implementation object.

Code Example 4
package client;

import java.rmi.*;
import server.ServerInterface;

public class ConnectionHelper {

    public static ServerInterface getConnection()
        throws Exception
    {
        return (ServerInterface)
            Naming.lookup("rmi://127.0.0.1:1099/Server");
    }

}
 

Again, note that this code assumes that the RMI registry and the client are running on the same machine. If this is not the case, adjust the IP address -- and port, if necessary -- to match.

Once you enter this into the NetBeans IDE project, you may be wondering how the project can access the ServerInterface class that you created in the JavaRMIServer project. Ideally, a separate JAR file would be available that contains the RMI interfaces that can be shared between the client and server projects, or a dynamic class loading mechanism would be established -- see the section "Dynamic Class Loading in RMI" in this technical tip for more details on how to do the latter.

However, to keep things simple, you can do one of two things:

  • Copy the source of the ServerInterface class over to the client package of the JavaFXClient project.
  • Modify the properties of the JavaFXClient project to include the JavaRMIServer project.

In either case, be sure to add the appropriate import statement at the top of the source-code listing, as shown in Code Example 4.

Create the JavaFX Script Client That Calls Upon the Connection Helper

Finally, Code Example 5 gives you the code that you can use to create a simple JavaFX Script client that communicates through RMI with the remote server. Place the source code from Code Example 5 in the MyClient.fx source listing.

Code Example 5
import java.lang.*;
import javafx.ui.*;
import java.rmi.*;

import server.ServerInterface;
import client.ConnectionHelper;


class ButtonClickModel {
    attribute numClicks: Number;
}

var model = new ButtonClickModel();

var win = Frame {
    width: 200
    content: GridPanel {
        border: EmptyBorder {
           top: 30
           left: 30
           bottom: 30
           right: 30
        }
        rows: 3
        columns: 1
        vgap: 10
        cells:
          [  Button {
                 text: "Click to make RMI connection!"
                 mnemonic: I
                 action: operation() {

                     try {

                         var remoteServer:ServerInterface =
                             ConnectionHelper.getConnection();

                         var results = remoteServer.ping("Test");
                         System.out.println("response: {results}");
                         model.numClicks++;

                     } catch (e:Exception) {
                         System.out.println("exception: {e}");
                     }
                 }
             },

             Label {
                 text: bind "Number of RMI connections: {model.numClicks}"

             }
          ]
    }
    visible: true
};
 

Now, compile and run the server project. Next, run the client project. You should see an interface similar to that shown in Figure 3. Click the button marked "Click to make RMI connection!" a few times, and check to see whether the response is displayed in the output console at the bottom of the NetBeans IDE. With each successful connection, the counter below the button should increment by one.

The JavaFX Client Invoking a Remote Server
Figure 3. The JavaFX Client Invoking a Remote Server
 

Where Did the RMI Compiler (rmic) Go?

Before J2SE 5.0, it was necessary to use the RMI Compiler (rmic) to create stubs and skeletons of classes for use with RMI's remote procedure calls. However, with J2SE 5.0 and Java SE 6, this is no longer necessary. The Java Virtual Machine* will handle the generation of any stubs and skeletons needed for marshaling procedure calls at runtime simply by accessing the appropriate interface class. This is an exciting enhancement, because you no longer have to use the RMI compiler on any classes before running an RMI-enabled application.

 
Conclusion

This article has presented a simple introduction to client-server programming using Java FX Script technology and RMI. In this case, the JavaFX platform encompasses the entire client. Part 3 of this series will discuss ways to handle client-server communication using the JavaFX platform and the Java API for XML Web Services (JAX-WS). Future articles in the series will address integrating JavaFX Script with existing client-side Java code.

_______
* As used on this web site, the terms "Java Virtual Machine" or "JVM" mean a virtual machine for the Java platform.

For More Information
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.