Skip to content

Real-Time & WebSocket

Viana uses STOMP over SockJS for all real-time communication. The server pushes ride events, location updates, and rating prompts to connected clients.


Connection

Endpoint: ws://localhost:8080/ws (SockJS fallback: http://localhost:8080/ws)

Authentication: JWT must be sent in the Authorization header during the STOMP handshake.

```javascript const socket = new SockJS('http://localhost:8080/ws'); const client = Stomp.over(socket);

client.connect( { Authorization: Bearer ${accessToken} }, () => { / connected / }, (error) => { / auth failed / } ); ```

Header, not query parameter

Previous versions passed the token as ?token=. This has been removed. The token must be in the Authorization: Bearer header. Query parameters are logged by proxies and appear in server access logs.


Message flow overview

sequenceDiagram
    participant C as Customer
    participant S as Server
    participant D as Driver

    C->>S: STOMP CONNECT (Bearer token)
    D->>S: STOMP CONNECT (Bearer token)

    C->>S: POST /api/rides (HTTP)
    S->>D: /topic/driver/{id}/requests (RideOfferDTO)

    D->>S: POST /api/driver/accept (HTTP)
    S->>C: /topic/customer/{id}/ride-status (ASSIGNED)
    S->>D: /topic/ride/{rideId}/expired (other drivers)

    loop Every location update while IN_PROGRESS
        D->>S: POST /redis/driver/location (HTTP)
        S->>C: /topic/customer/{id}/driver-location
    end

    D->>S: POST /api/driver/complete (HTTP)
    S->>C: /topic/customer/{id}/ride-status (COMPLETED)
    S->>D: /topic/driver/{id}/ride-status (COMPLETED)
    S->>C: /topic/customer/{id}/ride-rating-prompt
    S->>D: /topic/driver/{id}/ride-rating-prompt

Topics reference

Customer topics — subscribe after connecting as a customer

Topic Trigger Payload
/topic/customer/{customerId}/ride-status Driver accepts, arrives, starts, completes, or ride is cancelled/expired RideStatusDTO
/topic/customer/{customerId}/driver-location Driver location update while ride is IN_PROGRESS { lat, lon }
/topic/customer/{customerId}/ride-rating-prompt Ride transitions to COMPLETED RideStatusDTO

Driver topics — subscribe after connecting as a driver

Topic Trigger Payload
/topic/driver/{driverId}/requests New ride offer within matching radius RideOfferDTO
/topic/driver/{driverId}/ride-status Customer cancels an ACCEPTED ride, or ride completes RideStatusDTO
/topic/driver/{driverId}/ride-rating-prompt Ride transitions to COMPLETED RideStatusDTO

Ride topics — subscribe to a specific ride

Topic Trigger Payload
/topic/ride/{rideId}/expired Another driver accepted the same ride "Ride already assigned" (String)

Inbound message destinations (driver sends)

Drivers can send ride state updates via WebSocket instead of HTTP. Both paths call the same underlying service methods.

Destination Body Equivalent HTTP
/app/driver/accept { rideId } POST /api/driver/accept
/app/driver/arrived { rideId } POST /api/driver/arrived
/app/driver/start { rideId } POST /api/driver/start
/app/driver/complete { rideId } POST /api/driver/complete
/app/driver/location { lat, lon } POST /driver/location

Payload schemas

RideStatusDTO

json { "rideId": 42, "status": "ACCEPTED", "driverId": 7 }

driverId is null when the status update originates from the customer (e.g., cancellation).

RideOfferDTO

json { "rideId": 42, "message": "New ride request available", "customerId": 3, "pickupLocation": { "lat": 43.651, "lon": -79.347 }, "dropoffLocation": { "lat": 43.678, "lon": -79.409 }, "serviceType": "STANDARD", "estimatedFare": 14.80, "vehicleID": 5 }

Driver location update (customer receives)

json { "lat": 43.652, "lon": -79.348 }