Creating REST TourOptimizer JSON Input from a Java Optimization — JOpt TourOptimizer
This document explains how to translate a Java-defined optimization problem into a valid JSON payload for the JOpt.TourOptimizer REST API.
This bridge is particularly valuable when:
- Debugging: you build and inspect a problem in Java but want to submit it manually via the Swagger UI or a REST client.
- Hybrid production setups: Java is used for problem construction (nodes, resources, constraints) while the actual optimization is offloaded to a containerized REST server.
- Snapshot seeding: an already-optimized solution is embedded into the JSON payload so the REST server can use it as a warm start.
Sources (GitHub):
- CreateRestTourOptimizerInputWithoutSolutionExample.java
- CreateRestTourOptimizerInputWithSolutionExample.java
Overview
- Why translate Java to JSON?
- The two variants
- Core conversion pattern
- Example 1 - Without solution (fresh start)
- Example 2 - With solution (warm start)
- Compatible REST endpoints
- Implementation notes
- End-to-end workflow recipes
Why translate Java to JSON?
The JOpt core library is a Java API. The JOpt.TourOptimizer REST server accepts JSON payloads. These two examples demonstrate a serialization bridge that makes both worlds interoperable.
The benefits are significant in practice:
- No re-implementation: your Java problem definition is the single source of truth. You do not have to manually construct a JSON payload or maintain two versions.
- Exact reproduction: the JSON produced by these examples is fully compatible with the REST server. What you see from the Java run is exactly what the REST server will optimize.
- Progressive workflows: start with a Java-local run, capture the solution, then hand it off to a REST server as a warm-start seed — without changing the problem definition.
- Manual debugging via Swagger: paste the JSON output directly into the Swagger UI to inspect or reproduce a specific scenario.
The two variants
| Variant | What it serializes | Typical use case |
|---|---|---|
WithoutSolution | Problem definition only (nodes, resources, properties) | First-time submission to the REST server; fresh optimization |
WithSolution | Problem definition plus the result of a local run | Warm start: REST server continues from an already-found solution |
Both variants produce JSON that can be submitted to the same REST endpoints.
Core conversion pattern
The key utility method is reusable and can be dropped into any project that needs to bridge Java models to REST payloads:
public static String jsonFromOptimization(IOptimization opti)
throws IOException, ConvertException, SerializationException {
String licenseKey = "YOUR_JSON_LIC"; // Replace with your JSON license key
Duration timeOut = Duration.ofMinutes(10);
JSONConfig myExtension = JSONConfig.builder()
.keySetting(OptimizationKeySetting.of(licenseKey))
.timeOut(timeOut)
.build();
return JSONOptimization.asJSON(JSONOptimization.fromOptization(opti, Optional.of(myExtension)));
}
The timeOut value serves a dual purpose:
- It limits the serialization process on the Java side.
- It is embedded in the JSON payload and used by the REST server as the maximum allowed optimization duration.
Note: Replace
"YOUR_JSON_LIC"with a valid JSON license key. Without a valid license, the optimizer runs in a limited mode.
Example 1 - Without solution (fresh start)
Class: CreateRestTourOptimizerInputWithoutSolutionExample
This example constructs an optimization problem, serializes it to JSON, and prints the result. No local optimization run is performed — the JSON only encodes the problem definition.
What it does (step by step)
- Creates a new
Optimizationinstance. - Adds seven nodes (German cities: Koeln, Essen, Dueren, Nuernberg, Heilbronn, Wuppertal, Aachen) with two-day opening hours and a 20-minute visit duration each.
- Adds one resource ("Jack from Aachen") with two working days, a max working time of 9 hours, and a max travel distance of 1,200 km.
- Assigns a run identifier:
"MyJOptRun". - Wraps the optimization in a
JSONConfig(license + timeout). - Calls
JSONOptimization.fromOptization(...)followed byJSONOptimization.asJSON(...)to produce the JSON string. - Prints the JSON to stdout.
Skeleton
IOptimization myOpti = new Optimization();
// Build the problem
CreateRestTourOptimizerInputWithoutSolutionExample.addNodes(myOpti);
CreateRestTourOptimizerInputWithoutSolutionExample.addResources(myOpti);
myOpti.setOptimizationRunIdent("MyJOptRun");
// Serialize to REST-compatible JSON
JSONConfig myExtension = JSONConfig.builder()
.keySetting(OptimizationKeySetting.of(licenseKey))
.timeOut(Duration.ofMinutes(10))
.build();
String json = JSONOptimization.asJSON(JSONOptimization.fromOptization(myOpti, Optional.of(myExtension)));
System.out.println(json);
When to use this variant
- You want to submit a new, unsolved problem to the REST server.
- You are generating test payloads for the Swagger UI or integration tests.
- You want to inspect what the REST server will receive before sending a real request.
Example 2 — With solution (warm start)
Class: CreateRestTourOptimizerInputWithSolutionExample
This example extends the first by running the optimization locally before serializing. The resulting JSON snapshot includes the locally found solution, which the REST server can use as a starting point for further optimization instead of beginning from scratch.
What it does (step by step)
- Creates a new
Optimizationinstance and sets the license viaExampleLicenseHelper.setLicense(myOpti). - Adds the same nodes and resources as the first example.
- Assigns a run identifier:
"MyJOptRunWithSolution". - Runs the optimization locally using
myOpti.startRunAsync()and blocks until the result is available. - Serializes the post-run optimization state (problem + solution) using the same
JSONConfigandJSONOptimization.asJSON(...)pattern. - Prints the JSON to stdout.
Skeleton
IOptimization myOpti = new Optimization();
// License and problem definition
ExampleLicenseHelper.setLicense(myOpti);
CreateRestTourOptimizerInputWithSolutionExample.addNodes(myOpti);
CreateRestTourOptimizerInputWithSolutionExample.addResources(myOpti);
myOpti.setOptimizationRunIdent("MyJOptRunWithSolution");
// Run locally first — the solution will be embedded in the JSON
CompletableFuture<IOptimizationResult> resultFuture = myOpti.startRunAsync();
System.out.println(resultFuture.get()); // Block until done
// Serialize the post-run state (problem + solution) to REST-compatible JSON
JSONConfig myExtension = JSONConfig.builder()
.keySetting(OptimizationKeySetting.of(licenseKey))
.timeOut(Duration.ofMinutes(10))
.build();
String json = JSONOptimization.asJSON(JSONOptimization.fromOptization(myOpti, Optional.of(myExtension)));
System.out.println(json);
Key difference from the WithoutSolution variant
The critical distinction is when fromOptization(...) is called:
- Without solution: called on a fresh, unrun
IOptimization→ JSON contains only the problem definition. The REST server will optimize it entirely from scratch. - With solution: called on an already-run
IOptimization→ JSON embeds the current best solution. The REST server uses this as a seed and continues improving from there.
When to use this variant
- You have already run locally and want the REST server to continue improving the result (e.g., with a longer timeout or different properties).
- You want to use Java as a pre-solver to generate a good initial solution, then hand off to the cloud.
- You want to benchmark local vs. REST results starting from the same initial solution.
Compatible REST endpoints
The JSON produced by both examples is accepted by the following JOpt.TourOptimizer REST endpoints:
| Endpoint | Description |
|---|---|
/api/optimize/config/run | Starts optimization and streams progress + final result |
/api/optimize/config/runOnlyResult | Starts optimization and returns only the final result |
For production integrations, the recommended approach is to generate a typed client from the OpenAPI specification:
- Swagger annotation / API schema: https://swagger.dna-evolutions.com/v3/api-docs/OptimizeConfig
Implementation notes
The JSONConfig builder
JSONConfig carries the REST-specific metadata that the core library itself does not have. The two most important fields are:
keySetting: wraps your JSON license key viaOptimizationKeySetting.of(licenseKey). This is required for REST-server runs.timeOut: passed toJSONConfig.builder().timeOut(...). This duration controls the maximum time the REST server will spend optimizing. Choose a value appropriate for your scenario — the REST server honours this as a hard upper bound.
License key
The examples reference ExampleLicenseHelper.PUBLIC_JSON_LICENSE as a placeholder. In production:
- Replace this with your own JSON license key.
- Never hardcode keys in shared repositories. Use environment variables or a secrets manager.
Blocking the async call (WithSolution variant)
In the WithSolution example, resultFuture.get() is called explicitly before serialization. This is mandatory:
- The
IOptimizationobject is only fully populated with a solution once the run completes. - Calling
fromOptization(...)on an incomplete run would produce a JSON without a valid solution, defeating the purpose of the warm-start variant.
Reusable helper method
The WithoutSolution example exposes jsonFromOptimization(IOptimization opti) as a public static helper. This is the recommended entry point if you want to integrate the serialization bridge into your own code. It encapsulates the JSONConfig construction and JSONOptimization calls behind a clean single-method API.
End-to-end workflow recipes
Recipe A — Debug via Swagger UI
- Construct your problem in Java.
- Call
jsonFromOptimization(myOpti)(fromCreateRestTourOptimizerInputWithoutSolutionExample). - Copy the printed JSON.
- Open https://touroptimizer.dna-evolutions.com or your local Swagger UI.
- Paste into
/api/optimize/config/runOnlyResultand execute.
Recipe B — Java pre-solver → REST refinement
- Run the optimization locally using
CreateRestTourOptimizerInputWithSolutionExample. - Capture the printed JSON (which contains the local solution).
- Submit to the REST server at
/api/optimize/config/runwith a longer timeout to continue improving.
Recipe C — CI/CD integration test fixture
- Use
jsonFromOptimization(myOpti)in a test setup method to produce a deterministic JSON payload. - Store the output as a test fixture file.
- Use the fixture in REST integration tests against a locally running TourOptimizer container.
References
REST TourOptimizer
REST Clients
Related examples
- Load JSON and run locally
- Builder pattern for immutable config construction
- Load and save optimization snapshots
Agreement
For reading our license agreement and for further information about license plans, please visit www.dna-evolutions.com.
Authors
A product by dna-evolutions ©
Rest Examples (Java) — JOpt TourOptimizer
Rest Examples (Java) — JOpt TourOptimizer
Reading a REST JSON Config and Running It Locally — JOpt TourOptimizer
This document explains how to take a REST-compatible JSON payload — as produced by the JOpt.TourOptimizer REST server or by the Java serialization bridge — and execute it locally using the JOpt core library.