Skip to content

Latest commit

 

History

History
222 lines (174 loc) · 8.77 KB

File metadata and controls

222 lines (174 loc) · 8.77 KB

OptaWeb Vehicle Routing Backend

Quality Gate Status Reliability Rating Security Rating Maintainability Rating Lines of Code Coverage

  • 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

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 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.).

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 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

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 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 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.

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

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.

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.