Skip to content

About

Project for the Microservices Software Architectures course's final exam. It's an electric-vehicles sharing systems composed of multiple microservices orchestrated using a distributed orchestration engine based on Camunda

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

292 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ACME Mobility

ACME Mobility is the project for the Microservices Software Architectures, Academic Year 2025/2026 course. It implements a short-term urban rental platform for electric vehicles—cars, scooters, and kick scooters—distributed across city stations.

The repository includes both the executable system and the analysis and design artifacts required by the project specification: global choreography, participant projections, documentary and executable BPMN diagrams, and UML models using the TinySOA profile.

This is the project's only README. Run Docker commands from the acme-mobility directory.

Contents

Application features

Account, authentication, and session

  • User registration with name, email address, and password.
  • Automatic creation of a Jolie bank account associated with the user, with a UUID identifier and an initial balance of €100.
  • Login and logout through HTTP sessions and cookies.
  • Session recovery when the page is refreshed.
  • Display of total balance, reserved amount, and available balance.

Registration involves two services: the frontend first creates the user in the Rental Service, then creates the account through the dedicated Jolie REST service.

Map, stations, and vehicles

  • Leaflet/OpenStreetMap map of the seven configured stations in Bologna.
  • Display of the vehicles at each station.
  • Distinction between cars, scooters, and kick scooters.
  • Status and battery-level indicators.
  • Managed statuses: AVAILABLE, BOOKED, RENTED, MAINTENANCE, and CHARGING.
  • Access to instant rental or reservation selection from the map.

Instant rental

The user selects or enters the vehicle ID, which represents a QR-code scan. If the vehicle is available and the user does not already have a reservation:

  1. Camunda starts the instant-rental branch.
  2. The Bank Service reserves a €10 deposit.
  3. Fleet Management starts tracking and battery monitoring.
  4. The Stations Service simulates the physical unlock.
  5. The vehicle changes to RENTED.
  6. The UI opens the active ride.

The project does not use a camera: QR scanning is simulated through the vehicle identifier.

Short reservation

The user selects a station and a vehicle category. The Rental Service assigns the AVAILABLE vehicle of that type with the highest battery level, reserves €10 on the account, and changes its status to BOOKED.

The reservation:

  • lasts 30 minutes;
  • shows a countdown;
  • can be collected by scanning the assigned vehicle;
  • can be cancelled free of charge while at least 5 minutes remain;
  • converts the deposit into a charge when cancelled later;
  • also converts the deposit into a charge when it expires uncollected.

A user can have only one active reservation. A reserved vehicle can be collected only by the user to whom it was assigned.

Ride and telemetry

During a ride, Fleet Management:

  • chooses a destination station different from the departure station;
  • calculates a route with GraphHopper, using linear interpolation as a fallback;
  • simulates 20 vehicle movements after an initial 15-second delay;
  • updates position and battery every 5 seconds;
  • sends data to the Tracking Service and Battery Service through gRPC.

Telemetry delivery is best-effort. If an individual gRPC update fails, the failure is logged and the simulation continues; the affected service keeps its previous value until a later snapshot is delivered successfully. Active route simulations are held in the Fleet Gateway memory and are not resumed after a gateway restart.

The Rental Service periodically queries the Fleet Management gateway and publishes updates to the browser through Redis Pub/Sub and Server-Sent Events. The ride page displays the current map position, departure and destination stations, battery level, duration, connection state, and arrival at the destination. The UI enables ride completion when the simulation reports arrival.

Ride completion, payment, and summary

When ride completion is requested, Camunda coordinates:

  1. Reading the latest telemetry.
  2. Physically locking the vehicle at the arrival station.
  3. Stopping tracking and battery monitoring.
  4. Calculating and charging the fare.
  5. Releasing the reserved deposit.
  6. Persisting the completed rental.
  7. Sending the summary to the frontend.

Implemented rates are:

Vehicle Fixed fee Rate per minute
Car €2.00 €0.25
Scooter €1.50 €0.20
Kick scooter €1.00 €0.15

To make payment observable during a demo, one real second is equivalent to 15 billed seconds. The total is rounded to cents; a 10% penalty is added when the final battery level is below 15%.

The summary shows the vehicle, destination, duration, final battery level, price, and any penalty.

Damage reporting, charging, and maintenance

After the summary, the user can finish without reporting damage or select damaged parts from a vehicle-type-specific list and submit the report.

If no damage is reported:

  • with a battery level of at least 15%, the vehicle returns to AVAILABLE;
  • with a battery level below 15%, it changes to CHARGING; the Stations Service simulates charging up to 100% and notifies the Rental Service, which returns it to AVAILABLE.

