diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/README.tpl.qute.md b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/README.tpl.qute.md
deleted file mode 100644
index 26809cc0bf4ec..0000000000000
--- a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/README.tpl.qute.md
+++ /dev/null
@@ -1,3 +0,0 @@
-{#include readme-header /}
-
-> :warning: **INCOMPATIBLE WITH NATIVE**: Azure Functions Integration is not compatible with native yet!
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/host.json b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/host.json
deleted file mode 100644
index 9f633be4856b6..0000000000000
--- a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/host.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "version": "2.0",
- "extensionBundle": {
- "id": "Microsoft.Azure.Functions.ExtensionBundle",
- "version": "[3.*, 4.0.0)"
- }
-}
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/pom.tpl.qute.xml b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/pom.tpl.qute.xml
deleted file mode 100644
index 58b634e17a6b2..0000000000000
--- a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/pom.tpl.qute.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
- 1.19.0
- 11
- $\{artifactId}-{gen-info.time}
- {app-region}
- {resource-group}
-
-
-
-
- com.microsoft.azure
- azure-functions-maven-plugin
- $\{azure.functions.maven.plugin.version}
-
-
- $\{functionAppName}
-
- $\{functionResourceGroup}
-
- java-functions-app-service-plan
-
-
- $\{functionAppRegion}
-
-
-
-
-
-
-
-
- {function-os}
- 11
-
-
-
- FUNCTIONS_EXTENSION_VERSION
- ~4
-
-
-
-
-
- package-functions
-
- package
-
-
-
-
-
-
- maven-clean-plugin
- 3.1.0
-
-
-
- obj
-
-
-
-
-
-
-
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/src/main/resources/application.tpl.qute.yml b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/src/main/resources/application.tpl.qute.yml
deleted file mode 100644
index 8d74884950fe6..0000000000000
--- a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/src/main/resources/application.tpl.qute.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-quarkus:
- http:
- root-path: {root-context-path}
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-codestart/base/host.json b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-codestart/base/host.json
deleted file mode 100644
index 9f633be4856b6..0000000000000
--- a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-codestart/base/host.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "version": "2.0",
- "extensionBundle": {
- "id": "Microsoft.Azure.Functions.ExtensionBundle",
- "version": "[3.*, 4.0.0)"
- }
-}
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/local.settings.json b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/base/local.settings.json
similarity index 100%
rename from devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/base/local.settings.json
rename to devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/base/local.settings.json
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/base/src/main/resources/application.tpl.qute.yml b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/base/src/main/resources/application.tpl.qute.yml
new file mode 100644
index 0000000000000..a04a91b22e344
--- /dev/null
+++ b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/base/src/main/resources/application.tpl.qute.yml
@@ -0,0 +1,5 @@
+quarkus:
+ http:
+ root-path: {root-context-path}
+ azure-functions:
+ app-name: {project.artifact-id}-{gen-info.time}
\ No newline at end of file
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/codestart.yml b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/codestart.yml
similarity index 82%
rename from devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/codestart.yml
rename to devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/codestart.yml
index 90d341f05b794..20018f15077a1 100644
--- a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/codestart.yml
+++ b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/codestart.yml
@@ -1,9 +1,7 @@
name: azure-functions-http-example
ref: azure-functions-http
type: code
-tags:
- - example
- - maven-only
+tags: extension-codestart
metadata:
title: Azure Functions HTTP Integration example
description: This example contains a HTTP function ready for Azure.
@@ -15,12 +13,6 @@ language:
data:
# /api is the default root context azure functions will prepend
root-context-path: "/api"
- app-region:
- eastus
- resource-group:
- quarkus-examples
- function-os:
- linux
dependencies:
- io.quarkus:quarkus-azure-functions-http
- io.quarkus:quarkus-resteasy-reactive
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/java/src/integrationTest/java/org/acme/GreetingIT.java b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/java/src/integrationTest/java/org/acme/GreetingIT.java
new file mode 100644
index 0000000000000..7cb5a77aa344d
--- /dev/null
+++ b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/java/src/integrationTest/java/org/acme/GreetingIT.java
@@ -0,0 +1,19 @@
+package org.acme;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+import org.junit.jupiter.api.Test;
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.is;
+
+@QuarkusIntegrationTest
+public class GreetingIT {
+
+ @Test
+ public void testIt() {
+ given()
+ .when().get("/hello")
+ .then()
+ .statusCode(200)
+ .body(is("hello"));
+ }
+}
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/java/src/main/java/org/acme/GreetingResource.java b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/java/src/main/java/org/acme/GreetingResource.java
similarity index 100%
rename from devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/java/src/main/java/org/acme/GreetingResource.java
rename to devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/java/src/main/java/org/acme/GreetingResource.java
diff --git a/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/java/src/test/java/org/acme/GreetingTest.java b/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/java/src/test/java/org/acme/GreetingTest.java
similarity index 100%
rename from devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/examples/azure-functions-http-example/java/src/test/java/org/acme/GreetingTest.java
rename to devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/azure-functions-http-codestart/java/src/test/java/org/acme/GreetingTest.java
diff --git a/docs/src/main/asciidoc/azure-functions-http.adoc b/docs/src/main/asciidoc/azure-functions-http.adoc
index b6f281f358237..4496bd3014380 100644
--- a/docs/src/main/asciidoc/azure-functions-http.adoc
+++ b/docs/src/main/asciidoc/azure-functions-http.adoc
@@ -11,7 +11,8 @@ include::_attributes.adoc[]
The `quarkus-azure-functions-http` extension allows you to write microservices with RESTEasy Reactive (our Jakarta REST implementation),
Undertow (servlet), Reactive Routes, or xref:funqy-http.adoc[Funqy HTTP] and make these microservices deployable to the Azure Functions runtime.
-
+In other words, this extension is a bridge from the Azure Functions HttpTrigger and the Quarkus family
+of HTTP APIs.
One azure function deployment can represent any number of Jakarta REST, servlet, Reactive Routes, or xref:funqy-http.adoc[Funqy HTTP] endpoints.
include::{includes}/extension-status.adoc[]
@@ -30,9 +31,9 @@ include::{includes}/prerequisites.adoc[]
This guide walks you through running a maven project that can deploy a Resteasy Reactive endpoint to Azure Functions.
While only Jakarta REST is provided as an example, you can easily replace it with the HTTP framework of your choice.
-== Creating the Maven Deployment Project
+== Creating the Maven/Gradle Project
-You can download the example code from Quarkus's application generator at https://code.quarkus.io/d?e=azure-functions-http&cn=code.quarkus.io[this link].
+You can generate the example code from Quarkus's online application generator at https://code.quarkus.io/d?e=azure-functions-http&cn=code.quarkus.io[this link].
You can also generate this example with the Quarkus CLI:
@@ -41,6 +42,8 @@ You can also generate this example with the Quarkus CLI:
quarkus create app --extension=quarkus-azure-functions-http
----
+Add the `--gradle` switch if you want to generate a gradle project.
+
== Login to Azure
If you don't log in to Azure you won't be able to deploy.
@@ -52,66 +55,139 @@ az login
== Quarkus dev mode
-Quarkus dev mode works by just running your application as a HTTP endpoint.
+Quarkus dev mode works by just running your application as a HTTP endpoint. In dev mode
+there is no special interaction with the Azure Functions local runtime.
[source,bash,subs=attributes+]
----
./mvnw clean package quarkus:dev
----
+== Examining the project
+
+If you open the `pom.xml` or `build.gradle` build file of the generated project you'll see that
+the project is similar to any other Quarkus project.
+The `quarkus-azure-functions-http` extension is the integration point between
+Quarkus and Azure Functions.
+
+The current implementation of the `quarkus-azure-functions-http` extension no longer requires the
+`azure-functions-maven-plugin` or gradle equivalent. Local development and Azure Functions packaging and
+deployment is now all done by Quarkus.
+
+Build configuration is now all within `application.properties`. The only required configuration switch
+is `quarkus.azure-functions.app-name`.
+
+== Azure Deployment Descriptors
+
+The Azure Functions `host.json` deployment descriptor is automatically
+generated, but if you need to override it, declare it in the root directory of the project and
+rerun the build when you are ready.
+
+[#config-azure-paths]
+== Configuring Root Paths
+
+The default route prefix for an Azure Function is `/api`. All of your Jakarta REST, Servlet, Reactive Routes, and xref:funqy-http.adoc[Funqy HTTP] endpoints must
+explicitly take this into account. In the generated project this is handled by the
+`quarkus.http.root-path` switch in `application.properties`
+
+== Login to Azure
+
+If you don't log in to Azure you won't be able to deploy.
+
+[source,bash,subs=attributes+]
+----
+az login
+----
+
+== Quarkus dev mode
+Quarkus dev mode does not work currently with Azure Functions.
-== Run locally in Azure Functions simulated environment
+== Run locally in Azure Functions local environment
-If you want to try your app with a simulated local Azure Functions environment, you can
+If you want to try this example within the local Azure Functions environment, you can
use this command
[source,bash,subs=attributes+]
----
-./mvnw clean package azure-functions:run
+./mvnw quarkus:run
+----
+
+or
+
+[source,bash,subs=attributes+]
+----
+./gradlew --info --no-daemon quarkusRun
----
+Gradle is a bit quirky with process management, so you need the `--no-daemon` switch or control-c will not
+destroy the process cleanly and you'll have open ports.
+
Note that you must have the https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local#v2[Azure Functions Core Tools]
installed for this to work!
-== Deploy to Azure
+The URL to access the example would be:
+
+http://localhost:8081/api/hello
+
+== Quarkus Integration Testing
+
+You can implement integration tests using `@QuarkusIntegrationTest` functionality. When these
+integration tests run, the local Azure Functions environment will be spun up for the duration of integration testing.
-The `pom.xml` you generated in the previous step pulls in the `azure-functions-maven-plugin`. Running maven package
-generates config files and a staging directory required by the `azure-functions-maven-plugin`. Here's
-how to execute it.
+For maven:
[source,bash,subs=attributes+]
----
-./mvnw clean package azure-functions:deploy
+./mvnw -DskipITs=false verify
----
-If deployment is a success, the azure plugin will tell you the base URL to access your function.
+Make sure any integration tests you execute with maven use the `*IT.java` file pattern so that regular builds do not execute
+the test.
-i.e.
-[source]
+For Gradle:
+[source,bash,subs=attributes+]
----
-[INFO] HTTP Trigger Urls:
-[INFO] QuarkusHttp : https://{appName}.azurewebsites.net/api/{*path}
+./gradlew --info quarkusIntTest
----
-The URL to access the service would be
+Make sure any integration tests you execute with Gradle are located within `src/integrationTest/java`. Integration
+tests that exist in `src/test` will run with normal build and fail.
-https://{appName}.azurewebsites.net/api/hello
+== Deploy to Azure
-== Extension maven dependencies
+The `quarkus-azure-functions-http` extension handles all the work to deploy to Azure. By default,
+Quarkus will use the Azure CLI in the background to authenticate and deploy to Azure. If you have
+multiple subscriptions associated with your account, you must set the `quarkus.azure-functions.subscription-id`
+property in your `application.properties` file to the subscription you want to use.
+For other authentication mechanisms and deployment options see our config properties https://quarkus.io/guides/all-config[here].
-You must include the `quarkus-azure-functions-http` extension as this is a generic bridge between the Azure Functions
-runtime and the HTTP framework you are writing your microservices in.
+To run the deploy, after you build your project execute:
-== Azure Deployment Descriptors
+[source,bash,subs=attributes+]
+----
+./mvnw quarkus:deploy
+----
-Templates for Azure Functions deployment descriptors (`host.json`, `function.json`) are within
-the base directory of the project. Edit them as you need to. Rerun the build when you are ready.
+or
-[#config-azure-paths]
-== Configuring Root Paths
+[source,bash,subs=attributes+]
+----
+./gradlew --info deploy
+----
+
+If deployment is a success, Quarkus will output the endpoint URL of the example function to the console
+For Gradle, you must use the `--info` switch to see this output!
+
+i.e.
+[source]
+----
+[INFO] HTTP Trigger Urls:
+[INFO] HttpExample : https://{appName}.azurewebsites.net/api/{*path}
+----
+
+The URL to access the service would be something like
+
+https://{appName}.azurewebsites.net/api/hello
-The default route prefix for an Azure Function is `/api`. All of your Jakarta REST, Servlet, Reactive Routes, and xref:funqy-http.adoc[Funqy HTTP] endpoints must
-explicitly take this into account. In the generated project this is handled by the
-`quarkus.http.root-path` switch in `application.properties`
diff --git a/docs/src/main/asciidoc/azure-functions.adoc b/docs/src/main/asciidoc/azure-functions.adoc
index 17f5bd61e559d..df4d9a81a7523 100644
--- a/docs/src/main/asciidoc/azure-functions.adoc
+++ b/docs/src/main/asciidoc/azure-functions.adoc
@@ -100,15 +100,11 @@ deployment is now all done by Quarkus.
Build configuration is now all within `application.properties`. The only required configuration switch
is `quarkus.azure-functions.app-name`.
+== Azure Deployment Descriptors
-== Login to Azure
-
-If you don't log in to Azure you won't be able to deploy.
-
-[source,bash,subs=attributes+]
-----
-az login
-----
+The Azure Functions `host.json` deployment descriptor is automatically
+generated, but if you need to override it, declare it in the root directory of the project and
+rerun the build when you are ready.
== Quarkus dev mode
@@ -137,6 +133,11 @@ destroy the process cleanly and you'll have open ports.
Note that you must have the https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local#v2[Azure Functions Core Tools]
installed for this to work!
+The URL to access the example would be:
+
+https://localhost:8081/HttpExample?name=Bill
+
+
== Quarkus Integration Testing
You can implement integration tests using `@QuarkusIntegrationTest` functionality. When these
@@ -161,6 +162,15 @@ For Gradle:
Make sure any integration tests you execute with Gradle are located within `src/integrationTest/java`. Integration
tests that exist in `src/test` will run with normal build and fail.
+== Login to Azure
+
+If you don't log in to Azure you won't be able to deploy.
+
+[source,bash,subs=attributes+]
+----
+az login
+----
+
== Deploy to Azure
The `quarkus-azure-functions` extension handles all the work to deploy to Azure. By default,
@@ -197,9 +207,5 @@ The URL to access the service would be
https://{appName}.azurewebsites.net/api/HttpExample
-== Azure Deployment Descriptors
-
-Templates for Azure Functions deployment descriptors (`host.json`, `function.json`) are within
-base directory of the project. Edit them as you need to. Rerun the build when you are ready.
diff --git a/extensions/azure-functions-http/deployment/pom.xml b/extensions/azure-functions-http/deployment/pom.xml
index fa285088c0a76..459f7d344df8d 100644
--- a/extensions/azure-functions-http/deployment/pom.xml
+++ b/extensions/azure-functions-http/deployment/pom.xml
@@ -17,6 +17,10 @@
io.quarkus
quarkus-azure-functions-http
+
+ io.quarkus
+ quarkus-azure-functions-deployment
+
io.quarkus
quarkus-core-deployment
diff --git a/extensions/azure-functions-http/deployment/src/main/java/io/quarkus/azure/functions/resteasy/deployment/AzureFunctionsHttpProcessor.java b/extensions/azure-functions-http/deployment/src/main/java/io/quarkus/azure/functions/resteasy/deployment/AzureFunctionsHttpProcessor.java
index c8e0f1f65169d..6575a6ae588d1 100644
--- a/extensions/azure-functions-http/deployment/src/main/java/io/quarkus/azure/functions/resteasy/deployment/AzureFunctionsHttpProcessor.java
+++ b/extensions/azure-functions-http/deployment/src/main/java/io/quarkus/azure/functions/resteasy/deployment/AzureFunctionsHttpProcessor.java
@@ -1,17 +1,14 @@
package io.quarkus.azure.functions.resteasy.deployment;
-import java.util.Collections;
-import java.util.List;
+import java.lang.reflect.Method;
import org.jboss.logging.Logger;
-import io.quarkus.builder.BuildException;
-import io.quarkus.deployment.Feature;
+import io.quarkus.azure.functions.deployment.AzureFunctionBuildItem;
+import io.quarkus.azure.functions.resteasy.runtime.Function;
+import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.LaunchModeBuildItem;
-import io.quarkus.deployment.pkg.PackageConfig;
-import io.quarkus.deployment.pkg.builditem.LegacyJarRequiredBuildItem;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.vertx.http.deployment.RequireVirtualHttpBuildItem;
@@ -19,21 +16,19 @@ public class AzureFunctionsHttpProcessor {
private static final Logger log = Logger.getLogger(AzureFunctionsHttpProcessor.class);
@BuildStep
- public LegacyJarRequiredBuildItem forceLegacy(List features, PackageConfig config) throws BuildException {
- for (FeatureBuildItem item : features) {
- if (Feature.AZURE_FUNCTIONS.getName().equals(item.getName())) {
- throw new BuildException(
- "quarkus-azure-functions-http extension is incompatible with quarkus-azure-functions extension. Remove quarkus-azure-functions from your build.",
- Collections.EMPTY_LIST);
- }
- }
- // Azure Functions need a legacy jar and no runner
- config.addRunnerSuffix = false;
- return new LegacyJarRequiredBuildItem();
+ public RequireVirtualHttpBuildItem requestVirtualHttp(LaunchModeBuildItem launchMode) {
+ return launchMode.getLaunchMode() == LaunchMode.NORMAL ? RequireVirtualHttpBuildItem.MARKER : null;
}
@BuildStep
- public RequireVirtualHttpBuildItem requestVirtualHttp(LaunchModeBuildItem launchMode) {
- return launchMode.getLaunchMode() == LaunchMode.NORMAL ? RequireVirtualHttpBuildItem.MARKER : null;
+ public void registerFunction(BuildProducer producer) {
+ Method functionMethod = null;
+ for (Method method : Function.class.getMethods()) {
+ if (method.getName().equals("run")) {
+ functionMethod = method;
+ break;
+ }
+ }
+ producer.produce(new AzureFunctionBuildItem(Function.QUARKUS_HTTP, Function.class, functionMethod));
}
}
diff --git a/extensions/azure-functions-http/runtime/pom.xml b/extensions/azure-functions-http/runtime/pom.xml
index aac16f0ab69d8..8416a0cbae4ac 100644
--- a/extensions/azure-functions-http/runtime/pom.xml
+++ b/extensions/azure-functions-http/runtime/pom.xml
@@ -18,6 +18,10 @@
io.quarkus
quarkus-vertx-http
+
+ io.quarkus
+ quarkus-azure-functions
+
io.quarkus
quarkus-core
diff --git a/extensions/azure-functions-http/runtime/src/main/java/io/quarkus/azure/functions/resteasy/runtime/BaseFunction.java b/extensions/azure-functions-http/runtime/src/main/java/io/quarkus/azure/functions/resteasy/runtime/BaseFunction.java
index 7d1967fe1fcb5..4d62c27cea433 100644
--- a/extensions/azure-functions-http/runtime/src/main/java/io/quarkus/azure/functions/resteasy/runtime/BaseFunction.java
+++ b/extensions/azure-functions-http/runtime/src/main/java/io/quarkus/azure/functions/resteasy/runtime/BaseFunction.java
@@ -26,7 +26,6 @@
import io.netty.util.ReferenceCountUtil;
import io.quarkus.netty.runtime.virtual.VirtualClientConnection;
import io.quarkus.netty.runtime.virtual.VirtualResponseHandler;
-import io.quarkus.runtime.Quarkus;
import io.quarkus.vertx.http.runtime.VertxHttpRecorder;
public class BaseFunction {
@@ -34,30 +33,6 @@ public class BaseFunction {
private static final int BUFFER_SIZE = 8096;
- protected static void ensureQuarkusInitialized() {
- // The following will atomically call initQuarkus if this hasn't been done before,
- // and therefore make sure that deploymentStatus, started and bootstrapError are all set as necessary
- QuarkusInitializer.ensureQuarkusInitialized();
- }
-
- // needed for mock tests
- public static boolean throwException = true;
-
- private static void initQuarkus() {
- if (throwException) {
- Quarkus.manualInitialize();
- Quarkus.manualStart();
- } else {
- try {
- Quarkus.manualInitialize();
- Quarkus.manualStart();
-
- } catch (Exception ex) {
-
- }
- }
- }
-
protected HttpResponseMessage dispatch(HttpRequestMessage> request) {
try {
return nettyDispatch(request);
@@ -169,19 +144,4 @@ public void close() {
future.completeExceptionally(new RuntimeException("Connection closed"));
}
}
-
- private static final class QuarkusInitializer {
-
- static {
- // Using an initializer block ensures that initQuarkus is called exactly once,
- // and is called atomically, thereby making it thread-safe.
-
- initQuarkus();
- }
-
- private static void ensureQuarkusInitialized() {
- // No code needed; the static initializer block will take care of the initialization.
- // This method exists to ensure that this class is loaded, and therefore Quarkus is initialized.
- }
- }
}
diff --git a/extensions/azure-functions-http/runtime/src/main/java/io/quarkus/azure/functions/resteasy/runtime/Function.java b/extensions/azure-functions-http/runtime/src/main/java/io/quarkus/azure/functions/resteasy/runtime/Function.java
index dc199a5e7b384..dde4d70e945c0 100644
--- a/extensions/azure-functions-http/runtime/src/main/java/io/quarkus/azure/functions/resteasy/runtime/Function.java
+++ b/extensions/azure-functions-http/runtime/src/main/java/io/quarkus/azure/functions/resteasy/runtime/Function.java
@@ -12,15 +12,15 @@
public class Function extends BaseFunction {
- @FunctionName("QuarkusHttp")
+ public static final String QUARKUS_HTTP = "QuarkusHttp";
+
+ @FunctionName(QUARKUS_HTTP)
public HttpResponseMessage run(
@HttpTrigger(name = "req", dataType = "binary", methods = { HttpMethod.GET, HttpMethod.HEAD, HttpMethod.POST,
HttpMethod.PUT,
HttpMethod.OPTIONS }, route = "{*path}", authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage> request,
final ExecutionContext context) {
- ensureQuarkusInitialized();
-
return dispatch(request);
}
}
diff --git a/extensions/azure-functions-http/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/azure-functions-http/runtime/src/main/resources/META-INF/quarkus-extension.yaml
index f0bf92a0142b2..cf314451f2bfd 100644
--- a/extensions/azure-functions-http/runtime/src/main/resources/META-INF/quarkus-extension.yaml
+++ b/extensions/azure-functions-http/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -11,6 +11,5 @@ metadata:
status: "preview"
codestart:
name: "azure-functions-http"
- kind: "example"
languages: "java"
artifact: "io.quarkus:quarkus-project-core-extension-codestarts"
\ No newline at end of file
diff --git a/extensions/azure-functions-http/runtime/src/test/java/io/quarkus/azure/functions/resteasy/runtime/FunctionTest.java b/extensions/azure-functions-http/runtime/src/test/java/io/quarkus/azure/functions/resteasy/runtime/FunctionTest.java
index 4dc3a61516975..3e37c618f42d0 100644
--- a/extensions/azure-functions-http/runtime/src/test/java/io/quarkus/azure/functions/resteasy/runtime/FunctionTest.java
+++ b/extensions/azure-functions-http/runtime/src/test/java/io/quarkus/azure/functions/resteasy/runtime/FunctionTest.java
@@ -56,7 +56,6 @@ public class FunctionTest {
private final HttpResponseMessage response = mock(HttpResponseMessage.class);
static {
- BaseFunction.throwException = false;
}
@BeforeEach
diff --git a/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsAppNameBuildItem.java b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsAppNameBuildItem.java
new file mode 100644
index 0000000000000..66995bd53fdc5
--- /dev/null
+++ b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsAppNameBuildItem.java
@@ -0,0 +1,15 @@
+package io.quarkus.azure.functions.deployment;
+
+import io.quarkus.builder.item.SimpleBuildItem;
+
+final public class AzureFunctionsAppNameBuildItem extends SimpleBuildItem {
+ private final String appName;
+
+ public AzureFunctionsAppNameBuildItem(String appName) {
+ this.appName = appName;
+ }
+
+ public String getAppName() {
+ return appName;
+ }
+}
diff --git a/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsConfig.java b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsConfig.java
index 95c95a97110a6..049684836a21d 100644
--- a/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsConfig.java
+++ b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsConfig.java
@@ -39,10 +39,12 @@
public class AzureFunctionsConfig {
/**
- * App name for azure function project. This is required setting
+ * App name for azure function project. This is required setting.
+ *
+ * Defaults to the base artifact name
*/
@ConfigItem
- public String appName;
+ public Optional appName;
/**
* Azure Resource Group for your Azure Functions
@@ -141,7 +143,7 @@ public static class RuntimeConfig {
}
- public FunctionAppConfig toFunctionAppConfig(String subscriptionId) {
+ public FunctionAppConfig toFunctionAppConfig(String subscriptionId, String appName) {
Map appSettings = this.appSettings;
if (appSettings.isEmpty()) {
appSettings = new HashMap<>();
diff --git a/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsDeployCommand.java b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsDeployCommand.java
index 8430504515e35..aff10a43c92f2 100644
--- a/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsDeployCommand.java
+++ b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsDeployCommand.java
@@ -98,12 +98,13 @@ public void declare(BuildProducer producer) {
@BuildStep
public void deploy(DeployConfig deployConfig, AzureFunctionsConfig config,
+ AzureFunctionsAppNameBuildItem appName,
OutputTargetBuildItem output,
BuildProducer producer) throws Exception {
if (!deployConfig.isEnabled(AZURE_FUNCTIONS))
return;
- validateParameters(config);
+ validateParameters(config, appName.getAppName());
setCurrentOperation();
AzureMessager.setDefaultMessager(new QuarkusAzureMessager());
Azure.az().config().setLogLevel(HttpLogDetailLevel.NONE.name());
@@ -111,9 +112,10 @@ public void deploy(DeployConfig deployConfig, AzureFunctionsConfig config,
AzureTaskManager.register(new QuarkusAzureTaskManager());
initAzureAppServiceClient(config);
- final FunctionAppBase, ?, ?> target = createOrUpdateResource(config.toFunctionAppConfig(subscriptionId));
+ final FunctionAppBase, ?, ?> target = createOrUpdateResource(
+ config.toFunctionAppConfig(subscriptionId, appName.getAppName()));
Path outputDirectory = output.getOutputDirectory();
- Path functionStagingDir = outputDirectory.resolve("azure-functions").resolve(config.appName);
+ Path functionStagingDir = outputDirectory.resolve("azure-functions").resolve(appName.getAppName());
deployArtifact(functionStagingDir, target);
producer.produce(new DeployCommandActionBuildItem(AZURE_FUNCTIONS, true));
@@ -156,12 +158,12 @@ public AzureString getDescription() {
}
}
- protected void validateParameters(AzureFunctionsConfig config) throws BuildException {
+ protected void validateParameters(AzureFunctionsConfig config, String appName) throws BuildException {
// app name
- if (StringUtils.isBlank(config.appName)) {
+ if (StringUtils.isBlank(appName)) {
throw new BuildException(EMPTY_APP_NAME);
}
- if (config.appName.startsWith("-") || !config.appName.matches(APP_NAME_PATTERN)) {
+ if (appName.startsWith("-") || !appName.matches(APP_NAME_PATTERN)) {
throw new BuildException(INVALID_APP_NAME);
}
// resource group
diff --git a/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsProcessor.java b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsProcessor.java
index 15386c5b75c50..9c23eec031b80 100644
--- a/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsProcessor.java
+++ b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsProcessor.java
@@ -76,14 +76,23 @@ FeatureBuildItem feature() {
return new FeatureBuildItem(Feature.AZURE_FUNCTIONS);
}
+ @BuildStep
+ AzureFunctionsAppNameBuildItem appName(OutputTargetBuildItem output, AzureFunctionsConfig functionsConfig) {
+ String appName = functionsConfig.appName.orElse(output.getBaseName());
+ return new AzureFunctionsAppNameBuildItem(appName);
+ }
+
@BuildStep(onlyIf = IsNormal.class, onlyIfNot = NativeBuild.class)
public ArtifactResultBuildItem packageFunctions(List functions,
OutputTargetBuildItem target,
AzureFunctionsConfig functionsConfig,
PackageConfig packageConfig,
+ AzureFunctionsAppNameBuildItem appName,
JarBuildItem jar) throws Exception {
- if (functions == null || functions.isEmpty())
+ if (functions == null || functions.isEmpty()) {
+ log.warn("No azure functions exist in deployment");
return null;
+ }
AnnotationHandler handler = new AnnotationHandlerImpl();
HashSet methods = new HashSet<>();
for (AzureFunctionBuildItem item : functions)
@@ -97,7 +106,7 @@ public ArtifactResultBuildItem packageFunctions(List fun
Path rootPath = target.getOutputDirectory().resolve("..");
Path outputDirectory = target.getOutputDirectory();
- Path functionStagingDir = outputDirectory.resolve("azure-functions").resolve(functionsConfig.appName);
+ Path functionStagingDir = outputDirectory.resolve("azure-functions").resolve(appName.getAppName());
copyHostJson(rootPath, functionStagingDir);
diff --git a/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsRunCommand.java b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsRunCommand.java
index a8a5f7daf5b63..7797fd7b49901 100644
--- a/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsRunCommand.java
+++ b/extensions/azure-functions/deployment/src/main/java/io/quarkus/azure/functions/deployment/AzureFunctionsRunCommand.java
@@ -37,8 +37,9 @@ public class AzureFunctionsRunCommand {
@BuildStep
public RunCommandActionBuildItem run(List functions, OutputTargetBuildItem target,
+ AzureFunctionsAppNameBuildItem appName,
AzureFunctionsConfig config) throws Exception {
- Path stagingDir = getDeploymentStagingDirectoryPath(target, config);
+ Path stagingDir = getDeploymentStagingDirectoryPath(target, appName.getAppName());
File file = stagingDir.toFile();
if (!file.exists() || !file.isDirectory()) {
throw new BuildException("Staging directory does not exist. Rebuild the app", Collections.emptyList());
@@ -57,8 +58,8 @@ public RunCommandActionBuildItem run(List functions, Out
return launcher;
}
- protected Path getDeploymentStagingDirectoryPath(OutputTargetBuildItem target, AzureFunctionsConfig config) {
- return target.getOutputDirectory().resolve("azure-functions").resolve(config.appName);
+ protected Path getDeploymentStagingDirectoryPath(OutputTargetBuildItem target, String appName) {
+ return target.getOutputDirectory().resolve("azure-functions").resolve(appName);
}
protected void checkRuntimeExistence(final CommandHandler handler) throws AzureExecutionException {
diff --git a/independent-projects/tools/codestarts/src/main/java/io/quarkus/devtools/codestarts/core/strategy/FailOnDuplicateCodestartFileStrategyHandler.java b/independent-projects/tools/codestarts/src/main/java/io/quarkus/devtools/codestarts/core/strategy/FailOnDuplicateCodestartFileStrategyHandler.java
index c3b30e9e9ab24..5e3ded6653fbe 100644
--- a/independent-projects/tools/codestarts/src/main/java/io/quarkus/devtools/codestarts/core/strategy/FailOnDuplicateCodestartFileStrategyHandler.java
+++ b/independent-projects/tools/codestarts/src/main/java/io/quarkus/devtools/codestarts/core/strategy/FailOnDuplicateCodestartFileStrategyHandler.java
@@ -40,6 +40,8 @@ public void copyStaticFile(Source source, Path targetPath) throws IOException {
+ targetPath);
}
Files.createDirectories(targetPath.getParent());
+
source.copyTo(targetPath);
}
+
}
diff --git a/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartBuildIT.java b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartBuildIT.java
index 415070a21d879..32b90968cf96e 100644
--- a/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartBuildIT.java
+++ b/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartBuildIT.java
@@ -52,6 +52,10 @@ private static boolean isExcluded(String codestart) {
return true;
}
+ if (codestart.startsWith("azure-functions")) {
+ return true;
+ }
+
return EXCLUDED.contains(codestart);
}
diff --git a/integration-tests/virtual-http-resteasy/src/test/java/io/quarkus/it/virtual/FunctionTest.java b/integration-tests/virtual-http-resteasy/src/test/java/io/quarkus/it/virtual/FunctionTest.java
index 1a48ead8b5ec1..e6923d736cabd 100644
--- a/integration-tests/virtual-http-resteasy/src/test/java/io/quarkus/it/virtual/FunctionTest.java
+++ b/integration-tests/virtual-http-resteasy/src/test/java/io/quarkus/it/virtual/FunctionTest.java
@@ -18,7 +18,6 @@
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
-import io.quarkus.azure.functions.resteasy.runtime.BaseFunction;
import io.quarkus.azure.functions.resteasy.runtime.Function;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
@@ -30,7 +29,6 @@
public class FunctionTest {
@BeforeAll
public static void setFlag() {
- BaseFunction.throwException = false;
}
@Test
diff --git a/integration-tests/virtual-http/src/test/java/io/quarkus/it/virtual/FunctionTest.java b/integration-tests/virtual-http/src/test/java/io/quarkus/it/virtual/FunctionTest.java
index 0782c35e7ec3f..08adf8fab8f88 100644
--- a/integration-tests/virtual-http/src/test/java/io/quarkus/it/virtual/FunctionTest.java
+++ b/integration-tests/virtual-http/src/test/java/io/quarkus/it/virtual/FunctionTest.java
@@ -10,7 +10,6 @@
import jakarta.ws.rs.core.MediaType;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import com.microsoft.azure.functions.ExecutionContext;
@@ -18,7 +17,6 @@
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
-import io.quarkus.azure.functions.resteasy.runtime.BaseFunction;
import io.quarkus.azure.functions.resteasy.runtime.Function;
import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
@@ -28,11 +26,6 @@
*/
@QuarkusTest
public class FunctionTest {
- @BeforeAll
- public static void setFlag() {
- BaseFunction.throwException = false;
- }
-
@Test
public void testFunqy() {
final HttpRequestMessageMock req = new HttpRequestMessageMock();