You got a job to do?

AsynchroneRequestsYou are using the PTV xServer with really long running requests? Like PTV xTour requests with lots of depots and orders? Or you are doing bulk address calculations with PTV xLocate? Well, then this blog post is for you!

Take a simple (but long running) request :

Plan plan = client.planBasicTours(transportOrders, depots, fleet, planningParams, inputPlan);
System.out.println("Got result. Calculated " + plan.getChains().length + " chains.");

This simple line blocks your code until PTV xTour has calculated the tours and has returned the response. This may take hours and there is no chance to get information on the progress so far. Of course you can have a look on the PTV xServer’s status monitor. But you can not access this information using the API.

Starting with the PTV xServer 1.18 we have added a new way to run these long running requests. Just add the prefix start to your method call:

Job job = client.startPlanBasicTours(transportOrders, depots, fleet, planningParams, inputPlan);

This code immediately returns a so called job handle. This handle references the job which is running on the server. Using this handle we can query the job’s status and wait for the calculation to finish:

// take default WatchOptions for now...
WatchOptions watchOptions = new WatchOptions();

// A job has a status => QUEUING, RUNNING, SUCCEEDED, FAILED, DELETED, UNKNOWN
JobStatus status = job.getStatus();

// wait until the status turns to SUCCEEDED or FAILED
while(!status.equals(JobStatus.FAILED) && !status.equals(JobStatus.SUCCEEDED)) {
job = client.watchJob(job.getId(), watchOptions);
status = job.getStatus();
}

// fetch the result (or exception)
try {
Plan plan = client.fetchPlan(job.getId());
System.out.println("Got result. Calculated " + plan.getChains().length + " chains.");
} catch (Exception e) {
System.out.println("Calculation stopped with an exception: " + e);
}

The advantages of this approach are obvious:

  • the client does not have to remain connected all the time
  • if you lose the connection, you can try again, the results will not be lost
  • you can query the progress of your job: are we there yet?

For our java clients we have also added a convenience method which handles the while-loop watching the running job. This special method has the prefix run and works like this:

// We like to get progress information every 500 milliseconds
WatchOptions watchOptions = new WatchOptions();
watchOptions.setProgressUpdatePeriod(250);

// Do 2 retries, if connection is lost
// and wait 2 seconds in between
RetryOptions retryOptions = new RetryOptions();
retryOptions.setRetries(2);
retryOptions.setRetryInterval(2000);

Future future = client.runPlanBasicTourstransportOrders, depots, fleet, planningParams, inputPlan, watchOptions, new WatchCallback() {

@Override
public void onJobUpdate(Job job) {
if (job.getProgress() != null) {
PlanProgress planProgress = (PlanProgress) job.getProgress();
DistanceMatrixCalculationProgress dimaProgress = planProgress
.getDistanceMatrixCalculationProgress();
ImprovementProgress imProgress = planProgress.getImprovementProgress();
if (dimaProgress != null) {
DistanceMatrixProgress matrixProgress = dimaProgress.getCurrentDistanceMatrixProgress();
if (matrixProgress != null) {
System.out.println("Dima Calculation: " + dimaProgress.getCurrentDimaIndex() + ", "
+ matrixProgress.getCurrentRowIndex());
}
}
if (imProgress != null) {
KeyFigures bestPlan = imProgress.getBestPlan();
System.out.println("Ieration: " + imProgress.getIterationIndex() + ", TotalChainCost: "
+ bestPlan.getNumberOfUnscheduledOrders());
}
}
}
}, retryOptions);
System.out.println("Got future. Waiting for result.");
try {
System.out.println("Result = " + future.get().getChains().length);
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}

In addition to the WatchOptions this method also receives an argument of type RetryOptions which allows us to set the number of retries and a waiting interval in case the connection to the PTV xServer is lost.

Now, give it a try! Turn your synchronous calls into asynchronous job requests. If you have any questions, leave us a comment or contact our support.

Howto create your own webservice clients for PTV xServers

Gallery

Some time ago the PTV xServer development team was asked whether it was possible to create a web service client without our provided java clients and the bundled cxf framework.
The simple answer is: Yes! Those who would like to take the adventure and try it themselves should read on…

What you need for this

The prerequisites for this little sample are the following:

  • A JDK 6, or newer,
  • A Maven2 or Maven3 installation,
  • PTV xRoute Server (the sample runs with xRoute 1.16 but it should work with older versions too)

Create a Maven project

First of all we create a new directory and set up a Maven project file named pom.xmlRead more