From 6bb33806a29076eb286820ade002bbd54f2acccf Mon Sep 17 00:00:00 2001 From: Helber Belmiro Date: Wed, 23 Aug 2023 08:11:12 -0300 Subject: [PATCH] KOGITO-8410 Added support for GET method to Knative custom function (#3172) * KOGITO-8410 Added support to GET method to Knative custom function Signed-off-by: Helber Belmiro * KOGITO-8410 Added support for Number and Boolean to GetRequestKnativeParamsDecorator Signed-off-by: Helber Belmiro * KOGITO-8410 Removed GetRequestKnativeParamsDecorator Signed-off-by: Helber Belmiro * KOGITO-8410 Replaced PrefixParamsDecorator with CollectionParamsDecorator Signed-off-by: Helber Belmiro --------- Signed-off-by: Helber Belmiro --- .../CollectionParamsDecoratorSupplier.java | 0 .../customfunctions/KnativeTypeHandler.java | 46 ++++++++++------ .../main/resources/getKnativeFunction.sw.json | 31 +++++++++++ .../it/KnativeServingAddonIT.java | 27 ++++++++++ .../KnativeFunctionPayloadSupplier.java | 12 ++--- .../KnativeWorkItemHandler.java | 2 - .../serving/customfunctions/Operation.java | 54 +++++++++++++++++-- .../customfunctions/OperationTest.java | 38 ++++++++++--- .../customfunctions/WebClientProducer.java | 34 ++++++++++++ 9 files changed, 209 insertions(+), 35 deletions(-) rename kogito-serverless-workflow/{kogito-serverless-workflow-openapi-parser => kogito-serverless-workflow-rest-parser}/src/main/java/org/kie/kogito/serverless/workflow/suppliers/CollectionParamsDecoratorSupplier.java (100%) create mode 100644 quarkus/addons/knative/serving/integration-tests/src/main/resources/getKnativeFunction.sw.json create mode 100644 quarkus/addons/knative/serving/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/WebClientProducer.java diff --git a/kogito-serverless-workflow/kogito-serverless-workflow-openapi-parser/src/main/java/org/kie/kogito/serverless/workflow/suppliers/CollectionParamsDecoratorSupplier.java b/kogito-serverless-workflow/kogito-serverless-workflow-rest-parser/src/main/java/org/kie/kogito/serverless/workflow/suppliers/CollectionParamsDecoratorSupplier.java similarity index 100% rename from kogito-serverless-workflow/kogito-serverless-workflow-openapi-parser/src/main/java/org/kie/kogito/serverless/workflow/suppliers/CollectionParamsDecoratorSupplier.java rename to kogito-serverless-workflow/kogito-serverless-workflow-rest-parser/src/main/java/org/kie/kogito/serverless/workflow/suppliers/CollectionParamsDecoratorSupplier.java diff --git a/quarkus/addons/knative/serving/deployment/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/customfunctions/KnativeTypeHandler.java b/quarkus/addons/knative/serving/deployment/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/customfunctions/KnativeTypeHandler.java index 0319463bc40..b46269a3871 100644 --- a/quarkus/addons/knative/serving/deployment/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/customfunctions/KnativeTypeHandler.java +++ b/quarkus/addons/knative/serving/deployment/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/deployment/customfunctions/KnativeTypeHandler.java @@ -23,6 +23,7 @@ import org.jbpm.ruleflow.core.RuleFlowNodeContainerFactory; import org.jbpm.ruleflow.core.factory.NodeFactory; import org.jbpm.ruleflow.core.factory.WorkItemNodeFactory; +import org.jetbrains.annotations.NotNull; import org.kie.kogito.addons.quarkus.knative.serving.customfunctions.CloudEventKnativeParamsDecorator; import org.kie.kogito.addons.quarkus.knative.serving.customfunctions.KnativeWorkItemHandler; import org.kie.kogito.addons.quarkus.knative.serving.customfunctions.Operation; @@ -30,6 +31,7 @@ import org.kie.kogito.serverless.workflow.parser.ParserContext; import org.kie.kogito.serverless.workflow.parser.VariableInfo; import org.kie.kogito.serverless.workflow.parser.types.WorkItemTypeHandler; +import org.kie.kogito.serverless.workflow.suppliers.CollectionParamsDecoratorSupplier; import org.kie.kogito.serverless.workflow.suppliers.ParamsRestBodyBuilderSupplier; import org.kogito.workitem.rest.RestWorkItemHandler; @@ -57,19 +59,42 @@ public class KnativeTypeHandler extends WorkItemTypeHandler { WorkItemNodeFactory node = buildWorkItem(embeddedSubProcess, context, varInfo.getInputVar(), varInfo.getOutputVar()) .name(functionDef.getName()); - if (functionRef.getArguments() != null && !functionRef.getArguments().isEmpty()) { - List payloadFields = new ArrayList<>(); - functionRef.getArguments().fieldNames().forEachRemaining(payloadFields::add); + List payloadFields = getPayloadFields(functionRef); + + Operation operation = Operation.parse(trimCustomOperation(functionDef)); + + if (HttpMethod.GET.equals(operation.getHttpMethod())) { + node.workParameter(RestWorkItemHandler.PARAMS_DECORATOR, new CollectionParamsDecoratorSupplier(List.of(), payloadFields)); + } else { if (!payloadFields.isEmpty()) { - node.workParameter(PAYLOAD_FIELDS_PROPERTY_NAME, String.join(";", payloadFields)); + node.workParameter(PAYLOAD_FIELDS_PROPERTY_NAME, payloadFields); + } + if (operation.isCloudEvent()) { + node.workParameter(RestWorkItemHandler.PARAMS_DECORATOR, CloudEventKnativeParamsDecorator.class.getName()); + } else { + node.workParameter(RestWorkItemHandler.PARAMS_DECORATOR, PlainJsonKnativeParamsDecorator.class.getName()); } } + node.workParameter(KnativeWorkItemHandler.SERVICE_PROPERTY_NAME, operation.getService()) + .workParameter(KnativeWorkItemHandler.PATH_PROPERTY_NAME, operation.getPath()) + .workParameter(RestWorkItemHandler.METHOD, operation.getHttpMethod()); + return addFunctionArgs(workflow, fillWorkItemHandler(workflow, context, node, functionDef), functionRef); } + @NotNull + private static List getPayloadFields(FunctionRef functionRef) { + List payloadFields = new ArrayList<>(); + + if (functionRef.getArguments() != null && !functionRef.getArguments().isEmpty()) { + functionRef.getArguments().fieldNames().forEachRemaining(payloadFields::add); + } + return payloadFields; + } + @Override protected > WorkItemNodeFactory fillWorkItemHandler( Workflow workflow, ParserContext context, WorkItemNodeFactory node, FunctionDefinition functionDef) { @@ -77,21 +102,10 @@ public class KnativeTypeHandler extends WorkItemTypeHandler { functionDef.getMetadata().forEach(node::metaData); } - Operation operation = Operation.parse(trimCustomOperation(functionDef)); - - if (operation.isCloudEvent()) { - node.workParameter(RestWorkItemHandler.PARAMS_DECORATOR, CloudEventKnativeParamsDecorator.class.getName()); - } else { - node.workParameter(RestWorkItemHandler.PARAMS_DECORATOR, PlainJsonKnativeParamsDecorator.class.getName()); - } - Supplier requestTimeout = runtimeRestApi(functionDef, "timeout", context.getContext(), String.class, DEFAULT_REQUEST_TIMEOUT_VALUE); - return node.workParameter(KnativeWorkItemHandler.SERVICE_PROPERTY_NAME, operation.getService()) - .workParameter(KnativeWorkItemHandler.PATH_PROPERTY_NAME, operation.getPath()) - .workParameter(RestWorkItemHandler.BODY_BUILDER, new ParamsRestBodyBuilderSupplier()) - .workParameter(RestWorkItemHandler.METHOD, HttpMethod.POST) + return node.workParameter(RestWorkItemHandler.BODY_BUILDER, new ParamsRestBodyBuilderSupplier()) .workParameter(RestWorkItemHandler.REQUEST_TIMEOUT_IN_MILLIS, requestTimeout) .metaData(TaskDescriptor.KEY_WORKITEM_TYPE, RestWorkItemHandler.REST_TASK_TYPE) .workName(KnativeWorkItemHandler.NAME); diff --git a/quarkus/addons/knative/serving/integration-tests/src/main/resources/getKnativeFunction.sw.json b/quarkus/addons/knative/serving/integration-tests/src/main/resources/getKnativeFunction.sw.json new file mode 100644 index 00000000000..1802240e120 --- /dev/null +++ b/quarkus/addons/knative/serving/integration-tests/src/main/resources/getKnativeFunction.sw.json @@ -0,0 +1,31 @@ +{ + "id": "getKnativeFunction", + "version": "1.0", + "name": "Test Knative function", + "description": "This workflow tests a Knative function", + "start": "invokeFunction", + "functions": [ + { + "name": "greet", + "type": "custom", + "operation": "knative:services.v1.serving.knative.dev/default/serverless-workflow-greeting-quarkus?path=/plainJsonFunction&method=GET" + } + ], + "states": [ + { + "name": "invokeFunction", + "type": "operation", + "actions": [ + { + "functionRef": { + "refName": "greet", + "arguments": { + "name": ".name" + } + } + } + ], + "end": true + } + ] +} diff --git a/quarkus/addons/knative/serving/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/it/KnativeServingAddonIT.java b/quarkus/addons/knative/serving/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/it/KnativeServingAddonIT.java index 60b92485d7d..d360391c6e5 100644 --- a/quarkus/addons/knative/serving/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/it/KnativeServingAddonIT.java +++ b/quarkus/addons/knative/serving/integration-tests/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/it/KnativeServingAddonIT.java @@ -37,6 +37,8 @@ import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath; import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; @@ -85,6 +87,22 @@ static void afterAll() { } } + @Test + void executeHttpGet() { + mockExecuteHttpGetEndpoint(); + + given() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body("{\"name\": \"hbelmiro\" }").when() + .post("/getKnativeFunction") + .then() + .statusCode(HttpURLConnection.HTTP_CREATED) + .body("workflowdata.message", is("Hello")); + + wireMockServer.verify(getRequestedFor(urlEqualTo("/plainJsonFunction?name=hbelmiro"))); + } + @Test void executeWithEmptyParameters() { mockExecuteWithEmptyParametersEndpoint(); @@ -306,6 +324,15 @@ private void mockExecuteWithParametersEndpoint() { .put("message", "Hello")))); } + private void mockExecuteHttpGetEndpoint() { + wireMockServer.stubFor(get(urlEqualTo("/plainJsonFunction?name=hbelmiro")) + .willReturn(aResponse() + .withStatus(HttpURLConnection.HTTP_OK) + .withHeader("Content-Type", "application/json") + .withJsonBody(JsonNodeFactory.instance.objectNode() + .put("message", "Hello")))); + } + private void mockExecuteWithArrayEndpoint() { wireMockServer.stubFor(post(urlEqualTo("/arrayFunction")) .withRequestBody(equalToJson(JsonNodeFactory.instance.objectNode() diff --git a/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/KnativeFunctionPayloadSupplier.java b/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/KnativeFunctionPayloadSupplier.java index a5f2bd5fa9a..bad93914de8 100644 --- a/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/KnativeFunctionPayloadSupplier.java +++ b/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/KnativeFunctionPayloadSupplier.java @@ -15,13 +15,12 @@ */ package org.kie.kogito.addons.quarkus.knative.serving.customfunctions; -import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.function.Function; import static java.util.stream.Collectors.toMap; -import static org.kie.kogito.addons.quarkus.knative.serving.customfunctions.KnativeWorkItemHandler.PAYLOAD_FIELDS_DELIMITER; import static org.kie.kogito.addons.quarkus.knative.serving.customfunctions.KnativeWorkItemHandler.PAYLOAD_FIELDS_PROPERTY_NAME; final class KnativeFunctionPayloadSupplier { @@ -35,11 +34,8 @@ static Map getPayload(Map parameters) { } private static List getPayloadFields(Map parameters) { - String payloadFields = (String) parameters.remove(PAYLOAD_FIELDS_PROPERTY_NAME); - if (payloadFields != null) { - return Arrays.asList(payloadFields.split(PAYLOAD_FIELDS_DELIMITER)); - } else { - return List.of(); - } + @SuppressWarnings("unchecked") + List payloadFields = (List) parameters.remove(PAYLOAD_FIELDS_PROPERTY_NAME); + return Objects.requireNonNullElseGet(payloadFields, List::of); } } diff --git a/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/KnativeWorkItemHandler.java b/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/KnativeWorkItemHandler.java index 696c2685359..8ae77622bf8 100644 --- a/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/KnativeWorkItemHandler.java +++ b/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/KnativeWorkItemHandler.java @@ -43,8 +43,6 @@ public final class KnativeWorkItemHandler extends RestWorkItemHandler { public static final String PAYLOAD_FIELDS_PROPERTY_NAME = "knative_function_payload_fields"; - public static final String PAYLOAD_FIELDS_DELIMITER = ";"; - public static final String CLOUDEVENT_SENT_AS_PLAIN_JSON_ERROR_MESSAGE = "A Knative custom function argument cannot be a CloudEvent when the 'asCloudEvent' property are not set to 'true'"; private final KubernetesServiceCatalog kubernetesServiceCatalog; diff --git a/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/Operation.java b/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/Operation.java index 95b1c995382..acbfc13fb12 100644 --- a/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/Operation.java +++ b/quarkus/addons/knative/serving/runtime/src/main/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/Operation.java @@ -15,26 +15,51 @@ */ package org.kie.kogito.addons.quarkus.knative.serving.customfunctions; +import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Set; + +import io.vertx.core.http.HttpMethod; public final class Operation { + private static final Set SUPPORTED_METHODS = Set.of(HttpMethod.POST, HttpMethod.GET); + + private static final HttpMethod DEFAULT_HTTP_METHOD = HttpMethod.POST; + static final String CLOUD_EVENT_PARAMETER_NAME = "asCloudEvent"; static final String PATH_PARAMETER_NAME = "path"; + static final String METHOD_PARAMETER_NAME = "method"; + private final String service; private final String path; private final boolean isCloudEvent; + private final HttpMethod httpMethod; + private Operation(Builder builder) { this.service = Objects.requireNonNull(builder.service); this.path = builder.path != null ? builder.path : "/"; this.isCloudEvent = builder.isCloudEvent; + this.httpMethod = builder.httpMethod; + validate(this); + } + + private static void validate(Operation operation) { + if (!SUPPORTED_METHODS.contains(operation.getHttpMethod())) { + throw new UnsupportedOperationException( + MessageFormat.format("Knative custom function doesn''t support the {0} HTTP method. Supported methods are: {1}.", operation.getHttpMethod(), SUPPORTED_METHODS)); + } + + if (operation.isCloudEvent() && !operation.getHttpMethod().equals(HttpMethod.POST)) { + throw new UnsupportedOperationException(MessageFormat.format("Knative custom function can only send CloudEvents through POST method. Method used: {0}", operation.getHttpMethod())); + } } public String getService() { @@ -49,6 +74,10 @@ public boolean isCloudEvent() { return isCloudEvent; } + public HttpMethod getHttpMethod() { + return httpMethod; + } + public static Operation parse(String value) { String[] parts = value.split("\\?", 2); @@ -61,8 +90,9 @@ public static Operation parse(String value) { return builder() .withService(parts[0]) - .withPath(params.get("path")) + .withPath(params.get(PATH_PARAMETER_NAME)) .withIsCloudEvent(Boolean.parseBoolean(params.get(CLOUD_EVENT_PARAMETER_NAME))) + .withMethod(HttpMethod.valueOf(params.getOrDefault(METHOD_PARAMETER_NAME, DEFAULT_HTTP_METHOD.name()).toUpperCase())) .build(); } @@ -81,12 +111,23 @@ public boolean equals(Object o) { Operation operation = (Operation) o; return isCloudEvent == operation.isCloudEvent && Objects.equals(service, operation.service) - && Objects.equals(path, operation.path); + && Objects.equals(path, operation.path) + && Objects.equals(httpMethod, operation.httpMethod); + } + + @Override + public String toString() { + return "Operation{" + + "service='" + service + '\'' + + ", path='" + path + '\'' + + ", isCloudEvent=" + isCloudEvent + + ", httpMethod=" + httpMethod + + '}'; } @Override public int hashCode() { - return Objects.hash(service, path, isCloudEvent); + return Objects.hash(service, path, isCloudEvent, httpMethod); } public static class Builder { @@ -97,6 +138,8 @@ public static class Builder { private boolean isCloudEvent; + private HttpMethod httpMethod = DEFAULT_HTTP_METHOD; + private Builder() { } @@ -115,6 +158,11 @@ public Builder withIsCloudEvent(boolean isCloudEvent) { return this; } + public Builder withMethod(HttpMethod httpMethod) { + this.httpMethod = httpMethod; + return this; + } + public Operation build() { return new Operation(this); } diff --git a/quarkus/addons/knative/serving/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/OperationTest.java b/quarkus/addons/knative/serving/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/OperationTest.java index e39da433f3a..6ac1dc5a5c7 100644 --- a/quarkus/addons/knative/serving/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/OperationTest.java +++ b/quarkus/addons/knative/serving/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/OperationTest.java @@ -21,24 +21,43 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import io.vertx.core.http.HttpMethod; + import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType; import static org.kie.kogito.addons.quarkus.knative.serving.customfunctions.Operation.CLOUD_EVENT_PARAMETER_NAME; +import static org.kie.kogito.addons.quarkus.knative.serving.customfunctions.Operation.METHOD_PARAMETER_NAME; import static org.kie.kogito.addons.quarkus.knative.serving.customfunctions.Operation.PATH_PARAMETER_NAME; class OperationTest { + public static final String SERVICE = "service"; + public static Stream parseSource() { return Stream.of( - Arguments.of("service", Operation.builder().withService("service").build()), + Arguments.of(SERVICE, Operation.builder().withService(SERVICE).build()), + + Arguments.of("service?", Operation.builder().withService(SERVICE).build()), - Arguments.of("service?", Operation.builder().withService("service").build()), + Arguments.of("service?" + PATH_PARAMETER_NAME + "=/my_path", Operation.builder().withService(SERVICE).withPath("/my_path").build()), - Arguments.of("service?" + PATH_PARAMETER_NAME + "=/my_path", Operation.builder().withService("service").withPath("/my_path").build()), + Arguments.of("service?" + CLOUD_EVENT_PARAMETER_NAME + "=true", Operation.builder().withService(SERVICE).withIsCloudEvent(true).build()), - Arguments.of("service?" + CLOUD_EVENT_PARAMETER_NAME + "=true", Operation.builder().withService("service").withIsCloudEvent(true).build()), + Arguments.of("service?" + METHOD_PARAMETER_NAME + "=GET", Operation.builder().withService(SERVICE).withMethod(HttpMethod.GET).build()), + + Arguments.of("service?" + METHOD_PARAMETER_NAME + "=get", Operation.builder().withService(SERVICE).withMethod(HttpMethod.GET).build()), Arguments.of("service?" + PATH_PARAMETER_NAME + "=/my_path&" + CLOUD_EVENT_PARAMETER_NAME + "=true", - Operation.builder().withService("service").withPath("/my_path").withIsCloudEvent(true).build())); + Operation.builder().withService(SERVICE).withPath("/my_path").withIsCloudEvent(true).build()), + + Arguments.of("service?" + PATH_PARAMETER_NAME + "=/my_path&" + CLOUD_EVENT_PARAMETER_NAME + "=false&" + METHOD_PARAMETER_NAME + "=GET", + Operation.builder().withService(SERVICE).withPath("/my_path").withIsCloudEvent(false).withMethod(HttpMethod.GET).build())); + } + + public static Stream invalidOperationSource() { + return Stream.of( + Arguments.of(Operation.builder().withService(SERVICE).withMethod(HttpMethod.DELETE)), + Arguments.of(Operation.builder().withService(SERVICE).withIsCloudEvent(true).withMethod(HttpMethod.GET))); } @ParameterizedTest @@ -46,4 +65,11 @@ public static Stream parseSource() { void parse(String operationValue, Operation expectedOperation) { assertThat(Operation.parse(operationValue)).isEqualTo(expectedOperation); } -} \ No newline at end of file + + @ParameterizedTest + @MethodSource("invalidOperationSource") + void invalidOperation(Operation.Builder operationBuilder) { + assertThatExceptionOfType(UnsupportedOperationException.class) + .isThrownBy(operationBuilder::build); + } +} diff --git a/quarkus/addons/knative/serving/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/WebClientProducer.java b/quarkus/addons/knative/serving/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/WebClientProducer.java new file mode 100644 index 00000000000..71f9225df12 --- /dev/null +++ b/quarkus/addons/knative/serving/runtime/src/test/java/org/kie/kogito/addons/quarkus/knative/serving/customfunctions/WebClientProducer.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates. + * + * 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 org.kie.kogito.addons.quarkus.knative.serving.customfunctions; + +import javax.enterprise.inject.Produces; +import javax.inject.Inject; + +import io.vertx.ext.web.client.WebClientOptions; +import io.vertx.mutiny.core.Vertx; +import io.vertx.mutiny.ext.web.client.WebClient; + +public class WebClientProducer { + + @Inject + Vertx vertx; + + @Produces + WebClient webClient() { + return WebClient.create(vertx, new WebClientOptions()); + } +}