This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 8a6fca06e4 Add header variable support to Asynchronous web service,
fixes #5850 (#5875)
8a6fca06e4 is described below
commit 8a6fca06e4aa2c5616fc7bb6ed6beda8bd848f5a
Author: Hans Van Akelyen <[email protected]>
AuthorDate: Thu Oct 23 14:39:02 2025 +0200
Add header variable support to Asynchronous web service, fixes #5850 (#5875)
---
.../org/apache/hop/www/async/AsyncRunServlet.java | 21 ++++
.../java/org/apache/hop/www/async/AsyncStatus.java | 132 +-------------------
.../org/apache/hop/www/async/AsyncWebService.java | 91 ++------------
.../hop/www/async/AsyncWebServiceEditor.java | 45 +++++--
.../www/async/messages/messages_en_US.properties | 8 +-
.../apache/hop/www/async/AsyncGuiPluginTest.java | 92 ++++++++++++++
.../org/apache/hop/www/async/AsyncStatusTest.java | 111 +++++++++++++++++
.../apache/hop/www/async/AsyncWebServiceTest.java | 137 +++++++++++++++++++++
.../org/apache/hop/www/async/DefaultsTest.java | 64 ++++++++++
.../hop/ui/www/service/WebServiceEditor.java | 6 +-
.../www/service/messages/messages_en_US.properties | 2 +
11 files changed, 484 insertions(+), 225 deletions(-)
diff --git
a/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncRunServlet.java
b/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncRunServlet.java
index 99e16a9e78..841f5f546c 100644
---
a/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncRunServlet.java
+++
b/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncRunServlet.java
@@ -17,6 +17,8 @@
package org.apache.hop.www.async;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@@ -26,6 +28,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Enumeration;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -190,6 +193,24 @@ public class AsyncRunServlet extends BaseHttpServlet
implements IHopServerPlugin
}
}
workflow.setVariable(contentVariable, Const.NVL(content, ""));
+
+ String headerContentVariable =
variables.resolve(webService.getHeaderContentVariable());
+ String headerContent = "";
+ if (StringUtils.isNotEmpty(headerContentVariable)) {
+ // Create JSON object containing all request headers
+ ObjectMapper objectMapper = new ObjectMapper();
+ ObjectNode headersJson = objectMapper.createObjectNode();
+
+ Enumeration<String> headerNames = request.getHeaderNames();
+ while (headerNames.hasMoreElements()) {
+ String headerName = headerNames.nextElement();
+ String headerValue = request.getHeader(headerName);
+ headersJson.put(headerName, headerValue);
+ }
+ headerContent = objectMapper.writeValueAsString(headersJson);
+ }
+
+ workflow.setVariable(headerContentVariable, headerContent);
}
// Set all the other parameters as variables/parameters...
diff --git
a/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncStatus.java
b/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncStatus.java
index 923f28601b..18d71b24ac 100644
--- a/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncStatus.java
+++ b/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncStatus.java
@@ -23,8 +23,12 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.hop.www.HopServerPipelineStatus;
+@Getter
+@Setter
public class AsyncStatus {
private String service;
private String id;
@@ -47,132 +51,4 @@ public class AsyncStatus {
statusVariables = new HashMap<>();
pipelineStatuses = new ArrayList<>();
}
-
- /**
- * Gets service
- *
- * @return value of service
- */
- public String getService() {
- return service;
- }
-
- /**
- * @param service The service to set
- */
- public void setService(String service) {
- this.service = service;
- }
-
- /**
- * Gets id
- *
- * @return value of id
- */
- public String getId() {
- return id;
- }
-
- /**
- * @param id The id to set
- */
- public void setId(String id) {
- this.id = id;
- }
-
- /**
- * Gets logDate
- *
- * @return value of logDate
- */
- public Date getLogDate() {
- return logDate;
- }
-
- /**
- * @param logDate The logDate to set
- */
- public void setLogDate(Date logDate) {
- this.logDate = logDate;
- }
-
- /**
- * Gets startDate
- *
- * @return value of startDate
- */
- public Date getStartDate() {
- return startDate;
- }
-
- /**
- * @param startDate The startDate to set
- */
- public void setStartDate(Date startDate) {
- this.startDate = startDate;
- }
-
- /**
- * Gets endDate
- *
- * @return value of endDate
- */
- public Date getEndDate() {
- return endDate;
- }
-
- /**
- * @param endDate The endDate to set
- */
- public void setEndDate(Date endDate) {
- this.endDate = endDate;
- }
-
- /**
- * Gets statusDescription
- *
- * @return value of statusDescription
- */
- public String getStatusDescription() {
- return statusDescription;
- }
-
- /**
- * @param statusDescription The statusDescription to set
- */
- public void setStatusDescription(String statusDescription) {
- this.statusDescription = statusDescription;
- }
-
- /**
- * Gets statusVariables
- *
- * @return value of statusVariables
- */
- public Map<String, String> getStatusVariables() {
- return statusVariables;
- }
-
- /**
- * @param statusVariables The statusVariables to set
- */
- public void setStatusVariables(Map<String, String> statusVariables) {
- this.statusVariables = statusVariables;
- }
-
- /**
- * Gets pipelineStatuses
- *
- * @return value of pipelineStatuses
- */
- public List<HopServerPipelineStatus> getPipelineStatuses() {
- return pipelineStatuses;
- }
-
- /**
- * @param pipelineStatuses The pipelineStatuses to set
- */
- public void setPipelineStatuses(List<HopServerPipelineStatus>
pipelineStatuses) {
- this.pipelineStatuses = pipelineStatuses;
- }
}
diff --git
a/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncWebService.java
b/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncWebService.java
index fb7ec49971..f78a38860e 100644
---
a/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncWebService.java
+++
b/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncWebService.java
@@ -19,6 +19,8 @@ package org.apache.hop.www.async;
import java.util.ArrayList;
import java.util.List;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.commons.lang.StringUtils;
import org.apache.hop.core.Const;
import org.apache.hop.core.variables.IVariables;
@@ -35,6 +37,8 @@ import org.apache.hop.metadata.api.IHopMetadata;
image = "ui/images/server.svg",
documentationUrl = "/metadata-types/async-web-service.html",
hopMetadataPropertyType = HopMetadataPropertyType.SERVER_WEB_SERVICE_ASYNC)
+@Getter
+@Setter
public class AsyncWebService extends HopMetadataBase implements IHopMetadata {
@HopMetadataProperty private boolean enabled;
@@ -42,6 +46,7 @@ public class AsyncWebService extends HopMetadataBase
implements IHopMetadata {
@HopMetadataProperty private String statusVariables;
@HopMetadataProperty private String bodyContentVariable;
@HopMetadataProperty private String runConfigurationName;
+ @HopMetadataProperty private String headerContentVariable;
public AsyncWebService() {
this.enabled = true;
@@ -54,13 +59,15 @@ public class AsyncWebService extends HopMetadataBase
implements IHopMetadata {
String filename,
String statusVariables,
String bodyContentVariable,
- String runConfigurationName) {
+ String runConfigurationName,
+ String headerContentVariable) {
super(name);
this.enabled = enabled;
this.filename = filename;
this.statusVariables = statusVariables;
this.bodyContentVariable = bodyContentVariable;
this.runConfigurationName = runConfigurationName;
+ this.headerContentVariable = headerContentVariable;
}
/**
@@ -80,86 +87,4 @@ public class AsyncWebService extends HopMetadataBase
implements IHopMetadata {
}
return list;
}
-
- /**
- * Gets enabled
- *
- * @return value of enabled
- */
- public boolean isEnabled() {
- return enabled;
- }
-
- /**
- * @param enabled The enabled to set
- */
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- /**
- * Gets filename
- *
- * @return value of filename
- */
- public String getFilename() {
- return filename;
- }
-
- /**
- * @param filename The filename to set
- */
- public void setFilename(String filename) {
- this.filename = filename;
- }
-
- /**
- * Gets statusVariables
- *
- * @return value of statusVariables
- */
- public String getStatusVariables() {
- return statusVariables;
- }
-
- /**
- * @param statusVariables The statusVariables to set
- */
- public void setStatusVariables(String statusVariables) {
- this.statusVariables = statusVariables;
- }
-
- /**
- * Gets bodyContentVariable
- *
- * @return value of bodyContentVariable
- */
- public String getBodyContentVariable() {
- return bodyContentVariable;
- }
-
- /**
- * @param bodyContentVariable The bodyContentVariable to set
- */
- public void setBodyContentVariable(String bodyContentVariable) {
- this.bodyContentVariable = bodyContentVariable;
- }
-
- /**
- * Gets runConfigurationName
- *
- * @return value of runConfigurationName
- */
- public String getRunConfigurationName() {
- return runConfigurationName;
- }
-
- /**
- * Sets runConfigurationName
- *
- * @param runConfigurationName value of runConfigurationName
- */
- public void setRunConfigurationName(String runConfigurationName) {
- this.runConfigurationName = runConfigurationName;
- }
}
diff --git
a/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncWebServiceEditor.java
b/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncWebServiceEditor.java
index 315cb45ce3..18c514a185 100644
---
a/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncWebServiceEditor.java
+++
b/plugins/misc/async/src/main/java/org/apache/hop/www/async/AsyncWebServiceEditor.java
@@ -32,7 +32,6 @@ import org.apache.hop.ui.core.widget.TextVar;
import org.apache.hop.ui.hopgui.HopGui;
import org.apache.hop.ui.hopgui.file.workflow.HopWorkflowFileType;
import
org.apache.hop.ui.hopgui.perspective.dataorch.HopDataOrchestrationPerspective;
-import org.apache.hop.ui.www.service.WebServiceEditor;
import org.apache.hop.workflow.WorkflowMeta;
import org.apache.hop.workflow.config.WorkflowRunConfiguration;
import org.eclipse.swt.SWT;
@@ -51,7 +50,7 @@ import org.eclipse.swt.widgets.Text;
* @see AsyncWebService
*/
public class AsyncWebServiceEditor extends MetadataEditor<AsyncWebService> {
- private static final Class<?> PKG = WebServiceEditor.class;
+ private static final Class<?> PKG = AsyncWebServiceEditor.class;
private Text wName;
private Button wEnabled;
@@ -59,6 +58,7 @@ public class AsyncWebServiceEditor extends
MetadataEditor<AsyncWebService> {
private MetaSelectionLine<WorkflowRunConfiguration> wRunConfiguration;
private TextVar wStatusVars;
private TextVar wContentVar;
+ private TextVar wHeaderContentVariable;
public AsyncWebServiceEditor(
HopGui hopGui, MetadataManager<AsyncWebService> manager, AsyncWebService
metadata) {
@@ -177,9 +177,8 @@ public class AsyncWebServiceEditor extends
MetadataEditor<AsyncWebService> {
WorkflowRunConfiguration.class,
parent,
SWT.NONE,
- "Workflow run configuration",
- "This is the workflow run configuration to use on the server. "
- + "If left blank a standard local workflow engine is used.");
+ BaseMessages.getString(PKG,
"AsyncWebService.Runconfiguration.Label"),
+ BaseMessages.getString(PKG,
"AsyncWebService.Runconfiguration.Tooltip"));
FormData fdRunConfiguration = new FormData();
fdRunConfiguration.left = new FormAttachment(0, 0);
fdRunConfiguration.top = new FormAttachment(lastControl, margin);
@@ -191,7 +190,7 @@ public class AsyncWebServiceEditor extends
MetadataEditor<AsyncWebService> {
//
Label wlStatusVars = new Label(parent, SWT.RIGHT);
PropsUi.setLook(wlStatusVars);
- wlStatusVars.setText("Status variables (, separated)");
+ wlStatusVars.setText(BaseMessages.getString(PKG,
"AsyncWebService.StatusVariables.Label"));
FormData fdlStatusVars = new FormData();
fdlStatusVars.left = new FormAttachment(0, 0);
fdlStatusVars.right = new FormAttachment(middle, -margin);
@@ -206,11 +205,10 @@ public class AsyncWebServiceEditor extends
MetadataEditor<AsyncWebService> {
wStatusVars.setLayoutData(fdStatusVars);
lastControl = wlStatusVars;
- // Status variables
- //
+ // body content variables
Label wlContentVar = new Label(parent, SWT.RIGHT);
PropsUi.setLook(wlContentVar);
- wlContentVar.setText("Content variable");
+ wlContentVar.setText(BaseMessages.getString(PKG,
"AsyncWebService.BodyContentVariable.Label"));
FormData fdlContentVar = new FormData();
fdlContentVar.left = new FormAttachment(0, 0);
fdlContentVar.right = new FormAttachment(middle, -margin);
@@ -223,6 +221,32 @@ public class AsyncWebServiceEditor extends
MetadataEditor<AsyncWebService> {
fdContentVar.right = new FormAttachment(100, 0);
fdContentVar.top = new FormAttachment(wlContentVar, 0, SWT.CENTER);
wContentVar.setLayoutData(fdContentVar);
+ lastControl = wContentVar;
+
+ // HeaderContentVariable to read from
+ //
+ Label wlHeaderContentVariable = new Label(parent, SWT.RIGHT);
+ PropsUi.setLook(wlHeaderContentVariable);
+ wlHeaderContentVariable.setText(
+ BaseMessages.getString(PKG,
"AsyncWebService.HeaderContentVariable.Label"));
+ wlHeaderContentVariable.setToolTipText(
+ BaseMessages.getString(PKG,
"AsyncWebService.HeaderContentVariable.Tooltip"));
+ FormData fdlHeaderContentVariable = new FormData();
+ fdlHeaderContentVariable.left = new FormAttachment(0, 0);
+ fdlHeaderContentVariable.right = new FormAttachment(middle, -margin);
+ fdlHeaderContentVariable.top = new FormAttachment(lastControl, 2 * margin);
+ wlHeaderContentVariable.setLayoutData(fdlHeaderContentVariable);
+ wHeaderContentVariable =
+ new TextVar(manager.getVariables(), parent, SWT.SINGLE | SWT.LEFT |
SWT.BORDER);
+ wHeaderContentVariable.setToolTipText(
+ BaseMessages.getString(PKG,
"AsyncWebService.HeaderContentVariable.Tooltip"));
+ PropsUi.setLook(wHeaderContentVariable);
+ FormData fdHeaderContentVariable = new FormData();
+ fdHeaderContentVariable.left = new FormAttachment(middle, 0);
+ fdHeaderContentVariable.right = new FormAttachment(100, 0);
+ fdHeaderContentVariable.top = new FormAttachment(wlHeaderContentVariable,
0, SWT.CENTER);
+ wHeaderContentVariable.setLayoutData(fdHeaderContentVariable);
+ lastControl = wlHeaderContentVariable;
setWidgetsContent();
@@ -234,6 +258,7 @@ public class AsyncWebServiceEditor extends
MetadataEditor<AsyncWebService> {
wRunConfiguration.addListener(SWT.Modify, lsMod);
wStatusVars.addListener(SWT.Modify, lsMod);
wContentVar.addListener(SWT.Modify, lsMod);
+ wHeaderContentVariable.addListener(SWT.Modify, lsMod);
}
/**
@@ -333,6 +358,7 @@ public class AsyncWebServiceEditor extends
MetadataEditor<AsyncWebService> {
wFilename.setText(Const.NVL(ws.getFilename(), ""));
wStatusVars.setText(Const.NVL(ws.getStatusVariables(), ""));
wContentVar.setText(Const.NVL(ws.getBodyContentVariable(), ""));
+ wHeaderContentVariable.setText(Const.NVL(ws.getHeaderContentVariable(),
""));
try {
wRunConfiguration.fillItems();
wRunConfiguration.setText(Const.NVL(ws.getRunConfigurationName(), ""));
@@ -349,6 +375,7 @@ public class AsyncWebServiceEditor extends
MetadataEditor<AsyncWebService> {
ws.setStatusVariables(wStatusVars.getText());
ws.setBodyContentVariable(wContentVar.getText());
ws.setRunConfigurationName(wRunConfiguration.getText());
+ ws.setHeaderContentVariable(wHeaderContentVariable.getText());
}
@Override
diff --git
a/plugins/misc/async/src/main/resources/org/apache/hop/www/async/messages/messages_en_US.properties
b/plugins/misc/async/src/main/resources/org/apache/hop/www/async/messages/messages_en_US.properties
index 9687e2209c..0b8ec7ca9d 100644
---
a/plugins/misc/async/src/main/resources/org/apache/hop/www/async/messages/messages_en_US.properties
+++
b/plugins/misc/async/src/main/resources/org/apache/hop/www/async/messages/messages_en_US.properties
@@ -26,4 +26,10 @@ AsyncWebServiceEditor.Filename.Label=The workflow filename
AsyncWebServiceEditor.Name.Label=Asynchronous Web Service
AsyncWebServiceEditor.StatusVars.Label=The status variables (, separated)
AsyncWebService.name=Asynchronous Web Service
-AsyncWebService.description=Allows you to run a long running workflow
asynchronously
\ No newline at end of file
+AsyncWebService.description=Allows you to run a long running workflow
asynchronously
+AsyncWebService.BodyContentVariable.Label=Request body content variable
+AsyncWebService.HeaderContentVariable.Label=Request header content variable
+AsyncWebService.HeaderContentVariable.Tooltip=This is the name of the variable
which at runtime will contain the content of the request header content.
+AsyncWebService.StatusVariables.Label=Status variables (, separated)
+AsyncWebService.Runconfiguration.Label=Workflow run configuration
+AsyncWebService.Runconfiguration.Tooltip=This is the workflow run
configuration to use on the server. If left blank a standard local workflow
engine is used.
\ No newline at end of file
diff --git
a/plugins/misc/async/src/test/java/org/apache/hop/www/async/AsyncGuiPluginTest.java
b/plugins/misc/async/src/test/java/org/apache/hop/www/async/AsyncGuiPluginTest.java
new file mode 100644
index 0000000000..e515cff07c
--- /dev/null
+++
b/plugins/misc/async/src/test/java/org/apache/hop/www/async/AsyncGuiPluginTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.hop.www.async;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+/** Test class for AsyncGuiPlugin */
+public class AsyncGuiPluginTest {
+
+ @Test
+ public void testGetInstance() {
+ AsyncGuiPlugin instance1 = AsyncGuiPlugin.getInstance();
+ AsyncGuiPlugin instance2 = AsyncGuiPlugin.getInstance();
+
+ assertNotNull(instance1);
+ assertSame(instance1, instance2);
+ }
+
+ @Test
+ public void testConstructor() {
+ AsyncGuiPlugin plugin = new AsyncGuiPlugin();
+ assertNotNull(plugin);
+ }
+
+ @Test
+ public void testActionIds() {
+
assertNotNull(AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_ENABLE_ASYNC_LOGGING);
+
assertNotNull(AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_DISABLE_ASYNC_LOGGING);
+
+
assertTrue(AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_ENABLE_ASYNC_LOGGING.contains("enable"));
+
assertTrue(AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_DISABLE_ASYNC_LOGGING.contains("disable"));
+
+
assertTrue(AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_ENABLE_ASYNC_LOGGING.contains("async"));
+
assertTrue(AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_DISABLE_ASYNC_LOGGING.contains("async"));
+ }
+
+ @Test
+ public void testActionIdUniqueness() {
+ assertTrue(
+ !AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_ENABLE_ASYNC_LOGGING.equals(
+ AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_DISABLE_ASYNC_LOGGING));
+ }
+
+ @Test
+ public void testActionIdFormat() {
+ String enableId =
AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_ENABLE_ASYNC_LOGGING;
+ String disableId =
AsyncGuiPlugin.ACTION_ID_WORKFLOW_GRAPH_DISABLE_ASYNC_LOGGING;
+
+ assertTrue(enableId.startsWith("workflow-graph-action"));
+ assertTrue(disableId.startsWith("workflow-graph-action"));
+
+ assertTrue(enableId.matches(".*\\d+.*"));
+ assertTrue(disableId.matches(".*\\d+.*"));
+ }
+
+ @Test
+ public void testSingletonBehavior() {
+ AsyncGuiPlugin instance1 = AsyncGuiPlugin.getInstance();
+ AsyncGuiPlugin instance2 = AsyncGuiPlugin.getInstance();
+ AsyncGuiPlugin instance3 = AsyncGuiPlugin.getInstance();
+
+ assertSame(instance1, instance2);
+ assertSame(instance2, instance3);
+ assertSame(instance1, instance3);
+ }
+
+ @Test
+ public void testInstanceNotNull() {
+ AsyncGuiPlugin instance = AsyncGuiPlugin.getInstance();
+ assertNotNull(instance);
+ assertTrue(instance instanceof AsyncGuiPlugin);
+ }
+}
diff --git
a/plugins/misc/async/src/test/java/org/apache/hop/www/async/AsyncStatusTest.java
b/plugins/misc/async/src/test/java/org/apache/hop/www/async/AsyncStatusTest.java
new file mode 100644
index 0000000000..819850a621
--- /dev/null
+++
b/plugins/misc/async/src/test/java/org/apache/hop/www/async/AsyncStatusTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.hop.www.async;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.hop.www.HopServerPipelineStatus;
+import org.junit.jupiter.api.Test;
+
+/** Test class for AsyncStatus */
+public class AsyncStatusTest {
+
+ @Test
+ public void testDefaultConstructor() {
+ AsyncStatus status = new AsyncStatus();
+
+ assertNotNull(status.getLogDate());
+ assertNotNull(status.getStatusVariables());
+ assertNotNull(status.getPipelineStatuses());
+
+ assertTrue(status.getStatusVariables().isEmpty());
+ assertTrue(status.getPipelineStatuses().isEmpty());
+ }
+
+ @Test
+ public void testSettersAndGetters() {
+ AsyncStatus status = new AsyncStatus();
+
+ String service = "test-service";
+ status.setService(service);
+ assertEquals(service, status.getService());
+
+ String id = "test-id-123";
+ status.setId(id);
+ assertEquals(id, status.getId());
+
+ Date logDate = new Date();
+ Date startDate = new Date(System.currentTimeMillis() - 1000);
+ Date endDate = new Date();
+
+ status.setLogDate(logDate);
+ status.setStartDate(startDate);
+ status.setEndDate(endDate);
+
+ assertEquals(logDate, status.getLogDate());
+ assertEquals(startDate, status.getStartDate());
+ assertEquals(endDate, status.getEndDate());
+
+ String statusDescription = "Running";
+ status.setStatusDescription(statusDescription);
+ assertEquals(statusDescription, status.getStatusDescription());
+ }
+
+ @Test
+ public void testStatusVariables() {
+ AsyncStatus status = new AsyncStatus();
+ Map<String, String> variables = new HashMap<>();
+
+ variables.put("VAR1", "value1");
+ variables.put("VAR2", "value2");
+ variables.put("VAR3", "value3");
+
+ status.setStatusVariables(variables);
+
+ assertEquals(variables, status.getStatusVariables());
+ assertEquals(3, status.getStatusVariables().size());
+ assertEquals("value1", status.getStatusVariables().get("VAR1"));
+ assertEquals("value2", status.getStatusVariables().get("VAR2"));
+ assertEquals("value3", status.getStatusVariables().get("VAR3"));
+ }
+
+ @Test
+ public void testPipelineStatuses() {
+ AsyncStatus status = new AsyncStatus();
+
+ HopServerPipelineStatus pipeline1 = new HopServerPipelineStatus();
+ pipeline1.setPipelineName("pipeline1");
+ pipeline1.setStatusDescription("Running");
+
+ HopServerPipelineStatus pipeline2 = new HopServerPipelineStatus();
+ pipeline2.setPipelineName("pipeline2");
+ pipeline2.setStatusDescription("Finished");
+
+ status.getPipelineStatuses().add(pipeline1);
+ status.getPipelineStatuses().add(pipeline2);
+
+ assertEquals(2, status.getPipelineStatuses().size());
+ assertTrue(status.getPipelineStatuses().contains(pipeline1));
+ assertTrue(status.getPipelineStatuses().contains(pipeline2));
+ }
+}
diff --git
a/plugins/misc/async/src/test/java/org/apache/hop/www/async/AsyncWebServiceTest.java
b/plugins/misc/async/src/test/java/org/apache/hop/www/async/AsyncWebServiceTest.java
new file mode 100644
index 0000000000..28d9bf9668
--- /dev/null
+++
b/plugins/misc/async/src/test/java/org/apache/hop/www/async/AsyncWebServiceTest.java
@@ -0,0 +1,137 @@
+/*
+ * 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.hop.www.async;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.List;
+import org.apache.hop.core.variables.Variables;
+import org.junit.jupiter.api.Test;
+
+/** Test class for AsyncWebService */
+public class AsyncWebServiceTest {
+
+ @Test
+ public void testDefaultConstructor() {
+ AsyncWebService webService = new AsyncWebService();
+
+ assertTrue(webService.isEnabled());
+ assertEquals("ASYNC_CONTENT", webService.getBodyContentVariable());
+ }
+
+ @Test
+ public void testParameterizedConstructor() {
+ String name = "test-service";
+ boolean enabled = false;
+ String filename = "/path/to/workflow.hwf";
+ String statusVariables = "VAR1,VAR2,VAR3";
+ String bodyContentVariable = "CUSTOM_CONTENT";
+ String runConfigurationName = "test-run-config";
+ String headerContentVariable = "HEADER_CONTENT";
+
+ AsyncWebService webService =
+ new AsyncWebService(
+ name,
+ enabled,
+ filename,
+ statusVariables,
+ bodyContentVariable,
+ runConfigurationName,
+ headerContentVariable);
+
+ assertEquals(name, webService.getName());
+ assertEquals(enabled, webService.isEnabled());
+ assertEquals(filename, webService.getFilename());
+ assertEquals(statusVariables, webService.getStatusVariables());
+ assertEquals(bodyContentVariable, webService.getBodyContentVariable());
+ assertEquals(runConfigurationName, webService.getRunConfigurationName());
+ assertEquals(headerContentVariable, webService.getHeaderContentVariable());
+ }
+
+ @Test
+ public void testSettersAndGetters() {
+ AsyncWebService webService = new AsyncWebService();
+
+ webService.setEnabled(false);
+ assertFalse(webService.isEnabled());
+ webService.setEnabled(true);
+ assertTrue(webService.isEnabled());
+
+ String filename = "/test/workflow.hwf";
+ webService.setFilename(filename);
+ assertEquals(filename, webService.getFilename());
+
+ String statusVariables = "STATUS_VAR1,STATUS_VAR2";
+ webService.setStatusVariables(statusVariables);
+ assertEquals(statusVariables, webService.getStatusVariables());
+
+ String bodyContentVariable = "BODY_VAR";
+ webService.setBodyContentVariable(bodyContentVariable);
+ assertEquals(bodyContentVariable, webService.getBodyContentVariable());
+
+ String runConfigurationName = "RUN_CONFIG";
+ webService.setRunConfigurationName(runConfigurationName);
+ assertEquals(runConfigurationName, webService.getRunConfigurationName());
+
+ String headerContentVariable = "HEADER_VAR";
+ webService.setHeaderContentVariable(headerContentVariable);
+ assertEquals(headerContentVariable, webService.getHeaderContentVariable());
+ }
+
+ @Test
+ public void testGetStatusVariablesList() {
+ AsyncWebService webService = new AsyncWebService();
+ Variables variables = new Variables();
+
+ webService.setStatusVariables("");
+ List<String> emptyList = webService.getStatusVariablesList(variables);
+ assertTrue(emptyList.isEmpty());
+
+ webService.setStatusVariables(null);
+ List<String> nullList = webService.getStatusVariablesList(variables);
+ assertTrue(nullList.isEmpty());
+
+ webService.setStatusVariables("VAR1");
+ List<String> singleList = webService.getStatusVariablesList(variables);
+ assertEquals(1, singleList.size());
+ assertEquals("VAR1", singleList.get(0));
+
+ webService.setStatusVariables("VAR1,VAR2,VAR3");
+ List<String> multipleList = webService.getStatusVariablesList(variables);
+ assertEquals(3, multipleList.size());
+ assertEquals("VAR1", multipleList.get(0));
+ assertEquals("VAR2", multipleList.get(1));
+ assertEquals("VAR3", multipleList.get(2));
+ }
+
+ @Test
+ public void testGetStatusVariablesListWithVariableResolution() {
+ AsyncWebService webService = new AsyncWebService();
+ Variables variables = new Variables();
+
+ variables.setVariable("STATUS_VARS", "RESOLVED_VAR1,RESOLVED_VAR2");
+ webService.setStatusVariables("${STATUS_VARS}");
+
+ List<String> resolvedList = webService.getStatusVariablesList(variables);
+ assertEquals(2, resolvedList.size());
+ assertEquals("RESOLVED_VAR1", resolvedList.get(0));
+ assertEquals("RESOLVED_VAR2", resolvedList.get(1));
+ }
+}
diff --git
a/plugins/misc/async/src/test/java/org/apache/hop/www/async/DefaultsTest.java
b/plugins/misc/async/src/test/java/org/apache/hop/www/async/DefaultsTest.java
new file mode 100644
index 0000000000..67ed127786
--- /dev/null
+++
b/plugins/misc/async/src/test/java/org/apache/hop/www/async/DefaultsTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.hop.www.async;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+/** Test class for Defaults */
+public class DefaultsTest {
+
+ @Test
+ public void testAsyncStatusGroup() {
+ assertNotNull(Defaults.ASYNC_STATUS_GROUP);
+ assertEquals("ASYNC_STATUS_GROUP", Defaults.ASYNC_STATUS_GROUP);
+ }
+
+ @Test
+ public void testAsyncActionPipelineServiceName() {
+ assertNotNull(Defaults.ASYNC_ACTION_PIPELINE_SERVICE_NAME);
+ assertEquals(
+ "enable-asynchronous-pipeline-service-name",
Defaults.ASYNC_ACTION_PIPELINE_SERVICE_NAME);
+ }
+
+ @Test
+ public void testConstantsAreNotBlank() {
+ assertNotNull(Defaults.ASYNC_STATUS_GROUP);
+ assertNotNull(Defaults.ASYNC_ACTION_PIPELINE_SERVICE_NAME);
+
+ assertTrue(!Defaults.ASYNC_STATUS_GROUP.trim().isEmpty());
+ assertTrue(!Defaults.ASYNC_ACTION_PIPELINE_SERVICE_NAME.trim().isEmpty());
+ }
+
+ @Test
+ public void testConstantsAreDifferent() {
+
assertTrue(!Defaults.ASYNC_STATUS_GROUP.equals(Defaults.ASYNC_ACTION_PIPELINE_SERVICE_NAME));
+ }
+
+ @Test
+ public void testConstantsFormat() {
+ assertTrue(Defaults.ASYNC_STATUS_GROUP.contains("ASYNC"));
+ assertTrue(Defaults.ASYNC_ACTION_PIPELINE_SERVICE_NAME.contains("async"));
+
+ assertTrue(Defaults.ASYNC_STATUS_GROUP.contains("STATUS"));
+
assertTrue(Defaults.ASYNC_ACTION_PIPELINE_SERVICE_NAME.contains("pipeline"));
+ }
+}
diff --git
a/ui/src/main/java/org/apache/hop/ui/www/service/WebServiceEditor.java
b/ui/src/main/java/org/apache/hop/ui/www/service/WebServiceEditor.java
index 31eb27e6c5..6b3a124859 100644
--- a/ui/src/main/java/org/apache/hop/ui/www/service/WebServiceEditor.java
+++ b/ui/src/main/java/org/apache/hop/ui/www/service/WebServiceEditor.java
@@ -189,10 +189,8 @@ public class WebServiceEditor extends
MetadataEditor<WebService> {
PipelineRunConfiguration.class,
parent,
SWT.NONE,
- "Pipeline run configuration",
- "This is the pipeline run configuration to use on the server. "
- + "If left blank a standard local pipeline engine is used. "
- + "To return values please use a local pipeline engine.");
+ BaseMessages.getString(PKG,
"WebServiceEditor.Runconfiguration.Label"),
+ BaseMessages.getString(PKG,
"WebServiceEditor.Runconfiguration.Tooltip"));
FormData fdRunConfiguration = new FormData();
fdRunConfiguration.left = new FormAttachment(0, 0);
fdRunConfiguration.top = new FormAttachment(lastControl, margin);
diff --git
a/ui/src/main/resources/org/apache/hop/ui/www/service/messages/messages_en_US.properties
b/ui/src/main/resources/org/apache/hop/ui/www/service/messages/messages_en_US.properties
index 7c8cb4612e..ddc4a326a0 100644
---
a/ui/src/main/resources/org/apache/hop/ui/www/service/messages/messages_en_US.properties
+++
b/ui/src/main/resources/org/apache/hop/ui/www/service/messages/messages_en_US.properties
@@ -39,3 +39,5 @@ WebserviceGuiPlugin.GuiAction.SelectOutputField.Label=Select
the output field
WebserviceGuiPlugin.GuiAction.SelectService.Description=Select the web service
to update
WebserviceGuiPlugin.GuiAction.SelectService.Label=Select a web service
WebserviceGuiPlugin.GuiAction.ToolTip=Use the output of this transform as a
web service with Hop Server
+WebServiceEditor.Runconfiguration.Label=Pipeline run configuration
+WebServiceEditor.Runconfiguration.Tooltip=This is the pipeline run
configuration to use on the server. If left blank a standard local pipeline
engine is used. To return values please use a local pipeline engine.
\ No newline at end of file