Kingu is a NeTEx (Network Timetable Exchange) exporter service for NSR (National Stop Register) / Tiamat. It exports stop place data and related entities to the NeTEx XML format.
Kingu is a Spring Boot application that:
- Listens for export requests via Google Pub/Sub
- Queries the Tiamat database for stop places and related data
- Generates NeTEx-compliant XML exports
- Validates the generated NeTEx references
- Uploads the export files to Google Cloud Storage
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Pub/Sub │────▶│ Kingu │────▶│ GCS │
│ (trigger) │ │ (exporter) │ │ (storage) │
└─────────────────┘ └────────┬────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ Tiamat DB │
│ (PostgreSQL) │
└─────────────────┘
| Component | Description |
|---|---|
NetexExportRoute |
Apache Camel routes for handling export workflow |
StreamingPublicationDelivery |
Core export logic - streams data to NeTEx XML |
NetexXmlReferenceValidator |
Validates internal references in generated NeTEx |
StopPlaceRepository |
Database access for stop places and related entities |
- Java 21
- Spring Boot 3.x
- Apache Camel - Integration framework for message routing
- Hibernate/JPA - ORM for database access
- PostgreSQL with PostGIS - Geospatial database
- Google Cloud Pub/Sub - Message queue for export triggers
- Google Cloud Storage - Export file storage
- NeTEx Java Model - NeTEx XML schema bindings
The export is triggered by a JSON message with the following structure:
| Parameter | Type | Description |
|---|---|---|
name |
String | Export name (e.g., "03_Oslo") |
tariffZoneExportMode |
ExportMode | How to export tariff zones |
fareZoneExportMode |
ExportMode | How to export fare zones |
groupOfStopPlacesExportMode |
ExportMode | How to export stop place groups |
groupOfTariffZonesExportMode |
ExportMode | How to export tariff zone groups |
topographicPlaceExportMode |
ExportMode | How to export topographic places |
municipalityReferences |
List<String> | Filter by municipality IDs |
countyReferences |
List<String> | Filter by county IDs (e.g., "KVE:TopographicPlace:03") |
countryReferences |
List<String> | Filter by country IDs |
stopPlaceSearch |
StopPlaceSearch | Advanced stop place search criteria |
exportMultiSurface |
bolean | default is false for backward compatibility |
| Mode | Description |
|---|---|
NONE |
Do not export this entity type |
RELEVANT |
Export only entities related to the selected stop places |
ALL |
Export all entities of this type |
| Parameter | Type | Description |
|---|---|---|
query |
String | Text search query |
stopTypeEnumerations |
List | Filter by stop types |
netexIdList |
List<String> | Specific NeTEx IDs to export |
allVersions |
boolean | Include all versions (default: false) |
versionValidity |
VersionValidity | Version filter (CURRENT, ALL, etc.) |
pointInTime |
Instant | Export data valid at specific time |
The export generates a NeTEx PublicationDelivery containing:
- SiteFrame - Stop places, quays, tariff zones, topographic places
- ServiceFrame - Scheduled stop points, passenger stop assignments
- FareFrame - Fare zones, group of tariff zones
- ResourceFrame - Additional resources
Key configuration properties (via environment variables or application.properties):
# Database
spring.datasource.url=jdbc:postgresql://host:port/database
spring.datasource.username=username
# Pub/Sub
pubsub.kingu.outbound.topic.netex.export=topic-name
pubsub.kingu.inbound.subscription.netex.export=subscription-name
# GCS Storage
blobstore.gcs.bucket.name=bucket-name
blobstore.gcs.blob.path=export
# Export settings
async.export.path=/tmp
netexXmlReferenceValidator.throwOnValidationError=false- Java 21
- Docker (for PostgreSQL/PostGIS and Pub/Sub emulator)
- Maven
./mvnw clean install./mvnw test./mvnw spring-boot:run{
"name": "03_Oslo",
"tariffZoneExportMode": "RELEVANT",
"fareZoneExportMode": "RELEVANT",
"groupOfStopPlacesExportMode": "RELEVANT",
"groupOfTariffZonesExportMode": "RELEVANT",
"topographicPlaceExportMode": "RELEVANT",
"municipalityReferences": null,
"countyReferences": ["KVE:TopographicPlace:03"],
"countryReferences": null,
"exportMultiSurface": false,
"stopPlaceSearch": {
"query": null,
"stopTypeEnumerations": null,
"submode": null,
"netexIdList": null,
"allVersions": false,
"versionValidity": "CURRENT",
"withoutLocationOnly": false,
"withoutQuaysOnly": false,
"withDuplicatedQuayImportedIds": false,
"withNearbySimilarDuplicates": false,
"hasParking": false,
"version": null,
"tags": null,
"withTags": false,
"pointInTime": null
}
}attributes.EnturNetexExportStatus="Initiated" # When starting export
attributes.EnturNetexExportStatus="Completed" # When export is done
gcloud pubsub topics publish local.kingu.topic.netex.export \
--message='{"name":"03_Oslo","tariffZoneExportMode":"RELEVANT","fareZoneExportMode":"RELEVANT","groupOfStopPlacesExportMode":"RELEVANT","groupOfTariffZonesExportMode":"RELEVANT","topographicPlaceExportMode":"RELEVANT","municipalityReferences":null,"countyReferences":["KVE:TopographicPlace:39"],"countryReferences":null,"exportMultiSurface":true,"stopPlaceSearch":{"query":null,"stopTypeEnumerations":null,"submode":null,"netexIdList":null,"allVersions":false,"versionValidity":"CURRENT","withoutLocationOnly":false,"withoutQuaysOnly":false,"withDuplicatedQuayImportedIds":false,"withNearbySimilarDuplicates":false,"hasParking":false,"version":null,"tags":null,"withTags":false,"pointInTime":null}}' \
--attribute=EnturNetexExportStatus="Initiated" \
--project=ent-kingu-dev- Receive Message - Pub/Sub message triggers the export
- Parse Parameters - JSON message is parsed into
ExportParams - Create Export Job - Job is created with status
PROCESSING - Query Database - Stop places and related entities are queried
- Stream to NeTEx - Data is streamed to NeTEx XML format
- Validate References - Internal NeTEx references are validated
- Create ZIP - XML is compressed to ZIP file
- Upload to GCS - ZIP file is uploaded to Cloud Storage
- Complete Job - Job status is set to
FINISHED - Cleanup - Local temporary files are deleted
The project includes:
- Unit tests - For individual components
- Integration tests - Full export flow with Testcontainers
- Route tests - Apache Camel route testing
Run specific test class:
./mvnw test -Dtest=StreamingPublicationDeliveryIntegrationTest- Tiamat - The stop place register that Kingu exports from
- NeTEx - Network Timetable Exchange standard