Java clients

Two kinds of java clients are given.

Synchronous API

First, Java clients to call the synchronous APIs.

Let us note that many other clients can be generated using the given OpenAPI file, including clients for other HTTP libraries, or even other languages.

Asynchronous API

The asynchronous API enables listening to job events emitted by Optimization Server. All these events are relative to a job posted on Optimization Server.

They can be:

  • A solution of a job computed by a worker.
  • A job status emitted by the Optimization Server master that monitors the worker.
  • A KPI emitted by the worker that is carrying out the job.
  • A progress status emitted by the worker that is carrying out the job.
  • A log emitted by the worker that is carrying out the job.

Overview

The asynchronous API is described by the following interfaces:

public interface JobExecutionAsyncApi {

    CompletionStage<JobSolution> getJobSolution(String jobId, Duration timeout);

    JobEventSource getJobEventSource(JobSubscriptionFilter filter);

}

public interface JobExecutionSharedAsyncApi {
    
    JobEventSource getSharedJobEventSource(String subscriptionId);
  
}

public class JobSubscriptionFilter {
    private String jobId;
}

public interface JobEventSource extends ConnectableEventSource {

    CompletionStage<JobSolution> jobSolution();

    Flow.Publisher<JobStatusEvent> statusEvents();

    Flow.Publisher<KpiEvent> kpiEvents();

    Flow.Publisher<ProgressEvent> progressEvents();

    Flow.Publisher<LogEvent> logEvents();

}

public interface ConnectableEventSource {

    void connect();

    void disconnect();

}

The client program has to :

  • Retrieve a JobEventSource by calling getJobEventSource with a JobSubscriptionFilter that contains the id of the job to listen.
  • Subscribe to the publisher that emits the events it wants to listen to.
  • Call connect to tell the source to start emitting.

Here is a pseudo-code snippet that outlines these 3 steps:


import com.decisionbrain.optimserver.client.java.ApiException;
import com.decisionbrain.optimserver.client.java.async.api.ConsumerSubscriber;
import com.decisionbrain.optimserver.client.java.async.api.JobEventSource;
import com.decisionbrain.optimserver.client.java.async.api.JobExecutionAsyncApi;
import com.decisionbrain.optimserver.client.java.async.api.JobSubscriptionFilter;

import java.time.Duration;
import java.util.List;
import java.util.concurrent.CompletableFuture;

public class RunningJobListener {

    private final JobExecutionAsyncApi jobExecutionAsyncApi;

    public void onApplicationReady() {

        String jobId = "theJobToListen";
        CompletableFuture<Void> onComplete = new CompletableFuture<>();
        onComplete.whenComplete((v, e) ->
                LOGGER.info("The flow of events for this job is finished"));

        JobEventSource eventSource = jobExecutionAsyncApi.getJobEventSource(
                new JobSubscriptionFilter(jobId)
        );
        eventSource.statusEvents().subscribe(new ConsumerSubscriber<>(
                onComplete,
                jobStatusEvent ->
                        LOGGER.info(String.format("[STATUS]: %s", jobStatusEvent.getStatus().name()))
        ));

        eventSource.connect();

        jobExecutionAsyncApi.getJobSolution(jobDefinition.getId(), Duration.ofSeconds(3))
                .whenComplete((jobSolution, throwable) -> {
                    if (jobSolution != null) {
                        LOGGER.info("Solution retrieved before timeout");
                    }
                    if (throwable != null) {
                        LOGGER.error("Exception while waiting for solution", throwable);
                    }
                });
    }

}

To learn more, you can read the javadoc in this page

Features

An event source bound to one job

As shown in the example above, the JobEventSource emits all the events of the job identified by the id filled in the JobSubscriptionFilter .

All the events are relative to this job and this job only.

An event source bound to all jobs

A JobEventSource can also emits all the events of all the jobs. To achieve this, no job id should be supplied to the JobSubscriptionFilter .

An shared event source

A JobEventSource can be shared among several clients, where each alternatively receives a message.

Example: if 2 clients share a same a JobEventSource that emits e1 and e2, one receives e1 (but not e2) and the other receives e2 (but not e1).

This source can be retrieved by calling the JobExecutionSharedAsyncApi.getSharedJobEventSource() method.

Implementations

Optimization Server provides 3 clients that comply with this API

Not every implementation supplies the features described above

Implementation One job event source All jobs event source Shared event source
Spring AMPQ Yes Yes Yes
Jersey SSE Yes No No
Spring SSE Yes No No

Legacy

Optimization Server also provides 2 additional clients that support the STOMP Protocol which have not been migrated yet to comply with the API.

These clients are not generated. This list may be extended in the future to support other protocols.