{"id":15901582,"url":"https://github.com/axel-op/agnostic-serverless-functions-java","last_synced_at":"2025-04-02T19:42:44.446Z","repository":{"id":103258976,"uuid":"536296047","full_name":"axel-op/agnostic-serverless-functions-java","owner":"axel-op","description":"Code once, deploy on multiple FaaS providers (AWS Lambda, Azure Functions, Google Cloud Functions...)","archived":false,"fork":false,"pushed_at":"2023-11-21T13:30:14.000Z","size":172,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-08T10:26:23.471Z","etag":null,"topics":["agnostic-serverless-function","agnostic-to-frameworks","aws-lambda","azure-functions","faas","function-as-a-service","google-cloud-functions","java","java-service-provider","serverless","serverless-functions"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/axel-op.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2022-09-13T20:20:59.000Z","updated_at":"2022-10-22T18:09:02.000Z","dependencies_parsed_at":"2023-11-21T14:47:50.130Z","dependency_job_id":null,"html_url":"https://github.com/axel-op/agnostic-serverless-functions-java","commit_stats":{"total_commits":37,"total_committers":2,"mean_commits":18.5,"dds":"0.027027027027026973","last_synced_commit":"69f283a7a6ffb274fbba963e5d9592cf43851ce8"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axel-op%2Fagnostic-serverless-functions-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axel-op%2Fagnostic-serverless-functions-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axel-op%2Fagnostic-serverless-functions-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axel-op%2Fagnostic-serverless-functions-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axel-op","download_url":"https://codeload.github.com/axel-op/agnostic-serverless-functions-java/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246883433,"owners_count":20849486,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["agnostic-serverless-function","agnostic-to-frameworks","aws-lambda","azure-functions","faas","function-as-a-service","google-cloud-functions","java","java-service-provider","serverless","serverless-functions"],"created_at":"2024-10-06T11:05:08.197Z","updated_at":"2025-04-02T19:42:44.408Z","avatar_url":"https://github.com/axel-op.png","language":"Java","readme":"# Agnostic Serverless Functions in Java\n\nServerless functions are a great way to deploy backend services at a low cost. However, while the infrastructure is abstracted, the code has a strong dependency on the framework used. When a serverless function has been developed targeting a specific FaaS provider, switching to another provider requires some refactoring.\n\nThis project aims at reducing the dependency of serverless functions to a specific framework. An *agnostic serverless function* is here defined as a serverless function that doesn't have a direct dependency (in its code or in its configuration) to the framework of a particular FaaS provider.\n\nWith this project, the same code can be compiled to a function deployable on any supported FaaS platform. Currently, this project supports the following providers (other providers will be added in the future):\n\n- AWS Lambda\n- Azure Functions\n- Google Cloud Functions\n\n## Example\n\nCheck out [this template repository](https://github.com/axel-op/agnostic-serverless-functions-java-example) for a complete example of an agnostic serverless function in Java.\n\n## Usage\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"./diagram.png\" width=400\u003e\u003c/p\u003e\n\n### Code\n\nThe class containing the agnostic function must implement the [`Handler`](./interfaces/src/main/java/fr/axelop/agnosticserverlessfunctions/Handler.java) interface. It must be [registered as a *service provider*](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.html) so it can be loaded with a `ServiceLoader`. This means that there must be a resource file `META-INF/services/fr.axelop.agnosticserverlessfunctions.Handler` containing the fully qualified binary name of your handler class (in this example, it would be `com.example.MyHandler`). You can automate this process by using the [Google @AutoService](https://github.com/google/auto/tree/master/service) annotation.\n\nThere can only be one handler in your JAR.\n\n```java\npackage com.example;\n\nimport java.util.logging.Logger;\n\nimport fr.axelop.agnosticserverlessfunctions.Handler;\nimport fr.axelop.agnosticserverlessfunctions.HttpRequest;\nimport fr.axelop.agnosticserverlessfunctions.HttpResponse;\n\npublic class MyHandler implements Handler {\n\n    @Override\n    public HttpResponse handle(HttpRequest request, Logger logger) {\n        return HttpResponse.newBuilder()\n                .setStatusCode(200)\n                .setBody(request.getBody().isPresent()\n                        ? \"The request body was: \" + request.getBody().get()\n                        : \"There was no body in this \" + request.getMethod() + \" request!\")\n                .build();\n    }\n\n}\n```\n\n### Configuration\n\nYou'll need to add two dependencies from [my Maven repository](https://github.com/axel-op/maven-packages):\n\n- [`interfaces`](https://github.com/axel-op/maven-packages/packages/1617850) contains the classes that will be used to code the agnostic function.\n- `adapter` will add the classes needed to execute the function on the selected cloud provider.\n\n```xml\n\u003c!-- pom.xml --\u003e\n\u003cproject\u003e\n\n    \u003cproperties\u003e\n        \u003c!-- Can be: aws, azure, gcloud --\u003e\n        \u003c!-- This property can also be set by a command-line parameter --\u003e\n        \u003cfaas.provider\u003egcloud\u003c/faas.provider\u003e\n    \u003c/properties\u003e\n\n    \u003cdependencies\u003e\n        \u003cdependency\u003e\n            \u003cgroupId\u003efr.axelop.agnosticserverlessfunctions\u003c/groupId\u003e\n            \u003cartifactId\u003einterfaces\u003c/artifactId\u003e\n            \u003cversion\u003e0.0.1-SNAPSHOT\u003c/version\u003e\n        \u003c/dependency\u003e\n\n        \u003cdependency\u003e\n            \u003cgroupId\u003efr.axelop.agnosticserverlessfunctions\u003c/groupId\u003e\n            \u003cartifactId\u003e${faas.provider}-adapter\u003c/artifactId\u003e\n            \u003cversion\u003e0.0.1-SNAPSHOT\u003c/version\u003e\n            \u003cscope\u003eruntime\u003c/scope\u003e\n        \u003c/dependency\u003e\n    \u003c/dependencies\u003e\n\n\u003c/project\u003e\n```\n\n### Packaging and deployment\n\nThese steps are specific to each FaaS provider:\n\n- [AWS Lambda](./aws-adapter/README.md)\n- [Azure Functions](./azure-adapter/README.md)\n- [Google Cloud Functions](./gcloud-adapter/README.md)\n\nIf you're using GitHub Actions, use [`agnostic-serverless-functions-java-package-action`](https://github.com/axel-op/agnostic-serverless-functions-java-package-action) to package your function.\n\n## Advantages\n\n- Scalability: the deployment of the same code on different providers can be completely automated.\n- Migration: as there is no direct dependency between the business logic and the provider-specific framework, it's easy to switch to a different provider without modifying the code at all.\n- A/B testing: a same function can be deployed on multiple providers at the same time, making it easy to compare their performance.\n\n## Limitations and future improvements\n\n### Limited trigger types\n\nFor now, this project can only deploy HTTP-triggered functions.\n\n### Non-agnostic packaging and deployment\n\nWhile they can be entirely automated, the packaging and deployment steps differ between the cloud providers. A possible improvement is to script them so they can be triggered by a unique command.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxel-op%2Fagnostic-serverless-functions-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faxel-op%2Fagnostic-serverless-functions-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxel-op%2Fagnostic-serverless-functions-java/lists"}