Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update error handling when publishing assets #632

Merged
merged 27 commits into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f91b8da
chore[xxx] updated error handling in publishAssets method
Jan 25, 2024
bea3ac9
chore[xxx] formatted code
Jan 25, 2024
d3f0d02
chore[xxx] added new Exception & renamed method
Jan 25, 2024
34385d6
chore[xxx] added new method saveAssetsInRepository
Jan 25, 2024
86b969d
chore[xxx] added new method checkNoAssetsFound and Test
Jan 25, 2024
0401da3
chore[xxx] updated Method
Jan 30, 2024
c876f85
Merge branch 'main' into chore/xxx-publishAssets
Jan 30, 2024
18ce6cc
chore[xxx] updated Method
Jan 30, 2024
458812a
chore[xxx] fixed sonarcloud issues
Jan 30, 2024
167e618
chore[534] updated test name
Jan 31, 2024
13e48d9
Merge branch 'main' into chore/xxx-publishAssets
ds-lcapellino Feb 1, 2024
f3847fe
chore: refactor PublishServiceImpl
ds-lcapellino Feb 1, 2024
ebc0bcb
chore: map PublishAssetException to HTTP 404
ds-lcapellino Feb 1, 2024
fe0ed27
chore: refactor
ds-lcapellino Feb 1, 2024
dc923f9
chore: update CHANGELOG.md
ds-lcapellino Feb 1, 2024
b474837
feature: 534 improve logging
ds-lcapellino Feb 2, 2024
d027bc6
feature: 534 improve logging
ds-lcapellino Feb 2, 2024
9b270b9
feature: 534 improve logging
ds-lcapellino Feb 2, 2024
5b049a4
Merge pull request #970 from catenax-ng/feature/534-improve-logging
ds-lcapellino Feb 2, 2024
4933623
feature: 534 improve logging
ds-lcapellino Feb 2, 2024
f941671
Merge branch 'main' into chore/xxx-publishAssets
ds-lcapellino Feb 2, 2024
f7319b6
chore: refactor logging, fix merge conflicts
ds-lcapellino Feb 2, 2024
e801237
chore: refactor
ds-lcapellino Feb 5, 2024
1195b57
chore: refactor
ds-lcapellino Feb 5, 2024
9beadab
Merge pull request #946 from catenax-ng/chore/xxx-publishAssets
ds-lcapellino Feb 5, 2024
e2218cd
Update Dependencies Backend Action
ds-lcapellino Feb 5, 2024
6070822
Merge pull request #971 from catenax-ng/action/dependencies
ds-mmaul Feb 5, 2024
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Bumped cypress-io/github-action from 6.6.0 to 6.6.1
- Bumped tj-actions/changed-files from v41 to v42
- Fixed some response type descriptions within swagger documentation
- Error handling when publishing assets

### Removed

