Skip to content

gla-rad/eNav-AtoNService

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The GLA e-Navigation Service Architecture - AtoN Service

The AtoN Service repository contains the implementation of a service controlling the S125 AtoN information messages. This entails reading messages through the Geomesa. The core micro-service is built using the Springboot framework.

What is e-Navigation

The maritime domain is facing a number for challenges, mainly due to the increasing demand, that may increase the risk of an accident or loss of life. These challenges require technological solutions and e-Navigation is one such solution. The International Maritime Organization (IMO) adopted a ‘Strategy for the development and implementation of e‐Navigation’ (MSC85/26, Annexes 20 and 21), providing the following definition of e‐Navigation:

E-Navigation, as defined by the IMO, is the harmonised collection, integration, exchange, presentation and analysis of maritime information on-board and ashore by electronic means to enhance berth-to-berth navigation and related services, for safety and security at sea and protection of the marine environment.

In response, the International Association of Lighthouse Authorities (IALA) published a number of guidelines such as G1113 and G1114, which establish the relevant principles for the design and implementation of harmonised shore-based technical system architectures and propose a set of best practices to be followed. In these, the terms Common Shore‐Based System (CSS) and Common Shore‐based System Architecture (CSSA) were introduced to describe the shore‐based technical system of the IMO’s overarching architecture.

To ensure the secure communication between ship and CSSA, the International Electrotechnical Commission (IEC), in coordination with IALA, compiled a set of system architecture and operational requirements for e-Navigation into a standard better known as SECOM. This provides mechanisms for secure data exchange, as well as a TS interface design that is in accordance with the service guidelines and templates defined by IALA. Although SECOM is just a conceptual standard, the Maritime Connectivity Platform (MCP) provides an actual implementation of a decentralised framework that supports SECOM.

What is the GRAD e-Navigation Service Architecture

The GLA follow the developments on e-Navigation closely, contributing through their role as an IALA member whenever possible. As part of their efforts, a prototype GLA e-Navigation Service Architecture is being developed by the GLA Research and Development Directorate (GRAD), to be used as the basis for the provision of the future GLA e-Navigation services.

As a concept, the CSSA is based on the Service Oriented Architecture (SOA). A pure-SOA approach however was found to be a bit cumbersome for the GLA operations, as it usually requires the entire IT landscape being compatible, resulting in high investment costs. In the context of e-Navigation, this could become a serious problem, since different components of the system are designed by independent teams/manufacturers. Instead, a more flexible microservice architecture was opted for. This is based on a break-down of the larger functional blocks into small independent services, each responsible for performing its own orchestration, maintaining its own data and communicating through lightweight mechanisms such as HTTP/HTTPS. It should be pointed out that SOA and the microservice architecture are not necessarily that different. Sometimes, microservices are even considered as an extension or a more fine-grained version of SOA.

The e-Navigation AtoN Service

This is the core service supporting the provision of AtoN information. It follows the SECOM standard and it is implemented in accordance with the "Technical Specification for the Provision of AtoN Information Service to End-users" guideline being developed by IALA. It stores all the published AtoN messages generated by Niord (including VAtoN), allows clients to retrieve them based on various search criteria, and supports geo-spatial queries. It currently employs a premature version of the IHO S-125 data format, since the final data product specification is not yet published. The “AtoN Service” monitors the AtoN information published to the Message Broker and updates its list of defined datasets when applicable. It also supports the SECOM subscription operation.

Development Setup

To start developing just open the repository with the IDE of your choice. The original code has been generated using Intellij IDEA. Just open it by going to:

File -> New -> Project From Version Control

Provide the URL of the current repository and the local directory you want.

You don't have to use it if you have another preference. Just make sure you update the .gitignore file appropriately.

Build Setup

The project is using the latest OpenJDK 21 to build, although earlier versions should also work.

To build the project you will need Maven, which usually comes along-side the IDE. Nothing exotic about the goals, just clean and install should do:

mvn clean package

How to Run

This service can be used in two ways (based on the use or not of the Spring Cloud Config server).

  • Enabling the cloud config client and using the configurations located in an online repository.
  • Disabling the cloud config client and using the configuration provided locally.

Cloud Config Configuration

