RicoomPOS System Documentation

Plain Java + Jetty WebSocket-based POS with JavaFX client

System Overview

This POS system is implemented in plain Java using Jetty WebSockets for communication between the server and JavaFX client. Key features include:

  • Real-time product, sales, and user data synchronization
  • Offline sales storage and synchronization
  • Authentication via Basic Auth & JWT for reconnections
  • Automatic reconnect logic with network blips
  • Minimal database load due to token-based authentication

Architecture Diagram

  • JavaFX Client ↔ WebSocket ↔ Jetty Server ↔ MySQL
  • JWT Token management for reconnections
  • Offline sales queue on the client

WebSocket Communication

The client connects to the server via WebSocket. Authentication occurs during connection:

Authorization: Basic <base64(username:password)>
Authorization: Bearer <jwtToken>

Server responds with JSON:

{
  "type": "loginResponse",
  "status": "success",
  "message": "Authentication successful",
  "token": "<jwtToken>"
}

Common WebSocket close codes handled:

  • 1000 – Normal closure
  • 1006 – Abnormal closure (network blip)
  • 4001 – Authentication failure (no reconnect)

Client Reconnection Logic

Reconnection is handled automatically unless the user manually closes the client or authentication fails:

if (!reconnecting && !manualClose) {
    attemptReconnect();
}

JWT tokens are reused for reconnections to reduce MySQL authentication hits.

⚠️ Manual logout prevents auto-reconnect.

Offline Sales Handling

Sales made while offline are stored locally:

List<Sale> offlineSales = OfflineSalesStorage.loadOfflineSales();
if (!offlineSales.isEmpty()) {
    sendSales(offlineSales);
    OfflineSalesStorage.clearOfflineSales();
}

This ensures sales are synced automatically once the connection is restored.

Security Measures

  • Basic Auth for initial login
  • JWT tokens for reconnection to reduce DB usage
  • Server-side rate limiting recommended to prevent brute-force login attacks
  • Client-side token storage in memory only

Client Methods

Some core methods available in PosWebSocketClient:

  • connectWithAuth() – connect with JWT if available, else Basic Auth
  • sendSales(List<Sale>) – send sales to server
  • sendGetProductsRequest(int page, int size) – request product list
  • sendGetLowStockProducts(int threshold) – get low stock products
  • closeConnection(Runnable callback) – log out and close without reconnect

Server Logging

Use nohup java -jar pos-server.jar & to start the server. Logs are written to nohup.out. Example:

tail -f nohup.out

Jetty debug logs include:

  • Thread pool info
  • WebSocket connection lifecycle
  • Authentication events

Performance & Connectivity

  • Low internet areas: client reconnects automatically using JWT, avoiding repeated DB queries
  • CPU and memory usage reduced due to fewer authentication hits and lightweight Jetty server
  • Offline sales ensure no lost transactions

Reporting

The system supports multiple types of reports:

  • Daily, weekly, monthly sales reports
  • Category-wise stock reports
  • Low-stock alerts
  • Offline sales reconciliation report

Example request to server:

sendGetSalesBetween("2025-10-01", "2025-10-30");
sendGetLowStockProducts(10);

Category Sorting

Products can be sorted and filtered by category for easier inventory management:

sendGetProductsByCategory("stationary", 1, 50);
sendGetProductsByCategory("ICT", 1, 50);

Category-wise stock value aggregation is supported:

sendRequestStockValueByCategory();

Role-Based Security

The system enforces role-based access:

  • Admin: Full access – add/update products, users, categories, reports
  • Cashier: Can process sales and view products
  • Manager: Can view sales reports and stock values

Server ensures that actions are validated against user roles:

if(user.getRole() == Role.CASHIER) {
    // allow sale
} else {
    // block sensitive operations
}