Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ There is currently one database implementations available.
> **Note:** When switching between implementation it's a good practise to first execute a maven clean to remove
> old dependencies from the target directory in the app module.

## Development

See [development](doc/development.md) documentation.

## Common Environment variables

Below environment variable(s) can be used to configure which claims and information are used to fill the UserInfo
Expand Down Expand Up @@ -86,4 +90,3 @@ configured as needed.
- STD_DELETE
- STD_READ
- STD_UPDATE

Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ quarkus.datasource.devservices.enabled = false
quarkus.datasource.db-kind = postgresql
quarkus.datasource.jdbc.url = jdbc:postgresql://${POSTGRESQL_HOST:localhost}:${POSTGRESQL_PORT:5432}/${POSTGRESQL_DB:compas}
quarkus.datasource.jdbc.max-size = 16
quarkus.datasource.username = ${POSTGRESQL_USERNAME:postgres}
quarkus.datasource.password = ${POSTGRESQL_PASSWORD:postgres}
quarkus.datasource.username = ${POSTGRESQL_USERNAME:compas}
quarkus.datasource.password = ${POSTGRESQL_PASSWORD:compas}
Comment thread
david-monichi marked this conversation as resolved.

# Flyway configuration for PostgreSQL
quarkus.flyway.migrate-at-start = true
Expand Down
24 changes: 24 additions & 0 deletions app/src/main/resources/application-local.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2025 BearingPoint GmbH
#
# SPDX-License-Identifier: Apache-2.0

# Enable full logging for local development
# quarkus.log.level = ALL
# quarkus.log.category."org.lfenergy.compas.scl.data".level = ALL

quarkus.flyway.migrate-at-start = true
quarkus.flyway.locations = classpath:org/lfenergy/compas/scl/data/repository/postgresql/db/migration

