JPPF, java, parallel computing, distributed computing, grid computing, parallel, distributed, cluster, grid, cloud, open source, android, .net
JPPF, java, parallel computing, distributed computing, grid computing, parallel, distributed, cluster, grid, cloud, open source, android, .net
JPPF

The open source
grid computing
solution

 Home   About   Features   Download   Documentation   On Github   Forums 

The JPPFClient API

From JPPF 3.3 Documentation

Jump to: navigation, search

Contents

Main Page > Development guide > The JPPFClient API


A JPPF client is an object that will handle the communication between the application and the server. Its role is to:

  • manage one or multiple connections with the server
  • submit jobs and get their results
  • handle notifications of job results
  • manage each connection's life cycle events
  • provide the low-level machinery on the client side for the distributed class loading mechanism
  • provide an access point for the management and monitoring of each server

A JPPF client is represented by the class JPPFClient. We will detail its functionalities in the next sub-sections.

1 Creating and closing a JPPFClient

A JPPF client is a Java object, and is created via one of the constructors of the class JPPFClient. Each JPPF client has a unique identifier that is always transported along with any job that is submitted by this client. This identifier is what allows JPPF to know from where the classes used in the tasks should be loaded. In effect, each node in the grid will have a map of each client identifier with a unique class loader, creating the class loader when needed. The implication is that, if a new client identifier is specified, the classes used in any job / task submiotted by this client will be dynamically reloaded. This is what enables the immediate dynamic redeployment of code changes in the application. On the other hand, if a previously existing identifier is reused, then no dynamic redeployment occurs, and code changes will be ignored (i.e. the classes already loaded by the node will be reused), even if the application is restarted between 2 job submissions.

There are two forms of constructors for JPPFClient, each with a specific corresponding semantics:

Generic constructor with automatic identifier generation

 public JPPFClient()

When using this constructor, JPPF will automatically create a universal unique identifier (uuid) that is guaranteed to be unique on the grid. The first submission of a job will cause the classes it uses to be dynamically loaded by any node that executes the job.

Constructor specifying a user-defined client identifier

 public JPPFClient(String uuid)

In this case, the classes used by a job will be loaded only the first time they are used, including if the application has been restarted in the meantime, or if the JPPF client is created from a separate application. This behavior is more adapted to an application deployed in production, where the client identifier would only change when a new version of the application is deployed on the grid. It is a good practice to include a version number in the identifier.


As a JPPFClient uses a number of system and network resources, it is recommended to use it as a singleton. It is designed for concurrent use by multiple threads, which makes it safe for use with a singleton pattern. It is also recommended to release these resources when they are no longer needed, via a call to the JPPFClient.close() method. The following code sample illustrates what is considered a best practice for using a JPPFClient:

 public class MyApplication {
   // singleton instance of the JPPF client
   private static JPPFClient jppfClient = new JPPFClient();
 
   // allows access to the client from any other class
   public static JPPFClient getJPPFClient() {
     return jppfClient;
   }
 
   public static void main(String...args) {
     // enclosed in a try / catch to ensure resources are properly released
     try {
       jppfClient = new JPPFClient();
 
       // ... application-sepcific code here ...
     } finally {
       // close the client to release its resources
       if (jppfClient != null) jppfClient.close();
     }
   }
 }

2 Submitting a job

To submit a job, JPPFClient provides a single method:

 public List<JPPFTasks> submit(JPPFJob job)

This method has two different behaviors, depending on whether the job is blocking or non-blocking:

  • blocking job: the submit() method blocks until the job execution is complete. The return value is a list of tasks with their results, in the same order as the tasks that were added to the job.
  • non-blocking job: submit() returns immediately with a null value. It is up to the developer to collect the execution results by the means of a TaskResultListener set onto the job (see section Non-blocking jobs).

3 Cancelling a job

The ability to cancel a job is provided by JPPFClient's superclass AbstractGenericClient, which provides a cancelJob() method, defined as follows:

 // superclass of JPPFClient
 public abstract class AbstractGenericClient extends AbstractJPPFClient  {
   // cancel the job with the specified UUID
   public boolean cancelJob(final String jobUuid) throws Exception;
 }

This method will work even if the client is connected to multiple drivers. In this case, it will send the cancel request to all the drivers.

