Spring Boot (Kotlin + Web + Kafka) gateway that listens for mapped archive instances, dispatches cases and journal posts against FINT Arkiv adapters, exposes supporting archive metadata over HTTP, and republishes cacheable resources to downstream services.
- Reactive dispatch pipeline —
DispatchServiceorchestrates validation and routing for new, by-id, and search-or-new archive instances, composing non-blocking case creation with subsequent record uploads. - Archive metadata APIs — Internal controllers expose lightweight endpoints for case lookups and dozens of kodeverk collections backed by the shared FINT caches.
- Instance-flow Kafka integration — Dedicated consumer and producers handle
instance-mapped,instance-dispatched, and dispatch-error events using the Flyt instance-flow templates. - Resource publishing scheduler —
FintResourcePublishingConfigurationperiodically pulls updated archive resources, caches them, and pushes snapshots onto entity topics. - Operational guardrails — OAuth2 resource server, configurable timeouts per downstream client, Prometheus/Actuator endpoints, and deterministic retry/backoff policies.
| Component | Responsibility |
|---|---|
DispatchService |
Routes incoming ArchiveInstance payloads, coordinates case dispatch/search, and invokes RecordsProcessingService for journal posts and files. |
InstanceMappedEventConsumerConfiguration |
Builds the instance-flow listener container, wires the dispatch service, and emits success/decline/error events via the producer services. |
FintResourcePublishingConfiguration |
Schedules cache resets, polls FINT Archive resources through configured pipelines, writes to caches, and publishes to Kafka entity topics. |
CaseController/CaseRequestService |
Serves /internal/api/arkiv/saker/{year}/{number}/tittel, issuing Kafka request/reply lookups against the archive adapter. |
CodelistController |
Reads from the shared FintCache instances and renders multiple kodeverk collections and klassifikasjonssystem metadata as reference JSON. |
FintArchiveWebClientConfiguration & WebClientConfiguration |
Provide tuned WebClient beans (timeouts, connection pools) for archive adapters, Flyt file service, and resource pulls. |
Base path: /internal/api/arkiv
| Method | Path | Description | Request body | Response |
|---|---|---|---|---|
GET |
/saker/{caseYear}/{caseNumber}/tittel |
Fetches the case title for the given Noark mappeId. |
– | 200 OK with { "value": "<title>" }; 404 if unknown. |
GET |
/kodeverk/{type} |
Returns cached kodeverk entries (administrativEnhet, arkivdel, dokumentstatus, journalposttype, etc.). | – | 200 OK array of ResourceReference { "id": "<selfLink>", "displayName": "[code] Name #systemId" }. |
GET |
/kodeverk/klassifikasjonssystem |
Lists all klassifikasjonssystemer with their IDs and titles. | – | 200 OK array. |
GET |
/kodeverk/klasse?klassifikasjonssystemLink=<link> |
Lists classes that belong to a klassifikasjonssystem link. | – | 200 OK array; 404 if the system is missing. |
Kodeverk endpoints share the same response contract; each list is distinct (administrativEnhet, arkivdel, arkivressurs, partrolle, korrespondanseparttype, tilknyttetregistreringsom, sakstatus, skjermingshjemmel, tilgangsrestriksjon, dokumentstatus, dokumenttype, journalstatus, journalposttype, saksmappetype, variantformat, format, tilgangsgruppe).
InstanceMappedEventConsumerConfiguration.instanceMappedEventConsumerlistens to theinstance-mappedevent topic (partitioned by org/app defaults) and hands each record toDispatchService. Failed records are skipped with no retries via the sharedErrorHandlerFactory.InstanceDispatchedEventProducerServiceprovisions theinstance-dispatchedtopic (retention derived fromKafkaTopicProperties) and emits completion events after accepted dispatches. Keys should uniquely represent the archive instance for better ordering.InstanceDispatchingErrorProducerServicecreates theinstance-dispatching-errortopic and publishes structured error collections for DECLINED or FAILED dispatches.CaseRequestServiceissues Kafka request/reply calls toarkiv.noark.sakto resolve case titles, provisioning a reply topic scoped to the service’s application ID.FintResourcePublishingConfigurationensures entity topics exist for each pipeline and usesParameterizedTemplateto push updated resources, caching them locally for HTTP lookups.
The service relies on Spring Scheduling via FintResourcePublishingConfiguration:
- Cron reset: once per day at a randomized time between
reset.from-time-of-dayandreset.to-time-of-day, cached last-updated timestamps are cleared so subsequent pulls fetch full deltas. - Fixed-delay pull: every
pull.fixed-delay(default 15 minutes, after a 5-second initial delay) eachResourcePipelinepolls FINT Archive for updates, populates caches, and republishes to Kafka.
No other cron-style jobs exist; the dispatch path is fully event-driven.
Spring profiles included by default: fint-client, fint-oauth2-idp, flyt-file-client, flyt-kafka, flyt-logging, flyt-web-resource-server. Key properties:
| Property | Description |
|---|---|
fint.application-id |
Identifier reused for Kafka consumer groups and topic prefixes (default fint-flyt-archive-gateway). |
fint.org-id |
Current organization context; overrides live per overlay (local-staging defaults to fintlabs.no). |
novari.kafka.topic.instance-processing-events-retention-time |
Retention (hours) applied to instance-processing topics when provisioning. |
novari.flyt.archive.gateway.dispatch.fint-client.* |
Timeout and polling settings for posting cases, records, and files to the archive adapter. |
novari.flyt.archive.gateway.resource.publishing.* |
Window, offset, and pull cadence for resource caching and topic publishing. |
novari.flyt.archive.gateway.resource.fint-client.* |
Timeouts and retry strategy for resource lookups and case searches. |
novari.flyt.web-resource-server.security.api.internal.* |
Enables internal API protection plus authorized-org-id-role-pairs-json for org/role allow-lists. |
spring.kafka.bootstrap-servers |
Kafka bootstrap list (e.g., localhost:9092 in application-local-staging.yaml). |
server.port |
HTTP port (8301 for local-staging). |
spring.security.oauth2.client.* |
Credentials for the fint archive adapter and Flyt file-service OAuth2 clients. |
Prerequisites: Java 25+, Docker (for Kafka, if needed), and the Gradle wrapper.
- Start Kafka/Schema Registry (e.g.,
docker compose up kafka). Ensure it listens onlocalhost:9092to matchapplication-local-staging.yaml. - Export the local profile:
export SPRING_PROFILES_ACTIVE=local-staging - Provide required secrets via environment variables or a
.envfile (fint.core.oauth2.*,fint.sso.*, etc.). - Build and run:
./gradlew clean build ./gradlew bootRun
bootRunnow adds--sun-misc-unsafe-memory-access=allowto suppress the known Netty/JDK 24+ startup warning. - Exercise the APIs:
curl -H "Authorization: Bearer <token>" \ "http://localhost:8301/internal/api/arkiv/saker/2024/123/tittel" curl -H "Authorization: Bearer <token>" \ "http://localhost:8301/internal/api/arkiv/kodeverk/dokumenttype"
Running unit tests only:
./gradlew testManifests live under kustomize/:
kustomize/base/— shared FLAIS Application manifest plus configmaps/secrets referenced across environments.kustomize/templates/overlay.yaml.tpl— source templates for per-org overlays.kustomize/overlays/<org>/<env>/— generated overlays that pin org IDs, ingress rules, Kafka parameters, and secret references.script/render-overlay.sh— helper to regenerate everykustomize/overlays/**/kustomization.yamlafter changing templates.
After editing templates or base manifests run:
./script/render-overlay.shand commit both template and regenerated overlay files.
- OAuth2 resource server validates JWTs issued by
https://idp.felleskomponent.noand enforces internal API org/role mappings via the Flyt resource server starter. - Outbound calls use two OAuth2 clients: password-grant credentials for the FINT archive adapter and client-credentials for the Flyt file service.
- Kafka consumers/producers leverage org/application-scoped prefixes ensuring each tenant’s topics stay isolated.
- Internal APIs live under
/internal/api/**and require authorization according to the configured org-role pairs.
- Actuator health/info/prometheus endpoints are enabled (see
application-flyt-logging.yaml); scrape/actuator/prometheusfor metrics. - Logging integrates with the shared Flyt logging profile and emits structured entries for dispatch outcomes and resource pulls.
- Kafka listener and resource publishing logs indicate topic provisioning, cache sizes, and error conditions for easier incident triage.
RecordsProcessingServicestreams journalpost records/files sequentially; keep payload sizes manageable and verify the file-service timeouts before tightening Kafka consumer settings.- Resource caches are populated by the scheduler. If you call kodeverk endpoints immediately after boot, trigger the pull (or wait for
pull.initial-delay) to avoid empty lists. - Use the TODO markers in
InstanceDispatchedEventProducerServiceandInstanceDispatchingErrorProducerServiceas a guide—supplying deterministic keys simplifies debugging and replay.
- Create a topic branch off
main(e.g.,feature/<ticket>). - Implement changes plus unit/integration tests; run
./gradlew test(and./gradlew bootRunlocally if needed). - If kustomize manifests change, re-run
./script/render-overlay.shand commit the outputs. - Open a pull request with a summary of behavior changes and testing evidence.
———
FINT Flyt Archive Gateway is maintained by the FINT Flyt team. Reach out via the internal Slack channel or open an issue if you need enhancements or run into problems.