{"id":16408463,"url":"https://github.com/dsyer/azure-docs","last_synced_at":"2026-04-14T06:33:52.689Z","repository":{"id":137444476,"uuid":"130061582","full_name":"dsyer/azure-docs","owner":"dsyer","description":null,"archived":false,"fork":false,"pushed_at":"2020-06-15T09:34:01.000Z","size":78,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-27T02:40:12.964Z","etag":null,"topics":["java","spring","spring-boot"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dsyer.png","metadata":{"files":{"readme":"README.adoc","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-18T12:50:13.000Z","updated_at":"2018-09-25T18:51:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"525c2d5d-ff0d-4452-a096-141ed01ce3c5","html_url":"https://github.com/dsyer/azure-docs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dsyer/azure-docs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsyer%2Fazure-docs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsyer%2Fazure-docs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsyer%2Fazure-docs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsyer%2Fazure-docs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dsyer","download_url":"https://codeload.github.com/dsyer/azure-docs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dsyer%2Fazure-docs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31785677,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-14T02:24:21.117Z","status":"ssl_error","status_checked_at":"2026-04-14T02:24:20.627Z","response_time":153,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["java","spring","spring-boot"],"created_at":"2024-10-11T06:16:55.452Z","updated_at":"2026-04-14T06:33:52.671Z","avatar_url":"https://github.com/dsyer.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"= Spring Cloud Function 2.0 and Azure Functions\n\nhttps://github.com/spring-cloud/spring-cloud-function[Spring Cloud\nFunction] has had support for Microsoft\nhttps://azure.microsoft.com/en-gb/services/functions[Azure Functions]\nsince version 1.0, but in the latest 2.0 releases (still in milestone\nphase) we decided to change the programming model a bit. This article\ndescribes what the changes mean for users, and provides a bit of\nbackground behind the shift. We in the Spring team had a lot of fun\nworking on this and collaborating with the folks at Microsoft to get\nthe best blend of the two technologies for our users.\n\n== Azure Functions for Java\n\nMicrosoft has had Java support in Azure Functions for a while, and it\nenables developers to easily write and deploy Java code that connects\nin a serverless way to a wide range of platform services (events,\ndatabases, storage, HTTP gateways, etc.) in Azure. It comes with an\nannotation-based programming model that puts the function\nimplementations in Java methods. So you write a method and annotation\nit with `@FunctionName`, and it becomes an Azure Function. There is a\nrich set of tools based on a Maven plugin (currently) that drives the\nAzure command line and can be used to build a function, run and debug\nit locally and deploy it to the cloud. There is a\nhttps://docs.microsoft.com/en-us/azure/azure-functions/functions-create-first-java-maven[Quickstart\nGuide] on the Azure website which will help you get all the\npre-requisites installed and working, and there is more detailed\ndocumentation about how Azure Functions works in the\nhttps://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-java[Developer's\nGuide].\n\nThe annotations also tie the function method parameters and return\ntypes to the services used at deployment time. For example, if you\nwant to bind to an HTTP gateway at deployment time you use\n`@HttpTrigger`:\n\n```java\n@FunctionName(\"uppercase\")\npublic Bar execute(\n    @HttpTrigger(name = \"req\", methods = { HttpMethod.GET, HttpMethod.POST },\n        authLevel = AuthorizationLevel.ANONYMOUS) Foo foo,\n    ExecutionContext context) {\n  return new Bar(foo.getValue());\n}\n```\n\nIn this example we accept an incoming HTTP POST request and Azure\nbinds its body to a POJO of type `Foo`. We transform the `Foo` into a\n`Bar` and it comes back to the caller in the HTTP response.\n\nHTTP triggers are in the top 5 most popular integrations in Azure\nFunctions, but even more popular are the event-based and storage or\ndatabase-based triggers. The complete list can be found in the\nhttps://docs.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings[Triggers\nand Bindings] documentation - there is a table where you can click on\na specific binding or trigger and it will take you to reference page\nwhere there are code samples in all languages, including Java.\n\nHere's another example using the Azure Event Hub as an input and\nCosmos DB as an output. This example is\nhttps://github.com/dsyer/azure-docs[in github]:\n\n```java\n@FunctionName(\"uppercase\")\npublic Bar execute(\n  @EventHubTrigger(name = \"data\", eventHubName = \"events\",\n        connection = \"TRANSACTIONS_EVENT_HUB_CONNECTION_STRING\")\n    Foo data,\n    @CosmosDBOutput(name = \"document\", databaseName = \"inventory\",\n        collectionName = \"messages\",\n        connectionStringSetting = \"PRODUCT_ITEMS_DOCUMENTDB_CONNECTION_STRING\",\n        createIfNotExists = true)\n    OutputBinding\u003cBar\u003e document,\n    final ExecutionContext context) {\n  return document.setValue(new Bar(foo.getValue()));\n}\n```\n\nNOTE: If the incoming JSON cannot be converted to the function input\ntype (`Foo` in this case) you will see Azure fail with a confusing `no\nsuch method` error. If you see that you might be able to change the\n`@FunctionName` method to a `String` input and eyeball the data to\nmake sure it is bindable to the desired input type.\n\nThe annotations carry connection credential information through an\nindirection to environment variables that are configured in the\nfunction deployment. The configuration for all that happens in the\nbuild `pom.xml` through the Azure Functions Maven plugin. For example:\n\n```xml\n\u003cplugin\u003e\n  \u003cgroupId\u003ecom.microsoft.azure\u003c/groupId\u003e\n  \u003cartifactId\u003eazure-functions-maven-plugin\u003c/artifactId\u003e\n  \u003cconfiguration\u003e\n    \u003cresourceGroup\u003e${functionResourceGroup}\u003c/resourceGroup\u003e\n    \u003cappName\u003e${functionAppName}\u003c/appName\u003e\n    \u003cregion\u003e${functionAppRegion}\u003c/region\u003e\n    \u003cappSettings\u003e\n            \u003cproperty\u003e\n              \u003cname\u003eFUNCTIONS_EXTENSION_VERSION\u003c/name\u003e\n              \u003cvalue\u003ebeta\u003c/value\u003e\n            \u003c/property\u003e\n            \u003cproperty\u003e\n              \u003cname\u003eTRANSACTIONS_EVENT_HUB_CONNECTION_STRING\u003c/name\u003e\n            \u003cvalue\u003e${TRANSACTIONS_EVENT_HUB_CONNECTION_STRING}\u003c/value\u003e\n            \u003c/property\u003e\n            \u003cproperty\u003e\n              \u003cname\u003ePRODUCT_ITEMS_DOCUMENTDB_CONNECTION_STRING\u003c/name\u003e\n              \u003cvalue\u003e${PRODUCT_ITEMS_DOCUMENTDB_CONNECTION_STRING}\u003c/value\u003e\n            \u003c/property\u003e\n            \u003cproperty\u003e\n              \u003cname\u003eMSDEPLOY_RENAME_LOCKED_FILES\u003c/name\u003e\n              \u003cvalue\u003e1\u003c/value\u003e\n            \u003c/property\u003e\n    \u003c/appSettings\u003e\n  \u003c/configuration\u003e\n  \u003cexecutions\u003e\n    \u003cexecution\u003e\n            \u003cid\u003epackage-functions\u003c/id\u003e\n            \u003cgoals\u003e\n              \u003cgoal\u003epackage\u003c/goal\u003e\n            \u003c/goals\u003e\n    \u003c/execution\u003e\n  \u003c/executions\u003e\n\u003c/plugin\u003e\n```\n\nIn this case the environment variable names link the plugin\nconfiguration to the function binding declaration. For instance the\n`@EventHubTrigger` has a `connection` attribute that will be\npopeulated at runtime from the\n`TRANSACTIONS_EVENT_HUB_CONNECTION_STRING` environment variable. The\nplugin configures it remotely using a local environment variable with\nthe same name (notice the `${}` placeholders), which the developer or\nCI process is responsible for setting up at runtime.\n\nYour own personal connection strings are secrets and can be found in\nthe https://portal.azure.com[Azure Dashboard] - when you click on the\nrelevant resource there is usually a `Connection Strings` link (or\nsimilar) that you can copy and paste to your local process (e.g. in a\nscript that you run locally but do not check into source\ncontrol). E.g. you might use a `setup-env.sh` script like this:\n\n```\nexport PRODUCT_ITEMS_DOCUMENTDB_CONNECTION_STRING=\"AccountEndpoint=https://...\"\nexport TRANSACTIONS_EVENT_HUB_CONNECTION_STRING=\"Endpoint=sb://...\"\n```\n\nand source it once at the beginning of a terminal session.\n\nThere are some other plugin declarations in the `pom.xml` of the\nsample. They are all important but basically boilerplate - you should\nbe able to copy them and re-use the same configuration in all Azure\nFunction Applications.\n\n== Spring Cloud Function\n\nSpring Cloud Function aims to support similar serverless use cases\nwhen the application developer declares Spring beans of type\n`java.util.Function`. The advantages of using Spring Cloud Function on\nAzure, as opposed to vanilla Java functions, are that the actual\nbusiness logic code is (in principle) portable to other platforms, and\nit is a familiar programming model for existing Spring users. Also,\nall the usual benefits of Spring apply: dependency injection and\ncomprehensive integration with many other Java libraries.\n\nThe equivalent of both the examples above would be a single `@Bean`:\n\n```java\n@Bean\npublic Function\u003cFoo, Bar\u003e uppercase() {\n  return foo -\u003e new Bar(foo.getValue().toUpperCase());\n}\n```\n\nIn version 1.0 of Spring Cloud Function, the user had to map the\nMicrosoft annotations manually to a JSON deployment descriptor, and\nwrap it up manually into an archive with the right layout for the\nplatform. The process was brittle (but independent of the Azure Java\nprogramming model).\n\nIn version 2.0 this would still work, but we have chosen to support\nthe use of the Azure annotations a bit more explicitly. So now we have\na base class that application developers can extend and decorate with\nthe Azure annotations. The example above would be exactly the same\n`@Bean` and one of the `execute` methods above would be inserted into\nthe subclass of the Spring Cloud handler. Example:\n\n```java\npublic class UppercaseHandler extends AzureSpringBootRequestHandler\u003cFoo, Bar\u003e {\n  @FunctionName(\"uppercase\")\n    @HttpTrigger(name = \"req\", methods = { HttpMethod.GET,\n        HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) Foo foo,\n    ExecutionContext context) {\n  return super.handle(foo, context);\n}\n```\n\nNotice that the base class `AzureSpringBootRequestHandler` is generic\nwith type parameters for input and output. You have to match the input\ntype to the incoming event data, which will be presented in JSON and\nconverted using Jackson by Azure before Spring has anything to\ndo. There are 2 utility methods in the base class, one (`handle`)\nwhich returns the response object, and one (`handleOutput`) which\naccepts an `OutputBinding` and binds it to the output from the user\n`Function`.\n\nNOTE: The base class is pure boilerplate, and serves only as\nan external representation of the binding of your Spring functions\nto the serverless platform services. The Azure bindings would be ignored\nif you were running in a different platform, or locally via the\nSpring Cloud Function web adapter, for instance. It might be possible\nin the future to replace it with an interface declaration - the\nAzure platform doesn't permit this currently, but it's something we\nare looking at with the Microsoft team.\n\nThere are various configuration options that drive the runtime\nbehaviour of the Azure Function. The most important (and only\nmandatory) one is the `MAIN_CLASS`, which is the main\n`@SpringBootApplication` class that carries the declaration of the\n`Function` (or `Functions`). You can specify this as an environment\nvariable, or as the `Main-Class` entry in the application jar\nmanifest. As long as your app has a main class with precisely one\nfunction, there is no need to do anything else. In the sample app we\nuse the manifest to define the main class:\n\n```xml\n\u003cplugin\u003e\n  \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n  \u003cartifactId\u003emaven-jar-plugin\u003c/artifactId\u003e\n  \u003cconfiguration\u003e\n    \u003carchive\u003e\n      \u003cmanifest\u003e\n        \u003cmainClass\u003eexample.FunctionApplication\u003c/mainClass\u003e\n      \u003c/manifest\u003e\n    \u003c/archive\u003e\n  \u003c/configuration\u003e\n\u003c/plugin\u003e\n```\n\nIf your app has multiple `Function` beans, they can be mapped to the\nAzure function though the `@FunctionName` annotation - the bean name\n(or more precisely the name i nthe `FunctionCatalog`) matches the\nfunction name. In this way you can create an Azure Function\nApplication, which is a single deployment artifact for a group of\nfunctions. If you prefer, you can also use an arbitrary\n`@FunctionName` and configure the Spring Cloud Function name through\nan environment variable `FUNCTION_NAME` or a `function.name` in your\n`application.properties`.\n\nThere is another simple sample of how to set up a Spring Cloud\nFunction as an Azure Function in\nhttps://github.com/spring-cloud/spring-cloud-function/blob/master/spring-cloud-function-samples/function-sample-azure/README.adoc[the\nproject repo] - this one is an HTTP trigger from an Azure perspective,\nbut the Spring Cloud Function parts are very similar.\n\nNOTE: If you are at https://springoneplatform.io[Spring One Platform] this week, come along to a https://springoneplatform.io/2018/sessions/running-serverless-applications-using-spring-and-microsoft-azure[presentation on Spring and Azure Functions] by Jeff Hollan (Microsoft) and Oleg Zhurakousky (Pivotal).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsyer%2Fazure-docs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdsyer%2Fazure-docs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdsyer%2Fazure-docs/lists"}