In order to run the service in a Cloud Config configuration, you just need to provide the environment variables that allow is to connect to the cloud config server. This is assumed to be provided the GRAD e-Navigation Service Architecture Eureka Service.

The available environment variables are:

ENAV_CLOUD_CONFIG_URI=<The URL of the eureka cloud configuration server>
ENAV_CLOUD_CONFIG_BRANCH=<The cloud configuration repository branch to be used>
ENAV_CLOUD_CONFIG_USERNAME=<The cloud configration server username>
ENAV_CLOUD_CONFIG_PASSWORD=<The cloud configration server password>

The parameters will be picked up and used to populate the default bootstrap.properties of the service that look as follows:

server.port=8766
spring.application.name=aton-service
spring.application.version=<application.version>

# The Spring Cloud Discovery Config
spring.cloud.config.uri=${ENAV_CLOUD_CONFIG_URI}
spring.cloud.config.username=${ENAV_CLOUD_CONFIG_USERNAME}
spring.cloud.config.password=${ENAV_CLOUD_CONFIG_PASSWORD}
spring.cloud.config.label=${ENAV_CLOUD_CONFIG_BRANCH}
spring.cloud.config.fail-fast=false

As you can see, the service is called aton-service and uses the 8766 port when running.

To run the service, along with the aforementioned environment variables, you can use the following command:

java -jar \
    -DENAV_CLOUD_CONFIG_URI='<cloud config server url>' \
    -DENAV_CLOUD_CONFIG_BRANCH='<cloud config config repository branch>' \
    -DENAV_CLOUD_CONFIG_USERNAME='<config config repository username>' \
    -DENAV_CLOUD_CONFIG_PASSWORD='<config config repository passord>' \
    <aton-service.jar>

Local Config Configuration

In order to run the service in a Local Config configuration, you just need to provide a local configuration directory that contains the necessary .properties files (including bootstrap).

This can be done in the following way:

java -jar \
    --spring.config.location=optional:classpath:/,optional:file:<config_dir>/ \
    <aton-service.jar>

Examples of the required properties files can be seen below.

For bootstrapping, we need to disable the cloud config client, and clear our the environment variable inputs:

server.port=8766
spring.application.name=aton-service
spring.application.version=<application.version>

# Disable the cloud config
spring.cloud.config.enabled=false

# Clear out the environment variables
spring.cloud.config.uri=
spring.cloud.config.username=
spring.cloud.config.password=
spring.cloud.config.label=

While the application properties need to provide the service with an OAuth2.0 server like keycloak, logging configuration, the eureka client connection etc.:

# Configuration Variables
service.variable.hostname=<service.hostname>
service.variable.eureka.server.name=<eureka.server.name>
service.variable.eureka.server.port=<eureka.server.port>
service.variable.keycloak.server.name=<keycloak.server.name>
service.variable.keycloak.server.port=<keycloak.server.port>
service.variable.keycloak.server.realm=<keycloak.realm>
service.variable.kafka.server.name=<kafka.server.name>
service.variable.kafka.server.broker.port=<kafka.server.port>
service.variable.kafka.server.zookeeper.port=<zookeeper.server.port>
service.variable.database.server.name=<database.server.name>
service.variable.database.server.port=<database.server.port>
service.variable.mcp.service-registry.endpoint=<mcp.service-registry.endpoint>

# Eureka Client Configuration
eureka.client.service-url.defaultZone=http://${service.variable.eureka.server.name}:${service.variable.eureka.server.port}/eureka/
eureka.client.registryFetchIntervalSeconds=5
eureka.instance.preferIpAddress=true
eureka.instance.leaseRenewalIntervalInSeconds=10
eureka.instance.hostname=${service.variable.hostname}
eureka.instance.metadata-map.startup=${random.int}

# Spring-boot Admin Configuration
spring.boot.admin.client.url=http://${service.variable.server.eureka.name}:${service.variable.server.eureka.port}/admin

# Logging Configuration
# If we don't load the configuration for logback manually here, this is not
# picked up at the correct time by spring-cloud and the service asks to write
# to the /tmp/spring.log file. Another way of dealing with this is to add this
# information in the bootstrap.properties file.
logging.config=classpath:logback-delayed.xml
logging.file.name=/var/log/${spring.application.name}.log
logging.file.max-size=10MB
logging.pattern.rolling-file-name=${spring.application.name}-%d{yyyy-MM-dd}.%i.log

