fix(registry): prevent NullPointerException when specificAssetIds is null in DiscoveryIntegrationAasRegistry#887
Conversation
…null in DiscoveryIntegrationAasRegistry
There was a problem hiding this comment.
Pull Request Overview
This PR fixes a NullPointerException in the Digital Twin Registry that occurred when posting or replacing AAS descriptors without specificAssetIds. The fix adds defensive null checks and early return guards to prevent the application from crashing with HTTP 500 errors.
Key Changes:
- Added null safety checks for
specificAssetIdsin bothinsertAasDescriptor()andreplaceAasDescriptor()methods - Implemented early return pattern when identifiers are missing, with appropriate debug logging
- Added cleanup logic to remove existing discovery links when replacing descriptors with no identifiers
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| if (ids == null || ids.isEmpty()) { | ||
| log.debug("No specificAssetIds present for AAS '{}', skipping discovery integration update", aasDescriptorId); | ||
| discoveryApi.deleteAllAssetLinksById(aasDescriptorId); | ||
| return; | ||
| } |
There was a problem hiding this comment.
The cleanup logic deleteAllAssetLinksById() is only executed in replaceAasDescriptor() when ids are null/empty, but not in insertAasDescriptor(). This asymmetry could lead to inconsistent behavior. Consider documenting why cleanup is needed only during replacement, or ensure both methods handle the absence of identifiers consistently.
There was a problem hiding this comment.
The cleanup call to deleteAllAssetLinksById() is intentionally omitted in insertAasDescriptor().
When inserting a new AAS descriptor, the registry guarantees that the descriptor ID is unique and does not already exist in the system. Any attempt to insert a duplicate descriptor results in an HTTP 409 Conflict, preventing residual or stale discovery links from ever being created.
As a result, there is no need to perform a cleanup of discovery links during insertion — such links cannot exist yet.
In contrast, replaceAasDescriptor() explicitly handles cleanup to ensure that any previously registered discovery links are removed when an existing descriptor is updated or replaced with one that no longer contains identifiers.
This intentional asymmetry avoids redundant API calls and ensures consistent behavior while maintaining efficiency and clarity in the discovery integration process.
Furthermore, the internal implementation of the discovery service throws a 404 Not Found error if an attempt is made to delete non-existent links.
Including a deletion call during insertion would therefore generate unnecessary 404 responses and misleading log entries, implying a missing or inconsistent discovery state.
By omitting the cleanup step in insertAasDescriptor(), the registry avoids this confusion and keeps the integration behavior semantically correct.
fix(registry): add null safety for descriptor, and specificAssetIds in DiscoveryIntegrationAasRegistry
Description of Changes
This pull request fixes a
NullPointerExceptionthat occurred in the Digital Twin Registry when posting or replacing an AAS descriptor without providingspecificAssetIds.Root Cause
In the class
org.eclipse.digitaltwin.basyx.aasregistry.feature.discovery.integration.DiscoveryIntegrationAasRegistry,both
insertAasDescriptor()andreplaceAasDescriptor()methods called:without verifying whether
descr,globalAssetId, orspecificAssetIdswerenull.When an incoming AAS descriptor did not include these fields, the application threw a
NullPointerExceptionand returned HTTP 500 instead of the expected HTTP 201 Created.Solution Implemented
specificAssetIdslistspecificAssetIdsare missing.specificAssetIdsusingList.of()to avoid null propagation.This ensures that:
Related Issue
[BUG] DTR responds with HTTP500 on valid request #886
Closes #886
BaSyx Configuration for Testing
The issue and fix were verified using a local Docker setup:
No additional configuration required.
Test Procedure
AAS Files Used for Testing
No AAS files required — testing performed via REST API requests with minimal descriptor payloads such as:
{ "id": "simple-shell" }Optional verification with descriptor including asset identifiers:
{ "id": "urn:uuid:e5c96ab5-896a-1234-8761-efd74777ca97", "idShort": "myAas", "specificAssetIds": [ { "name": "manufacturerPartId", "value": "123-345-567103" } ], "submodelDescriptors": [ { "id": "e5c96ab5-896a-482c-8761-efd74777ca97", "semanticId": { "type": "ExternalReference", "keys": [ { "type": "GlobalReference", "value": "urn:bamm:io.catenax.material_for_recycling:1.1.0#MaterialForRecycling" } ] }, "endpoints": [ { "interface": "SUBMODEL-3.0", "protocolInformation": { "href": "https://edc.data.plane/mypath/submodel", "endpointProtocol": "HTTP", "endpointProtocolVersion": [ "1.1" ], "subprotocol": "DSP", "subprotocolBody": "id=123;dspEndpoint=http://edc.control.plane/api/v1/dsp", "subprotocolBodyEncoding": "plain", "securityAttributes": [ { "type": "NONE", "key": "NONE", "value": "NONE" } ] } } ] } ] }Both payloads confirm stable operation with and without identifiers.
Additional Information
DiscoveryIntegrationUtils) to encapsulate the null-safe extraction and mapping logic, reducing duplication across registry methods.✅ Tested environments: