{"id":18594192,"url":"https://github.com/immutables/eventual","last_synced_at":"2025-07-24T01:03:04.663Z","repository":{"id":71445633,"uuid":"145950423","full_name":"immutables/eventual","owner":"immutables","description":"\"Eventual Provides\" aka \"Future Injection\" is an experimental (from 2015) Guice add-on for injection and asynchronous resolution of future dependencies","archived":false,"fork":false,"pushed_at":"2018-08-26T04:06:03.000Z","size":1657,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-05-16T11:09:25.658Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/immutables.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":"2018-08-24T06:15:38.000Z","updated_at":"2020-02-19T13:05:30.000Z","dependencies_parsed_at":"2023-04-21T16:17:03.696Z","dependency_job_id":null,"html_url":"https://github.com/immutables/eventual","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/immutables/eventual","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immutables%2Feventual","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immutables%2Feventual/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immutables%2Feventual/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immutables%2Feventual/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/immutables","download_url":"https://codeload.github.com/immutables/eventual/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/immutables%2Feventual/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266775330,"owners_count":23982271,"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","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-11-07T01:14:47.666Z","updated_at":"2025-07-24T01:03:04.561Z","avatar_url":"https://github.com/immutables.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/immutables/eventual.svg?branch=master)](https://travis-ci.org/immutables/eventual)\n\n## Eventual Providers\n\nGuice add-ons to resolve future-provided dependencies.\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.immutables\u003c/groupId\u003e\n  \u003cartifactId\u003eeventual\u003c/artifactId\u003e\n  \u003cversion\u003e1.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nCreates special mix-in module created from defining class with special asynchronous\ntransformation methods annotated with `@EventuallyProvides`, which is asynchronous analog to Guice's `@Provides`. Used to annotate asynchronous provider methods used to describe transformation of async values.\n\n```java\n\n@Eventually.Provides\nC combine(A a, B b) {\n  return new C(a.a(), b.b());\n}\n```\n\nIn this provider method above we created binding for `ListenableFuture\u003cC\u003e` that will be functionally equivalent to the following regular `@Provides` method:\n\n```java\n@Provides\nListenableFuture\u003cC\u003e combine(ListenableFuture\u003cA\u003e a, ListenableFuture\u003cB\u003e b) {\n  return Futures.transform(Futures.allAsList(Arrays.asList(a, b)),\n      (List\u003cObject\u003e input) -\u003e {\n        A a = (A) input.get(0);\n        B b = (B) input.get(1);\n        return new C(a.a(), b.b());\n      });\n}\n```\n\nHere's more involved example\n\n```java\n@Singleton // all futures will be singletons\npublic class Providers { // no need to extend AbstractModule or implement Module\n\n  @Eventually.Provides\n  A createA() {\n    return ...;\n  }\n\n  @Eventually.Provides\n  ListenableFuture\u003cB\u003e loadB() {\n    // loading of B is itself asyncronous, so we return future\n    return ...;\n  }\n\n  @Eventually.Provides\n  C combine(A a, B b) {\n    // when A and B ready, we calculate C\n    return new C(a.value(), b.calculate());\n  }\n\n  // Only exposed values can be injected between modules,\n  // All other are hidden inside private module\n  @Exposed\n  @Eventually.Provides\n  Z transformed(C c) {\n    // when C is ready, we calculate Z from it\n    return c.transformed();\n  }\n}\n\nModule futureModule = EventualModules.definedBy(new Providers());\n\nListenableFuture\u003cModule\u003e completedModule =\n    EventualModules.completedFrom(Guice.createInjector(futureModule));\n\n// inject Z when all futures completed\nZ z = Guice.createInjector(completedModule.get()).getInstance(Z.class);\n```\n\nHaving dependency on `ListenableFuture\u003cA\u003e` and `ListenableFuture\u003cB\u003e`, this module exposed\ncombined and transformed `ListenableFuture\u003cZ\u003e` available to injector.\n\nWhile super-classes could be used and will be scanned for such methods, method overriding is\nnot handled properly so avoid overriding provider methods. Use delegation to regular methods if some functionality should be implemented or overridden.\n\nIn order to customize dispatching, injector could provided with binding to\n`@Eventually.Async Executor`. So you need to mix in\n\nOn the very abstract level this library achieves transformation: `P(A, B... Z) -\u003e I(A, B... Z)`:\n\n* Define providers `P(A, B... Z)`\n* and use it create (_definedBy_) a module `M(F[A], F[B]... F[Z])`,\n* then use it to create (_createInjector_) injector `I(F[A], F[B]... F[Z])`\n* use injector to get future (_completedFrom_) module `F[M(A, B... Z)]`\n* when future is fulfilled, you create injector `I(A, B... Z)` from the dereferenced module.\n\nBuilder was introduced to somewhat simplify composition of eventual provider modules.\n\n```java\n// Here's equivalent to the example above\nInjector resulting = new EventualModules.Builder()\n    .add(new Providers())\n    .joinInjector();\n\n// Other builder methods:\n//  .skipFailed()\n//  .executor(Executor)\n//  .toFuture()\n```\n\nThe alternative to the solution would be to use plain composition of futures. But even with java 8 lambdas, it's still might be cumbersome to reason about complicated chains of transformation. Definitely, this kind of utility might be also be built specifically for Java 8 without using Guice.\nThis is built with Guava's `ListenableFuture` and not with `CompletableFuture`, sorry.\n\n### Examples\n\n[See FutureJection slides and sample \"Barbican\" project](examples/README.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimmutables%2Feventual","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fimmutables%2Feventual","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fimmutables%2Feventual/lists"}