mp.jwt.verify.issuer = ${JWT_VERIFY_ISSUER:http://127.0.0.1:8089/auth/realms/compas}

compas.scl-data-service.features.soft-delete-enabled = true

# Run with local PostgreSQL database provided by "app/src/test/resources/docker-compose.yml"
# For more details have a look at the [development documentation](doc/development.md).

#quarkus.datasource.devservices.enabled = false
#quarkus.datasource.db-kind = postgresql
#quarkus.datasource.jdbc.url = jdbc:postgresql://${POSTGRESQL_HOST:localhost}:${POSTGRESQL_PORT:5432}/${POSTGRESQL_DB:compas}
#quarkus.datasource.jdbc.max-size = 16
#quarkus.datasource.username = ${POSTGRESQL_USERNAME:postgres}
#quarkus.datasource.password = ${POSTGRESQL_PASSWORD:postgres}
2 changes: 2 additions & 0 deletions app/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ quarkus.websocket.max-frame-size = 157286400
quarkus.log.level = INFO
quarkus.log.category."org.lfenergy.compas.scl.data".level = INFO

compas.scl-data-service.features.soft-delete-enabled = ${SCL_DATA_SERVICE_SOFT_DELETE_ENABLED:false}

# Add scanning these dependencies for scanning, also used by native compilation.
quarkus.index-dependency.websocket-commons.group-id = org.lfenergy.compas.core
quarkus.index-dependency.websocket-commons.artifact-id = websocket-commons
Expand Down
37 changes: 37 additions & 0 deletions app/src/test/resources/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# SPDX-FileCopyrightText: 2025 BearingPoint GmbH
#
# SPDX-License-Identifier: Apache-2.0

version: '3.8'

services:
keycloak:
image: ghcr.io/ase-compas/compas/compas-keycloak:main
container_name: keycloak
labels:
compas: true
ports:
- "8089:8080"
environment:
- KC_HOSTNAME=http://127.0.0.1:8089/auth/
- KC_HTTP_RELATIVE_PATH=auth
- KC_HTTP_ENABLED=true
- KC_PROXY_HEADERS=xforwarded
- KC_BOOTSTRAP_ADMIN_USERNAME=admin
- KC_BOOTSTRAP_ADMIN_PASSWORD=admin

postgresql:
image: postgres:latest
container_name: compas_postgresql
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: compas
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
60 changes: 60 additions & 0 deletions doc/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!--
SPDX-FileCopyrightText: 2025 BearingPoint GmbH

SPDX-License-Identifier: Apache-2.0
-->

# Development

Run application with local postgresql database in development mode:
```bash
cd src/test/resources/docker-compose.yml
docker-compose up keycloak

mvn -DskipTests=true -Dquarkus.profile=local package io.quarkus:quarkus-maven-plugin::dev
```

In case of issues enable full debug logging by uncommenting the enable `ALL` logs in the `src/main/resources/application.properties` file:
```properties
quarkus.log.level = ALL
quarkus.log.category."org.lfenergy.compas.scl.data".level = ALL
```

## Verify setup

To verify that the setup is correct, you can use the following curl command to list all ICDs in the database:
```
curl -X GET "http://localhost:8080/scl-data-service/icd/list" -H "Authorization: Bearer <ACCESS_TOKEN>" -H "accept: application
```

The `<ACCESS_TOKEN>` should be replaced with a valid JWT token obtained from Keycloak with following command:
```bash
curl -X POST "http://localhost:8089/auth/realms/compas/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=scl-data-service&username=scl-data-editor&password=editor&grant_type=password"
```

## Connecting to local database

To connect to the local PostgreSQL database, you first need to start the PostgreSQL service using Docker Compose:
```
cd app/src/test/resources/docker-compose.yml
docker-compose up postgresql
```

then enable the postgresql configuration by uncomment following lines in file `src/main/resources/application-local.properties`:
```properties
quarkus.datasource.devservices.enabled = false
quarkus.datasource.db-kind = postgresql
quarkus.datasource.jdbc.url = jdbc:postgresql://${POSTGRESQL_HOST:localhost}:${POSTGRESQL_PORT:5432}/${POSTGRESQL_DB:compas}
quarkus.datasource.jdbc.max-size = 16
quarkus.datasource.username = ${POSTGRESQL_USERNAME:postgres}
quarkus.datasource.password = ${POSTGRESQL_PASSWORD:postgres}
```

Start the application in development mode with the local profile:
```bash
mvn -DskipTests=true -Dquarkus.profile=local package io.quarkus:quarkus-maven-plugin::dev
```

You can then verify the setup described above by using the same curl commands as mentioned earlier.
1 change: 1 addition & 0 deletions doc/postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Table: scl_file
| type | varchar(3) | True | The type of SCL stored |
| name | varchar(255) | True | The name of the SCL File |
| scl_data | text | True | The SCL XML Content |
| is_deleted | boolean | False | Flag indicating whether the record is marked as deleted |

## Development

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
import org.lfenergy.compas.scl.data.repository.CompasSclDataRepository;
import org.lfenergy.compas.scl.extensions.model.SclFileType;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import javax.sql.DataSource;
import jakarta.transaction.Transactional;
import java.sql.Array;
Expand All @@ -27,7 +25,6 @@
import static jakarta.transaction.Transactional.TxType.SUPPORTS;
import static org.lfenergy.compas.scl.data.exception.CompasSclDataServiceErrorCode.*;

@ApplicationScoped
public class CompasSclDataPostgreSQLRepository implements CompasSclDataRepository {
private static final String ID_FIELD = "id";
private static final String MAJOR_VERSION_FIELD = "major_version";
Expand All @@ -39,9 +36,23 @@ public class CompasSclDataPostgreSQLRepository implements CompasSclDataRepositor
private static final String HITEM_WHEN_FIELD = "hitem_when";
private static final String HITEM_WHAT_FIELD = "hitem_what";

private final DataSource dataSource;
protected final DataSource dataSource;

protected static String DELETE_SCL_FILE_SQL = """
delete from scl_file
where scl_file.id = ?
and scl_file.type = ?
""";

protected static String DELETE_SCL_FILE_SQL_BY_VERSION = """
delete from scl_file
where scl_file.id = ?
and scl_file.type = ?
and scl_file.major_version = ?
and scl_file.minor_version = ?
and scl_file.patch_version = ?
""";

@Inject
public CompasSclDataPostgreSQLRepository(DataSource dataSource) {
this.dataSource = dataSource;
}
Expand All @@ -56,6 +67,7 @@ public List<IItem> list(SclFileType type) {
from (select distinct on (scl_file.id) *
from scl_file
where scl_file.type = ?
AND scl_file.is_deleted = false
Comment thread
david-monichi marked this conversation as resolved.
Outdated
order by scl_file.id
, scl_file.major_version desc
, scl_file.minor_version desc
Expand Down Expand Up @@ -115,6 +127,7 @@ left outer join (
and scl_data.patch_version = scl_file.patch_version
where scl_file.id = ?
and scl_file.type = ?
and scl_file.is_deleted = false
order by scl_file.major_version
, scl_file.minor_version
, scl_file.patch_version
Expand Down Expand Up @@ -162,6 +175,7 @@ public String findByUUID(SclFileType type, UUID id, Version version) {
and scl_file.major_version = ?
and scl_file.minor_version = ?
and scl_file.patch_version = ?
and scl_file.is_deleted = false
""";

try (var connection = dataSource.getConnection();
Expand Down Expand Up @@ -191,6 +205,7 @@ public boolean hasDuplicateSclName(SclFileType type, String name) {
select distinct on (scl_file.id) scl_file.name
from scl_file
where scl_file.type = ?
and scl_file.is_deleted = false
order by scl_file.id
, scl_file.major_version desc
, scl_file.minor_version desc
Expand Down Expand Up @@ -221,6 +236,7 @@ public IAbstractItem findMetaInfoByUUID(SclFileType type, UUID id) {
from scl_file
where scl_file.id = ?
and scl_file.type = ?
and scl_file.is_deleted = false
order by scl_file.major_version desc, scl_file.minor_version desc, scl_file.patch_version desc
""";

Expand Down Expand Up @@ -304,14 +320,9 @@ insert into scl_label(scl_id, major_version, minor_version, patch_version, label
@Override
@Transactional(REQUIRED)
public void delete(SclFileType type, UUID id) {
var sql = """
delete from scl_file
where scl_file.id = ?
and scl_file.type = ?
""";

try (var connection = dataSource.getConnection();
var stmt = connection.prepareStatement(sql)) {
var stmt = connection.prepareStatement(DELETE_SCL_FILE_SQL)) {
stmt.setObject(1, id);
stmt.setString(2, type.name());
stmt.executeUpdate();
Expand All @@ -323,17 +334,9 @@ public void delete(SclFileType type, UUID id) {
@Override
@Transactional(REQUIRED)
public void delete(SclFileType type, UUID id, Version version) {
var sql = """
delete from scl_file
where scl_file.id = ?
and scl_file.type = ?
and scl_file.major_version = ?
and scl_file.minor_version = ?
and scl_file.patch_version = ?
""";

try (var connection = dataSource.getConnection();
var stmt = connection.prepareStatement(sql)) {
var stmt = connection.prepareStatement(DELETE_SCL_FILE_SQL_BY_VERSION)) {
stmt.setObject(1, id);
stmt.setString(2, type.name());
stmt.setInt(3, version.getMajorVersion());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: 2025 BearingPoint GmbH
//
// SPDX-License-Identifier: Apache-2.0

package org.lfenergy.compas.scl.data.repository.postgresql;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.lfenergy.compas.scl.data.repository.CompasSclDataRepository;

import javax.sql.DataSource;

public class CompasSclDataPostgreSQLRepositoryConfiguration {

private static final Logger LOGGER = LogManager.getLogger(CompasSclDataPostgreSQLRepositoryConfiguration.class);

@ConfigProperty(name = "compas.scl-data-service.features.soft-delete-enabled", defaultValue = "false")
private boolean softDeleteEnabled;

@Produces
@ApplicationScoped
CompasSclDataRepository softDeleteCompasSclDataPostgreSQLRepository(DataSource dataSource) {
if (!softDeleteEnabled) {
LOGGER.warn("Soft delete feature is disabled, using default repository.");
return new CompasSclDataPostgreSQLRepository(dataSource);
}
LOGGER.info("Soft delete feature is enabled. Using SoftDeleteCompasSclDataPostgreSQLRepository.");
return new SoftDeleteCompasSclDataPostgreSQLRepository(dataSource);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-FileCopyrightText: 2025 BearingPoint GmbH
//
// SPDX-License-Identifier: Apache-2.0

package org.lfenergy.compas.scl.data.repository.postgresql;

import javax.sql.DataSource;

public class SoftDeleteCompasSclDataPostgreSQLRepository extends CompasSclDataPostgreSQLRepository {

private static final String SOFT_DELETE_SCL_FILE_SQL = """
UPDATE scl_file
SET is_deleted = true
where scl_file.id = ?
and scl_file.type = ?
""";

private static final String SOFT_DELETE_SCL_FILE_SQL_BY_VERSION = """
delete from scl_file
where scl_file.id = ?
and scl_file.type = ?
and scl_file.major_version = ?
and scl_file.minor_version = ?
and scl_file.patch_version = ?
""";

public SoftDeleteCompasSclDataPostgreSQLRepository(DataSource dataSource) {
super(dataSource);
DELETE_SCL_FILE_SQL = SOFT_DELETE_SCL_FILE_SQL;
DELETE_SCL_FILE_SQL_BY_VERSION = SOFT_DELETE_SCL_FILE_SQL_BY_VERSION;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* SPDX-FileCopyrightText: 2025 BearingPoint GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/

--
-- Update SCL File Table to add soft deletion
--

ALTER TABLE scl_file
ADD COLUMN is_deleted BOOLEAN DEFAULT false;

comment on column scl_file.is_deleted is 'Flag indicating whether the SCL file is soft deleted.';
Loading