If damage is reported, the vehicle changes to MAINTENANCE and is added to the Maintenance Service queue. The simulated duration is:

1 minute × (1 + number of damages)

The Maintenance Service keeps an in-memory FIFO queue, recovers vehicles already under maintenance from the Rental Service on startup, and processes the queue every day at 09:00 in the Europe/Rome time zone. On completion, it sets the battery to 100% and requests that the vehicle return to AVAILABLE.

A separate BPMN process, started every day at midnight, also finds available or already-maintained vehicles whose last maintenance was at least 30 days earlier, marks them as MAINTENANCE, and queues them.

How it works

The Rental Service is the application entry point and owns the persistent state of users, process sessions, stations, vehicles, reservations, and rentals. It does not contain the full flow in a Java sequence: it publishes messages to Camunda and provides job workers that implement BPMN process tasks.

Camunda stores workflow state and coordinates calls to banking, stations, Fleet Management, and maintenance. For each authenticated user, the Rental Service associates a ProcessSession with the current Camunda instance.

The frontend does not decide autonomously which stage a rental is in:

BPMN state
  → Rental Service policy
  → GET /api/rentals/resume
  → Angular guard
  → canonical route

This ensures that refreshes, manually entered URLs, and asynchronous updates return the user to the page consistent with the actual process state. Reservation, scanning, cancellation, ride-completion, and reporting commands are also authorized on the backend according to the BPMN stage.

Redis transports process notifications and balance changes. SSE events speed up UI refreshes, while /resume remains the authoritative source for navigation.

Main flow

sequenceDiagram
    actor U as User / Angular
    participant R as Rental Service
    participant C as Camunda
    participant B as Bank Jolie
    participant S as Stations Service
    participant F as Fleet Management

    U->>R: login and open map
    R->>C: create/resume user instance
    U->>R: scan QR or reserve
    R->>C: correlate command
    C->>B: reserve €10 via SOAP
    C->>F: start monitoring via REST
    F->>F: tracking + battery via gRPC
    C->>S: unlock vehicle via REST
    loop simulated ride
        C->>F: request telemetry
        C-->>U: position and battery via SSE
    end
    U->>R: end ride
    C->>S: lock vehicle
    C->>F: stop monitoring
    C->>B: charge fare and release reservation
    C-->>U: summary
    U->>R: no damage or report
Loading

Architecture

flowchart LR
    UI["Angular Frontend<br/>:4200"] -->|REST + SSE| Rental["Rental Service<br/>:8080"]
    UI -->|account-registration REST| Registration["Account Registration<br/>Jolie :8082"]

    Rental <-->|gRPC / REST| Camunda["Camunda 8 + Zeebe<br/>:8083 / :26500"]
    Rental -->|SOAP| Bank["Bank Service<br/>Jolie :8000"]
    Rental -->|REST| Stations["Stations Service<br/>:8084"]
    Rental -->|REST| Maintenance["Maintenance Service<br/>:8085"]
    Rental -->|REST| Gateway["Fleet Gateway<br/>:8091"]
    Rental <--> Redis["Redis<br/>:6379"]
    Rental --> RentalDB[("Rental PostgreSQL<br/>:5432")]

    Bank --> BankDB[("Bank PostgreSQL<br/>:5433")]
    Registration --> BankDB

    Gateway -->|gRPC| Tracking["Tracking Service<br/>:8092"]
    Gateway -->|gRPC| Battery["Battery Service<br/>:8093"]
Loading

Services

Component Technology Responsibility
frontend Angular 21, TypeScript, Leaflet UI, authentication, map, reservation, ride, summary, and reporting
rental-service Java 21, Spring Boot 3.2.5 Public APIs, domain state, Camunda workers, integrations, and SSE
orchestration Camunda 8.9.1 all-in-one BPMN process execution, Zeebe, and Camunda web applications
bank-service Jolie, SOAP Balance, deposit reservation, release, and charges
bank-account-registration-service Jolie, REST Bank-account creation
stations-service Java 21, Spring Boot Station catalog and unlock, lock, and charging simulation
maintenance-service Java 21, Spring Boot Maintenance queue and simulation
fm-gateway Java 21, Spring Boot Fleet Management REST API and route simulation
tracking-service Java 21, Spring Boot, gRPC Position state of tracked vehicles
battery-service Java 21, Spring Boot, gRPC Battery state of tracked vehicles
rental-service-db PostgreSQL 18 Users, BPMN sessions, fleet, reservations, and rentals
bank-service-db PostgreSQL 18 Accounts, balances, reserved amounts, and banking tokens
redis Redis Pub/Sub between workers, SSE notifications, and balance updates

Executable BPMN processes

The Rental Service deploys three processes:

