Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
452a23c
Added Endpoints
GW1708 Apr 7, 2025
8f2c5c6
Updated endpoints and added javadoc for service methods.
GW1708 Apr 8, 2025
f1bbcfc
Implemented createShells, getBulkOperationResult and getBulkOperation…
GW1708 Apr 8, 2025
6a3ffb7
fixed small issues
GW1708 Apr 9, 2025
ab9d9ab
implemented integration tests for bulkCreateShells, getBulkOperationS…
GW1708 Apr 9, 2025
5b41132
Implemented integration tests for transaction rollback. Todo: Fix tra…
GW1708 Apr 30, 2025
648d60b
Refactored Package Structure
GW1708 Aug 11, 2025
88f62c1
Enabled Async on App level
GW1708 Aug 11, 2025
634d0cd
Transaction logic is now in a dedicated service class. This might hel…
GW1708 Aug 11, 2025
bc9664e
Refactored test class. Commit and Rollback tests are now tested on th…
GW1708 Aug 11, 2025
989222f
Spotless run
GW1708 Aug 11, 2025
40d12a4
Set @Async and @Transactional annotations in a consistent way with th…
GW1708 Aug 11, 2025
962f622
improved code quality
GW1708 Aug 11, 2025
69695a4
small fixes for bulk status
tbischoff2 Sep 2, 2025
b626fb0
small fixes for create
tbischoff2 Sep 2, 2025
ba6c000
start implementing transactions
tbischoff2 Sep 3, 2025
e027174
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Sep 3, 2025
9006db8
adapt to changes in main, update shells, optimized in-memory backup
tbischoff2 Sep 4, 2025
3497e8c
fixes in BulkOperationControllerIT
tbischoff2 Sep 4, 2025
bd521b9
update test
tbischoff2 Sep 4, 2025
b33ea0b
change test
tbischoff2 Sep 4, 2025
70ff2fe
update test
tbischoff2 Sep 4, 2025
e9d000b
update test
tbischoff2 Sep 5, 2025
1d304ee
update test
tbischoff2 Sep 5, 2025
b66f066
update test
tbischoff2 Sep 5, 2025
c554613
remove sonar warnings
tbischoff2 Sep 5, 2025
0c45dda
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Sep 17, 2025
dfa1b46
limit number of status in store
tbischoff2 Sep 17, 2025
9ec1399
implement JPA transactions
tbischoff2 Sep 18, 2025
b2c618c
implement bulk delete
tbischoff2 Sep 19, 2025
8f740b3
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Sep 22, 2025
018c47d
improve BulkOperationControllerIT
tbischoff2 Sep 23, 2025
4bf19a9
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Sep 25, 2025
b0d1c44
implement Bulk Queue
tbischoff2 Sep 26, 2025
4e23109
implement createSubmodel
tbischoff2 Sep 29, 2025
1c8e066
implement createSubmodel
tbischoff2 Sep 29, 2025
f5e0ef0
refactor handles
tbischoff2 Sep 29, 2025
0bb9a2c
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Oct 21, 2025
5182c86
Bulk Update Submodels
tbischoff2 Oct 21, 2025
2fb3e68
bulk delete submodels
tbischoff2 Oct 21, 2025
8efa968
cleanup
tbischoff2 Oct 21, 2025
59394e4
cleanup
tbischoff2 Oct 22, 2025
7fc2213
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Oct 27, 2025
02659e3
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Oct 28, 2025
2cf5e19
update documentation
tbischoff2 Oct 29, 2025
c7bb6f8
improve error messages
tbischoff2 Nov 3, 2025
e3f81ee
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Nov 3, 2025
7c97b7d
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Nov 3, 2025
5f92028
update changelog.md
tbischoff2 Nov 3, 2025
9f80372
update changelog.md
tbischoff2 Nov 3, 2025
3d8583a
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Nov 19, 2025
010e513
Merge remote-tracking branch 'remotes/origin/main' into feature/bulkO…
tbischoff2 Dec 12, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,37 @@ public interface AasRepository {
* @throws ResourceNotFoundException if the requested resource does not exist
*/
public void deleteSubmodel(String submodelId) throws ResourceNotFoundException;


/**
* Starts a transaction.
*/
public void startTransaction();


/**
* Commits a Transaction.
*/
public void commitTransaction();


/**
* Rollback a Transaction.
*/
public void rollbackTransaction();


/**
* Returns a value indicating whether a transaction is active.
*
* @return True when a transaction is active, false otherwise.
*/
public boolean getTransactionActive();


/**
* Clears the repos and deletes all descriptors.
* Only used for tests!
*/
public void clear();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2021 Fraunhofer IOSB, eine rechtlich nicht selbstaendige
* Einrichtung der Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.fraunhofer.iosb.ilt.faaast.registry.core.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;


/**
* Exception class for bad request.
*/
@ResponseStatus(value = HttpStatus.FORBIDDEN)
public class ForbiddenException extends RuntimeException {

public ForbiddenException() {
super();
}


public ForbiddenException(final String message, final Throwable cause) {
super(message, cause);
}


public ForbiddenException(final String message) {
super(message);
}


public ForbiddenException(final Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2021 Fraunhofer IOSB, eine rechtlich nicht selbstaendige
* Einrichtung der Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.fraunhofer.iosb.ilt.faaast.registry.core.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;


/**
* Exception class for bad request.
*/
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public class InternalServerErrorException extends RuntimeException {

public InternalServerErrorException() {
super();
}


public InternalServerErrorException(final String message, final Throwable cause) {
super(message, cause);
}


public InternalServerErrorException(final String message) {
super(message);
}


public InternalServerErrorException(final Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2021 Fraunhofer IOSB, eine rechtlich nicht selbstaendige
* Einrichtung der Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.fraunhofer.iosb.ilt.faaast.registry.core.exception;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;


/**
* Exception class for completed status request.
*/
@ResponseStatus(value = HttpStatus.FOUND)
public class MovedPermanentlyException extends RuntimeException {
private final HttpHeaders headers;

public MovedPermanentlyException() {
super();
headers = new HttpHeaders();
}


public MovedPermanentlyException(final String message, Exception cause) {
super(message, cause);
headers = new HttpHeaders();
}


public MovedPermanentlyException(final Throwable cause) {
super(cause);
headers = new HttpHeaders();
}


public MovedPermanentlyException(final String message, HttpHeaders headers) {
super(message);
this.headers = headers;
}


public HttpHeaders getHeaders() {
return headers;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2021 Fraunhofer IOSB, eine rechtlich nicht selbstaendige
* Einrichtung der Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.fraunhofer.iosb.ilt.faaast.registry.core.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;


/**
* Exception class for bad request.
*/
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
public class UnauthorizedException extends RuntimeException {

public UnauthorizedException() {
super();
}


public UnauthorizedException(final String message, final Throwable cause) {
super(message, cause);
}


public UnauthorizedException(final String message) {
super(message);
}


public UnauthorizedException(final Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2021 Fraunhofer IOSB, eine rechtlich nicht selbstaendige
* Einrichtung der Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.fraunhofer.iosb.ilt.faaast.registry.core.util;

import java.util.HashMap;
import java.util.Map;
import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.DeserializationException;
import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.SerializationException;
import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.JsonDeserializer;
import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.JsonSerializer;
import org.eclipse.digitaltwin.aas4j.v3.model.Descriptor;


/**
* Helper class with methods to create deep copies.
*/
public class DeepCopyHelper {

private DeepCopyHelper() {}


/**
* Create a deep copy of a list of {@link org.eclipse.digitaltwin.aas4j.v3.model.Descriptor} objects.
*
* @param <T> type of the desriptor.
* @param descriptor which should be deep copied.
* @param outputClass of the referable.
* @return the deep copied descriptor.
*/
public static <T extends Descriptor> T deepCopy(Descriptor descriptor, Class<T> outputClass) {
if (outputClass == null) {
throw new IllegalArgumentException("outputClass must be non-null");
}
if ((descriptor != null) && !outputClass.isAssignableFrom(descriptor.getClass())) {
throw new IllegalArgumentException(
String.format("type mismatch - can not create deep copy of instance of type %s with target type %s", descriptor.getClass(), outputClass));
}
try {
return new JsonDeserializer().read(new JsonSerializer().write(descriptor), outputClass);
}
catch (SerializationException | DeserializationException e) {
throw new IllegalArgumentException("deep copy of descriptor failed", e);
}
}


/**
* Creates a backup of a map of {@link org.eclipse.digitaltwin.aas4j.v3.model.Descriptor} objects.
*
* @param <T> type of the desriptor.
* @param descriptors the descriptor map.
* @return a map with descriptor backups.
*/
public static <T extends Descriptor> Map<String, String> createBackupMap(Map<String, ? extends T> descriptors) {
HashMap<String, String> retval = new HashMap<>();
for (var entry: descriptors.entrySet()) {
retval.put(entry.getKey(), createBackup(entry.getValue()));
}
return retval;
}


/**
* restores a map of {@link org.eclipse.digitaltwin.aas4j.v3.model.Descriptor} objects from a backup map..
*
* @param <T> type of the desriptor.
* @param backupDescriptors the descriptor backup map.
* @param outputClass of the descriptors
* @return a map with the restored descriptors.
*/
public static <T extends Descriptor> Map<String, T> restoreBackupMap(Map<String, String> backupDescriptors, Class<? extends T> outputClass) {
HashMap<String, T> retval = new HashMap<>();
for (var entry: backupDescriptors.entrySet()) {
retval.put(entry.getKey(), restoreBackup(entry.getValue(), outputClass));
}
return retval;
}


private static String createBackup(Descriptor descriptor) {
try {
return new JsonSerializer().write(descriptor);
}
catch (SerializationException e) {
throw new IllegalArgumentException("create backup of descriptor failed", e);
}
}


private static <T extends Descriptor> T restoreBackup(String backupDescriptor, Class<T> outputClass) {
try {
return new JsonDeserializer().read(backupDescriptor, outputClass);
}
catch (DeserializationException e) {
throw new IllegalArgumentException("restore backup of descriptor failed", e);
}
}
}
18 changes: 16 additions & 2 deletions docs/source/api/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ The Registry allows accessing the data via REST-API.

Please be aware, that HTTPS is used.

The Registry uses a configurable API prefix for all API calls. By default, the prefix is "/api/v3.0". The prefix can be changed in the Configuration.

## Supported API calls

- Asset Administration Shell Registry Interface
Expand All @@ -16,12 +18,24 @@ Please be aware, that HTTPS is used.
- /submodel-descriptors ![GET](https://img.shields.io/badge/GET-blue) ![POST](https://img.shields.io/badge/POST-brightgreen)
- /submodel-descriptors/{submodelIdentifier} ![GET](https://img.shields.io/badge/GET-blue) ![PUT](https://img.shields.io/badge/PUT-orange) ![DELETE](https://img.shields.io/badge/DELETE-red)

- Description Interface
- /description ![GET](https://img.shields.io/badge/GET-blue)

- Discovery Interface
- /lookup/shells ![GET](https://img.shields.io/badge/GET-blue)
- /lookup/shells/{aasIdentifier} ![GET](https://img.shields.io/badge/GET-blue) ![POST](https://img.shields.io/badge/POST-orange) ![DELETE](https://img.shields.io/badge/DELETE-red)

- Description Interface
- /description ![GET](https://img.shields.io/badge/GET-blue)
- Async Bulk Asset Administration Shell Registry API
- /bulk/shell-descriptors ![POST](https://img.shields.io/badge/POST-brightgreen) ![PUT](https://img.shields.io/badge/PUT-orange) ![DELETE](https://img.shields.io/badge/DELETE-red)

- Async Bulk Submodel Registry API
- /bulk/submodel-descriptors ![POST](https://img.shields.io/badge/POST-brightgreen) ![PUT](https://img.shields.io/badge/PUT-orange) ![DELETE](https://img.shields.io/badge/DELETE-red)

- Async Bulk Status API
- /bulk/status/{handleId} ![GET](https://img.shields.io/badge/GET-blue)

- Async Bulk Result API
- /bulk/result/{handleId} ![GET](https://img.shields.io/badge/GET-blue)

## Example

Expand Down
5 changes: 3 additions & 2 deletions docs/source/changelog/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

**New Features & Major Changes**
- HTTP
- Add discovery API (v3.0.1)
- Ignore trailing slashes in URLs
- Add discovery API (v3.0.1)
- Ignore trailing slashes in URLs
- Support Async Bulk APIs

**Internal changes & bugfixes**
- General
Expand Down
Loading