{"id":16486357,"url":"https://github.com/rashidi/boot-cloud-function-background-sample","last_synced_at":"2025-04-04T17:49:24.038Z","repository":{"id":37833063,"uuid":"401213302","full_name":"rashidi/boot-cloud-function-background-sample","owner":"rashidi","description":"Sample GCP Background Function with Spring Cloud Function for GCP.","archived":false,"fork":false,"pushed_at":"2023-04-06T01:58:01.000Z","size":121,"stargazers_count":2,"open_issues_count":6,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-10T03:15:57.284Z","etag":null,"topics":["gcp-cloud-functions","spring-cloud-function","spring-data-mongodb","test-containers","tutorial-code"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rashidi.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":"2021-08-30T04:15:22.000Z","updated_at":"2023-01-18T14:35:31.000Z","dependencies_parsed_at":"2024-12-17T21:30:37.669Z","dependency_job_id":"75a58e70-da80-4543-9d87-08de805b4119","html_url":"https://github.com/rashidi/boot-cloud-function-background-sample","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rashidi%2Fboot-cloud-function-background-sample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rashidi%2Fboot-cloud-function-background-sample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rashidi%2Fboot-cloud-function-background-sample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rashidi%2Fboot-cloud-function-background-sample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rashidi","download_url":"https://codeload.github.com/rashidi/boot-cloud-function-background-sample/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247226195,"owners_count":20904465,"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":["gcp-cloud-functions","spring-cloud-function","spring-data-mongodb","test-containers","tutorial-code"],"created_at":"2024-10-11T13:29:07.623Z","updated_at":"2025-04-04T17:49:24.005Z","avatar_url":"https://github.com/rashidi.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Spring Cloud GCP Background Function Example\nDemonstrate updating user's status through GCP Background Function\n\n## Dependencies:\n- [JDK](https://openjdk.java.net/) 11 or later\n- [Project Lombok](https://projectlombok.org/)\n- [Spring Cloud Function GCP Adapter](https://cloud.spring.io/spring-cloud-function/reference/html/spring-cloud-function.html#_google_cloud_functions_alpha)\n- [Spring Data MongoDB](https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/)\n- [MongoDB TestContainers](https://www.testcontainers.org/modules/databases/mongodb/)\n- [LocalServerTestSupport.java from Spring Cloud Function samples](https://github.com/spring-cloud/spring-cloud-function/blob/main/spring-cloud-function-samples/function-sample-gcp-http/src/test/java/com/example/LocalServerTestSupport.java)\n\nFull dependencies can be found in [pom.xml](pom.xml)\n\n## Implementations\n\n### Test Implementation\nWe will start by implementing test which will verify that User's status will be updated. Our test will be based on \nthe following scenario:\n\n```gherkin\nGiven user status is ACTIVE\nWhen a message is published with user status DORMANT\nThen user status in database should be DORMANT\n```\n\nThis is demonstrated in the following implementation:\n\n```java\nclass UpdateUserStatusApplicationTests {\n\n    @Test\n    @DisplayName(\"User status will be updated based on provided value in message\")\n    void contextLoads() throws IOException, InterruptedException {\n        var restTemplate = new TestRestTemplate();\n        var message = messageWithNewUserStatus();\n\n        try(var process = startServer(UpdateUserStatusApplication.class, MONGO_DB_CONTAINER)) {\n            restTemplate.postForObject(\"http://localhost:8080/\", message, String.class);\n        }\n\n        var updatedUser = findById(user.getId());\n\n        assertThat(updatedUser.getStatus()).isEqualTo(DORMANT);\n    }\n    \n    private User findById(ObjectId id) {\n        return template.findById(id, User.class);\n    }\n\n    private PubSubMessage messageWithNewUserStatus() {\n        var message = new PubSubMessage();\n\n        message.setAttributes(Map.of(\n                \"id\", user.getId().toString(),\n                \"status\", DORMANT.name()\n        ));\n\n        return message;\n    }\n\n}\n```\n\nFull implementation can be found in [UpdateUserStatusApplicationTests](src/test/java/scratches/boot/cloud/user/UpdateUserStatusApplicationTests.java).\n\n### Repository Implementation\n[UserRepository](src/main/java/scratches/boot/cloud/user/UserRepository.java) will be responsible to update [User](src/main/java/scratches/boot/cloud/user/User.java) \nbased on provided [UserStatus](src/main/java/scratches/boot/cloud/user/UserStatus.java)\n\n```java\n@Repository\n@AllArgsConstructor\npublic class UserRepository {\n\n    private final MongoTemplate template;\n\n    public void updateStatusById(ObjectId id, UserStatus newStatus) {\n        template.updateFirst(\n                query(where(\"_id\").is(id)),\n                update(\"status\", newStatus),\n                User.class\n        );\n    }\n\n}\n```\n\n### Function Implementation\nNext, we will implement a [Background Function](https://cloud.google.com/functions/docs/writing/background) that will be triggered through \n[PubSubMessage](src/main/java/scratches/boot/cloud/user/PubSubMessage.java). `PubSubMessage` is a `class` that contains the structure of \n[GCP Pubsub Message](https://cloud.google.com/pubsub/docs/reference/rest/v1/PubsubMessage) structure.\n\n```java\n@Component\n@AllArgsConstructor\npublic class UpdateUserStatusFunction implements Consumer\u003cPubSubMessage\u003e {\n\n    private final UserRepository repository;\n\n    @Override\n    public void accept(PubSubMessage message) {\n        var attributes = message.getAttributes();\n\n        var id = new ObjectId(attributes.get(\"id\"));\n        var newStatus = UserStatus.valueOf(attributes.get(\"status\"));\n\n        repository.updateStatusById(id, newStatus);\n    }\n\n}\n```\n\n### Define Configuration Main Class\nFinally, we will need to specify our configuration main class. This is defined in [MANIFEST.MF](src/main/resources/META-INF/MANIFEST.MF)\n\n```manifest\nMain-Class: scratches.boot.cloud.user.UpdateUserStatusApplication\n\n```\n\n## Verify\nOnce all are implemented, we will verify that our implementation works by executing `UpdateUserStatusApplicationTests.contextLoads`. If all \nimplementation is correct, our verification that asserts `UserStatus` is now `DORMANT` will pass.\n\n```java\nclass UpdateUserStatusApplicationTests {\n\n    @Test\n    @DisplayName(\"User status will be updated based on provided value in message\")\n    void contextLoads() throws IOException, InterruptedException {\n        var updatedUser = findById(user.getId());\n\n        assertThat(updatedUser.getStatus()).isEqualTo(DORMANT);\n    }\n\n}\n```\n\n## Running the Function Locally\nWe can also run the function locally through the following command:\n\n```shell\nmvn function:run\n```\n\nYou can find more information at [Spring Cloud Function - Google Cloud Functions](https://cloud.spring.io/spring-cloud-function/reference/html/spring-cloud-function.html#_google_cloud_functions_alpha)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frashidi%2Fboot-cloud-function-background-sample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frashidi%2Fboot-cloud-function-background-sample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frashidi%2Fboot-cloud-function-background-sample/lists"}