File Purpose
rental_process.bpmn Instant rental, reservation, payment, telemetry, ride completion, reporting, and charging
maintenance_process.bpmn Daily discovery and queuing of vehicles requiring maintenance
update_status.bpmn Asynchronous vehicle status and battery updates

The Camunda runtime uses a maximum of 2 GB of memory in Compose. Zeebe data and file-based H2 secondary storage are kept in Docker volumes.

Persistence and networks

Compose creates three networks:

  • acme-net, for application services;
  • camunda, for orchestration and the Rental Service;
  • fleet-management-net, for the gateway, tracking, and battery services.

Persistent data is separated into volumes for Rental PostgreSQL, Bank PostgreSQL, Zeebe, and Camunda. Re-creatable volumes are also available for the Maven cache, target output, node_modules, and the Angular cache.

Repository structure

MSA-Project/
├── README.md                         # main documentation
├── LICENSE
├── docs/
│   ├── index.html                    # project website entry point
│   ├── pages/                        # architecture and service documentation
│   └── assets/                       # styles, scripts, and report PDF
├── deliverables/
│   ├── asmP_Specifiche_progetto_2025-26.md
│   ├── choreography.md               # global choreography
│   ├── general_diagram_doc.bpmn      # documentary BPMN
│   ├── projections/                  # participant projections
│   ├── TinySOA/                      # UML/Sirius models and TinySOA profile
│   └── report_ACME_Mobility.pdf      # final project report
└── acme-mobility/
    ├── docker-compose.yml
    ├── application.yaml              # Camunda configuration
    ├── .env                          # Camunda version and local configuration
    ├── frontend/
    ├── rental-service/
    │   ├── db/init.sql
    │   └── src/main/resources/bpmn/
    ├── bank-service/
    ├── bank-account-registration-service/
    ├── stations-service/
    ├── maintenance-service/
    └── fleet-management-service/
        ├── fm-gateway/
        ├── tracking-service/
        └── battery-service/

For frontend details, the src/app directory is organized into core (guards, services, and models), features (login, registration, map, reservation, and rental), and shared (header, map, and reusable components).

Java services follow the Spring separation between controllers, services, integrations, DTOs, configuration, and tests. The Rental Service adds JPA repositories, domain models, process-session management, and Camunda job workers.

Starting with Docker Compose

Requirements

  • Docker Desktop or Docker Engine with Docker Compose v2.
  • At least 8 GB assigned to Docker is recommended for the full stack.
  • The ports listed in the next section must be available.
  • An Internet connection is required on the first build to download images and dependencies.

On ARM64 hosts, the two Jolie containers run under linux/amd64 emulation, so the first startup may take longer.

First startup or rebuild

From the repository root:

cd acme-mobility
docker compose up --build

The command builds local images, starts all backend services, and then starts the frontend. Compose waits for dependency health checks before exposing the UI.

When the frontend container is ready, open:

For the Camunda interface, local credentials are demo / demo.

To run in the background:

docker compose up -d --build

Subsequent startups

If images, Dockerfiles, and dependencies have not changed:

docker compose up

or:

docker compose up -d

Stopping while preserving data and caches

docker compose down

This removes project containers and networks, but preserves databases, Camunda state, and caches in volumes.

Stopping with a complete reset

docker compose down -v

The -v option also removes all named project volumes. At the next startup, the following are recreated:

  • users, accounts, reservations, and rentals;
  • initial fleet data;
  • Camunda/Zeebe state;
  • Maven and Angular caches;
  • container node_modules.

Use down -v when a clean environment is needed, not as a simple stop when data should be preserved.

Checking status

docker compose ps
docker compose logs -f

To follow only the main components:

docker compose logs -f orchestration rental-service frontend

The project uses the standard logging-level mechanism and starts with APPLICATION_LOG_LEVEL=INFO, configured in acme-mobility/.env: only essential domain events, warnings, and errors are shown. To disable application logs:

APPLICATION_LOG_LEVEL=OFF docker compose up

To temporarily enable jobs, service-to-service calls, and telemetry as well:

APPLICATION_LOG_LEVEL=DEBUG docker compose up

Ports and endpoints

Host port Service Purpose
4200 Frontend Angular application
8080 Rental Service /api, SSE, and health APIs
8082 Account Registration REST POST /createAccount
8083 Camunda Camunda UI and APIs
8084 Stations Service Station REST APIs
8085 Maintenance Service Maintenance REST APIs
8000 Bank Service SOAP endpoint
8091 Fleet Management Gateway Monitoring REST API
8092 Tracking Service HTTP/health port
8093 Battery Service HTTP/health port
26500 Zeebe gRPC gateway
9600 Camunda management Health and management
5432 Rental PostgreSQL Application database
5433 Bank PostgreSQL Banking database
6379 Redis Pub/Sub

