diff --git a/.gitignore b/.gitignore
index 1dfd7048..4d08f121 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,4 +29,7 @@ target/
build/
### VS Code ###
-.vscode/
\ No newline at end of file
+.vscode/
+
+# Bob-Shell
+.bob/notes/
\ No newline at end of file
diff --git a/experimental/fluent/func/src/test/java/io/serverlessworkflow/fluent/func/FuncDSLTest.java b/experimental/fluent/func/src/test/java/io/serverlessworkflow/fluent/func/FuncDSLTest.java
index a11d2c75..a6520977 100644
--- a/experimental/fluent/func/src/test/java/io/serverlessworkflow/fluent/func/FuncDSLTest.java
+++ b/experimental/fluent/func/src/test/java/io/serverlessworkflow/fluent/func/FuncDSLTest.java
@@ -266,7 +266,13 @@ void get_named_with_authentication_uses_auth_policy() {
assertEquals("GET", http.getWith().getMethod());
assertEquals(
"http://service/api/users",
- http.getWith().getEndpoint().getUriTemplate().getLiteralUri().toString(),
+ http.getWith()
+ .getEndpoint()
+ .getEndpointConfiguration()
+ .getUri()
+ .getLiteralEndpointURI()
+ .getLiteralUri()
+ .toString(),
"endpoint should be set from get(name, endpoint, auth)");
assertNotNull(
@@ -371,7 +377,13 @@ void post_named_with_authentication() {
assertEquals("POST", http.getWith().getMethod());
assertEquals(
"https://orders.example.com/api/orders",
- http.getWith().getEndpoint().getUriTemplate().getLiteralUri().toString());
+ http.getWith()
+ .getEndpoint()
+ .getEndpointConfiguration()
+ .getUri()
+ .getLiteralEndpointURI()
+ .getLiteralUri()
+ .toString());
assertEquals(body, http.getWith().getBody());
assertNotNull(http.getWith().getEndpoint().getEndpointConfiguration().getAuthentication());
@@ -409,7 +421,13 @@ void call_with_preconfigured_http_spec() {
assertEquals("POST", http.getWith().getMethod());
assertEquals(
"http://service/api",
- http.getWith().getEndpoint().getUriTemplate().getLiteralUri().toString());
+ http.getWith()
+ .getEndpoint()
+ .getEndpointConfiguration()
+ .getUri()
+ .getLiteralEndpointURI()
+ .getLiteralUri()
+ .toString());
assertEquals(
"svc-auth",
http.getWith()
diff --git a/experimental/test/pom.xml b/experimental/test/pom.xml
index 5661f582..6cf53a5c 100644
--- a/experimental/test/pom.xml
+++ b/experimental/test/pom.xml
@@ -71,6 +71,13 @@
io.serverlessworkflow
serverlessworkflow-impl-jq
+ test
+
+
+ io.serverlessworkflow
+ serverlessworkflow-impl-openapi
+ ${project.version}
+ test
org.glassfish.jersey.media
diff --git a/experimental/test/src/test/java/io/serverlessworkflow/fluent/test/FuncOpenAPITest.java b/experimental/test/src/test/java/io/serverlessworkflow/fluent/test/FuncOpenAPITest.java
new file mode 100644
index 00000000..dbcdd207
--- /dev/null
+++ b/experimental/test/src/test/java/io/serverlessworkflow/fluent/test/FuncOpenAPITest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2020-Present The Serverless Workflow Specification Authors
+ *
+ * Licensed 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 io.serverlessworkflow.fluent.test;
+
+import static io.serverlessworkflow.fluent.func.dsl.FuncDSL.openapi;
+
+import io.serverlessworkflow.fluent.func.FuncWorkflowBuilder;
+import io.serverlessworkflow.impl.WorkflowApplication;
+import io.serverlessworkflow.impl.WorkflowDefinition;
+import io.serverlessworkflow.impl.WorkflowInstance;
+import io.serverlessworkflow.impl.WorkflowModel;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Map;
+import mockwebserver3.MockResponse;
+import mockwebserver3.MockWebServer;
+import okhttp3.Headers;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class FuncOpenAPITest {
+
+ private static MockWebServer mockWebServer;
+
+ @BeforeEach
+ public void setup() throws IOException {
+ mockWebServer = new MockWebServer();
+ mockWebServer.start(0);
+ }
+
+ @AfterEach
+ public void tearDown() {
+ mockWebServer.close();
+ }
+
+ @Test
+ void test_openapi_document_with_non_jq_uri_string() {
+ String mockedSwaggerDoc =
+ """
+ {
+ "swagger": "2.0",
+ "info": { "version": "1.0.0", "title": "Mock Petstore" },
+ "host": "localhost:%d",
+ "basePath": "/v2",
+ "schemes": [ "http" ],
+ "paths": {
+ "/pet/findByStatus": {
+ "get": {
+ "operationId": "findPetsByStatus",
+ "parameters": [
+ {
+ "name": "status",
+ "in": "query",
+ "required": true,
+ "type": "string"
+ }
+ ],
+ "responses": { "200": { "description": "OK" } }
+ }
+ }
+ }
+ }
+ """
+ .formatted(mockWebServer.getPort());
+
+ mockWebServer.enqueue(
+ new MockResponse(200, Headers.of("Content-Type", "application/json"), mockedSwaggerDoc));
+ mockWebServer.enqueue(
+ new MockResponse(
+ 200,
+ Headers.of("Content-Type", "application/json"),
+ """
+ { "description": "OK" }
+ """));
+ var w =
+ FuncWorkflowBuilder.workflow("openapi-call-workflow")
+ .tasks(
+ openapi()
+ .document(URI.create(mockWebServer.url("/v2/swagger.json").toString()))
+ .operation("findPetsByStatus")
+ .parameters(Map.of("status", "available")))
+ .build();
+
+ try (WorkflowApplication app = WorkflowApplication.builder().build()) {
+
+ WorkflowDefinition def = app.workflowDefinition(w);
+ WorkflowInstance instance = def.instance(Map.of());
+ WorkflowModel model = instance.start().join();
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(model).isNotNull();
+ softly.assertThat(model.asMap()).contains(Map.of("description", "OK"));
+ });
+ }
+ }
+}
diff --git a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpTaskFluent.java b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpTaskFluent.java
index 61cf0db6..89ca52fd 100644
--- a/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpTaskFluent.java
+++ b/fluent/spec/src/main/java/io/serverlessworkflow/fluent/spec/spi/CallHttpTaskFluent.java
@@ -84,23 +84,21 @@ default SELF endpoint(String expr, Consumer= 0 || trimmed.indexOf('}') >= 0) {
- template.setLiteralUriTemplate(trimmed);
- } else {
- template.setLiteralUri(URI.create(trimmed));
- }
- endpoint.setUriTemplate(template);
- return endpoint;
- }
- // Let the runtime engine to verify if it's a valid jq expression since ${} it's not the only
- // way of checking it.
- endpoint.setRuntimeExpression(expr);
+ if (auth != null) {
+ endpoint.setEndpointConfiguration(
+ new EndpointConfiguration(buildEndpointUri(trimmed)).withAuthentication(auth));
+ } else if (isUrlLike(trimmed)) {
+ endpoint.setUriTemplate(buildUriTemplate(trimmed));
+ } else {
+ // Let the runtime engine to verify if it's a valid jq expression since ${} it's not the only
+ // way of checking it.
+ endpoint.setRuntimeExpression(uri);
+ }
return endpoint;
}
+ private static EndpointUri buildEndpointUri(String uri) {
+ EndpointUri endpointUri = new EndpointUri();
+ if (isUrlLike(uri)) {
+ endpointUri.setLiteralEndpointURI(buildUriTemplate(uri));
+ } else {
+ endpointUri.setExpressionEndpointURI(uri);
+ }
+ return endpointUri;
+ }
+
+ private static UriTemplate buildUriTemplate(String trimmed) {
+ UriTemplate template = new UriTemplate();
+ if (trimmed.indexOf('{') >= 0 || trimmed.indexOf('}') >= 0) {
+ template.setLiteralUriTemplate(trimmed);
+ } else {
+ template.setLiteralUri(URI.create(trimmed));
+ }
+ return template;
+ }
+
private static boolean isUrlLike(String value) {
// same idea as UriTemplate.literalUriTemplate_Pattern: ^[A-Za-z][A-Za-z0-9+\\-.]*://.*
int idx = value.indexOf("://");
diff --git a/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/CallHttpAuthDslTest.java b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/CallHttpAuthDslTest.java
index 874cce3b..94fedc45 100644
--- a/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/CallHttpAuthDslTest.java
+++ b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/CallHttpAuthDslTest.java
@@ -47,7 +47,8 @@ void when_call_http_with_basic_auth_on_endpoint_expr() {
assertThat(wf.getDo().get(0).getTask().getCallTask().get()).isNotNull();
// Endpoint expression is set
- assertThat(args.getEndpoint().getRuntimeExpression()).isEqualTo(EXPR_ENDPOINT);
+ assertThat(args.getEndpoint().getEndpointConfiguration().getUri().getExpressionEndpointURI())
+ .isEqualTo(EXPR_ENDPOINT);
// Auth populated: BASIC (others null)
var auth =
@@ -83,7 +84,8 @@ void when_call_http_with_bearer_auth_on_endpoint_expr() {
var args = wf.getDo().get(0).getTask().getCallTask().getCallHTTP().getWith();
- assertThat(args.getEndpoint().getRuntimeExpression()).isEqualTo(EXPR_ENDPOINT);
+ assertThat(args.getEndpoint().getEndpointConfiguration().getUri().getExpressionEndpointURI())
+ .isEqualTo(EXPR_ENDPOINT);
var auth =
args.getEndpoint().getEndpointConfiguration().getAuthentication().getAuthenticationPolicy();
@@ -112,7 +114,8 @@ void when_call_http_with_digest_auth_on_endpoint_expr() {
var args = wf.getDo().get(0).getTask().getCallTask().getCallHTTP().getWith();
- assertThat(args.getEndpoint().getRuntimeExpression()).isEqualTo(EXPR_ENDPOINT);
+ assertThat(args.getEndpoint().getEndpointConfiguration().getUri().getExpressionEndpointURI())
+ .isEqualTo(EXPR_ENDPOINT);
var auth =
args.getEndpoint().getEndpointConfiguration().getAuthentication().getAuthenticationPolicy();
@@ -158,7 +161,8 @@ void when_call_http_with_oidc_auth_on_endpoint_expr_with_client() {
var args = wf.getDo().get(0).getTask().getCallTask().getCallHTTP().getWith();
- assertThat(args.getEndpoint().getRuntimeExpression()).isEqualTo(EXPR_ENDPOINT);
+ assertThat(args.getEndpoint().getEndpointConfiguration().getUri().getExpressionEndpointURI())
+ .isEqualTo(EXPR_ENDPOINT);
var auth =
args.getEndpoint().getEndpointConfiguration().getAuthentication().getAuthenticationPolicy();
@@ -203,7 +207,8 @@ void when_call_http_with_oauth2_alias_on_endpoint_expr_without_client() {
var args = wf.getDo().get(0).getTask().getCallTask().getCallHTTP().getWith();
- assertThat(args.getEndpoint().getRuntimeExpression()).isEqualTo(EXPR_ENDPOINT);
+ assertThat(args.getEndpoint().getEndpointConfiguration().getUri().getExpressionEndpointURI())
+ .isEqualTo(EXPR_ENDPOINT);
var auth =
args.getEndpoint().getEndpointConfiguration().getAuthentication().getAuthenticationPolicy();
diff --git a/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/CallOpenApiDslTest.java b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/CallOpenApiDslTest.java
index 70a91f28..fc2cc4b6 100644
--- a/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/CallOpenApiDslTest.java
+++ b/fluent/spec/src/test/java/io/serverlessworkflow/fluent/spec/dsl/CallOpenApiDslTest.java
@@ -55,7 +55,13 @@ void when_call_openapi_with_basic_auth_on_document_expr() {
// Document and endpoint expression
assertThat(with.getDocument()).isNotNull();
assertThat(with.getDocument().getEndpoint()).isNotNull();
- assertThat(with.getDocument().getEndpoint().getRuntimeExpression()).isEqualTo(EXPR_DOCUMENT);
+ assertThat(
+ with.getDocument()
+ .getEndpoint()
+ .getEndpointConfiguration()
+ .getUri()
+ .getExpressionEndpointURI())
+ .isEqualTo(EXPR_DOCUMENT);
// Endpoint configuration URI expression
var endpointConfig = with.getDocument().getEndpoint().getEndpointConfiguration();