Expand Down
2 changes: 1 addition & 1 deletion DEPENDENCIES_FRONTEND
Original file line number Diff line number Diff line change
Expand Up @@ -1204,7 +1204,7 @@ npm/npmjs/@angular/compiler/16.2.12, MIT, approved, clearlydefined
npm/npmjs/@angular/core/16.2.12, MIT, approved, clearlydefined
npm/npmjs/@angular/forms/16.2.12, MIT, approved, clearlydefined
npm/npmjs/@angular/language-service/16.2.12, MIT AND Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND ISC AND Unlicense AND CC-BY-4.0 AND LicenseRef-Public-domain, approved, #11035
npm/npmjs/@angular/material/16.2.13, , restricted, clearlydefined
npm/npmjs/@angular/material/16.2.13, MIT, restricted, clearlydefined
npm/npmjs/@angular/platform-browser-dynamic/16.2.12, MIT, approved, clearlydefined
npm/npmjs/@angular/platform-browser/16.2.12, MIT, approved, clearlydefined
npm/npmjs/@angular/router/16.2.12, MIT, approved, clearlydefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,12 @@ public class ImportController {

@PostMapping(value = "/import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ImportResponse> importJson(@RequestPart("file") MultipartFile file) {
log.info("Received request to import assets.");
List<String> jsonSchemaErrors = jsonFileValidator.isValid(file);
ValidationResponse validationResponse = new ValidationResponse(jsonSchemaErrors);

if (!jsonSchemaErrors.isEmpty()) {
log.warn("Asset import request cannot be processed. Errors: {}", validationResponse);
return ResponseEntity
.badRequest()
.body(new ImportResponse(validationResponse));
Expand All @@ -155,6 +157,7 @@ public ResponseEntity<ImportResponse> importJson(@RequestPart("file") MultipartF
assetBaseSet.getValue())
).toList();

log.info("Successfully imported {} assets.", importStateMessages.size());
ImportResponse importResponse = new ImportResponse(importStateMessages);

return ResponseEntity.ok(importResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public interface AssetRepository {

List<AssetBase> getAssetsById(List<String> assetIds);

boolean existsById(String assetId);

AssetBase getAssetByChildId(String childId);

List<AssetBase> getAssets();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/********************************************************************************
* Copyright (c) 2023, 2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://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.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
package org.eclipse.tractusx.traceability.assets.domain.importpoc.exception;

public class PublishAssetException extends RuntimeException {
public PublishAssetException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2023 Contributors to the Eclipse Foundation
* Copyright (c) 2023,2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -23,11 +23,15 @@
import org.eclipse.tractusx.traceability.assets.application.importpoc.PublishService;
import org.eclipse.tractusx.traceability.assets.domain.asbuilt.repository.AssetAsBuiltRepository;
import org.eclipse.tractusx.traceability.assets.domain.asplanned.repository.AssetAsPlannedRepository;
import org.eclipse.tractusx.traceability.assets.domain.base.AssetRepository;
import org.eclipse.tractusx.traceability.assets.domain.base.model.AssetBase;
import org.eclipse.tractusx.traceability.assets.domain.base.model.ImportState;
import org.eclipse.tractusx.traceability.assets.domain.importpoc.exception.PublishAssetException;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;


@Slf4j
@RequiredArgsConstructor
Expand All @@ -40,18 +44,40 @@ public class PublishServiceImpl implements PublishService {
@Override
public void publishAssets(String policyId, List<String> assetIds) {
//Update assets with policy id
List<AssetBase> assetAsPlannedList = assetAsPlannedRepository.getAssetsById(assetIds).stream()
.filter(assetAsPlanned -> ImportState.TRANSIENT.equals(assetAsPlanned.getImportState()))
.peek(assetAsPlanned -> assetAsPlanned.setImportState(ImportState.IN_SYNCHRONIZATION))
.peek(assetAsPlanned -> assetAsPlanned.setPolicyId(policyId))
.toList();
assetAsPlannedRepository.saveAll(assetAsPlannedList);

List<AssetBase> assetAsBuiltList = assetAsBuiltRepository.getAssetsById(assetIds).stream()
.filter(assetAsBuilt -> ImportState.TRANSIENT.equals(assetAsBuilt.getImportState()))
.peek(assetAsBuilt -> assetAsBuilt.setImportState(ImportState.IN_SYNCHRONIZATION))
.peek(assetAsBuilt -> assetAsBuilt.setPolicyId(policyId))
.toList();
assetAsBuiltRepository.saveAll(assetAsBuiltList);
assetIds.forEach(this::throwIfNotExists);

log.info("Updating status of asPlannedAssets.");
updateAssetWithStatusAndPolicy(policyId, assetIds, assetAsPlannedRepository);
log.info("Updating status of asBuiltAssets.");
updateAssetWithStatusAndPolicy(policyId, assetIds, assetAsBuiltRepository);
}
private void throwIfNotExists(String assetId) {
if (!(assetAsBuiltRepository.existsById(assetId) || assetAsPlannedRepository.existsById(assetId))) {
throw new PublishAssetException("No asset found with the provided ID: " + assetId);
}
}


private void updateAssetWithStatusAndPolicy(String policyId, List<String> assetIds, AssetRepository repository) {
List<AssetBase> assetList = repository.getAssetsById(assetIds);
List<AssetBase> saveList = assetList.stream()
.filter(this::validTransientState)
.map(asset -> {
asset.setImportState(ImportState.IN_SYNCHRONIZATION);
asset.setPolicyId(policyId);
return asset;
}).toList();

List<AssetBase> assetBases = repository.saveAll(saveList);

log.info("Successfully set {} in status IN_SYNCHRONIZATION", assetBases.stream().map(AssetBase::getId).collect(Collectors.joining(", ")));
}

private boolean validTransientState(AssetBase assetBase) {
if (ImportState.TRANSIENT.equals(assetBase.getImportState())) {
return true;
}
throw new PublishAssetException("Asset with ID " + assetBase.getId() + " is not in TRANSIENT state.");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ public AssetBase getAssetById(String assetId) {
.orElseThrow(() -> new AssetNotFoundException("Asset with id %s was not found.".formatted(assetId)));
}

@Override
@Transactional
public boolean existsById(String assetId) {
return jpaAssetAsBuiltRepository.existsById(assetId);
}

@Override
public List<AssetBase> getAssetsById(List<String> assetIds) {
return jpaAssetAsBuiltRepository.findByIdIn(assetIds).stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public AssetBase getAssetById(String assetId) {
.orElseThrow(() -> new AssetNotFoundException("Asset with id %s was not found.".formatted(assetId)));
}

@Override
@Transactional
public boolean existsById(String assetId) {
return jpaAssetAsPlannedRepository.existsById(assetId);
}

@Override
public List<AssetBase> getAssetsById(List<String> assetIds) {
return jpaAssetAsPlannedRepository.findByIdIn(assetIds).stream().map(AssetAsPlannedEntity::toDomain)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.eclipse.tractusx.traceability.assets.application.importpoc.validation.exception.JsonFileProcessingException;
import org.eclipse.tractusx.traceability.assets.domain.asbuilt.exception.AssetNotFoundException;
import org.eclipse.tractusx.traceability.assets.domain.importpoc.exception.ImportException;
import org.eclipse.tractusx.traceability.assets.domain.importpoc.exception.PublishAssetException;
import org.eclipse.tractusx.traceability.bpn.domain.model.BpnNotFoundException;
import org.eclipse.tractusx.traceability.common.domain.ParseLocalDateException;
import org.eclipse.tractusx.traceability.common.model.UnsupportedSearchCriteriaFieldException;
Expand Down Expand Up @@ -110,6 +111,13 @@ ResponseEntity<ErrorResponse> handleAssetNotFoundException(AssetNotFoundExceptio
.body(new ErrorResponse(exception.getMessage()));
}

@ExceptionHandler(PublishAssetException.class)
ResponseEntity<ErrorResponse> handlePublishAssetException(PublishAssetException exception) {
log.warn("handlePublishAssetException", exception);
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ErrorResponse(exception.getMessage()));
}

@ExceptionHandler(ImportException.class)
ResponseEntity<ErrorResponse> handleImportException(ImportException exception) {
log.warn("handleImportException", exception);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

class ImportControllerIT extends IntegrationTestSpecification {

Expand Down Expand Up @@ -397,4 +399,38 @@ void givenValidFile_whenPublishData_thenStatusShouldChangeToInSynchronization()
assertThat(ImportState.IN_SYNCHRONIZATION).isEqualTo(asset.getImportState());

}

@Test
void givenInvalidAssetID_whenPublishData_thenStatusCode404() throws JoseException {
// given
String path = getClass().getResource("/testdata/importfiles/validImportFile.json").getFile();
File file = new File(path);

given()
.header(oAuth2Support.jwtAuthorization(JwtRole.ADMIN))
.when()
.multiPart(file)
.post("/api/assets/import")
.then()
.statusCode(200)
.extract().as(ImportResponse.class);

RegisterAssetRequest registerAssetRequest = new RegisterAssetRequest("Trace-X policy", List.of("test", "urn:uuid:254604ab-2153-45fb-8cad-54ef09f4080f"));


// when
given()
.header(oAuth2Support.jwtAuthorization(JwtRole.ADMIN))
.contentType(ContentType.JSON)
.when()
.body(registerAssetRequest)
.post("/api/assets/publish")
.then()
.statusCode(404);

//then
AssetBase asset = assetAsBuiltRepository.getAssetById("urn:uuid:254604ab-2153-45fb-8cad-54ef09f4080f");
assertNull(asset.getPolicyId());
assertEquals(asset.getImportState(), ImportState.TRANSIENT);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2023 Contributors to the Eclipse Foundation
* Copyright (c) 2023, 2024 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
Expand All @@ -26,4 +26,5 @@ public record ValidationResponse(List<String> validationErrors) {
public static ValidationResponse emptyValidationResult() {
return new ValidationResponse(List.of());
}

}
Loading