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) &&

Reply via email to