{"id":40565200,"url":"https://github.com/streamingpool/streamingpool-core","last_synced_at":"2026-01-21T01:08:09.201Z","repository":{"id":57740861,"uuid":"78855454","full_name":"streamingpool/streamingpool-core","owner":"streamingpool","description":null,"archived":false,"fork":false,"pushed_at":"2021-05-11T12:45:00.000Z","size":745,"stargazers_count":5,"open_issues_count":3,"forks_count":5,"subscribers_count":5,"default_branch":"master","last_synced_at":"2023-07-07T10:43:09.450Z","etag":null,"topics":["java-8","long-living-reactive-streams","reactive-streams"],"latest_commit_sha":null,"homepage":"http://www.streamingpool.org/","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/streamingpool.png","metadata":{"files":{"readme":"README.asciidoc","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-13T14:18:52.000Z","updated_at":"2023-07-07T10:43:09.451Z","dependencies_parsed_at":"2022-09-06T23:30:38.373Z","dependency_job_id":null,"html_url":"https://github.com/streamingpool/streamingpool-core","commit_stats":null,"previous_names":[],"tags_count":30,"template":null,"template_full_name":null,"purl":"pkg:github/streamingpool/streamingpool-core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamingpool%2Fstreamingpool-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamingpool%2Fstreamingpool-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamingpool%2Fstreamingpool-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamingpool%2Fstreamingpool-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/streamingpool","download_url":"https://codeload.github.com/streamingpool/streamingpool-core/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamingpool%2Fstreamingpool-core/sbom","scorecard":{"id":855028,"data":{"date":"2025-08-11","repo":{"name":"github.com/streamingpool/streamingpool-core","commit":"3d56015e90de1e3788212a5dba029f8cd254021c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Code-Review","score":0,"reason":"Found 2/25 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":9,"reason":"binaries present in source code","details":["Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 11 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T23:40:46.279Z","repository_id":57740861,"created_at":"2025-08-23T23:40:46.279Z","updated_at":"2025-08-23T23:40:46.279Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28620575,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T23:49:58.628Z","status":"ssl_error","status_checked_at":"2026-01-20T23:47:29.996Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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-8","long-living-reactive-streams","reactive-streams"],"created_at":"2026-01-21T01:08:08.573Z","updated_at":"2026-01-21T01:08:09.194Z","avatar_url":"https://github.com/streamingpool.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n:source-highlighter: pygments\n\nimage:https://img.shields.io/travis/streamingpool/streamingpool-core/master.svg[]\nimage:https://img.shields.io/github/release/streamingpool/streamingpool-core.svg[]\nimage:https://img.shields.io/github/license/streamingpool/streamingpool-core.svg[]\nimage:https://codecov.io/gh/streamingpool/streamingpool-core/branch/master/graph/badge.svg[\"codecov\", link=\"https://codecov.io/gh/streamingpool/streamingpool-core\"]\nimage:https://api.codacy.com/project/badge/Grade/b398bb4734f64bd28767234b88a75c93[\"Codacy code quality\", link=\"https://www.codacy.com/app/tensorics/streamingpool-core?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=streamingpool/streamingpool-core\u0026utm_campaign=Badge_Grade\"]\n\n== Getting Started\nIn order to use the Streaming Pool, just get the latest version from https://search.maven.org/#search%7Cga%7C1%7Ca%3A%22streamingpool-core%22[Maven Central].\n\nMaven:\n[source,xml]\n----\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.streamingpool\u003c/groupId\u003e\n    \u003cartifactId\u003estreamingpool-core\u003c/artifactId\u003e\n    \u003cversion\u003eX.Y.Z\u003c/version\u003e\n\u003c/dependency\u003e\n----\nGradle:\n[source,groovy]\n----\ncompile 'org.streamingpool:streamingpool-core:X.Y.Z'\n----\n\nIt is possible to check the examples by cloning this repository and checking the `src/examples` folder. There, core functionality of the Streaming Pool project are explained.\n\nKeep in mind that Streaming Pool assumes that http://projects.spring.io/spring-framework/[Spring Framework] is used for managing the application Beans.\n\n== Motivation\nWhen connecting together heterogeneous and complex systems, it is not easy to exchange data between components. Streams of data are successfully used in industry in order to overcome this problem, especially in the case of \"live\" data. Streams are a specialization of the Observer design pattern and they provide asynchronous and non-blocking data flow.\n\nThe ongoing effort of the http://reactivex.io/[ReactiveX] initiative is one example that demonstrates how demanding this technology is even for big companies. Bridging the discrepancies of different technologies with common interfaces is already done by the http://www.reactive-streams.org/[Reactive Streams] initiative and, in the JVM world, via https://github.com/reactive-streams/reactive-streams-jvm[reactive-streams-jvm] interfaces.\n\nStreaming Pool is a framework for providing and discovering reactive streams. Through the mechanism of dependency injection provided by the http://projects.spring.io/spring-framework/[Spring Framework], Streaming Pool provides a so called `DiscoveryService`. This object can discover and chain streams of data that are technologically agnostic, through the use of instances of the `StreamId` interface. The stream to be discovered must be present in the Streaming Pool system (by providing it using the `ProvidingService`) or it must be possible to create it (using one of the registered `StreamFactory`). In the latter case, the stream is lazily created on demand.\nThe application (client) that uses a stream does not need to know which is the source of the information, it may be a component of the application itself or a distributed system. In this way, it is possible to create truly decoupled systems that are resilient to changes and are easy to mock or test.\n\n== Introduction\nA common use case in modern Software applications is to access the values from a particular source. In the context of Internet of Things the source can be a sensor or a device. In business applications the source can be a real time indicator or application state. At CERN a common problem is to listen for devices values of the control system of different machines.\n\nAll these problems can be solved using the well-known Observable-Observer pattern or a Reactive Stream of the data. Streaming Pool assumes you want to use a Reactive Stream for accessing your data.\n\nThere are technologies that already solve this problem, such as https://projectreactor.io/[Project Reactor] and https://github.com/ReactiveX/RxJava[RxJava]. They provide stream creation, manipulation and subscription capabilities and they are great. Streaming Pool sits on top of these technologies.\n\nThe goal of Streaming Pool is to manage, reuse and share Reactive Streams, locally (in the same JVM) or remotely (distributed environment). The only required knowledge is the ID or `StreamId` that describes the Reactive Stream to obtain.\n\n=== StreamId\nA `StreamId` is an object that implements the `StreamId\u003cT\u003e` interface. The generic type indicates the type of the data in the Reactive Stream. For each `StreamId\u003cT\u003e` there is a corresponding `Publisher\u003cT\u003e` and we enforce to have a consistent type by design.\n\nNote that the `StreamId` interface is a marker interface, it is used as a key to distinguish `Publisher` instances in the Streaming Pool. Depending on your needs, the `StreamId` can be used to carry information about the characteristics of the Reactive Stream you want to get (especially useful in combination with a `StreamFactory`).\n\n[CAUTION]\n====\nSince the `StreamId` acts as key in the Streaming Pool for the corresponding `Publisher` it *must implement* `equals(Object o)` and `hashCode()` methods. If it is not the case, the `Publisher` in the Streaming Pool will not be reused and the behavior could be unpredictable.\n====\n\n=== Discover a stream\n[source,java]\n----\nclass TemperatureAdapter {\n    @Autowired\n    private DiscoveryService discoveryService;\n\n    public Flowable\u003cDouble\u003e temperaturesOf(Building building, Floor floor) {\n        StreamId\u003cDouble\u003e temperatureStreamId = TemperatureStreamId.builder()\n          .ofBuilding(building)\n          .ofFloor(floor)\n          .build();\n\n        Publisher\u003cDouble\u003e temperatureStream = discoveryService.discover(temperatureStreamId);\n        return Flowable.fromPublisher(temperatureStream);\n    }\n}\n----\nIn this example, the `Publisher` (Reactive Stream) related to the specified `deviceStreamId` is then returned. Behind the scenes, the Streaming Pool engine will retrieve the proper `Publisher`.\n\n[NOTE]\n====\nKeep in mind that you can query for the same ID multiple times and you will get the same instance of the `Publisher` (like in a `Map\u003cStreamId\u003cT\u003e, Publisher\u003cT\u003e\u003e`).\n====\n\n=== Provide a stream\n[source,java]\n----\nclass TemperatureProvider {\n    @Autowired\n    private ProvidingService providingService;\n\n    public void provideTemperatureStream(Building building, Floor floor, Flowable\u003cDouble\u003e temperatures) {\n      StreamId\u003cDouble\u003e temperatureStreamId = TemperatureStreamId.builder()\n        .ofBuilding(building)\n        .ofFloor(floor)\n        .build();\n\n        providingService.provide(temperatureStreamId, temperatures);\n    }\n}\n----\nIn the case you want to provide a Reactive Stream, you can easily do so by using the `ProvidingService` interface. It has a single method that will register in the Streaming Pool system the given `Publisher` associated to the given `StreamId`. Later on, you can discover the stream by querying a `DiscoveryService` with the same `StreamId`.\n\n[NOTE]\n====\nIt is currently not possible to remove a Reactive Stream from the Streaming Pool. This feature is scheduled to be implemented, but it is not part of the current development.\n====\n\n=== How to lazily create Reactive Streams\nYou do not have to explicitly provide `Publisher` instances in the Streaming Pool. A common way of creating Reactive Streams is through the use of `StreamFactory`. A `StreamFactory` is a mechanism that is used to create a `Publisher` from a given `StreamId`. When looking for a `StreamId` that has not been provided using the `ProvidingService`, the framework checks if any registered `StreamFactory` is able to create it.\n\nUsing this mechanism, a `Publisher` is created on-demand (lazily) if it is not already present in the Streaming Pool system. A Stream Factory is a class that implements the interface `StreamFactory`.\n\n==== Stream factory\n[source,java]\n----\n\u003cT\u003e Optional\u003cPublisher\u003cT\u003e\u003e create(StreamId\u003cT\u003e id, DiscoveryService discoveryService);\n----\nA `StreamFactory` needs to implement the `create(...)` method in which they have to:\n\n1. decide if it can create a `Publisher` for the given `StreamId`\n2. actually create the `Publisher` and return it\n\nDuring the stream creation, you have access to the `DiscoveryService` in the case you need to lookup other Reactive Streams. You should be aware though that circular dependencies during stream creation are detected and the discovery method will throw accordingly.\n\n*`StreamId` discovery is not thread-safe*, therefore it is *forbidden* to use different threads inside a `StreamFactory#create` method. This case is checked and Streaming Pool will throw an exception.\n\n[NOTE]\n====\nIn case the `StreamFactory` is not able to create the current `StreamId`, by convention it must return an empty `Optional`.\n====\n\n[IMPORTANT]\n====\nBy method signature, the type of the `StreamId` and the type of the produced `Publisher` must match. Often, you will have your own types of `StreamId`, so after proper checking you can cast to your own instance of `StreamId`. Again, after the creation is ok to cast again the `Publisher` to a `Publisher\u003cT\u003e` to satisfy the Java compiler. This trick is needed, mostly, because of the generics implementation in Java.\n====\n\nIn order to use your `StreamFactory`, you have to register it. Streaming Pool makes extensive use of Spring dependency injection, and it collects all the objects that are implementing the `StreamFactory` interface in the context. Those Beans will be then registered in the Streaming Pool and they will be used in the discovery process if needed. Therefore, you just have to provide a Bean for your factories.\n\n=== How discovery works\nOne of the key feature of Streaming Pool is the discovery of a Reactive Stream using the `DiscoveryService`.\n\nThe discovery can be summarized by the following pseudo-code.\n[source]\n----\nfunction discover(SteamId id)\n\n    if streamingPoolContains(id) \u003c1\u003e\n        return getStreamFor(id)\n\n    if not streamFactoriesCanCreate(id) \u003c2\u003e\n        throws exception\n\n    return streamFactoriesCreate(id) \u003c3\u003e\n----\n\u003c1\u003e check if the `StreamId` is already present in the Streaming Pool and return it.\n\u003c2\u003e if the stream cannot be created by any factory, then an error is thrown. In this case, make sure you are registering your `StreamFactory` correctly.\n\u003c3\u003e a `StreamFactory` is able to create the Reactive Stream, so it the stream is created and registered in the Streaming Pool.\n\n== Examples\nIt is possible to find examples of the Streaming Pool features in the folder `src/examples` in the repository source code. The examples are expressed as JUnit tests and they can be run and modified. The goal is to provide a quickstart for understanding how Streaming Pool works.\n\nWe assume that you have a basic understanding of http://projects.spring.io/spring-framework/[Spring Framework] dependency injection using annotations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstreamingpool%2Fstreamingpool-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstreamingpool%2Fstreamingpool-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstreamingpool%2Fstreamingpool-core/lists"}