Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ target/
bin/
**/bin/

certs/
hakuna.log
pom.xml.versionsBackup
**/pom.xml.versionsBackup
16 changes: 16 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FROM maven:3.9.6-eclipse-temurin-21-alpine AS build
WORKDIR /build

COPY . /build

RUN mvn -DskipTests -pl webapp-jakarta/hakunapi-simple-webapp-jakarta -am clean package

FROM tomcat:jdk21-openjdk
ENV CATALINA_OUT=/dev/stdout

# Copy the built WAR from the build stage
COPY --from=build /build/webapp-jakarta/hakunapi-simple-webapp-jakarta/target/*.war /usr/local/tomcat/webapps/features.war

EXPOSE 8080

CMD ["catalina.sh", "run"]
43 changes: 43 additions & 0 deletions Dockerfile-hotreload
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
FROM maven:3.9.6-eclipse-temurin-21-alpine AS build
WORKDIR /build

COPY . /build

# Copy hotswap-agent properties into the resources directory
# Needed for configuring hotswap-agent behavior
# Currently set up for watching ftl files and all target/classes of current modules under /src
# If a new one get created, you will need to update this file accordingly
COPY ./docker/hotswap-agent.properties /build/webapp-jakarta/hakunapi-simple-webapp-jakarta/src/main/resources/hotswap-agent.properties

RUN mvn -DskipTests -pl webapp-jakarta/hakunapi-simple-webapp-jakarta clean package

FROM tomcat:jdk21-openjdk
ARG HOTSWAP_VERSION=2.0.1
ENV CATALINA_OUT=/dev/stdout

# install tools, download and install JetBrains JBR,
# and download HotswapAgent into the JBR lib directory
RUN apt-get update -qq \
&& apt-get install -y -qq curl tar gzip \
# create install dir \
&& mkdir -p /opt/jbr \
# download and extract JetBrains JBR (cache-redirector URL)
&& curl -fSL "https://cache-redirector.jetbrains.com/intellij-jbr/jbr_jcef-21.0.8-linux-x64-b1163.59.tar.gz" -o /tmp/jbr.tar.gz \
&& tar -xzf /tmp/jbr.tar.gz -C /opt/jbr --strip-components=1 \
&& rm /tmp/jbr.tar.gz \
# set JAVA_HOME to the JBR path (used by catalina.sh). Also ensure tools dir exists for hotswap \
&& mkdir -p /opt/jbr/lib/hotswap \
# download HotswapAgent into the JBR lib
&& curl -fSL "https://github.com/HotswapProjects/HotswapAgent/releases/download/RELEASE-${HOTSWAP_VERSION}/hotswap-agent-${HOTSWAP_VERSION}.jar" -o /opt/jbr/lib/hotswap/hotswap-agent.jar \
&& chmod 644 /opt/jbr/lib/hotswap/hotswap-agent.jar

# Point Tomcat to use the JBR we installed
ENV JAVA_HOME=/opt/jbr
ENV PATH=$JAVA_HOME/bin:$PATH

# Copy the built WAR from the build stage
COPY --from=build /build/webapp-jakarta/hakunapi-simple-webapp-jakarta/target/*.war /usr/local/tomcat/webapps/features.war

EXPOSE 8080

CMD ["catalina.sh", "run"]
100 changes: 100 additions & 0 deletions docker/cfg/addresses.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# General information about the api
# Not required, dummy values provided by the service
api.title=INSPIRE Simple Addresses, Finland
api.version=0.1
api.description=Example implementation of OGC API Services with hakunapi. INSPIRE Simple Addresses from Finland. Data from 13.02.2023 https://www.avoindata.fi/data/fi/dataset/rakennusten-osoitetiedot-koko-suomi by Finnish Digital and Population Data services Agency.
#api.contact.name=Name of Contact
#api.contact.email=concat@email.com
#api.contact.url=https://github.com/nlsfi/hakunapi
api.license.name=Data accessed from the API is licensed by the Digital and Population Data Services Agency CC BY 4.0 licence.
api.license.url=https://creativecommons.org/licenses/by/4.0/

# List of servers
## Required, comma-separated list of server the API is
servers=dev
## The url of the server has to be correct as it is used for all links generated by the server
servers.dev.url=http://localhost:8080/features
servers.dev.description=Development server

# API level configuration
formats=geojson,html,gpkg
formats.geojson.type=json
# force lon,lat axisOrder on GeoJSON output even if output CRS is lat,lon by authority
# formats.geojson.forceLonLat=true
formats.html.type=html
formats.gpkg.type=gpkg
formats.gpkg.dir=/app/features_addresses/tmp
getfeatures.limit.default=10
getfeatures.limit.max=10000

# Configure known srids (hakunapi will always add 84 (lon, lat) and 4326 (lat, lon))
srid=3067,4258
# Let hakunapi know that EPSG:4258 is lat,lon order
srid.4258.latLon=true

# Collections and their configurations

## Required, comma-separated list of all collections
collections=addresses

collections.addresses.title=Simple Addresses
collections.addresses.description=Addresses of Finlands Buildings

## Select a strategy for case-insensitive comparisons
## Valid values can be found from CaseInsensitiveStrategy enum (default value is `lower`)
## If we indexed an expression `upper(thoroughfare_name)` then it would make sense to configure this to `upper`
collections.addresses.casei=lower

## Should properties with null values be omitted from the response
collections.addresses.writeNulls=true

## PostgreSQL/PostGIS configuration
### This collection is backed by 'pg' (PostgreSQL/PostGIS) source/driver
collections.addresses.type=pg
### Name of {db}.properties
collections.addresses.db=db
collections.addresses.schema=public
collections.addresses.table=simple_addresses

### Spatial extent of the collection, required by some clients to recognize the colletion as a spatial feature collection
collections.addresses.extent.spatial.crs84=15.0537852,58.6074565,33.9935374,70.2641566

### Supported Coordinate Reference Systems (CRS:84 is always and automatically included)
collections.addresses.srid=3067,4258


### Required, mapping for primary id property
collections.addresses.id.mapping=id

### Mapping for primary geometry property
collections.addresses.geometry.mapping=geom

### List of all (other) properties
collections.addresses.properties=inspireId_localId,inspireId_namespace,component_ThoroughfareName,component_PostalDescriptor,component_AdminUnitName_1,component_AdminUnitName_4,locator_designator_addressNumber,locator_level,locator_level_href,position_specification,position_specification_href,position_method,position_method_href,position_default,building,parcel

### property is mapped to a static value instead of column reference if mapping is single-quoted
collections.addresses.properties.inspireId_localId.mapping=id
collections.addresses.properties.inspireId_namespace.mapping='https://github.com/INSPIRE-MIF/2017.2/GeoJSON/ads/examples/'

collections.addresses.properties.component_ThoroughfareName.mapping=thoroughfare_name
collections.addresses.properties.component_PostalDescriptor.mapping=postal_descriptor
collections.addresses.properties.component_AdminUnitName_1.mapping='Suomi'
collections.addresses.properties.component_AdminUnitName_4.mapping=admin_unit_name_4

collections.addresses.properties.locator_designator_addressNumber.mapping=address_number
collections.addresses.properties.locator_level.mapping='siteLevel'
collections.addresses.properties.locator_level_href.mapping='https://inspire.ec.europa.eu/codelist/LocatorLevelValue/siteLevel'

collections.addresses.properties.position_specification.mapping='building'
collections.addresses.properties.position_specification_href.mapping='https://inspire.ec.europa.eu/codelist/GeometrySpecificationValue/building'
collections.addresses.properties.position_method.mapping='byOtherParty'
collections.addresses.properties.position_method_href.mapping='https://inspire.ec.europa.eu/codelist/GeometryMethodValue/byOtherParty'
collections.addresses.properties.position_default.mapping='true'

### If the name of the property matches the name of the backing column no mapping is required
### collections.addresses.properties.building.mapping=building
### collections.addresses.properties.parcel.mapping=parcel

## Queryables
collections.addresses.parameters=inspireId_localId,component_ThoroughfareName,component_PostalDescriptor,component_AdminUnitName_4,locator_designator_addressNumber,building,parcel

103 changes: 103 additions & 0 deletions docker/cfg/addresses_gpkg.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# General information about the api
# Not required, dummy values provided by the service
api.title=INSPIRE Simple Addresses, Finland
api.version=0.1
api.description=Example implementation of OGC API Services with hakunapi. INSPIRE Simple Addresses from Finland. Data from 13.02.2023 https://www.avoindata.fi/data/fi/dataset/rakennusten-osoitetiedot-koko-suomi by Finnish Digital and Population Data services Agency.
#api.contact.name=Name of Contact
#api.contact.email=concat@email.com
#api.contact.url=https://github.com/nlsfi/hakunapi
api.license.name=Data accessed from the API is licensed by the Digital and Population Data Services Agency CC BY 4.0 licence.
api.license.url=https://creativecommons.org/licenses/by/4.0/

# List of servers
## Required, comma-separated list of server the API is
servers=dev
## The url of the server has to be correct as it is used for all links generated by the server
servers.dev.url=http://localhost:8080/features
servers.dev.description=Development server

# API level configuration
formats=json,html,gpkg
formats.gpkg.dir=/app/features_addresses/tmp
getfeatures.limit.default=10
getfeatures.limit.max=10000

# Configure known srids (hakunapi will always add 84 (lon, lat) and 4326 (lat, lon))
srid=3067,4258
# Let hakunapi know that EPSG:4258 is lat,lon order
srid.4258.latLon=true

# Instead of loading PostGIS source drivers (the default) allow and load only GpkgSimpleSource
db.classes=fi.nls.hakunapi.source.gpkg.GpkgSimpleSource

# Collections and their configurations

## Required, comma-separated list of all collections
collections=simple_addresses

# Title and Description are extracted from gpkg_contents but can be overridden here if necessary
# collections.simple_addresses.title=Simple Addresses
# collections.simple_addresses.description=Addresses of Finlands Buildings

## Select a strategy for case-insensitive comparisons
## Valid values can be found from CaseInsensitiveStrategy enum (default value is `lower`)
## If we indexed an expression `upper(thoroughfare_name)` then it would make sense to configure this to `upper`
collections.simple_addresses.casei=lower

## Should properties with null values be omitted from the response
collections.simple_addresses.writeNulls=true

## GeoPackage configuration
### This collection is backed by 'gpkg' (GeoPackage) source/driver
### This is optional if only a single source type is available (via db.classes)
# collections.simple_addresses.type=gpkg

### File location of the geopackage file, absolute or relative (to directory containing this file)
### Currently only files are supported (remote source files over http(s) not supported)
collections.simple_addresses.db=simple_addresses.gpkg

### Table containing the features. collection id (simple_addresses here) will be used as fallback
# collections.simple_addresses.table=simple_addresses

### Spatial extent of the collection, required by some clients to recognize the colletion as a spatial feature collection
### Extent is extracted from gpkg_contents but can be overridden here if necessary
# collections.simple_addresses.extent.spatial.crs84=15.0537852,58.6074565,33.9935374,70.2641566

### Supported Coordinate Reference Systems for this collection (CRS:84 is always and automatically included)
collections.simple_addresses.srid=3067,4258

### Currently gpkg source always maps the primary key of the feature table to id property
### Geometry column is extracted from gpkg_geometry_columns

### Missing/empty or "*" publishes all columns from feature table as properties
# collections.simple_addresses.properties=*

### Manually list of all (other) property names
collections.simple_addresses.properties=inspireId_localId,inspireId_namespace,component_ThoroughfareName,component_PostalDescriptor,component_AdminUnitName_1,component_AdminUnitName_4,locator_designator_addressNumber,locator_level,locator_level_href,position_specification,position_specification_href,position_method,position_method_href,position_default,building,parcel

### Backing column of a property is configured via .mapping
collections.simple_addresses.properties.inspireId_localId.mapping=id
### property is mapped to a static value instead of column reference if mapping is single-quoted
collections.simple_addresses.properties.inspireId_namespace.mapping='https://github.com/INSPIRE-MIF/2017.2/GeoJSON/ads/examples/'

collections.simple_addresses.properties.component_ThoroughfareName.mapping=thoroughfare_name
collections.simple_addresses.properties.component_PostalDescriptor.mapping=postal_descriptor
collections.simple_addresses.properties.component_AdminUnitName_1.mapping='Suomi'
collections.simple_addresses.properties.component_AdminUnitName_4.mapping=admin_unit_name_4

collections.simple_addresses.properties.locator_designator_addressNumber.mapping=address_number
collections.simple_addresses.properties.locator_level.mapping='siteLevel'
collections.simple_addresses.properties.locator_level_href.mapping='https://inspire.ec.europa.eu/codelist/LocatorLevelValue/siteLevel'

collections.simple_addresses.properties.position_specification.mapping='building'
collections.simple_addresses.properties.position_specification_href.mapping='https://inspire.ec.europa.eu/codelist/GeometrySpecificationValue/building'
collections.simple_addresses.properties.position_method.mapping='byOtherParty'
collections.simple_addresses.properties.position_method_href.mapping='https://inspire.ec.europa.eu/codelist/GeometryMethodValue/byOtherParty'
collections.simple_addresses.properties.position_default.mapping='true'

### If the name of the property matches the name of the backing column no .mapping is required
### collections.simple_addresses.properties.building.mapping=building
### collections.simple_addresses.properties.parcel.mapping=parcel

## Queryables (names of the properties, not columns in the backing source)
collections.simple_addresses.parameters=inspireId_localId,component_ThoroughfareName,component_PostalDescriptor,component_AdminUnitName_4,locator_designator_addressNumber,building,parcel
7 changes: 7 additions & 0 deletions docker/cfg/db.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# HikariCP configuration file
dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
dataSource.user=address_reader
dataSource.password=test
dataSource.databaseName=address_fin
dataSource.portNumber=5432
dataSource.serverName=db
53 changes: 53 additions & 0 deletions docker/docker-compose-hot-reload.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: hakunapi

services:
db:
image: postgis/postgis:18-3.6
restart: unless-stopped
environment:
POSTGRES_DB: address_fin
POSTGRES_USER: address_reader
POSTGRES_PASSWORD: test
volumes:
- ./init-addresses.sh:/docker-entrypoint-initdb.d/init-addresses.sh:ro
- ../examples/finnish_addresses/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql:ro
- ../examples/finnish_addresses/simple_addresses.sql:/docker-entrypoint-initdb.d/simple_addresses.sql:ro
- ../examples/finnish_addresses/suomi_kunnat.csv:/docker-entrypoint-initdb.d/suomi_kunnat.csv:ro
- ../examples/finnish_addresses/suomi_osoitteet.csv:/docker-entrypoint-initdb.d/suomi_osoitteet.csv:ro
- ../examples/finnish_addresses/cfg:/docker-entrypoint-initdb.d/cfg:ro
- db_data:/var/lib/postgresql
ports:
- "5432:5432"
hakunapi:
build:
context: ../.
dockerfile: Dockerfile-hotreload
restart: unless-stopped
ports:
- "8080:8080"
- "41467:41467"
volumes:
# mount the working example config dir so hakunapi can read addresses.properties (read-only)
- ./cfg:/app/config:ro
- ../src:/app/java:ro
environment:
# Tell Tomcat / hakunapi where to find the config file and pass JVM flags to Tomcat
CATALINA_OPTS: >-
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:41467
-Dfeatures.hakuna.config.path=/app/config/addresses.properties
-javaagent:"/opt/jbr/lib/hotswap/hotswap-agent.jar"
-XX:HotswapAgent=external
-XX:+AllowEnhancedClassRedefinition
-XX:+ClassUnloading
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED
--add-opens=java.base/java.io=ALL-UNNAMED
--add-opens=java.base/sun.security.action=ALL-UNNAMED
--add-opens=java.base/jdk.internal.reflect=ALL-UNNAMED
--add-opens=java.base/java.net=ALL-UNNAMED
depends_on:
- db

volumes:
db_data: {}
39 changes: 39 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: hakunapi

services:
db:
image: postgis/postgis:18-3.6
restart: unless-stopped
environment:
POSTGRES_DB: address_fin
POSTGRES_USER: address_reader
POSTGRES_PASSWORD: test
volumes:
- ./init-addresses.sh:/docker-entrypoint-initdb.d/init-addresses.sh:ro
- ../examples/finnish_addresses/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql:ro
- ../examples/finnish_addresses/simple_addresses.sql:/docker-entrypoint-initdb.d/simple_addresses.sql:ro
- ../examples/finnish_addresses/suomi_kunnat.csv:/docker-entrypoint-initdb.d/suomi_kunnat.csv:ro
- ../examples/finnish_addresses/suomi_osoitteet.csv:/docker-entrypoint-initdb.d/suomi_osoitteet.csv:ro
- ../examples/finnish_addresses/cfg:/docker-entrypoint-initdb.d/cfg:ro
- db_data:/var/lib/postgresql
ports:
- "5432:5432"
hakunapi:
build: ../.
restart: unless-stopped
ports:
- "8080:8080"
- "41467:41467"
volumes:
# mount the working example config dir so hakunapi can read addresses.properties (read-only)
- ./cfg:/app/config:ro
environment:
# Tell Tomcat / hakunapi where to find the config file and pass JVM flags to Tomcat
CATALINA_OPTS: >-
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:41467
-Dfeatures.hakuna.config.path=/app/config/addresses.properties
depends_on:
- db

volumes:
db_data: {}
21 changes: 21 additions & 0 deletions docker/hotswap-agent.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
autoHotswap=true
watchResources=/app/java/hakunapi-html/src/main/resources
extraClasspath=/app/java/hakunapi-config-test/target/classes; \
/app/java/hakunapi-core/target/classes; \
/app/java/hakunapi-cql2/target/classes; \
/app/java/hakunapi-cql2-functions/target/classes; \
/app/java/hakunapi-crs-properties/target/classes; \
/app/java/hakunapi-csv/target/classes; \
/app/java/hakunapi-esbulk/target/classes; \
/app/java/hakunapi-geojson/target/classes; \
/app/java/hakunapi-gml/target/classes; \
/app/java/hakunapi-gpkg;/target/classes \
/app/java/hakunapi-jsonfg/target/classes; \
/app/java/hakunapi-proj-gt/target/classes; \
/app/java/hakunapi-proj-jhe/target/classes; \
/app/java/hakunapi-smile/target/classes; \
/app/java/hakunapi-source-gpkg/target/classes; \
/app/java/hakunapi-source-oracle/target/classes; \
/app/java/hakunapi-source-postgis/target/classes; \
/app/java/hakunapi-telemetry/target/classes; \
/app/java/hakunapi-telemetry-opentelemetry/target/classes;
Loading