The APIs used directly by the frontend are:

/api/auth/*              login, session, logout, and registration
/api/rentals/map         stations and vehicles
/api/rentals/resume      BPMN phase and canonical route
/api/rentals/scan        simulated QR scan
/api/rentals/book        reservation by station and type
/api/rentals/bookings    reservation details
/api/rentals/undoBooking cancellation
/api/rentals/end         ride completion
/api/rentals/report      damage submission
/api/rentals/report/no-report
/api/notifications       SSE stream
/createAccount           Jolie account creation

The containerized frontend proxies /api to rental-service:8080 and /createAccount to bank-account-registration-service:8080.

Initial data

With new volumes, SQL scripts create:

  • 7 real stations in Bologna;
  • 99 total vehicles, 33 per category;
  • available vehicles and a few initial maintenance cases;
  • demonstration accounts with sufficient, insufficient, or missing balance;
  • demonstration users for the main scenarios.

An account that can be used immediately is:

email:    user@acme.com
password: password123
balance:  €100

It is also possible to register a new user through the UI; the corresponding account starts with €100.

Development and testing

Frontend on the host

Compose already starts the frontend. To work with Angular directly on the host, start the stack, free port 4200, and use Node 22.12–24:

cd acme-mobility
docker compose up -d --build
docker compose stop frontend

cd frontend
npm ci
npm start

npm start uses the host proxy:

  • /api → http://localhost:8080;
  • /createAccount → http://localhost:8082.

The container instead uses npm run start:docker, Compose hostnames, and file polling. To recreate the Angular cache:

npm run clean:cache

Configuration verification

cd acme-mobility
docker compose config --quiet

Frontend

cd acme-mobility/frontend
npm ci
npm run build
npm test -- --watch=false --browsers=ChromeHeadless

Java services

JDK 21 is required:

cd acme-mobility/rental-service
mvn test

cd ../stations-service
mvn test

cd ../maintenance-service
mvn test

cd ../fleet-management-service/fm-gateway
mvn test

cd ../tracking-service
mvn test

cd ../battery-service
mvn test

Recommended manual path

  1. Start with docker compose up --build.
  2. Register a new user or use the demo account.
  3. Verify the map.
  4. Complete an instant rental until arrival.
  5. End the ride and complete the no-damage branch.
  6. Verify the summary and return to the map.
  7. Make a reservation, then try cancellation and collection.
  8. Repeat a ride while submitting a damage report.
  9. Check that containers remain healthy and do not restart unexpectedly.

Project artifacts

Specification and choreography

The projections cover the user, Rental Service, bank, stations, Fleet Management, Tracking Service, Battery Monitoring Service, and Maintenance Service.

SOA modeling

The TinySOA directory contains UML models, Sirius diagrams, and the TinySOA profile for rental, rental startup, reservation cancellation, money reservation, maintenance, and periodic vehicle checks.

Technical documentation

  • Project website: navigable overview of architecture, services, technologies, BPMN, choreography, deployment, and UML artifacts.
  • Final report: complete analysis, architectural decisions, implementation, and evaluation.
  • Deployment guide: Docker topology, startup, ports, and runtime configuration.
  • Architecture guide: components, protocols, orchestration, and persistence.

Status against the specification

The implementation covers the required participants and technologies:

  • ACME Mobility capabilities orchestrated with Camunda;
  • Jolie bank reached by the BPMS through SOAP;
  • stations and Fleet Management exposed through REST;
  • Fleet Management divided at least into tracking and battery monitoring;
  • services distributed as containerized applications;
  • choreography, projections, BPMN, and TinySOA SOA modeling.

Some aspects are deliberately simulated or do not yet perfectly match the domain description:

  • the app is a responsive web application, not a native mobile app;
  • QR scanning uses a vehicle ID rather than a camera;
  • the reservation selects a type at a station and the backend assigns the vehicle with the highest battery level, rather than allowing selection of a specific vehicle;
  • the current price uses a fixed fee and simulated time, rather than the distance required by the specification;
  • completed rentals are persisted, but the UI has no history page;
  • GraphHopper is used for route geometry, with a linear fallback;
  • the maintenance queue and deduplication are in memory and are rebuilt from the Rental Service after a restart;
  • local Camunda secondary storage uses H2 and the configuration is intended for development/demonstration, not production.

Concurrency, security, banking idempotency, callback authentication, and restart resilience are intentionally simplified for this academic demonstration and require additional hardening before any production use. Current code and tests remain the source of truth for the implementation.

About

Project for the Microservices Software Architectures course's final exam. It's an electric-vehicles sharing systems composed of multiple microservices orchestrated using a distributed orchestration engine based on Camunda

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages