= OptaWeb Vehicle Routing Backend

- Maintains and persists user data created through the UI (e.g. visit locations).
- Uses 3rd party services to obtain travel distances between locations based on
  real-world geographical data.
- Uses OptaPlanner to optimize the route between locations.
- Provides network endpoints for interaction with the web UI.

== Project Structure

[literal]
....
org.optaweb.vehiclerouting
├── domain
├── plugin
│   ├── persistence
│   ├── planner
│   ├── routing
│   └── websocket
└── service
    ├── demo
    ├── distance
    ├── location
    └── route
....

=== Root Package

The root package name is identical to the Maven Group ID of the project
(`org.optaweb.vehiclerouting`).
It contains a class annotated with `@SpringBootApplication`,
which enables Spring auto-configuration and component scanning in sub-packages.

=== Domain Package

Contains "business objects" that model the domain of this project,
for example Visit, Depot, Location, Vehicle.
These objects are strictly business-oriented and must not be influenced
by any tools and frameworks (e.g. ORM, marshalling formats etc.).

=== Services Package

Contains classes that implement "use cases".
A use case is for example adding new location, changing vehicle capacity
or finding coordinates for an address.
The business rules that govern use cases are expressed using the domain objects.

Use cases often need to interact with outer layers, such as persistence, web and
optimization.
To keep the code loosely coupled, the interaction with the outer layers
is expressed in terms of interfaces.
Their implementations are provided by Spring IoC container at runtime.

=== Plugins Package

Contains outer layers such as optimization, persistence, routing and web.

== Configuration

There are multiple ways how to set configuration properties.
When running locally, you'll probably want to use one of these:

* Set it using `application.properties` (you'll find it under `/src/main/resources/`).
* A command line argument when running the packaged application
(e.g. `java -jar optaweb-vehicle-routing-backend.jar --app.my-property=value1`).
* An environment variable when running the application with `spring-boot:run`.
+
For example: `app_my_property=value1 ./mvnw spring-boot:run`
if the property name is `app.my-property` (this requires
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-relaxed-binding[relaxed binding]
which only works if the property is defined using `@ConfigurationProperties`).

[NOTE]
It's not possible to set properties simply via `-D` when running
the application using Spring Boot Maven plugin (`./mvnw spring-boot:run -Dmy-property`).
Any system properties that should be set by the plugin to the forked Java process
in which the application runs need to be specified using `systemPropertiesVariables`
https://docs.spring.io/spring-boot/docs/current/maven-plugin/examples/run-system-properties.html[plugin configuration].

You can learn more about Spring Boot Externalized Configuration in
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config[Spring Boot Guide].

[TIP]
Use `src/main/resources/application-local.properties` to store your personal configuration
without affecting Git working tree.

See also the complete list of
https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html[
common application properties] available in Spring Boot.

[cols="m,d,a,d",options="header"]
|===

|Property
|Type
|Example
|Description

|app.demo.size
|positive integer
|42
|Number of locations that will be created when user loads the demo.

|app.optimizer.timeout
|java.time.Duration
|* 1m
 * 150s
 * P2dT21h (PnDTnHnMn.nS)
|How long the solver should run after a location change occurs.

|app.region.country-codes
|List of https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2[ISO 3166-1 alpha-2] country codes
|`US`, `GB,IE`, `DE,AT,CH`, may be empty
|Restricts geosearch results.

|app.routing.osm-file
|String
|belgium-latest.osm.pbf
|Name of the OSM file that should be loaded by GraphHopper.
 The file must be placed under `local/openstreetmap/`.

|server.address
|IP address or hostname
|10.0.0.123, my-vrp.geo-1.openshiftapps.com
|Network address to which the server should bind.

|server.port
|Port number
|4000, 8081
|Server HTTP port.

|===

== Logging

Our logging backend is Logback.
Spring Environment allows to configure most logging aspects
including levels, patterns and log files
in the same way as any other xref:#configuration[Configuration]
(most often using `application.properties` or arguments `--property=value`).
See Spring Boot
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-logging.html#boot-features-custom-log-levels[
Logging] documentation for more information.

For example, you may use:

- `logging.level.org.optaweb.vehiclerouting=debug`
  to enable debug level for the backend code,
- `logging.level.org.optaplanner.core=warn`
  to reduce OptaPlanner logging,
- `logging.level.org.springframework.web.socket=trace`
  to access more details when investigating problems with WebSocket connection.

== Dependency Rules

Compile-time dependencies are only allowed in the direction from outer layers
towards the center.
This means plugins -> services -> domain.

The domain has no dependencies.

Services only depend on the domain.
If a service needs to send a result (e.g. to a database or web socket),
it uses an output boundary interface.
Its implementation is injected by the IoC container.

Plugins depend on services in two ways.
Firstly, they invoke services based on events such as a user input
or a route update coming from the optimization engine.
Services are injected into plugins, which moves the burden of their
construction and dependency resolution to the IoC container.
Secondly, plugins implement services' output boundary interfaces to handle
use case results, e.g. persisting changes to database, sending response to web UI.

== Development Guide

=== Automatic Restart

https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-devtools-restart[Automatic restart]
is provided by Spring Boot DevTools.
It scans files on the classpath, so you only need to recompile your changes
to trigger application restart.
No IDE configuration is needed.

If your IDE has a compile-on-save feature (Eclipse, NetBeans),
you just need to save the files that have changed since last compilation.

IntelliJ IDEA saves changes automatically and you need to use either
Recompile action, which recompiles the file in active tab, or
Build Project action which recompiles all changes.
See https://www.jetbrains.com/help/idea/compilation-types.html[Compilation Types].

=== Running Backend from IntelliJ IDEA

1. Run `org.optaweb.vehiclerouting.OptaWebVehicleRoutingApplication`
   from Project window.
   This will create a Run Configuration that you will edit in the next step.
   A failure on the first run is expected due to wrong working directory.

2. Select `Run > Edit Configurations...` and then select
   `Spring Boot > OptaWebVehicleRoutingApplication`.

3. Change *Working directory* to the backend module (`optaweb-vehicle-routing-backend`).

4. Optionally, set *On Update action* to *Hot swap classes and update trigger file if failed*.
   This will allow you to use the Update action to quickly restart the application.
+
See https://blog.jetbrains.com/idea/2018/04/spring-and-spring-boot-in-intellij-idea-2018-1/[Spring and Spring Boot in IntelliJ IDEA 2018.1]
for more details.