4 Exploring the server connections

The JPPF client handles one or more connections to one or multiple servers. Each individual connection is represented as an instance of the interface JPPFClientConnection. It is possible to explore these connections using the following methods in JPPFClient:

 // Get all the client connections handled by this JPPFClient
 public List<JPPFClientConnection> getAllConnections()
 
 // Get the names of all the client connections handled by this JPPFClient
 public List<String> getAllConnectionNames()
 
 // Get a connection given its name
 public JPPFClientConnection getClientConnection(String name)

5 Receiving notifications for new and failed connections

The JPPF client emits an event each time a new connection is established with a server. It is possible to receive these events by registering an implementation of the listener interface ClientListener with the client. Since the connections are generally established during the initialization of the client, i.e. when calling its constructor, JPPFClient provides a different form of the two constructors we have seen in Creating and closing a JPPFClient :

 // Initialize with the specified listeners and a generated uuid
 public JPPFClient(ClientListener...listeners)
 // Initialize with the specified listeners and user-defined uuid
 public JPPFClient(String uuid,  ClientListener...clientListeners)

It is also possible to add and remove listeners using these two more "conventional" methods:

 // register a listener with this client
 public void addClientListener(ClientListener listener)
 // remove a listener from the registered listeners
 public synchronized void removeClientListener(ClientListener listener)

Here is a sample ClientListener implementation:

 public class MyClientListener implements ClientListener {
   @Override
   public void newConnection(ClientEvent event) {
     // the new connection is the source of the event
     JPPFClientConnection connection = event.getConnection();
     System.out.println("New connection with name " + connection.getName());
   }
 
   @Override
   public void connectionFailed(ClientEvent event) {
     JPPFClientConnection connection = event.getConnection();
     System.out.println("Connection " + connection.getName() + " has failed");
   }
 }
 
 ClientListener  myClientListener =  new MyClientListener();
 // initialize the client and register the listener
 JPPFClient jppfClient = new JPPFClient(myClientListener);

6 Receiving status notifications for existing server connections

Each individual server connection has a status that depends on the state of its network connection to the server and whether it is executing a job request. A connection status is represented by the enum JPPFClientConnectionStatus, and has the following possible values: NEW, DISCONNECTED, CONNECTING, ACTIVE, EXECUTING or FAILED.

JPPFConnection extends the interface ClientConnectionStatusHandler, which provides the following methods to handle the connection status and register or remove listeners:

 public interface ClientConnectionStatusHandler {
   // Get the status of this connection
   JPPFClientConnectionStatus getStatus();
   // Set the status of this connection
   void setStatus(JPPFClientConnectionStatus status);
   // Register a connection status listener with this connection
   void addClientConnectionStatusListener(ClientConnectionStatusListener listener);
   // Remove a connection status listener from the registered listeners
   void removeClientConnectionStatusListener(ClientConnectionStatusListener listener);
 }

Here is a sample status listener implementation:

 public class MyStatusListener implements ClientConnectionStatusListener {
   @Override
   public void statusChanged(ClientConnectionStatusEvent event) {
     // obtain the client connection from the event
     JPPFClientConnection connection =
       (JPPFClientConnection) event.getClientConnectionStatusHandler();
     // get the new status
     JPPFClientConnectionStatus status = connection.getStatus();
     System.out.println("Connection " + connection.getName() + " status changed to "
       + status);
   }
 }

To put all of this together, let's take the sample listener from the previous section and modify it to add a status listener to each new connection:

 final MyStatusListener myListener = new MyStatusListener();
 
 public class MyClientListener implements ClientListener {
   @Override
   public void newConnection(ClientEvent event) {
     // the new connection is the source of the event
     JPPFClientConnection connection = event.getConnection();
     System.out.println("New connection with name " + connection.getName());
     // register to receive status events on the new connection
     connection.addClientConnectionStatusListener(myListener);
   }
 
   @Override
   public void connectionFailed(ClientEvent event) {
     JPPFClientConnection connection = event.getConnection();
     System.out.println("Connection " + connection.getName() + " has failed");
     // remove the status listener reference
     connection.removeClientConnectionStatusListener(myListener);
   }
 }
Main Page > Development guide > The JPPFClient API

JPPF Copyright © 2005-2020 JPPF.org Powered by MediaWiki