From 9d936003e29f594b465f78aa829fa492d481dab9 Mon Sep 17 00:00:00 2001 From: Pierre Villard Date: Mon, 2 Mar 2026 09:49:28 +0100 Subject: [PATCH] NIFI-15670 - Flow import/export with stateful components state Signed-off-by: Pierre Villard --- .../nifi/flow/VersionedComponentState.java | 72 +++++++++++++++++++ .../flow/VersionedConfigurableExtension.java | 10 +++ 2 files changed, 82 insertions(+) create mode 100644 src/main/java/org/apache/nifi/flow/VersionedComponentState.java diff --git a/src/main/java/org/apache/nifi/flow/VersionedComponentState.java b/src/main/java/org/apache/nifi/flow/VersionedComponentState.java new file mode 100644 index 0000000..6b786e9 --- /dev/null +++ b/src/main/java/org/apache/nifi/flow/VersionedComponentState.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.nifi.flow; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +public class VersionedComponentState { + + private Map clusterState; + private List> localNodeStates; + + @Schema(description = "The cluster-scoped state of the component, or null if not exported") + public Map getClusterState() { + return clusterState; + } + + public void setClusterState(final Map clusterState) { + this.clusterState = clusterState; + } + + @Schema(description = "The local-scoped state of the component ordered by node ordinal index, or null if not exported") + public List> getLocalNodeStates() { + return localNodeStates; + } + + public void setLocalNodeStates(final List> localNodeStates) { + this.localNodeStates = localNodeStates; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final VersionedComponentState that = (VersionedComponentState) o; + return Objects.equals(clusterState, that.clusterState) && Objects.equals(localNodeStates, that.localNodeStates); + } + + @Override + public int hashCode() { + return Objects.hash(clusterState, localNodeStates); + } + + @Override + public String toString() { + return "VersionedComponentState[clusterState=%s, localNodeStates=%s]".formatted( + clusterState != null ? clusterState.size() + " entries" : "null", + localNodeStates != null ? localNodeStates.size() + " nodes" : "null"); + } +} diff --git a/src/main/java/org/apache/nifi/flow/VersionedConfigurableExtension.java b/src/main/java/org/apache/nifi/flow/VersionedConfigurableExtension.java index d21059d..236120e 100644 --- a/src/main/java/org/apache/nifi/flow/VersionedConfigurableExtension.java +++ b/src/main/java/org/apache/nifi/flow/VersionedConfigurableExtension.java @@ -28,6 +28,7 @@ public abstract class VersionedConfigurableExtension extends VersionedComponent private Map properties; private Map propertyDescriptors; + private VersionedComponentState componentState; @Override @Schema(description = "The type of the extension component") @@ -74,4 +75,13 @@ public void setPropertyDescriptors(Map prop this.propertyDescriptors = propertyDescriptors; } + @Schema(description = "The state of the component, if exported with state") + public VersionedComponentState getComponentState() { + return componentState; + } + + public void setComponentState(final VersionedComponentState componentState) { + this.componentState = componentState; + } + }