An event-driven police incident management system built with Java, Spring Boot, and Apache Kafka. The system follows Event Sourcing and CQRS patterns to provide a scalable, maintainable solution for managing police operations, incidents, calls, and resources.
The Police Incident Management System is designed to handle the complete lifecycle of police operations, from receiving calls and reporting incidents to managing officers, vehicles, units, and their assignments. The system uses an event-driven architecture where all operations produce events to Kafka, ensuring a complete audit trail and enabling eventual consistency across distributed components.
- Event-Driven Architecture: All operations produce events to Kafka, representing requests/commands from the edge layer
- RESTful API: Comprehensive REST API for all system operations with UI-friendly enhancements
- Event Sourcing: Complete audit trail through immutable events
- CQRS Pattern: Separation of command and query responsibilities
- Scalable Design: Built for horizontal scaling and high availability
- UI-Friendly API: Enhanced API design for easier frontend development
- Flexible date format parsing
- Comprehensive error messages with valid enum values
- Related resources in responses
- Composite endpoints for multi-step workflows
- Batch operations with partial failure handling
- Standardized response metadata
- Webhook subscriptions for real-time notifications
- Idempotency key support for safe retries
- Query proxy endpoints for projection data
- Java 17 or higher
- Maven 3.6+
- Docker and Docker Compose (for Kafka and NATS)
-
Start Infrastructure Services (using Docker Compose):
docker compose up -d
This starts:
- Kafka (3 brokers) on ports 9092-9094
- NATS (3-node cluster) on ports 4222-4224
- PostgreSQL on port 5432
- MongoDB on port 27017
- InfluxDB on port 8086
- Elasticsearch on port 9200 (for event indexing and search)
- Kafka Connect on port 8083 (for Elasticsearch indexing)
- Kafka UI on http://localhost:8080
- NATS Tower on http://localhost:8099
-
Build the project:
mvn clean install
-
Run the edge server:
mvn -pl edge spring-boot:run
-
Access the API:
- Base URL:
http://localhost:8080/api/v1 - Health check:
http://localhost:8080/api/v1/health - Swagger UI:
http://localhost:8080/swagger-ui.html
- Base URL:
-
Access Admin UIs:
- Kafka UI: http://localhost:8080 (Kafka management)
- Kafka Connect REST API: http://localhost:8083 (Connector management)
- NATS Tower: http://localhost:8099 (NATS cluster management)
- NATS Monitoring:
- nats-1: http://localhost:8222
- nats-2: http://localhost:8223
- nats-3: http://localhost:8224
-
Deploy Kafka Connect Connectors (optional, for Elasticsearch indexing):
# Step 1: Install OpenSearch connector plugin # Download from: https://github.com/opensearch-project/opensearch-kafka-connect/releases # Place JAR in: docker/kafka-connect/plugins/opensearch-sink/lib/ # Or use: ./scripts/download-opensearch-connector.sh <version> # Step 2: Restart Kafka Connect to load plugin docker compose restart kafka-connect # Step 3: Deploy all connectors ./scripts/deploy-connectors.sh # Step 4: Check connector health ./scripts/check-connectors.sh
The project includes a comprehensive demo script that exercises the entire system through a realistic police incident management scenario. This is the easiest way to see the system in action:
# Run the complete demo scenario
./scripts/demo-scenario.shWhat the demo does:
- Automatically starts all services using Docker Compose (edge service + 3 projection services + infrastructure)
- Creates initial resources: Officers, vehicles, units, locations, and persons
- Runs a complete incident workflow:
- Starts a shift and checks in officers
- Receives a call and reports an incident
- Dispatches units and creates assignments
- Creates activities and involves parties
- Completes activities and clears the incident
- Queries projections to verify data was processed correctly
- Documents all created resources for reference
Output and Logging:
- All output is automatically logged to:
/tmp/police-demo-YYYYMMDD-HHMMSS.log - Created resource IDs are stored in:
/tmp/police-demo-data.json - The log file location is displayed at the start and end of the script
- If the script fails, check the log file for detailed error messages
Environment Variables:
START_SERVICES=true(default) - Automatically start Docker servicesSTOP_SERVICES=false(default) - Keep services running after demoEDGE_BASE_URL- Override edge service URL (default: http://localhost:8080/api/v1)DOCKER_COMPOSE_FILE- Override compose file (default: docker-compose-integration.yml)
Examples:
# Run demo without starting services (assumes services already running)
START_SERVICES=false ./scripts/demo-scenario.sh
# Run demo and stop services when done
STOP_SERVICES=true ./scripts/demo-scenario.sh
# Use custom URLs
EDGE_BASE_URL=http://localhost:8080/api/v1 ./scripts/demo-scenario.shPrerequisites:
- Docker and Docker Compose installed
curlinstalled (required)jqinstalled (optional, for better JSON formatting)
The demo script uses docker-compose-integration.yml which includes all infrastructure services (Kafka, NATS, PostgreSQL) plus the application services (edge + 3 projections) in a single compose file for easy testing.
π API Documentation
Complete REST API specification and usage guide:
- OpenAPI Specification - Full API specification in OpenAPI 3.0.3 format
- API endpoints organized by domain (Officers, Vehicles, Incidents, Calls, etc.)
- Request/response examples
- Event production details
ποΈ Architecture Documentation
System architecture and design patterns:
- Overview - High-level architecture introduction
- Event Sourcing - Event sourcing pattern and implementation
- CQRS Design - Command Query Responsibility Segregation
- Component Architecture - System components and their interactions
- Event Bus - Kafka and NATS/JetStream event buses
- Data Flow - How data flows through the system
- Kafka Connect Elasticsearch - Event indexing to Elasticsearch
- Testing Strategy - Testing principles, patterns, and practices
π Event Documentation
Complete event specifications:
- Event Index - Complete list of all 55 events
- Individual event specifications with UML diagrams
- Event naming conventions
- Domain model effects
All events follow the "Requested" naming convention, representing requests/commands from the edge layer:
RegisterOfficerRequested- Request to register an officerReportIncidentRequested- Request to report an incidentDispatchIncidentRequested- Request to dispatch units- And 52 more events...
π― Domain Model
Domain model documentation describing the core entities and their relationships:
- Party/Place/Thing (PPT) entities: PoliceOfficer, PoliceVehicle, Unit, Person, Location
- Moment-Interval (MI) entities: Incident, CallForService, Activity, Assignment, Shift, Dispatch
- Role entities: ResourceAssignment, InvolvedParty, OfficerShift, IncidentLocation, CallLocation
π§ Development Process
Development guidelines and process:
- Event-driven architecture approach
- Event naming conventions
- Testing strategy
- Increment development steps (8-step process)
- Quality standards
π Development Plan
Comprehensive development plan tracking all increments and their status:
- Phase-by-phase implementation plan
- Increment details with requirements, tests, and implementation
- Status tracking for completed and pending work
The system follows an event-driven architecture where:
- Edge servers receive HTTP requests (commands) and produce events using a double-publish pattern
- Events represent requests/commands from the edge, not state changes
- All events are published to Kafka for event sourcing and long-term storage
- Critical events (ending in "Requested") are also published to NATS/JetStream for near realtime processing
- No state reconstruction in the edge layer - events are simply produced to event buses
- All operations are asynchronous via event buses
All events follow the "Requested" naming pattern:
- Registration/Creation:
Register{Entity}Requested,Create{Entity}Requested,Start{Entity}Requested - Updates:
Update{Entity}Requested - Status Changes:
Change{Entity}StatusRequested - Lifecycle:
Complete{Entity}Requested,End{Entity}Requested,Clear{Entity}Requested - Relationships:
Link{Entity}To{Target}Requested,Unlink{Entity}From{Target}Requested
- Language: Java 17
- Framework: Spring Boot, Spring Framework
- Primary Event Bus: Apache Kafka (event sourcing and long-term storage)
- Secondary Event Bus: NATS/JetStream (critical events for near realtime processing)
- Build Tool: Maven
- Testing: JUnit 5, Kafka Test Containers
policesystem/
βββ common/ # Shared code (events, base classes)
βββ edge/ # Edge server (REST API, command handlers)
β βββ Dockerfile # Docker image for edge service
βββ operational-projection/ # Operational projection service
β βββ Dockerfile # Docker image for operational projection
βββ resource-projection/ # Resource projection service
β βββ Dockerfile # Docker image for resource projection
βββ workforce-projection/ # Workforce projection service
β βββ Dockerfile # Docker image for workforce projection
βββ scripts/ # Utility scripts
β βββ demo-scenario.sh # Complete demo scenario script
β βββ deploy-connectors.sh
β βββ check-connectors.sh
β βββ ... # Other utility scripts
βββ doc/ # Documentation
β βββ api/ # API documentation
β βββ architecture/ # Architecture documentation
β βββ domainmodel/ # Domain model documentation
β βββ events/ # Event specifications
βββ docker-compose.yml # Infrastructure services (Kafka, NATS, PostgreSQL, etc.)
βββ docker-compose-integration.yml # Full stack for integration testing/demo
βββ AGENTS.md # Development process guidelines
βββ DEVELOPMENT_PLAN.md # Development plan and tracking
βββ README.md # This file
The system provides REST API endpoints organized by domain:
- Officers: Register, update, change status, batch registration
- Vehicles: Register, update, change status
- Units: Create, update, change status
- Persons: Register, update
- Locations: Create, update, link/unlink to incidents and calls
- Incidents: Report, update, dispatch, arrive, clear, change status, create with relations
- Calls: Receive, update, dispatch, arrive, clear, change status, link to incidents/dispatches
- Activities: Start, update, complete, change status, link to incidents
- Assignments: Create, complete, change status, link to dispatches, manage resources
- Shifts: Start, end, change status, record changes, manage officer check-ins/check-outs
- Dispatches: Create, change status
- Involved Parties: Involve, update, end involvement
- Resource Assignments: Assign, unassign, change status
- Incident Dispatch Workflow: Complete incident dispatch workflow in a single call (create incident, dispatch, assignment, and resource assignments)
- Webhooks: Register webhook subscriptions for real-time event notifications
- Query Proxy: Query projection services through the edge (
/api/v1/query/{domain}/{id}/full,/api/v1/query/{domain}/{id}/exists,/api/v1/query/{domain}with filtering, pagination, sorting) - Idempotency: Support for idempotency keys via
Idempotency-Keyheader for safe request retries
- Flexible Date Formats: Accepts multiple ISO 8601 date formats (e.g.,
2024-01-15T10:40:00Z,2024-01-15T10:40:00+00:00,2024-01-15T10:40:00.000+00:00) - Enhanced Error Messages: Error responses include
validValuesfield with valid enum options for validation errors - Related Resources: Response DTOs include
relatedResourcesfield with IDs of related entities (e.g., dispatchId, assignmentIds, callIds) - Composite Endpoints: Create resources with relationships in one call (e.g.,
POST /incidents/with-relations) - Batch Operations: Register multiple officers in one call with partial failure handling (
POST /officers/batch) - Standardized Responses: All responses include
ResponseMetadatawith correlationId, timestamp, version, and links
See the API Documentation for complete endpoint details.
The system produces 55 different events to Kafka, organized by domain:
- Officer Events: RegisterOfficerRequested, UpdateOfficerRequested, ChangeOfficerStatusRequested
- Vehicle Events: RegisterVehicleRequested, UpdateVehicleRequested, ChangeVehicleStatusRequested
- Unit Events: CreateUnitRequested, UpdateUnitRequested, ChangeUnitStatusRequested
- Person Events: RegisterPersonRequested, UpdatePersonRequested
- Location Events: CreateLocationRequested, UpdateLocationRequested, Link/Unlink events
- Incident Events: ReportIncidentRequested, DispatchIncidentRequested, ArriveAtIncidentRequested, ClearIncidentRequested, etc.
- Call Events: ReceiveCallRequested, DispatchCallRequested, ArriveAtCallRequested, ClearCallRequested, etc.
- Activity Events: StartActivityRequested, CompleteActivityRequested, ChangeActivityStatusRequested, etc.
- Assignment Events: CreateAssignmentRequested, CompleteAssignmentRequested, ChangeAssignmentStatusRequested, etc.
- Shift Events: StartShiftRequested, EndShiftRequested, ChangeShiftStatusRequested, RecordShiftChangeRequested
- Officer Shift Events: CheckInOfficerRequested, CheckOutOfficerRequested, UpdateOfficerShiftRequested
- Dispatch Events: CreateDispatchRequested, ChangeDispatchStatusRequested
- Resource Assignment Events: AssignResourceRequested, UnassignResourceRequested, ChangeResourceAssignmentStatusRequested
- Involved Party Events: InvolvePartyRequested, EndPartyInvolvementRequested, UpdatePartyInvolvementRequested
See the Event Index for the complete list.
All events are published to domain-specific Kafka topics:
officer-eventsvehicle-eventsunit-eventsperson-eventslocation-eventsincident-eventscall-eventsactivity-eventsassignment-eventsshift-eventsofficer-shift-eventsdispatch-eventsresource-assignment-eventsinvolved-party-events
Critical events (all command events ending in "Requested") are also published to NATS JetStream subjects following the pattern commands.{domain}.{action}:
commands.officer.register,commands.officer.update,commands.officer.change-statuscommands.vehicle.register,commands.vehicle.update,commands.vehicle.change-statuscommands.unit.create,commands.unit.update,commands.unit.change-statuscommands.person.register,commands.person.updatecommands.location.create,commands.location.updatecommands.incident.report,commands.incident.dispatch, etc.- And all other critical command events...
This double-publish pattern ensures:
- Kafka: Event sourcing, long-term storage, and eventual consistency
- NATS/JetStream: Low-latency delivery for near realtime processing of critical events
# Run all tests
mvn test
# Run tests for a specific module
mvn -pl edge test
# Run a specific test class
mvn -pl edge -Dtest=OfficerControllerTest testThe project includes Docker support for all services:
Build Docker images:
# Build all services
docker compose -f docker-compose-integration.yml build
# Build specific service
docker compose -f docker-compose-integration.yml build edge-serviceRun services with Docker:
# Start all services (infrastructure + applications)
docker compose -f docker-compose-integration.yml up -d
# View logs
docker compose -f docker-compose-integration.yml logs -f edge-service
# Stop all services
docker compose -f docker-compose-integration.yml downService Ports:
- Edge Service:
8080 - Operational Projection:
8081 - Resource Projection:
8082 - Workforce Projection:
8083 - PostgreSQL:
5432 - Kafka:
9092-9094 - NATS:
4222-4224
The project uses Checkstyle for code quality. Configuration is in checkstyle.xml.
Follow the 8-step increment development process defined in AGENTS.md:
- Write Requirements
- Write Tests
- Write Implementation Code
- Run Tests for the Feature
- Run All Tests (Regression Check)
- Update Development Plan
- Commit and Create Pull Request
- Write Technical Demo Suggestion
When contributing to this project:
- Follow the development process in AGENTS.md
- Ensure all tests pass
- Update relevant documentation
- Follow the event naming conventions
- Write tests before implementation (TDD)
Proprietary - All rights reserved
For questions or issues, please refer to the documentation or contact the development team.