This is an automated email from the ASF dual-hosted git repository.

mcgilman pushed a commit to branch NIFI-15326
in repository https://gitbox.apache.org/repos/asf/nifi.git

commit 24cd6283be1d38c4c9eacdd25be15c0477d85650
Author: Matt Gilman <[email protected]>
AuthorDate: Thu Dec 11 09:16:07 2025 -0500

    NIFI-15326: Adding support of configuration step documentation.
    NIFI-15322: Adapting to new connector configuration step model.
---
 .../connectors/kafkas3/KafkaConnectionStep.java    | 32 ++++++++
 .../api/dto/ConfigurationStepConfigurationDTO.java | 13 +++
 .../org/apache/nifi/audit/ConnectorAuditor.java    | 94 ++++++++--------------
 .../org/apache/nifi/web/NiFiServiceFacade.java     |  5 +-
 .../apache/nifi/web/StandardNiFiServiceFacade.java |  8 +-
 .../org/apache/nifi/web/api/ConnectorResource.java |  5 +-
 .../org/apache/nifi/web/api/dto/DtoFactory.java    | 29 ++++---
 .../org/apache/nifi/web/api/dto/EntityFactory.java |  3 +-
 .../java/org/apache/nifi/web/dao/ConnectorDAO.java |  5 +-
 .../nifi/web/dao/impl/StandardConnectorDAO.java    | 53 +++++-------
 .../web/dao/impl/StandardConnectorDAOTest.java     | 27 +++----
 11 files changed, 137 insertions(+), 137 deletions(-)

diff --git 
a/nifi-connectors/nifi-kafka-to-s3-bundle/nifi-kafka-to-s3-connector/src/main/java/org/apache/nifi/connectors/kafkas3/KafkaConnectionStep.java
 
