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   Forums 

The JPPFClient API

From JPPF 6.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 two methods:

public class JPPFClient extends AbstractGenericClient {
  // Submit a job synchronously and wait for the results
  public List<Tasks<?>> submit(JPPFJob job)

  // Submit a job asynchronously and return immediately
  public JPPFJob submitAsync(JPPFJob job)
}

These methods have different behaviors:

  • 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.
  • submitAsync() returns immediately, not waiting for the job to execute. It is up to the developer to collect the execution results, generally via the JPPF job API.

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

6 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.submit(job);

7 Changing and retrieving the load-balancer settings

The load-balancer configuration can be dynamically updated and retrieved, even while the client is executing jobs, using the following methods in JPPFClient:

public class JPPFClient extends AbstractGenericClient {
  // Get the current load-balancer settings
  public LoadBalancingInformation getLoadBalancerSettings()

  // Change the load balancer settings
  public void setLoadBalancerSettings(String algorithm, Properties parameters)
    throws Exception
}

The parameters of the setLoadBalancerSettings() method are those of the load-balancing algorithm and must not be prefixed. The getLoadBalancerSettings() method provides the current configuration encapsulated in a LoadBalancingInformation object.

Example usage:

JPPFClient jppfCLient = new JPPFClient();
// configure the "proportional" load-balancer algorithm
TypedProperties props = new TypedProperties()
  .setInt("initialSize", 5)
  .setInt("proportionalityFactor", 1);
jppfClient.setLoadBalancerSettings("proportional", props);

// retrieve the load-balancer configuration
LoadBalancingInformation lbi = jppfClient.getLoadBalancerSettings();
System.out.println("current algorithm is " + lbi.getAlgorithm());
System.out.println("algorithm parameters: " + lbi.getParameters());

8 Default job execution policies

A JPPFClient instance can have a default client and/or server side execution policy. The default policies are applied only to submitted jobs that don't have an execution policy (i.e. the execution policy is null). Default execution policies can be set or retrieved with the following methods:

public class JPPFClient extends AbstractGenericClient {
  // Get the default server-side job execution policy
  public ExecutionPolicy getDefaultPolicy()
  // Set the default server-side job execution policy
  public void setDefaultPolicy(ExecutionPolicy defaultServerPolicy)
  // Get the default client-side job execution policy
  public ExecutionPolicy getDefaultClientPolicy()
  // Set the default client-side job execution policy
  public void setDefaultClientPolicy(ExecutionPolicy defaultClientPolicy)
}
Note: default policies can also be set within the JPPF client configuration, as documented here.

Here is an example usage:

try (JPPFClient client = new JPPFClient()) {
  // by default, jobs can only execute on nodes with at least 4 CPUs 
  client.setDefaultPolicy(new AtLeast("availableProcessors", 4));
  // by default, jobs cannot execute in the client local executor
  client.setDefaultClientPolicy(new Equal("jppf.channel.local", false));
}

9 Inspecting the jobs queue

You can list and count the jobs queued in a JPPFClient instance, using the following methods:

public class JPPFClient extends AbstractGenericClient {
  // Get the list of currently queued jobs
  public List<JPPFJob> getQueuedJobs()
 
  // Get a list of currently queued jobs, filtered by a JobSelector
  public List<JPPFJob> getQueuedJobs(JobSelector selector)
 
  // Get the current number of queued jobs
  public int getQueuedJobsCount()
 
  // Get the current number of jobs that satisfy a job selector
  public int getQueuedJobsCount(JobSelector selector)
}

Note that you can view or count either all jobs or jobs filtered by a job selector.

Example usage:

JPPFJob job = new JPPFJob();
job.setBlocking(false);
job.add(new MyTask());

try (JPPFClient client = new JPPFClient()) [
  client.submitJob(job);
  List<JPPFJob> jobs = client.getQueuedJobs();
  // ... do something with the list of queued jobs ..
  final List<Task<?>> results = job.awaitResults();
  // ... process the results ...
}
Main Page > Development guide > The JPPFClient API

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