# SECOM Logging Configuration
logging.secom.requests.file.name=/var/log/${spring.application.name}-secom-requests.log
logging.secom.requests.rollingpolicy.file-name=${spring.application.name}-secom-requests.%d{yyyy-MM-dd}.%i.log
logging.secom.requests.rollingpolicy.max-file-size=10MB
logging.secom.requests.rollingpolicy.max-history:10
logging.secom.requests.rollingpolicy.total-size-cap:100MB

# Management Endpoints
management.endpoint.logfile.external-file=/var/log/${spring.application.name}.log
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
management.endpoint.httpexchanges.enabled=true
management.endpoint.health.probes.enabled: true

# Springdoc configuration
springdoc.swagger-ui.path=/swagger-ui.html
springdoc.swagger-ui.display-query-params=true
springdoc.swagger-ui.url=/api/secom/openapi.json
springdoc.packagesToScan=org.grad.eNav.atonService.controllers

# Spring JPA Configuration - PostgreSQL
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.show-sql=true
spring.jpa.properties.hibernate.search.backend.lucene_version=LATEST
spring.jpa.properties.hibernate.search.backend.directory.root=./lucene/
spring.jpa.properties.hibernate.search.schema_management.strategy=create-or-update
spring.jpa.properties.hibernate.search.backend.analysis.configurer=class:org.grad.eNav.atonService.config.CustomLuceneAnalysisConfigurer

# Datasource Configuration
spring.datasource.url=jdbc:postgresql:///${service.variable.database.server.name}:${service.variable.database.server.port}/aton_service
spring.datasource.username=<changeit>
spring.datasource.password=<changeit>

# Keycloak Configuration
keycloak.enabled=true
spring.security.oauth2.client.registration.keycloak.client-id=aton-service
spring.security.oauth2.client.registration.keycloak.client-secret=<changeit>
spring.security.oauth2.client.registration.keycloak.client-name=Keycloak
spring.security.oauth2.client.registration.keycloak.provider=keycloak
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid
spring.security.oauth2.client.registration.keycloak.redirect-uri={baseUrl}/login/oauth2/code/{registrationId}
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://${service.variable.keycloak.server.name}:${service.variable.keycloak.server.port}/realms/${service.variable.keycloak.server.realm}
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://${service.variable.keycloak.server.name}:${service.variable.keycloak.server.port}/realms/${service.variable.keycloak.server.realm}

# Feign
feign.client.config.default.connectTimeout=60000
feign.client.config.default.readTimeout=20000

# Feign Security
spring.security.oauth2.client.registration.feign.client-id=aton-service
spring.security.oauth2.client.registration.feign.client-secret=<changeit>
spring.security.oauth2.client.registration.feign.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.feign.scope=web-origins,openid
spring.security.oauth2.client.provider.feign.token-uri=http://${service.variable.keycloak.server.name}:${service.variable.keycloak.server.port}/realms/niord/protocol/openid-connect/token

# Kafka Configuration
kafka.brokers=${service.variable.kafka.server.name}:${service.variable.kafka.server.broker.port}
kafka.zookeepers=${service.variable.kafka.server.name}:${service.variable.kafka.server.zookeeper.port}
kafka.consumer.count=1

# Web Socket Configuration
gla.rad.atonService.web-socket.name=aton-service-websocket
gla.rad.atonService.web-socket.prefix=topic

# Listening geometry definition
gla.rad.aton-service.geometry=POLYGON ((-180 -90, -180 90, 180 90, 180 -90, -180 -90))

# Front-end Information
gla.rad.service.info.name=AtoN Service
gla.rad.service.info.version=${spring.application.version}
gla.rad.service.info.organization=Research and Development Directorate of GLA of UK and Ireland
gla.rad.service.info.electronicMailAddresses[0]=Nikolaos.Vastardis@gla-rad.org
gla.rad.service.info.electronicMailAddresses[1]=enquiries@gla-rad.org
gla.rad.service.info.url=https://www.gla-rad.org/
gla.rad.service.info.phone=+44 01255 245000
gla.rad.service.info.fax=+44 01255 245000
gla.rad.service.info.city=Harwich
gla.rad.service.info.postalCode=CO12 3JW
gla.rad.service.info.country=United Kingdom
gla.rad.service.info.locales=en_GB,cy_GB,gd_GB,ga_IE
gla.rad.service.info.administrativeArea=England, Wales, Scotland & the whole of Ireland
gla.rad.service.info.ihoProducerCode=GB01