b/nifi-connectors/nifi-kafka-to-s3-bundle/nifi-kafka-to-s3-connector/src/main/java/org/apache/nifi/connectors/kafkas3/KafkaConnectionStep.java
index 793b1e9be0d..22ae253a98f 100644
--- 
a/nifi-connectors/nifi-kafka-to-s3-bundle/nifi-kafka-to-s3-connector/src/main/java/org/apache/nifi/connectors/kafkas3/KafkaConnectionStep.java
+++ 
b/nifi-connectors/nifi-kafka-to-s3-bundle/nifi-kafka-to-s3-connector/src/main/java/org/apache/nifi/connectors/kafkas3/KafkaConnectionStep.java
@@ -29,6 +29,37 @@ import java.util.List;
 public class KafkaConnectionStep {
     public static final String STEP_NAME = "Kafka Connection";
 
+    // Temporary documentation to verify the inline documentation feature in 
the UI.
+    // In practice, this content should probably be loaded from an external 
file.
+    private static final String KAFKA_CONNECTION_DOCUMENTATION = """
+        # Kafka Connection Configuration
+
+        This step configures the connection to your Apache Kafka cluster.
+
+        ## Kafka Server Settings
+
+        Enter the bootstrap servers for your Kafka cluster. You can specify 
multiple brokers
+        as a comma-separated list (e.g., 
`broker1:9092,broker2:9092,broker3:9092`).
+
+        ### Security Configuration
+
+        Select the appropriate security protocol based on your Kafka cluster 
configuration:
+
+        | Protocol | Description |
+        |----------|-------------|
+        | PLAINTEXT | No encryption or authentication |
+        | SSL | TLS encryption without SASL authentication |
+        | SASL_PLAINTEXT | SASL authentication without encryption |
+        | SASL_SSL | Both SASL authentication and TLS encryption (recommended) 
|
+
+        If using SASL authentication, provide your username and password 
credentials.
+
+        ## Schema Registry (Optional)
+
+        If your Kafka topics use Avro, Protobuf, or JSON Schema, configure the 
Schema Registry
+        URL to enable schema-based serialization and deserialization.
+        """;
+
     public static final ConnectorPropertyDescriptor KAFKA_BROKERS = new 
ConnectorPropertyDescriptor.Builder()
         .name("Kafka Brokers")
         .description("A comma-separated list of Kafka brokers to connect to.")
@@ -127,6 +158,7 @@ public class KafkaConnectionStep {
     public static final ConfigurationStep KAFKA_CONNECTION_STEP = new 
ConfigurationStep.Builder()
         .name(STEP_NAME)
         .description("Configure Kafka connection settings")
+        .documentation(KAFKA_CONNECTION_DOCUMENTATION)
         .propertyGroups(List.of(
             KAFKA_SERVER_GROUP,
             SCHEMA_REGISTRY_GROUP
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ConfigurationStepConfigurationDTO.java
 
b/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ConfigurationStepConfigurationDTO.java
index 9dd55b524c1..94b0c7ff710 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ConfigurationStepConfigurationDTO.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ConfigurationStepConfigurationDTO.java
@@ -29,6 +29,7 @@ public class ConfigurationStepConfigurationDTO {
 
     private String configurationStepName;
     private String configurationStepDescription;
+    private String configurationStepDocumentation;
     private List<PropertyGroupConfigurationDTO> propertyGroupConfigurations;
 
     /**
@@ -55,6 +56,18 @@ public class ConfigurationStepConfigurationDTO {
         this.configurationStepDescription = configurationStepDescription;
     }
 
+    /**
+     * @return the configuration step documentation in markdown
+     */
+    @Schema(description = "Extended documentation or help text for the 
configuration step.")
+    public String getConfigurationStepDocumentation() {
+        return configurationStepDocumentation;
+    }
+
+    public void setConfigurationStepDocumentation(final String 
configurationStepDocumentation) {
+        this.configurationStepDocumentation = configurationStepDocumentation;
+    }
+
     /**
      * @return the property group configurations
      */
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ConnectorAuditor.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ConnectorAuditor.java
index 18785143dcf..e26e0d2aa3b 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ConnectorAuditor.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ConnectorAuditor.java
@@ -24,13 +24,13 @@ import 
org.apache.nifi.action.component.details.FlowChangeExtensionDetails;
 import org.apache.nifi.action.details.ActionDetails;
 import org.apache.nifi.action.details.FlowChangeConfigureDetails;
 import org.apache.nifi.components.connector.AssetReference;
-import org.apache.nifi.components.connector.ConfigurationStepConfiguration;
 import org.apache.nifi.components.connector.ConnectorConfiguration;
 import org.apache.nifi.components.connector.ConnectorNode;
 import org.apache.nifi.components.connector.ConnectorState;
 import org.apache.nifi.components.connector.ConnectorValueReference;
-import org.apache.nifi.components.connector.PropertyGroupConfiguration;
+import org.apache.nifi.components.connector.NamedStepConfiguration;
 import org.apache.nifi.components.connector.SecretReference;
+import org.apache.nifi.components.connector.StepConfiguration;
 import org.apache.nifi.components.connector.StringLiteralValue;
 import org.apache.nifi.web.api.dto.ConfigurationStepConfigurationDTO;
 import org.apache.nifi.web.api.dto.ConnectorValueReferenceDTO;
@@ -224,17 +224,14 @@ public class ConnectorAuditor extends NiFiAuditor {
                                               final 
ConfigurationStepConfigurationDTO configurationStepConfiguration, final 
ConnectorDAO connectorDAO) throws Throwable {
         final ConnectorNode connector = connectorDAO.getConnector(connectorId);
 
-        // Capture the current property values before the update
-        final Map<String, Map<String, String>> previousValues = 
extractCurrentPropertyValues(connector, configurationStepName);
+        // Capture the current property values before the update (flat map: 
property name -> value)
+        final Map<String, String> previousValues = 
extractCurrentPropertyValues(connector, configurationStepName);
 
         proceedingJoinPoint.proceed();
 
         if (isAuditable()) {
-            // Extract the new property values from the DTO
-            final Map<String, Map<String, String>> newValues = 
extractPropertyValuesFromDto(configurationStepConfiguration);
-
-            // Generate audit actions for each changed property
-            final List<Action> actions = 
generateConfigurationChangeActions(connector, configurationStepName, 
previousValues, newValues);
+            // Generate audit actions for each changed property, using the DTO 
for group structure
+            final List<Action> actions = 
generateConfigurationChangeActions(connector, configurationStepName, 
previousValues, configurationStepConfiguration);
             if (!actions.isEmpty()) {
                 saveActions(actions, logger);
             }
@@ -246,23 +243,17 @@ public class ConnectorAuditor extends NiFiAuditor {
      *
      * @param connector the connector node
      * @param configurationStepName the name of the configuration step
-     * @return a map of property group name to property name to property value
+     * @return a map of property name to property value
      */
-    private Map<String, Map<String, String>> 
extractCurrentPropertyValues(final ConnectorNode connector, final String 
configurationStepName) {
-        final Map<String, Map<String, String>> result = new HashMap<>();
+    private Map<String, String> extractCurrentPropertyValues(final 
ConnectorNode connector, final String configurationStepName) {
+        final Map<String, String> result = new HashMap<>();
 
         final ConnectorConfiguration configuration = 
connector.getWorkingFlowContext().getConfigurationContext().toConnectorConfiguration();
-        for (final ConfigurationStepConfiguration stepConfig : 
configuration.getConfigurationStepConfigurations()) {
-            if (Objects.equals(stepConfig.stepName(), configurationStepName)) {
-                for (final PropertyGroupConfiguration groupConfig : 
stepConfig.propertyGroupConfigurations()) {
-                    final String groupName = groupConfig.groupName();
-                    final Map<String, String> propertyValues = new HashMap<>();
-
-                    for (final Map.Entry<String, ConnectorValueReference> 
entry : groupConfig.propertyValues().entrySet()) {
-                        propertyValues.put(entry.getKey(), 
formatValueReference(entry.getValue()));
-                    }
-
-                    result.put(groupName, propertyValues);
+        for (final NamedStepConfiguration namedStepConfig : 
configuration.getNamedStepConfigurations()) {
+            if (Objects.equals(namedStepConfig.stepName(), 
configurationStepName)) {
+                final StepConfiguration stepConfig = 
namedStepConfig.configuration();
+                for (final Map.Entry<String, ConnectorValueReference> entry : 
stepConfig.getPropertyValues().entrySet()) {
+                    result.put(entry.getKey(), 
formatValueReference(entry.getValue()));
                 }
                 break;
             }
@@ -271,33 +262,6 @@ public class ConnectorAuditor extends NiFiAuditor {
         return result;
     }
 
-    /**
-     * Extracts property values from the configuration step DTO.
-     *
-     * @param configurationStepDto the configuration step DTO
-     * @return a map of property group name to property name to property value
-     */
-    private Map<String, Map<String, String>> 
extractPropertyValuesFromDto(final ConfigurationStepConfigurationDTO 
configurationStepDto) {
-        final Map<String, Map<String, String>> result = new HashMap<>();
-
-        if (configurationStepDto.getPropertyGroupConfigurations() != null) {
-            for (final PropertyGroupConfigurationDTO groupDto : 
configurationStepDto.getPropertyGroupConfigurations()) {
-                final String groupName = groupDto.getPropertyGroupName();
-                final Map<String, String> propertyValues = new HashMap<>();
-
-                if (groupDto.getPropertyValues() != null) {
-                    for (final Map.Entry<String, ConnectorValueReferenceDTO> 
entry : groupDto.getPropertyValues().entrySet()) {
-                        propertyValues.put(entry.getKey(), 
formatValueReferenceDto(entry.getValue()));
-                    }
-                }
-
-                result.put(groupName, propertyValues);
-            }
-        }
-
-        return result;
-    }
-
     /**
      * Formats a ConnectorValueReference as a string for audit logging.
      *
@@ -340,33 +304,39 @@ public class ConnectorAuditor extends NiFiAuditor {
     }
 
     /**
-     * Generates audit actions for configuration changes by comparing previous 
and new values.
+     * Generates audit actions for configuration changes by comparing previous 
values with the new values from the DTO.
      *
      * @param connector the connector node
      * @param configurationStepName the configuration step name
-     * @param previousValues the previous property values
-     * @param newValues the new property values
+     * @param previousValues the previous property values (flat map: property 
name -> value)
+     * @param configurationStepDto the configuration step DTO containing new 
values with group structure
      * @return list of actions for changed properties
      */
     private List<Action> generateConfigurationChangeActions(final 
ConnectorNode connector, final String configurationStepName,
-                                                            final Map<String, 
Map<String, String>> previousValues, final Map<String, Map<String, String>> 
newValues) {
+                                                            final Map<String, 
String> previousValues, final ConfigurationStepConfigurationDTO 
configurationStepDto) {
         final List<Action> actions = new ArrayList<>();
         final Date timestamp = new Date();
 
         final FlowChangeExtensionDetails connectorDetails = new 
FlowChangeExtensionDetails();
         connectorDetails.setType(connector.getComponentType());
 
-        // Iterate through all property groups in the new values
-        for (final Map.Entry<String, Map<String, String>> groupEntry : 
newValues.entrySet()) {
-            final String groupName = groupEntry.getKey();
-            final Map<String, String> newGroupValues = groupEntry.getValue();
-            final Map<String, String> previousGroupValues = 
previousValues.getOrDefault(groupName, new HashMap<>());
+        if (configurationStepDto.getPropertyGroupConfigurations() == null) {
+            return actions;
+        }
+
+        // Iterate through all property groups in the DTO to preserve group 
names for audit logging
+        for (final PropertyGroupConfigurationDTO groupDto : 
configurationStepDto.getPropertyGroupConfigurations()) {
+            final String groupName = groupDto.getPropertyGroupName();
+
+            if (groupDto.getPropertyValues() == null) {
+                continue;
+            }
 
             // Check each property in this group
-            for (final Map.Entry<String, String> propertyEntry : 
newGroupValues.entrySet()) {
+            for (final Map.Entry<String, ConnectorValueReferenceDTO> 
propertyEntry : groupDto.getPropertyValues().entrySet()) {
                 final String propertyName = propertyEntry.getKey();
-                final String newValue = propertyEntry.getValue();
-                final String previousValue = 
previousGroupValues.get(propertyName);
+                final String newValue = 
formatValueReferenceDto(propertyEntry.getValue());
+                final String previousValue = previousValues.get(propertyName);
 
                 // Only create an action if the value changed
                 if (!Objects.equals(previousValue, newValue)) {
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
index f32a9924b73..aee15d1c45e 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/NiFiServiceFacade.java
@@ -82,9 +82,8 @@ import org.apache.nifi.web.api.dto.PropertyDescriptorDTO;
 import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
 import org.apache.nifi.web.api.dto.RemoteProcessGroupPortDTO;
 import org.apache.nifi.web.api.dto.ReportingTaskDTO;
-import org.apache.nifi.web.api.dto.ConnectorDTO;
 import org.apache.nifi.web.api.dto.ConfigurationStepConfigurationDTO;
-import org.apache.nifi.web.api.dto.PropertyGroupConfigurationDTO;
+import org.apache.nifi.web.api.dto.ConnectorDTO;
 import org.apache.nifi.web.api.dto.ResourceDTO;
 import org.apache.nifi.web.api.dto.SnippetDTO;
 import org.apache.nifi.web.api.dto.SystemDiagnosticsDTO;
@@ -221,7 +220,7 @@ public interface NiFiServiceFacade {
 
     void verifyCanVerifyConnectorConfigurationStep(String connectorId, String 
configurationStepName);
 
-    List<ConfigVerificationResultDTO> 
performConnectorConfigurationStepVerification(String connectorId, String 
configurationStepName, List<PropertyGroupConfigurationDTO> 
propertyGroupConfigurations);
+    List<ConfigVerificationResultDTO> 
performConnectorConfigurationStepVerification(String connectorId, String 
configurationStepName, ConfigurationStepConfigurationDTO 
configurationStepConfiguration);
 
     SearchResultsDTO searchConnector(String connectorId, String query);
 
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
index de1e068bdc2..df04e148d2b 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
@@ -286,7 +286,6 @@ import org.apache.nifi.web.api.dto.ProcessorConfigDTO;
 import org.apache.nifi.web.api.dto.ProcessorDTO;
 import org.apache.nifi.web.api.dto.ProcessorRunStatusDetailsDTO;
 import org.apache.nifi.web.api.dto.PropertyDescriptorDTO;
-import org.apache.nifi.web.api.dto.PropertyGroupConfigurationDTO;
 import org.apache.nifi.web.api.dto.PropertyHistoryDTO;
 import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
 import org.apache.nifi.web.api.dto.RemoteProcessGroupPortDTO;
@@ -3696,8 +3695,8 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
 
     @Override
     public List<ConfigVerificationResultDTO> 
performConnectorConfigurationStepVerification(final String connectorId,
-            final String configurationStepName, final 
List<PropertyGroupConfigurationDTO> propertyGroupConfigurations) {
-        final List<ConfigVerificationResult> verificationResults = 
connectorDAO.verifyConfigurationStep(connectorId, configurationStepName, 
propertyGroupConfigurations);
+            final String configurationStepName, final 
ConfigurationStepConfigurationDTO configurationStepConfiguration) {
+        final List<ConfigVerificationResult> verificationResults = 
connectorDAO.verifyConfigurationStep(connectorId, configurationStepName, 
configurationStepConfiguration);
         return verificationResults.stream()
                 .map(result -> 
dtoFactory.createConfigVerificationResultDto(result))
                 .collect(Collectors.toList());
@@ -3713,7 +3712,8 @@ public class StandardNiFiServiceFacade implements 
NiFiServiceFacade {
     @Override
     public ConnectorPropertyAllowableValuesEntity 
getConnectorPropertyAllowableValues(final String connectorId,
             final String stepName, final String groupName, final String 
propertyName, final String filter) {
-        final List<AllowableValue> allowableValues = 
connectorDAO.fetchAllowableValues(connectorId, stepName, groupName, 
propertyName, filter);
+        // groupName is retained for REST API backward compatibility but is no 
longer used by the underlying API
+        final List<AllowableValue> allowableValues = 
connectorDAO.fetchAllowableValues(connectorId, stepName, propertyName, filter);
 
         final List<AllowableValueEntity> allowableValueEntities = 
allowableValues.stream()
                 .map(av -> 
entityFactory.createAllowableValueEntity(dtoFactory.createAllowableValueDto(av),
 true))
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java
index 3c95ad6aa5d..ffc3fc264d8 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ConnectorResource.java
@@ -56,7 +56,6 @@ import 
org.apache.nifi.web.api.dto.ConfigVerificationResultDTO;
 import org.apache.nifi.web.api.dto.BundleDTO;
 import org.apache.nifi.web.api.dto.ConfigurationStepConfigurationDTO;
 import org.apache.nifi.web.api.dto.ConnectorDTO;
-import org.apache.nifi.web.api.dto.PropertyGroupConfigurationDTO;
 import org.apache.nifi.web.api.dto.search.SearchResultsDTO;
 import org.apache.nifi.web.api.entity.ConfigurationStepEntity;
 import org.apache.nifi.web.api.entity.ConfigurationStepNamesEntity;
@@ -1011,8 +1010,8 @@ public class ConnectorResource extends 
ApplicationResource {
 
         final 
Consumer<AsynchronousWebRequest<VerifyConnectorConfigStepRequestEntity, 
List<ConfigVerificationResultDTO>>> updateTask = asyncRequest -> {
             try {
-                final List<PropertyGroupConfigurationDTO> 
propertyGroupConfigurations = 
requestDto.getConfigurationStep().getPropertyGroupConfigurations();
-                final List<ConfigVerificationResultDTO> results = 
serviceFacade.performConnectorConfigurationStepVerification(connectorId, 
configurationStepName, propertyGroupConfigurations);
+                final ConfigurationStepConfigurationDTO configurationStep = 
requestDto.getConfigurationStep();
+                final List<ConfigVerificationResultDTO> results = 
serviceFacade.performConnectorConfigurationStepVerification(connectorId, 
configurationStepName, configurationStep);
                 asyncRequest.markStepComplete(results);
             } catch (final Exception e) {
                 logger.error("Failed to verify Connector Configuration Step", 
e);
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
index d3d5ee6da89..17e3c4ed55f 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java
@@ -73,15 +73,15 @@ import 
org.apache.nifi.components.validation.ValidationStatus;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.components.connector.AssetReference;
 import org.apache.nifi.components.connector.ConfigurationStep;
-import org.apache.nifi.components.connector.ConfigurationStepConfiguration;
 import org.apache.nifi.components.connector.ConnectorConfiguration;
 import org.apache.nifi.components.connector.ConnectorNode;
 import org.apache.nifi.components.connector.ConnectorPropertyDescriptor;
 import org.apache.nifi.components.connector.ConnectorPropertyGroup;
 import org.apache.nifi.components.connector.ConnectorValueReference;
 import org.apache.nifi.components.connector.FrameworkFlowContext;
-import org.apache.nifi.components.connector.PropertyGroupConfiguration;
+import org.apache.nifi.components.connector.NamedStepConfiguration;
 import org.apache.nifi.components.connector.SecretReference;
+import org.apache.nifi.components.connector.StepConfiguration;
 import org.apache.nifi.components.connector.StringLiteralValue;
 import org.apache.nifi.connectable.ConnectableType;
 import org.apache.nifi.connectable.Connection;
@@ -5278,14 +5278,16 @@ public final class DtoFactory {
         final ConfigurationStepConfigurationDTO dto = new 
ConfigurationStepConfigurationDTO();
         dto.setConfigurationStepName(step.getName());
         dto.setConfigurationStepDescription(step.getDescription());
+        dto.setConfigurationStepDocumentation(step.getDocumentation());
 
-        // Get the current configuration values for this step
-        final ConfigurationStepConfiguration stepConfig = 
configuration.getConfigurationStepConfigurations().stream()
+        // Get the current configuration values for this step from the flat 
StepConfiguration
+        final StepConfiguration stepConfig = 
configuration.getNamedStepConfigurations().stream()
                 .filter(c -> step.getName().equals(c.stepName()))
+                .map(NamedStepConfiguration::configuration)
                 .findFirst()
                 .orElse(null);
 
-        // Convert property groups from the schema, merging in current values
+        // Convert property groups from the schema, merging in current values 
from flat stepConfig
         final List<PropertyGroupConfigurationDTO> propertyGroupDtos = 
step.getPropertyGroups().stream()
                 .map(propertyGroup -> 
createPropertyGroupConfigurationDtoFromGroup(propertyGroup, stepConfig))
                 .collect(Collectors.toList());
@@ -5293,7 +5295,7 @@ public final class DtoFactory {
         return dto;
     }
 
-    private PropertyGroupConfigurationDTO 
createPropertyGroupConfigurationDtoFromGroup(final ConnectorPropertyGroup 
propertyGroup, final ConfigurationStepConfiguration stepConfig) {
+    private PropertyGroupConfigurationDTO 
createPropertyGroupConfigurationDtoFromGroup(final ConnectorPropertyGroup 
propertyGroup, final StepConfiguration stepConfig) {
         if (propertyGroup == null) {
             return null;
         }
@@ -5311,18 +5313,15 @@ public final class DtoFactory {
         }
         dto.setPropertyDescriptors(propertyDescriptorMap);
 
-        // Get the current property values for this group if they exist
+        // Get the current property values for this group's properties from 
flat stepConfig
         // Use LinkedHashMap to preserve the order from the connector
         final Map<String, ConnectorValueReferenceDTO> propertyValues = new 
LinkedHashMap<>();
         if (stepConfig != null) {
-            final PropertyGroupConfiguration groupConfig = 
stepConfig.propertyGroupConfigurations().stream()
-                    .filter(g -> propertyGroup.getName().equals(g.groupName()))
-                    .findFirst()
-                    .orElse(null);
-
-            if (groupConfig != null) {
-                for (final Map.Entry<String, ConnectorValueReference> entry : 
groupConfig.propertyValues().entrySet()) {
-                    propertyValues.put(entry.getKey(), 
createConnectorValueReferenceDto(entry.getValue()));
+            // For each property in this group, check if there's a value in 
the flat stepConfig
+            for (final ConnectorPropertyDescriptor propertyDescriptor : 
propertyGroup.getProperties()) {
+                final ConnectorValueReference valueRef = 
stepConfig.getPropertyValue(propertyDescriptor.getName());
+                if (valueRef != null) {
+                    propertyValues.put(propertyDescriptor.getName(), 
createConnectorValueReferenceDto(valueRef));
                 }
             }
         }
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
index 5e6cacb6960..cd748204af9 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/EntityFactory.java
@@ -913,8 +913,7 @@ public final class EntityFactory {
     }
 
     public ConnectorPropertyAllowableValuesEntity 
createConnectorPropertyAllowableValuesEntity(
-            final String configurationStepName, final String 
propertyGroupName, final String propertyName,
-            final List<AllowableValueEntity> allowableValues) {
+            final String configurationStepName, final String 
propertyGroupName, final String propertyName, final List<AllowableValueEntity> 
allowableValues) {
         final ConnectorPropertyAllowableValuesEntity entity = new 
ConnectorPropertyAllowableValuesEntity();
         entity.setConfigurationStepName(configurationStepName);
         entity.setPropertyGroupName(propertyGroupName);
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ConnectorDAO.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ConnectorDAO.java
index 3ae78f4966f..2a3ef150758 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ConnectorDAO.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/ConnectorDAO.java
@@ -21,7 +21,6 @@ import org.apache.nifi.components.AllowableValue;
 import org.apache.nifi.components.ConfigVerificationResult;
 import org.apache.nifi.components.connector.ConnectorNode;
 import org.apache.nifi.web.api.dto.ConfigurationStepConfigurationDTO;
-import org.apache.nifi.web.api.dto.PropertyGroupConfigurationDTO;
 
 import java.util.List;
 
@@ -51,9 +50,9 @@ public interface ConnectorDAO {
 
     void verifyCanVerifyConfigurationStep(String id, String 
configurationStepName);
 
-    List<ConfigVerificationResult> verifyConfigurationStep(String id, String 
configurationStepName, List<PropertyGroupConfigurationDTO> 
propertyGroupConfigurations);
+    List<ConfigVerificationResult> verifyConfigurationStep(String id, String 
configurationStepName, ConfigurationStepConfigurationDTO 
configurationStepConfiguration);
 
-    List<AllowableValue> fetchAllowableValues(String id, String stepName, 
String groupName, String propertyName, String filter);
+    List<AllowableValue> fetchAllowableValues(String id, String stepName, 
String propertyName, String filter);
 }
 
 
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectorDAO.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectorDAO.java
index fd07e81eb5f..13de988b8b6 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectorDAO.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardConnectorDAO.java
@@ -24,21 +24,20 @@ import org.apache.nifi.components.connector.ConnectorNode;
 import org.apache.nifi.components.connector.ConnectorRepository;
 import org.apache.nifi.components.connector.ConnectorValueReference;
 import org.apache.nifi.components.connector.ConnectorValueType;
-import org.apache.nifi.components.connector.PropertyGroupConfiguration;
 import org.apache.nifi.components.connector.SecretReference;
+import org.apache.nifi.components.connector.StepConfiguration;
 import org.apache.nifi.components.connector.StringLiteralValue;
-import org.apache.nifi.web.api.dto.ConfigurationStepConfigurationDTO;
-import org.apache.nifi.web.api.dto.ConnectorValueReferenceDTO;
-import org.apache.nifi.web.api.dto.PropertyGroupConfigurationDTO;
 import org.apache.nifi.controller.FlowController;
 import org.apache.nifi.controller.flow.FlowManager;
 import org.apache.nifi.web.NiFiCoreException;
 import org.apache.nifi.web.ResourceNotFoundException;
+import org.apache.nifi.web.api.dto.ConfigurationStepConfigurationDTO;
+import org.apache.nifi.web.api.dto.ConnectorValueReferenceDTO;
+import org.apache.nifi.web.api.dto.PropertyGroupConfigurationDTO;
 import org.apache.nifi.web.dao.ConnectorDAO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -121,30 +120,29 @@ public class StandardConnectorDAO implements ConnectorDAO 
{
     public void updateConnectorConfigurationStep(final String id, final String 
configurationStepName, final ConfigurationStepConfigurationDTO 
configurationStepDto) {
         final ConnectorNode connector = getConnector(id);
 
-        // Convert DTO to domain object - extract the property groups from the 
configuration step
-        final List<PropertyGroupConfiguration> propertyGroups = new 
ArrayList<>();
-        if (configurationStepDto.getPropertyGroupConfigurations() != null) {
-            
propertyGroups.addAll(configurationStepDto.getPropertyGroupConfigurations().stream()
-                    .map(this::convertToPropertyGroupConfiguration)
-                    .toList());
-        }
+        // Convert DTO to domain object - flatten all property groups into a 
single StepConfiguration
+        final StepConfiguration stepConfiguration = 
convertToStepConfiguration(configurationStepDto);
 
         // Update the connector configuration through the repository
         try {
-            getConnectorRepository().configureConnector(connector, 
configurationStepName, propertyGroups);
+            getConnectorRepository().configureConnector(connector, 
configurationStepName, stepConfiguration);
         } catch (final Exception e) {
             throw new IllegalStateException("Failed to update connector 
configuration: " + e, e);
         }
     }
 
-    private PropertyGroupConfiguration 
convertToPropertyGroupConfiguration(final PropertyGroupConfigurationDTO dto) {
+    private StepConfiguration convertToStepConfiguration(final 
ConfigurationStepConfigurationDTO dto) {
         final Map<String, ConnectorValueReference> propertyValues = new 
HashMap<>();
-        if (dto.getPropertyValues() != null) {
-            for (final Map.Entry<String, ConnectorValueReferenceDTO> entry : 
dto.getPropertyValues().entrySet()) {
-                propertyValues.put(entry.getKey(), 
convertToConnectorValueReference(entry.getValue()));
+        if (dto.getPropertyGroupConfigurations() != null) {
+            for (final PropertyGroupConfigurationDTO groupDto : 
dto.getPropertyGroupConfigurations()) {
+                if (groupDto.getPropertyValues() != null) {
+                    for (final Map.Entry<String, ConnectorValueReferenceDTO> 
entry : groupDto.getPropertyValues().entrySet()) {
+                        propertyValues.put(entry.getKey(), 
convertToConnectorValueReference(entry.getValue()));
+                    }
+                }
             }
         }
-        return new PropertyGroupConfiguration(dto.getPropertyGroupName(), 
propertyValues);
+        return new StepConfiguration(propertyValues);
     }
 
     private ConnectorValueReference convertToConnectorValueReference(final 
ConnectorValueReferenceDTO dto) {
@@ -176,26 +174,19 @@ public class StandardConnectorDAO implements ConnectorDAO 
{
     }
 
     @Override
-    public List<ConfigVerificationResult> verifyConfigurationStep(final String 
id, final String configurationStepName, final 
List<PropertyGroupConfigurationDTO> propertyGroupConfigurationDtos) {
+    public List<ConfigVerificationResult> verifyConfigurationStep(final String 
id, final String configurationStepName, final ConfigurationStepConfigurationDTO 
configurationStepDto) {
         final ConnectorNode connector = getConnector(id);
-
-        final List<PropertyGroupConfiguration> propertyGroupConfigurations = 
new ArrayList<>();
-        if (propertyGroupConfigurationDtos != null) {
-            for (final PropertyGroupConfigurationDTO dto : 
propertyGroupConfigurationDtos) {
-                
propertyGroupConfigurations.add(convertToPropertyGroupConfiguration(dto));
-            }
-        }
-
-        return connector.verifyConfigurationStep(configurationStepName, 
propertyGroupConfigurations);
+        final StepConfiguration stepConfiguration = 
convertToStepConfiguration(configurationStepDto);
+        return connector.verifyConfigurationStep(configurationStepName, 
stepConfiguration);
     }
 
     @Override
-    public List<AllowableValue> fetchAllowableValues(final String id, final 
String stepName, final String groupName, final String propertyName, final 
String filter) {
+    public List<AllowableValue> fetchAllowableValues(final String id, final 
String stepName, final String propertyName, final String filter) {
         final ConnectorNode connector = getConnector(id);
         if (filter == null || filter.isEmpty()) {
-            return connector.fetchAllowableValues(stepName, groupName, 
propertyName);
+            return connector.fetchAllowableValues(stepName, propertyName);
         } else {
-            return connector.fetchAllowableValues(stepName, groupName, 
propertyName, filter);
+            return connector.fetchAllowableValues(stepName, propertyName, 
filter);
         }
     }
 }
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/StandardConnectorDAOTest.java
 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/StandardConnectorDAOTest.java
index e33d2aded8c..bb96b35271e 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/StandardConnectorDAOTest.java
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/StandardConnectorDAOTest.java
@@ -55,7 +55,6 @@ class StandardConnectorDAOTest {
 
     private static final String CONNECTOR_ID = "test-connector-id";
     private static final String STEP_NAME = "test-step";
-    private static final String GROUP_NAME = "test-group";
     private static final String PROPERTY_NAME = "test-property";
 
     @BeforeEach
@@ -159,13 +158,13 @@ class StandardConnectorDAOTest {
             new AllowableValue("value2", "Value 2", "Second value")
         );
         
when(connectorRepository.getConnector(CONNECTOR_ID)).thenReturn(connectorNode);
-        when(connectorNode.fetchAllowableValues(STEP_NAME, GROUP_NAME, 
PROPERTY_NAME)).thenReturn(expectedValues);
+        when(connectorNode.fetchAllowableValues(STEP_NAME, 
PROPERTY_NAME)).thenReturn(expectedValues);
 
-        final List<AllowableValue> result = 
connectorDAO.fetchAllowableValues(CONNECTOR_ID, STEP_NAME, GROUP_NAME, 
PROPERTY_NAME, null);
+        final List<AllowableValue> result = 
connectorDAO.fetchAllowableValues(CONNECTOR_ID, STEP_NAME, PROPERTY_NAME, null);
 
         assertEquals(expectedValues, result);
-        verify(connectorNode).fetchAllowableValues(STEP_NAME, GROUP_NAME, 
PROPERTY_NAME);
-        verify(connectorNode, never()).fetchAllowableValues(any(), any(), 
any(), any());
+        verify(connectorNode).fetchAllowableValues(STEP_NAME, PROPERTY_NAME);
+        verify(connectorNode, never()).fetchAllowableValues(any(), any(), 
any());
     }
 
     @Test
@@ -174,13 +173,13 @@ class StandardConnectorDAOTest {
             new AllowableValue("value1", "Value 1", "First value")
         );
         
when(connectorRepository.getConnector(CONNECTOR_ID)).thenReturn(connectorNode);
-        when(connectorNode.fetchAllowableValues(STEP_NAME, GROUP_NAME, 
PROPERTY_NAME)).thenReturn(expectedValues);
+        when(connectorNode.fetchAllowableValues(STEP_NAME, 
PROPERTY_NAME)).thenReturn(expectedValues);
 
-        final List<AllowableValue> result = 
connectorDAO.fetchAllowableValues(CONNECTOR_ID, STEP_NAME, GROUP_NAME, 
PROPERTY_NAME, "");
+        final List<AllowableValue> result = 
connectorDAO.fetchAllowableValues(CONNECTOR_ID, STEP_NAME, PROPERTY_NAME, "");
 
         assertEquals(expectedValues, result);
-        verify(connectorNode).fetchAllowableValues(STEP_NAME, GROUP_NAME, 
PROPERTY_NAME);
-        verify(connectorNode, never()).fetchAllowableValues(any(), any(), 
any(), any());
+        verify(connectorNode).fetchAllowableValues(STEP_NAME, PROPERTY_NAME);
+        verify(connectorNode, never()).fetchAllowableValues(any(), any(), 
any());
     }
 
     @Test
@@ -190,13 +189,13 @@ class StandardConnectorDAOTest {
             new AllowableValue("filtered-value", "Filtered Value", "Filtered 
result")
         );
         
when(connectorRepository.getConnector(CONNECTOR_ID)).thenReturn(connectorNode);
-        when(connectorNode.fetchAllowableValues(STEP_NAME, GROUP_NAME, 
PROPERTY_NAME, filter)).thenReturn(expectedValues);
+        when(connectorNode.fetchAllowableValues(STEP_NAME, PROPERTY_NAME, 
filter)).thenReturn(expectedValues);
 
-        final List<AllowableValue> result = 
connectorDAO.fetchAllowableValues(CONNECTOR_ID, STEP_NAME, GROUP_NAME, 
PROPERTY_NAME, filter);
+        final List<AllowableValue> result = 
connectorDAO.fetchAllowableValues(CONNECTOR_ID, STEP_NAME, PROPERTY_NAME, 
filter);
 
         assertEquals(expectedValues, result);
-        verify(connectorNode).fetchAllowableValues(STEP_NAME, GROUP_NAME, 
PROPERTY_NAME, filter);
-        verify(connectorNode, never()).fetchAllowableValues(STEP_NAME, 
GROUP_NAME, PROPERTY_NAME);
+        verify(connectorNode).fetchAllowableValues(STEP_NAME, PROPERTY_NAME, 
filter);
+        verify(connectorNode, never()).fetchAllowableValues(STEP_NAME, 
PROPERTY_NAME);
     }
 
     @Test
@@ -204,7 +203,7 @@ class StandardConnectorDAOTest {
         when(connectorRepository.getConnector(CONNECTOR_ID)).thenReturn(null);
 
         assertThrows(ResourceNotFoundException.class, () ->
-            connectorDAO.fetchAllowableValues(CONNECTOR_ID, STEP_NAME, 
GROUP_NAME, PROPERTY_NAME, null)
+            connectorDAO.fetchAllowableValues(CONNECTOR_ID, STEP_NAME, 
PROPERTY_NAME, null)
         );
 
         verify(connectorRepository).getConnector(CONNECTOR_ID);


Reply via email to