This is an automated email from the ASF dual-hosted git repository. JHoelli pushed a commit to branch marking_pipeline_falsely_as_rewuire_attention in repository https://gitbox.apache.org/repos/asf/streampipes.git
commit db93aabc5dc63cdda8fe63677066dda55773d4b9 Author: Jacqueline Höllig <[email protected]> AuthorDate: Mon Nov 2 09:59:35 2026 +0100 pop up and status --- .../streampipes/rest/impl/PipelineResource.java | 8 ++++ .../components/pipeline/pipeline.component.ts | 54 +++++++++++++++------- .../editor/services/pipeline-validation.service.ts | 20 +++++++- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineResource.java index d4513a9ad4..bd114638a9 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineResource.java @@ -24,6 +24,7 @@ import org.apache.streampipes.commons.exceptions.NoSuitableSepasAvailableExcepti import org.apache.streampipes.manager.api.extensions.ExtensionServiceRequestManager; import org.apache.streampipes.manager.execution.status.PipelineStatusManager; import org.apache.streampipes.manager.matching.PipelineVerificationHandlerV2; +import org.apache.streampipes.manager.matching.output.OutputSchemaUnavailableException; import org.apache.streampipes.manager.pipeline.PipelineEditChanges; import org.apache.streampipes.manager.pipeline.PipelineManager; import org.apache.streampipes.manager.pipeline.compact.CompactPipelineManagement; @@ -286,6 +287,13 @@ public class PipelineResource extends AbstractAuthGuardedRestResource { public ResponseEntity<?> validatePipeline(@RequestBody Pipeline pipeline) { try { return ok(new PipelineVerificationHandlerV2(resourceManager.getServiceDiscovery(), pipeline, requestManager).verifyPipeline()); + } catch (OutputSchemaUnavailableException e) { + LOG.warn("Could not validate pipeline because the output schema for {} is unavailable", e.getAppId(), e); + return serverError(new Notification( + "Extension unavailable", + "Pipeline validation requires an extension that is currently unavailable.", + e.getAppId() + )); } catch (JsonSyntaxException e) { return badRequest(new Notification(NotificationType.UNKNOWN_ERROR, e.getMessage())); } catch (Exception e) { diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.ts b/ui/src/app/editor/components/pipeline/pipeline.component.ts index 2ee290631e..ca84474d63 100644 --- a/ui/src/app/editor/components/pipeline/pipeline.component.ts +++ b/ui/src/app/editor/components/pipeline/pipeline.component.ts @@ -75,6 +75,7 @@ import { } from '@jsplumb/browser-ui'; import { PipelineStyleService } from '../../services/pipeline-style.service'; import { IdGeneratorService } from '../../../core-services/id-generator/id-generator.service'; +import { HttpErrorResponse } from '@angular/common/http'; import { NgStyle } from '@angular/common'; import { StyleDirective } from '@ngbracket/ngx-layout/extended'; import { DroppedPipelineElementComponent } from './dropped-pipeline-element/dropped-pipeline-element.component'; @@ -485,10 +486,7 @@ export class PipelineComponent implements OnInit, OnDestroy { }, status => { pe.settings.loadingStatus = false; - this.showErrorDialog( - status.error.title, - status.error.description, - ); + this.handlePipelineValidationFailure(status); }, ); } @@ -590,6 +588,22 @@ export class PipelineComponent implements OnInit, OnDestroy { }); } + private handlePipelineValidationFailure(status: HttpErrorResponse): void { + const error = status.error as Notification; + const title = error?.title ?? 'Pipeline validation failed'; + const description = error?.description ?? status.message; + const summaryDescription = error?.additionalInformation + ? `${description} (${error.additionalInformation})` + : description; + + this.pipelineValidationService.reportRemoteValidationFailure( + title, + summaryDescription, + ); + this.pipelineValid = false; + this.showErrorDialog(title, description); + } + showMatchingErrorDialog(notifications: Notification[]) { this.dialogService.open(MatchingErrorComponent, { panelType: PanelType.STANDARD_PANEL, @@ -620,15 +634,20 @@ export class PipelineComponent implements OnInit, OnDestroy { ); this.objectProvider .updatePipeline(this.currentPipelineModel) - .subscribe(pm => { - this.modifyPipeline(pm); - this.triggerPipelineCacheUpdateEmitter.emit(); - this.announceConfiguredElement(pipelineElementConfig); - if (this.previewModeActive) { - this.deletePreviewEmitter.emit(true); - } - this.validatePipeline(pm); - }); + .subscribe( + pm => { + this.modifyPipeline(pm); + this.triggerPipelineCacheUpdateEmitter.emit(); + this.announceConfiguredElement( + pipelineElementConfig, + ); + if (this.previewModeActive) { + this.deletePreviewEmitter.emit(true); + } + this.validatePipeline(pm); + }, + status => this.handlePipelineValidationFailure(status), + ); } else { this.validatePipeline(); } @@ -643,9 +662,8 @@ export class PipelineComponent implements OnInit, OnDestroy { this.currentPipelineModel = this.objectProvider.makePipeline( this.rawPipelineModel, ); - this.objectProvider - .updatePipeline(this.currentPipelineModel) - .subscribe(pm => { + this.objectProvider.updatePipeline(this.currentPipelineModel).subscribe( + pm => { this.modifyPipeline(pm); this.pipelineValid = this.pipelineValidationService.isValidPipeline( @@ -653,7 +671,9 @@ export class PipelineComponent implements OnInit, OnDestroy { this.readonly, pm, ); - }); + }, + status => this.handlePipelineValidationFailure(status), + ); } openTopicsDialog(pipelineElementConfig: PipelineElementConfig) { diff --git a/ui/src/app/editor/services/pipeline-validation.service.ts b/ui/src/app/editor/services/pipeline-validation.service.ts index f6eb6c97b3..5da39ab479 100644 --- a/ui/src/app/editor/services/pipeline-validation.service.ts +++ b/ui/src/app/editor/services/pipeline-validation.service.ts @@ -36,8 +36,9 @@ import { Connection } from '@jsplumb/browser-ui'; export class PipelineValidationService { private jsplumbFactoryService = inject(JsplumbFactoryService); - errorMessages: any = []; + errorMessages: UserErrorMessage[] = []; pipelineValid = false; + private remoteValidationErrors: UserErrorMessage[] = []; availableErrorMessages: UserErrorMessage[] = [ new UserErrorMessage( @@ -71,6 +72,9 @@ export class PipelineValidationService { previewConfig: boolean, pm?: PipelineModificationMessage, ) { + if (pm) { + this.remoteValidationErrors = []; + } const jsplumbBridge = this.jsplumbFactoryService.getJsplumbBridge(previewConfig); const streamInAssembly = this.isStreamInAssembly(rawPipelineModel); @@ -112,17 +116,29 @@ export class PipelineValidationService { this.errorMessages.push(this.availableErrorMessages[5]); } + this.errorMessages.push(...this.remoteValidationErrors); + this.pipelineValid = streamInAssembly && actionInAssembly && allElementsConnected && onlyOnePipelineCreated && allElementsConfigured && - (pm ? pm.pipelineValid : true); + (pm ? pm.pipelineValid : true) && + this.remoteValidationErrors.length === 0; return this.pipelineValid; } + reportRemoteValidationFailure(title: string, content: string): void { + this.remoteValidationErrors = [new UserErrorMessage(title, content)]; + this.errorMessages = [ + ...this.errorMessages, + ...this.remoteValidationErrors, + ]; + this.pipelineValid = false; + } + isEmptyPipeline(rawPipelineModel) { return ( !this.isActionInAssembly(rawPipelineModel) &&
