Lightweight Java 21 engine that connects to RabbitMQ and PostgreSQL, loads configuration from a .env file, and listens to a single RabbitMQ queue while routing messages by their event key.
- Java 21+
- Maven 3.9+
- RabbitMQ and PostgreSQL reachable from the app (or the docker-compose services)
Copy .env.example to .env and set the values:
LOG_LEVEL(e.g.,INFO,DEBUG)POSTGRES_URL(jdbc url)
POSTGRES_USER,POSTGRES_PASSWORD,POSTGRES_POOL_SIZE,POSTGRES_CONNECTION_TIMEOUT_MSRABBITMQ_URI(amqp uri)
RABBITMQ_QUEUE_DURABLEKEYCLOAK_ISSUER,KEYCLOAK_CLIENT_ID,KEYCLOAK_CLIENT_SECRET(for SDMIS API access)SDMIS_API_BASE_URL,SDMIS_API_TIMEOUT_MS(defaults tohttp://localhost:3001)DECISION_MAX_DISTANCE_KM,DECISION_MIN_ENERGY_LEVEL(optional decision filters)
Queues and their direction (SUB/PUB) are defined in src/main/java/cpe/qg/engine/events/Queues.java.
mvn test
mvn packageThe assembly plugin creates target/app-qg-java-engine-1.0-SNAPSHOT-jar-with-dependencies.jar.
java -jar target/app-qg-java-engine-1.0-SNAPSHOT-jar-with-dependencies.jarThe App entrypoint runs connectivity checks against RabbitMQ and PostgreSQL, then listens to the queues defined in Queues and dispatches each message based on its event field. Clean shutdown on Ctrl+C closes RabbitMQ and PostgreSQL resources.
Messages consumed from the subscribed queues must contain an event field, e.g.:
{"event":"assignment_request","payload":{...}}To react to new events:
- Declare the event key in
Events(seesrc/main/java/cpe/qg/engine/events/Events.java). - Implement
EventHandlerwith the matchingeventKey()and business logic:
class CustomHandler implements EventHandler {
private final MessageBrokerClient broker;
private final boolean durable;
CustomHandler(MessageBrokerClient broker, boolean durable) { this.broker = broker; this.durable = durable; }
@Override
public String eventKey() { return Events.ASSIGNMENT_REQUEST.key(); }
@Override
public void handle(EventMessage message) {
broker.declareQueue(Events.INCIDENT_ACK.key(), durable);
broker.publish(Events.INCIDENT_ACK.key(), "{\"status\":\"received\"}");
}
}- Register the handler in
App.buildHandlers(...):
private static List<EventHandler> buildHandlers(RabbitConfig config, RabbitMqClient broker) {
return List.of(new CustomHandler(broker, config.durableQueue()));
}The app listens to all queues marked as SUB in Queues and dispatches every message to the handler matching the event key.
Build and run with Docker:
docker build -t qg-engine .
docker run --env-file .env --network pt-net qg-enginesrc/main/java/cpe/qg/engine/config– environment loading and typed configssrc/main/java/cpe/qg/engine/logging– SLF4J/Logback setupsrc/main/java/cpe/qg/engine/database– PostgreSQL connector (HikariCP)src/main/java/cpe/qg/engine/messaging– RabbitMQ connectorsrc/main/java/cpe/qg/engine/events– events, queues, handlers, and listenersrc/main/java/cpe/qg/engine/service– connectivity probe