# Service S-100 configuration
gla.rad.service.info.copyright=\u00A9 2023 GLA Research & Development
gla.rad.service.s100.exchangeSet.dir=/opt/e-nav/s-100/atonService
gla.rad.service.s100.exchangeSet.prefix=atonServiceExchangeSet
gla.rad.service.s100.dataProduct.location=/xsd/S125.xsd

# Service SECOM configuration
gla.rad.service.secom.rootCertificateAlias=mcp-root
gla.rad.service.secom.subscriptions.restrictDuplicates=true

# SECOM Configuration Properties
secom.service-registry.url=${service.variable.mcp.service-registry.endpoint}
secom.security.ssl.keystore=<path.to.keystore>
secom.security.ssl.keystore-type=jks
secom.security.ssl.keystore-password=<changeit>
secom.security.ssl.truststore=<path.to.truststore>
secom.security.ssl.truststore-type=jks
secom.security.ssl.truststore-password=<changeit>
secom.security.ssl.insecureSslPolicy=true

Operation

The core operation of the AtoN Service involves monitoring the “S125” topic of the Kafka publish-subscribe broker, for messages generated by the Message Broker. Upon a message being published there, whether an AtoN creation/update or a deletion, the service will react by updating its AtoN database and then initiating an S-125 dataset update operation. The whole operation starts when the service receives a message from the publish-subscribe channel. First, the message validity is checked (for example if it is correctly formatted), and then the affected geometry is compared against the geographical area defined for this AtoN Service instance. This allows the application to provide a selective service with a specific coverage and not clutter its database with AtoN information that could be potentially irrelevant. If any of those checks fail, then the received message is dropped.

If the received message is valid, the service will process it and extract the AtoN information which will subsequently be stored in its AtoN database. Afterwards, the AtoN Service will attempt to identify which of the already defined S-125 datasets are affected by the AtoN information received. Normally we expect only one dataset to be affected, namely the one that includes the geographical location of the AtoN in question. However, in some more complex scenarios, where datasets can be defined in a hierarchical way, there could potentially be multiple ones. For all affected datasets, the updated S-125 content will be generated and the output will once again be stored in the database.

The new content will include all AtoN that fall into the geographical boundaries defined for the specific S-125 dataset. An important point to be made here is that the service will also create an additional data entry for the updated dataset content in a separate database table for logging purposes. This way, all dataset changes will be recorded and can be retrieved for auditing purposes.

Finally, once all the affected S-125 datasets have been updated, the active SECOM subscriptions that are affected by the dataset changes will be informed. Active SECOM subscriptions in this context are all the subscriptions initiated via the SECOM “subscribe” interface which are valid in terms of the starting and ending dates and times specified.

Two more areas of functionality provided by the AtoN Service involve the management of S-125 datasets and SECOM subscriptions. In terms of the S-125 datasets, these are assigned with detailed identification information and can be defined for specific geographical areas. This functionality is currently accessible through the application’s own web-interface (GUI), and only authorised users have access to it. The contents of an S-125 dataset however are generated automatically by the service.

SECOM subscriptions on the other hand, are generated upon SECOM client requests towards the SECOM “Subscription” interface of the “AtoN Service”. Subscriptions can be setup on a specific S-125 dataset, on a geographic area, or any combination of the two. In the same way, subscriptions can also be dropped by the clients using the SECOM “Delete Subscription”. In certain cases however, when the subscription period finishes, or the dataset specified in a subscription has been deleted, it is the responsibility of the “AtoN Service” to cancel the subscription and inform the corresponding clients.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

Distributed under the Apache License, Version 2.0. See LICENSE for more information.

Contact

Nikolaos Vastardis - Nikolaos.Vastardis@gla-rad.org

About

A Springboot implementation of an AtoN information service for the GRAD e-Navigation Service Architecture, controlling the S-125 AtoN information

Resources

License

Stars

Watchers

Forks

Releases

No releases published