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 5.1 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 Resetting the JPPF client

A JPPFClient can be reset at runtime, to allow the recycling of its server connections, along with dynamic reloading of its configuration. Two methods are provided for this :

public class JPPFClient extends AbstractGenericClient {
  // close this client, reload the configuration, then open it again
  public void reset()

  // close this client, then open it again using the specified confguration
  public void reset(TypedProperties configuration)
}

Note that jobs that were already submitted by the client are not lost: they remain queued in the client and will be resubmitted as soon as one or more server connections become available again.

3 Submitting a job

To submit a job, JPPFClient provides a single method:

public List<Task<?>> submitJob(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).

4 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.

5 Exploring the server connections (deprecated)


Deprecation notice: the APIs described here were deprecated in JPPF 5.1 and are no longer working. They are superseded by the connection pools APIs and will be removed in a future version.



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)

6 Receiving notifications for new and failed connections (deprecated)


Deprecation notice: the APIs described here were deprecated in JPPF 5.1 and are no longer working. They are superseded by the connection pools APIs and will be removed in a future version.



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)''';

7 Switching local execution on or off

The JPPFClient API allows users to dynamically turn the local (in the client JVM) execution of jobs on or off, and determine whether it is active or not. This is done via these two methods:

// Determine whether local execution is enabled on this client
public boolean isLocalExecutionEnabled()

// Specify whether local execution is enabled on this client
public void setLocalExecutionEnabled(boolean localExecutionEnabled)

Turning local execution on or off will affect the next job to be executed, but not any that is currently executing.

8 Registering additional class loaders to handle requests from the driver

In some unusual use cases, it may be necessary to register addtional class loaders witht he cllient for a given job. This can happen if some of the tasks in the job are loaded with different class loaders, or in some situations when the job is submitted from task executing in a a node. To enable this, the super class of JPPFClient, AbstractGenericClient, provides the following method:

public class AbstractGenericClient extends AbstractJPPFClient {
  // register a class loader for the specified job uuid
  public ClassLoader registerClassLoader(ClassLoader cl, String uuid)
}

The class loader must be registered before the job is submitted, otherwise it will have no effect. Additionally, the unregistration of the class loader is automatically performed by the JPPF client, once the job has completed.

Example usage:

JPPFClient client = new JPPFClient();
JPPFJob job = newJPPFJob();
// let's assume MyTask is loaded from a separate class loader
MyTask myTask = ...;
job.add(task);
ClassLoader cl = myTask.getClass().getClassLoader();
// register the class loader for the job, before submitting it
client.registerClassLoader(cl, job.getUuid());
List<Task<?>> result = client.submitJob(job);
Main Page > Development guide > The JPPFClient API

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