-
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.
org.optaweb.vehiclerouting ├── domain ├── plugin │ ├── persistence │ ├── planner │ ├── routing │ └── websocket └── service ├── demo ├── distance ├── location └── route
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.
Contains "business objects" that model the domain of this project, for example Customer, 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.).
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.
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 isapp.my-property
(this requires 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
plugin configuration.
|
You can learn more about Spring Boot Externalized Configuration in 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 common application properties available in Spring Boot.
Property | Type | Example | Description |
---|---|---|---|
|
positive integer |
42 |
Number of locations that will be created when user loads the demo. |
|
java.time.Duration |
|
How long the solver should run after a location change occurs. |
|
List of ISO 3166-1 alpha-2 country codes |
|
Restricts geosearch results. |
|
String |
belgium-latest.osm.pbf |
Name of the OSM file that should be loaded by GraphHopper.
The file must be placed under |
|
IP address or hostname |
10.0.0.123, my-vrp.geo-1.openshiftapps.com |
Network address to which the server should bind. |
|
Port number |
4000, 8081 |
Server HTTP port. |
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 Configuration
(most often using application.properties
or arguments --property=value
).
See Spring Boot
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.
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.
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 Compilation Types.
-
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. -
Select
Run > Edit Configurations…
and then selectSpring Boot > OptaWebVehicleRoutingApplication
. -
Change Working directory to the backend module (
optaweb-vehicle-routing-backend
). -
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 Spring and Spring Boot in IntelliJ IDEA 2018.1 for more details.