{"id":16838901,"url":"https://github.com/akarnokd/reactive4javaflow","last_synced_at":"2025-03-22T05:30:50.810Z","repository":{"id":23204504,"uuid":"98419292","full_name":"akarnokd/Reactive4JavaFlow","owner":"akarnokd","description":"Reactive Programming library based on the Java 9 Flow API and a 4th generation ReactiveX-style architecture.","archived":false,"fork":false,"pushed_at":"2023-01-30T04:03:09.000Z","size":1257,"stargazers_count":50,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-18T08:21:43.739Z","etag":null,"topics":["java","reactive","reactive-streams"],"latest_commit_sha":null,"homepage":null,"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/akarnokd.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}},"created_at":"2017-07-26T12:16:51.000Z","updated_at":"2024-03-31T14:19:45.000Z","dependencies_parsed_at":"2023-02-10T13:15:39.104Z","dependency_job_id":null,"html_url":"https://github.com/akarnokd/Reactive4JavaFlow","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akarnokd%2FReactive4JavaFlow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akarnokd%2FReactive4JavaFlow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akarnokd%2FReactive4JavaFlow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akarnokd%2FReactive4JavaFlow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akarnokd","download_url":"https://codeload.github.com/akarnokd/Reactive4JavaFlow/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244912800,"owners_count":20530764,"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":["java","reactive","reactive-streams"],"created_at":"2024-10-13T12:27:18.347Z","updated_at":"2025-03-22T05:30:47.177Z","avatar_url":"https://github.com/akarnokd.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reactive4JavaFlow\n\n\u003ca href='https://github.com/akarnokd/Reactive4JavaFlow/actions?query=workflow%3A%22Java+CI+with+Gradle%22'\u003e\u003cimg src='https://github.com/akarnokd/Reactive4JavaFlow/workflows/Java%20CI%20with%20Gradle/badge.svg'\u003e\u003c/a\u003e\n[![codecov.io](http://codecov.io/github/akarnokd/Reactive4JavaFlow/coverage.svg?branch=master)](http://codecov.io/github/akarnokd/Reactive4JavaFlow?branch=master)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.akarnokd/reactive4javaflow/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.akarnokd/reactive4javaflow)\n\n\nReactive Programming library based on the Java 9 Flow API and a 4th generation ReactiveX-style architecture.\n\n### Gradle\n\n```groovy\ncompile \"com.github.akarnokd:reactive4javaflow:0.1.5\"\n```\n\n# Getting Started\n\nThe base package of Reactive4JavaFlow is `hu.akarnokd.reactive4javaflow` where the main reactive classes are located.\nNote that the library requires a JDK 9 compatible runtime, thus it is not compatible with most of what is\ncurrently available on Android.\n\nThe library doesn't declare modules (Project Jigsaw) and should be usable from both classpath and modularized environments.\n\n## `Folyam` \n\nThe `Folyam` base reactive type is the 0 .. N element, backpressure aware, Java 9 Flow.Publisher implementation. \nThe word means flow or stream in hungarian and was chosen to avoid name clashing with existing libraries and types (such\nas `Flowable`, `Flux`, `Stream` and unfortunately `Flow` too). The name is also one of the few words describing the\ntarget concept that doesn't use accented letters.\n\n`Folyam` features most of the typical [ReactiveX](http://reactivex.io/documentation/operators.html) operators commonly \nfound in RxJava and Reactor and couple of the less common extension operators from \n[RxJava 2 Extensions](https://github.com/akarnokd/RxJava2Extensions#features).\n\n### Hello world!\n\n```java\nimport hu.akarnokd.reactive4javaflow.*;\n\nFolyam.just(\"Hello world!\")\n      .subscribe(System.out::println);\n```\n\nOperators that work with multiple sources and may need to delay errors now have separate methods with `DelayError`\npostfix: `concatDelayError`, `flatMapDelayError`.\n\n## `Esetleg`\n\nThe `Esetleg` base reactive type is the 0 .. 1 element, backpressure aware, Java 9 FLow.Publisher implementation.\nIt resembles the RxJava 2 `Maybe` type and is similar to Reactor's `Mono` type. The word itself means maybe or\nperhaps.\n\n### Hello world!\n\n```java\nAutoDisposable d = Esetleg.fromCallable(() -\u003e \"Hello world\")\n.subscribeWith(new AbstractFolyamSubscriber\u003c\u003e() {\n    @Override public void onNext(String s) {\n        System.out.print(s);\n    }\n    @Override public void onError(Throwable ex) {\n        ex.printStackTrace();\n    }\n    @Override public void onComplete() {\n        System,out.println(\"!\");\n    }\n});\n\nd.close();\n```\n\n## `AutoDisposable`\n\nThe resource manager type is the `AutoDisposable` interface, which extends from `java.util.AutoCloseable` and thus can\nbe used in **try-with-resources**. Unlike RxJava 2 `Disposable`, the interface doesn't offer any means to check if\nthe resource is disposed.\n\nThe `AbstractFolyamSubscriber` shown in the previous section's example also implements `AutoDisposable` and together\nwith `hu.akarnokd.reactive4javaflow.disposables.CompositeAutoDisposable` can be used to track and mass-close resources.\n\nThe `disposables.BooleanAutoDisposable` can help in testing and `SequentialAutoDisposable` may help with\ncustom operators or individual resource tracking.\n\n## `ParallelFolyam`\n\nJust like RxJava 2 and Reactor 3, the library offers parallel operations through the `Folyam.parallel()` method. The\n`ParallelFolyam` features the same operators as RxJava 2 does plus several of the sequential and less common operators\nsuch as the asynchronous `mapWhen()`.\n\n```java\nFolyam.range(1, 100)\n.parallel()\n.runOn(SchedulerServices.computation())\n.sumInt()\n.test()\n.assertResult(5050);\n```\n\n## Schedulers\n\nThe library offers the standard set of global schedulers in `SchedulerServices` (named to avoid too much conflict with\nRxJava and Reactor): `computation`, `io`, `newThread`, `single`, `trampoline` and `newExecutor`. Testing can be done with the\n`TestSchedulerService` class. \n\nIn addition, the `SchedulerServices` allows creating custom schedulers, parameterized by name, priority and daemon-ness\nvia `newParallel`, `newIO`, `newThread` and `newSingle`. The utility class also supports creating blocking schedulers via\n`newBlocking` and sharing an existing worker via `newShared`.\n\nThe `SchedulerService` interface implemented by the scheduler offers the ability to schedule tasks of\n`Runnable` directly or on a `Worker`; immediately, delayed or periodically. The `Worker` interface\nimplements `AutoDisposable` and all of the pending tasks can be cancelled via `Worker.close()`.\n\nThe current API design in `Folyam` and `Esetleg` doesn't offer operators with default schedulers; the\n`SchedulerService` to be used must be specified as parameter to these operators.\n\n```java\nFolyam.intervalRange(1, 5, 100, 100, TimeUnit.MILLISECONDS, SchedulerServices.single())\n.blockingSubscribe(System.out::println);\n```\n\n## Functional interfaces\n\nUnfortunately, Java's default functional interfaces don't support throwing checked exceptions, therefore\na set of new interfaces were added and used throughout the API:\n\n```java\nimport hu.akarnokd.reactive4javaflow.functionals.*;\n\nCheckedFunction\u003cInteger, Integer\u003e f = v -\u003e { throw new IOException(); };\n\nFolyam.just(1).map(f).test().assertFailure(IOException.class);\n```\n\n## Processors (hot sources)\n\nThe library features almost all standard \"subject\" types from RxJava in the `processors` subpackage:\n\n- `DirectProcessor`: emit items directly to multiple subscribers, signals error if a particular subscriber is not ready to receive items (similar to RxJava's `PublishProcessor`),\n- `MulticastProcessor`: coordinates the backpressure between subscribers (no standard RxJava equivalent),\n- `FirstProcessor`: takes and caches the first item or terminal signal and exposes it as an `Esetleg` reactive type (similar to `MaybeSubject`),\n- `LastProcessor`: waits for and caches the last item or terminal signal and exposes it as a `Folyam` (similar to `AsyncProcessor`),\n- `CachingProcessor`: caches items (unbounded, size and/or time bound) and replays them to current and future subscribers (similar to `ReplayProcessor`),\n- `SolocastProcessor`: buffers items until a single subscriber is able to consume them (similar to `UnicastProcessor`).\n\nThe `BehaviorProcessor` is currently not replicated in this library and can be emulated via `new CachingProcessor\u003c\u003e(1)`.\n\n## Connectable flows\n\nThe cold-to-hot conversion is available via the `Folyam.publish()` and `Folyam.replay()` operators which return a\n`ConnectableFolyam` instance.\n\nUnlike RxJava and Reactor, the `ConnectableFolyam` has 3 states: fresh, running, terminated. In order to get back\nto the fresh state, one has to call `ConnectableFolyam.reset()` in the terminated state.\n\nThe reason for this design difference is that the RxJava behavior often causes trouble in preparing subscribers\nafter the first round has completed, which can lead to data loss in case of `publish()`.\n\n```java\nConnectableFolyam\u003cInteger\u003e cf = Folyam.range(1, 5).publish();\n\ncf.subscribe(System.out::println);\ncf.subscribe(System.out::println);\n\ncf.connect();\n\n// the source has run to completion and\n// publish will complete any latecommers\n\ncf.test().assertResult();\n\n// go back to the fresh state\n\ncf.reset();\n\n// prepare the next set of subscribers without\n// the source to rush ahead\n\ncf.subscribe(System.out::println);\ncf.subscribe(System.out::println);\n\ncf.connect();\n\n```\n\nA more prominent effect is when `replay` or `replayLast()` is used. Once the source completed, all or\nthe last items are still available to late subscribers until `reset` is called.\n\n\nThe usual `autoConnect()` and `refCount` operators are supported along with `refCount` overloads that\nallows specifying the minimum subscriber count and/or a grace period before closing the connection after\nthe last subscriber has cancelled.\n\n## Testing\n\nTesting the `Folyam` and `Esetleg` types can be done via the convenient `.test()` method which uses\na `TestConsumer` class behind the scenes (similar to `TestSubscriber`).\n\nScheduler-dependent operators can be tested with the help of the `TestSchedulerService` and its `advanceTimeBy` method\nas the mean to move time forward.\n\n```java\nTestSchedulerService sch = new TestSchedulerService();\n\nTestConsumer\u003cInteger\u003e tc = Folyam.just(1).delay(5, TimeUnit.MILLISECONDS, sch).test();\n\ntc.assertEmpty();\n\ntc.advanceTimeBy(5, TimeUnit.MILLISECONDS);\n\ntc.assertResult(1);\n\n```\n\n## Plugins \u0026 hooks\n\nThe `FolyamPlugins` offers the ability to hook the assembling of operators (`onAssembly`), when they get\nsubscribed `onSubscribe` and when there is an undeliverable exception `onError`. \n\nThe `FolyamPluins` also allows overriding the initial and current schedulers returned by `SchedulerServices`.\nNote that accessing `SchedulerServices` - for example, to create a custom scheduler via one of the `newXXX` methods\nmay prematurely initialize the other schedulers. Therefore, it is recommended to hook the\ncurrent schedulers only (`setOnComputationSchedulerService`).\n\n## Operator fusion\n\nThe **Reactive4JavaFlow** library is a 4th generation reactive solution that supports the operator fusion concept\nmore extensively than RxJava 2 does at the moment. Since there is no standard, multi-library API for operator fusion anyway, this\nlibrary defines the core interfaces in the `hu.akarnokd.reactive4javaflow.fused` package:\n\n- `ConditionalSubscriber`: with its `tryOnNext` method, such subscriber can avoid `request(1)` calls and keep draining longer without costly atomic decrements\n- `FusedQueue`: base interface for queues with minimal number of operations and a `poll()` method that can throw a `Throwable`\n- `FusedSubscription`: the combination of `FusedQueue` and the Java 9 `Flow.Subscription` interfaces to establish and run fused queues\n- `FusedDynamicSource`: represents a source that can produce an item, null or throw an exception at the runtime of the flow\n- `FusedStaticSource`: special variant of the dynamic source that can hosts a constant (or is empty) and allows assembly time optimizations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakarnokd%2Freactive4javaflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakarnokd%2Freactive4javaflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakarnokd%2Freactive4javaflow/lists"}