├── .build └── deploy-doc.sh ├── .github ├── project.yml ├── release │ ├── maven-settings.xml.gpg │ └── smallrye-sign.asc.gpg └── workflows │ ├── build.yml │ ├── pre-release.yml │ └── release.yml ├── .gitignore ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── cdi ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── smallrye │ │ │ └── reactive │ │ │ └── streams │ │ │ └── cdi │ │ │ └── ReactiveEngineProvider.java │ └── resources │ │ └── META-INF │ │ └── beans.xml │ └── test │ ├── java │ └── io │ │ └── smallrye │ │ └── reactive │ │ └── streams │ │ └── cdi │ │ ├── MyBean.java │ │ └── ReactiveEngineProviderTest.java │ └── resources │ └── log4j2-test.xml ├── doc ├── assets │ ├── images │ │ ├── collect.png │ │ ├── concat.png │ │ ├── converters.png │ │ ├── distinct.png │ │ ├── dropWhile.png │ │ ├── empty.png │ │ ├── example.png │ │ ├── failed.png │ │ ├── filter.png │ │ ├── findFirst.png │ │ ├── flatMap.png │ │ ├── flatMapCompletionStage.png │ │ ├── flatMapIterable.png │ │ ├── flatMapRsPublisher.png │ │ ├── forEach.png │ │ ├── fromCompletionStage.png │ │ ├── fromCompletionStageNullable.png │ │ ├── fromIterable.png │ │ ├── generate.png │ │ ├── identity.png │ │ ├── ignore.png │ │ ├── iterate.png │ │ ├── limit.png │ │ ├── map.png │ │ ├── of-many.png │ │ ├── of-single.png │ │ ├── ofNullable.png │ │ ├── onComplete.png │ │ ├── onError.png │ │ ├── onErrorResume.png │ │ ├── onErrorResumeWith.png │ │ ├── onErrorResumeWithRsPublisher.png │ │ ├── onTerminate.png │ │ ├── peek.png │ │ ├── reduce-identity.png │ │ ├── reduce.png │ │ ├── skip.png │ │ ├── takeWhile.png │ │ └── toList.png │ └── style │ │ ├── foundation-potion.css │ │ └── style.css ├── docinfo.html ├── execution-model.adoc ├── getting-started.adoc ├── index.adoc ├── intro.adoc └── operators.adoc ├── examples ├── quickstart-camel │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── reactive │ │ └── operators │ │ └── quickstart │ │ └── QuickStart.java ├── quickstart-vertx │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── reactive │ │ └── operators │ │ └── quickstart │ │ ├── DataGenerator.java │ │ ├── DataProcessor.java │ │ └── QuickStart.java ├── quickstart │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── smallrye │ │ └── reactive │ │ └── operators │ │ └── quickstart │ │ └── QuickStart.java └── snippets │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── io │ │ └── smallrye │ │ └── reactive │ │ └── operators │ │ └── snippets │ │ ├── Comparison.java │ │ └── Operators.java │ └── resources │ ├── META-INF │ └── beans.xml │ └── log4j2.yaml ├── implementation ├── pom.xml └── src │ ├── main │ ├── java │ │ └── io │ │ │ └── smallrye │ │ │ └── reactive │ │ │ └── streams │ │ │ ├── Engine.java │ │ │ ├── operators │ │ │ ├── Operator.java │ │ │ ├── ProcessingStage.java │ │ │ ├── ProcessingStageFactory.java │ │ │ ├── ProcessorOperator.java │ │ │ ├── PublisherOperator.java │ │ │ ├── PublisherStage.java │ │ │ ├── PublisherStageFactory.java │ │ │ ├── TerminalOperator.java │ │ │ ├── TerminalStage.java │ │ │ └── TerminalStageFactory.java │ │ │ ├── spi │ │ │ ├── ExecutionModel.java │ │ │ └── Transformer.java │ │ │ ├── stages │ │ │ ├── CancelStageFactory.java │ │ │ ├── CollectStageFactory.java │ │ │ ├── ConcatStageFactory.java │ │ │ ├── CoupledStageFactory.java │ │ │ ├── DistinctStageFactory.java │ │ │ ├── DropWhileStageFactory.java │ │ │ ├── FailedPublisherStageFactory.java │ │ │ ├── FilterStageFactory.java │ │ │ ├── FindFirstStageFactory.java │ │ │ ├── FlatMapCompletionStageFactory.java │ │ │ ├── FlatMapIterableStageFactory.java │ │ │ ├── FlatMapStageFactory.java │ │ │ ├── FromCompletionStageFactory.java │ │ │ ├── FromCompletionStageNullableFactory.java │ │ │ ├── FromIterableStageFactory.java │ │ │ ├── FromPublisherStageFactory.java │ │ │ ├── LimitStageFactory.java │ │ │ ├── MapStageFactory.java │ │ │ ├── OnCompleteStageFactory.java │ │ │ ├── OnErrorResumeStageFactory.java │ │ │ ├── OnErrorResumeWithStageFactory.java │ │ │ ├── OnErrorStageFactory.java │ │ │ ├── OnTerminateStageFactory.java │ │ │ ├── PeekStageFactory.java │ │ │ ├── ProcessorStageFactory.java │ │ │ ├── SkipStageFactory.java │ │ │ ├── Stages.java │ │ │ ├── SubscriberStageFactory.java │ │ │ └── TakeWhileStageFactory.java │ │ │ └── utils │ │ │ ├── CancellablePublisher.java │ │ │ ├── CancellationSubscriber.java │ │ │ ├── Casts.java │ │ │ ├── CollectorSubscriber.java │ │ │ ├── CompletionStageToPublisher.java │ │ │ ├── ConnectableProcessor.java │ │ │ ├── CouplingProcessor.java │ │ │ ├── DefaultSubscriberWithCompletionStage.java │ │ │ ├── DelegatingSubscriber.java │ │ │ ├── EmptySubscription.java │ │ │ ├── FlowableCollector.java │ │ │ ├── SubscriptionObserver.java │ │ │ ├── WrappedProcessor.java │ │ │ ├── WrappedSubscriber.java │ │ │ ├── WrappedSubscription.java │ │ │ └── recovery │ │ │ ├── OnErrorResumeWith.java │ │ │ ├── OnErrorResumeWithSubscriber.java │ │ │ ├── OnErrorReturn.java │ │ │ └── OnErrorReturnSubscriber.java │ └── resources │ │ └── META-INF │ │ └── services │ │ └── org.eclipse.microprofile.reactive.streams.operators.spi.ReactiveStreamsEngine │ └── test │ └── java │ ├── io │ └── smallrye │ │ └── reactive │ │ └── streams │ │ ├── APITest.java │ │ ├── EngineTest.java │ │ ├── stages │ │ ├── CancelStageFactoryTest.java │ │ ├── CollectStageFactoryTest.java │ │ ├── ConcatStageFactoryTest.java │ │ ├── CoupledStageFactoryTest.java │ │ ├── DistinctStageFactoryTest.java │ │ ├── DropWhileStageFactoryTest.java │ │ ├── FailedPublisherStageFactoryTest.java │ │ ├── FilterStageFactoryTest.java │ │ ├── FindFirstStageFactoryTest.java │ │ ├── FlatMapCompletionStageFactoryTest.java │ │ ├── FlatMapIterableStageFactoryTest.java │ │ ├── FlatMapStageFactoryTest.java │ │ ├── FromCompletionStageFactoryNullableTest.java │ │ ├── FromCompletionStageFactoryTest.java │ │ ├── FromIterableStageFactoryTest.java │ │ ├── FromPublisherStageFactoryTest.java │ │ ├── LimitStageFactoryTest.java │ │ ├── MapStageFactoryTest.java │ │ ├── OnCompleteStageFactoryTest.java │ │ ├── OnErrorResumeWithStageFactoryTest.java │ │ ├── OnErrorStageFactoryTest.java │ │ ├── OnTerminateStageFactoryTest.java │ │ ├── PeekStageFactoryTest.java │ │ ├── ProcessorStageFactoryTest.java │ │ ├── SkipStageFactoryTest.java │ │ ├── StageTestBase.java │ │ ├── SubscriberStageFactoryTest.java │ │ └── TakeWhileStageFactoryTest.java │ │ └── utils │ │ ├── WrappedSubscriberTest.java │ │ └── WrappedSubscriptionTest.java │ └── tck │ └── ReactiveStreamsEngineImplTck.java ├── pom.xml ├── release └── pom.xml ├── tck ├── pom.xml └── src │ └── test │ ├── java │ └── io │ │ └── smallrye │ │ └── reactive │ │ └── streams │ │ └── tck │ │ ├── ApplicationEnhancer.java │ │ ├── InContainerIT.java │ │ └── ProducerInjectionProcessor.java │ └── resources │ ├── META-INF │ └── services │ │ └── org.jboss.arquillian.core.spi.LoadableExtension │ └── log4j2-test.xml └── vertx-execution-model ├── pom.xml └── src ├── main ├── java │ └── io │ │ └── smallrye │ │ └── reactive │ │ └── streams │ │ └── vertx │ │ └── VertxExecutionModel.java └── resources │ └── META-INF │ └── services │ └── io.smallrye.reactive.streams.spi.ExecutionModel └── test └── java └── io └── smallrye └── reactive └── streams └── stages ├── CollectStageFactoryTest.java ├── ConcatStageFactoryTest.java ├── DistinctStageFactoryTest.java ├── DropWhileStageFactoryTest.java ├── FailedPublisherStageFactoryTest.java ├── FilterStageFactoryTest.java ├── FindFirstStageFactoryTest.java ├── FlatMapCompletionStageFactoryTest.java ├── FlatMapIterableStageFactoryTest.java ├── FlatMapStageFactoryTest.java ├── FromCompletionStageFactoryNullableTest.java ├── FromCompletionStageFactoryTest.java ├── FromIterableStageFactoryTest.java ├── FromPublisherStageFactoryTest.java ├── LimitStageFactoryTest.java ├── MapStageFactoryTest.java ├── OnCompleteStageFactoryTest.java ├── OnErrorResumeWithStageFactoryTest.java ├── OnErrorStageFactoryTest.java ├── OnTerminateStageFactoryTest.java ├── PeekStageFactoryTest.java ├── ProcessorStageFactoryTest.java ├── SkipStageFactoryTest.java ├── StageTestBase.java ├── SubscriberStageFactoryTest.java └── TakeWhileStageFactoryTest.java /.build/deploy-doc.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo "Cleaning" 3 | mvn clean -N 4 | 5 | 6 | echo "Building the doc" 7 | 8 | mvn javadoc:aggregate 9 | mvn -N -Pdoc 10 | 11 | echo "Cloning repo" 12 | cd target 13 | git clone -b gh-pages git@github.com:smallrye/smallrye-reactive-streams-operators.git site 14 | echo "Copy content" 15 | cp -R generated-docs/* site 16 | 17 | echo "Pushing" 18 | cd site 19 | git add -A 20 | git commit -m "update site" 21 | git push origin gh-pages 22 | 23 | echo "Done" 24 | -------------------------------------------------------------------------------- /.github/project.yml: -------------------------------------------------------------------------------- 1 | name: SmallRye Reactive Streams Operators 2 | release: 3 | current-version: 1.0.14-SNAPSHOT 4 | next-version: 1.0.15-SNAPSHOT 5 | -------------------------------------------------------------------------------- /.github/release/maven-settings.xml.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/.github/release/maven-settings.xml.gpg -------------------------------------------------------------------------------- /.github/release/smallrye-sign.asc.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/.github/release/smallrye-sign.asc.gpg -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: SmallRye Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths-ignore: 8 | - '.gitignore' 9 | - 'CODEOWNERS' 10 | - 'LICENSE' 11 | - 'NOTICE' 12 | - 'README*' 13 | pull_request: 14 | paths-ignore: 15 | - '.gitignore' 16 | - 'CODEOWNERS' 17 | - 'LICENSE' 18 | - 'NOTICE' 19 | - 'README*' 20 | 21 | jobs: 22 | build: 23 | runs-on: ubuntu-latest 24 | strategy: 25 | matrix: 26 | java: [8, 11] 27 | name: build with jdk ${{matrix.java}} 28 | 29 | steps: 30 | - uses: actions/checkout@v2 31 | name: checkout 32 | 33 | - uses: actions/setup-java@v1.4.3 34 | name: set up jdk ${{matrix.java}} 35 | with: 36 | java-version: ${{matrix.java}} 37 | 38 | - name: build with maven 39 | run: mvn -B verify --file pom.xml 40 | 41 | quality: 42 | needs: [build] 43 | if: github.event_name == 'push' && startsWith('smallrye', github.repository) 44 | runs-on: ubuntu-latest 45 | name: quality 46 | 47 | steps: 48 | - uses: actions/checkout@v2 49 | - uses: actions/setup-java@v1.4.3 50 | with: 51 | java-version: 8 52 | 53 | - name: sonar 54 | env: 55 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 56 | SONAR_TOKEN: ${{secrets.SONAR_TOKEN}} 57 | run: mvn -B verify --file pom.xml -Pcoverage javadoc:javadoc sonar:sonar -Dsonar.projectKey=smallrye_smallrye-reactive-streams-operators -Dsonar.login=$SONAR_TOKEN 58 | -------------------------------------------------------------------------------- /.github/workflows/pre-release.yml: -------------------------------------------------------------------------------- 1 | name: SmallRye Pre Release 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - '.github/project.yml' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | name: pre release 12 | 13 | steps: 14 | - uses: radcortez/project-metadata-action@master 15 | name: retrieve project metadata 16 | id: metadata 17 | with: 18 | github-token: ${{secrets.GITHUB_TOKEN}} 19 | metadata-file-path: '.github/project.yml' 20 | 21 | - name: Validate version 22 | if: contains(steps.metadata.outputs.current-version, 'SNAPSHOT') 23 | run: | 24 | echo '::error::Cannot release a SNAPSHOT version.' 25 | exit 1 26 | 27 | - uses: radcortez/milestone-review-action@master 28 | name: milestone review 29 | with: 30 | github-token: ${{secrets.GITHUB_TOKEN}} 31 | milestone-title: ${{steps.metadata.outputs.current-version}} 32 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: SmallRye Release 2 | 3 | on: 4 | pull_request: 5 | types: [closed] 6 | paths: 7 | - '.github/project.yml' 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | name: release 13 | if: ${{github.event.pull_request.merged == true}} 14 | env: 15 | GITHUB_TOKEN: ${{secrets.RELEASE_TOKEN}} 16 | 17 | steps: 18 | - uses: radcortez/project-metadata-action@master 19 | name: retrieve project metadata 20 | id: metadata 21 | with: 22 | github-token: ${{secrets.GITHUB_TOKEN}} 23 | metadata-file-path: '.github/project.yml' 24 | 25 | - uses: actions/checkout@v2 26 | with: 27 | token: ${{secrets.RELEASE_TOKEN}} 28 | 29 | - uses: actions/setup-java@v1.4.3 30 | with: 31 | java-version: 8 32 | 33 | - name: maven release ${{steps.metadata.outputs.current-version}} 34 | run: | 35 | java -version 36 | gpg --quiet --batch --yes --decrypt --passphrase="${{secrets.SECRET_PASSPHRASE}}" --output smallrye-sign.asc .github/release/smallrye-sign.asc.gpg 37 | gpg --quiet --batch --yes --decrypt --passphrase="${{secrets.SECRET_PASSPHRASE}}" --output maven-settings.xml .github/release/maven-settings.xml.gpg 38 | gpg --fast-import --no-tty --batch --yes smallrye-sign.asc 39 | git config --global user.name "SmallRye CI" 40 | git config --global user.email "smallrye@googlegroups.com" 41 | git checkout -b release 42 | mvn -B release:prepare -Prelease -DreleaseVersion=${{steps.metadata.outputs.current-version}} -DdevelopmentVersion=${{steps.metadata.outputs.next-version}} -s maven-settings.xml 43 | git checkout ${{github.base_ref}} 44 | git rebase release 45 | mvn -B release:perform -Prelease -s maven-settings.xml 46 | git push 47 | git push --tags 48 | 49 | - uses: radcortez/milestone-release-action@master 50 | name: milestone release 51 | with: 52 | github-token: ${{secrets.GITHUB_TOKEN}} 53 | milestone-title: ${{steps.metadata.outputs.current-version}} 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | *.class 5 | 6 | .classpath 7 | .project 8 | .idea 9 | *.iml 10 | 11 | # Log file 12 | *.log 13 | 14 | # BlueJ files 15 | *.ctxt 16 | 17 | # Mobile Tools for Java (J2ME) 18 | .mtj.tmp/ 19 | 20 | # Package Files # 21 | *.jar 22 | *.war 23 | *.nar 24 | *.ear 25 | *.zip 26 | *.tar.gz 27 | *.rar 28 | 29 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 30 | hs_err_pid* 31 | ### JEnv template 32 | # JEnv local Java version configuration file 33 | .java-version 34 | 35 | # Used by previous versions of JEnv 36 | .jenv-version 37 | ### Eclipse template 38 | 39 | .metadata 40 | bin/ 41 | tmp/ 42 | *.tmp 43 | *.bak 44 | *.swp 45 | *~.nib 46 | local.properties 47 | .settings/ 48 | .loadpath 49 | .recommenders 50 | 51 | # External tool builders 52 | .externalToolBuilders/ 53 | 54 | # Locally stored "Eclipse launch configurations" 55 | *.launch 56 | 57 | # PyDev specific (Python IDE for Eclipse) 58 | *.pydevproject 59 | 60 | # CDT-specific (C/C++ Development Tooling) 61 | .cproject 62 | 63 | # CDT- autotools 64 | .autotools 65 | 66 | # Java annotation processor (APT) 67 | .factorypath 68 | 69 | # PDT-specific (PHP Development Tools) 70 | .buildpath 71 | 72 | # sbteclipse plugin 73 | .target 74 | 75 | # Tern plugin 76 | .tern-project 77 | 78 | # TeXlipse plugin 79 | .texlipse 80 | 81 | # STS (Spring Tool Suite) 82 | .springBeans 83 | 84 | # Code Recommenders 85 | .recommenders/ 86 | 87 | # Scala IDE specific (Scala & Java development for Eclipse) 88 | .cache-main 89 | .scala_dependencies 90 | .worksheet 91 | ### Maven template 92 | target/ 93 | pom.xml.tag 94 | pom.xml.releaseBackup 95 | pom.xml.versionsBackup 96 | pom.xml.next 97 | release.properties 98 | dependency-reduced-pom.xml 99 | buildNumber.properties 100 | .mvn/timing.properties 101 | 102 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 103 | !/.mvn/wrapper/maven-wrapper.jar 104 | 105 | ### Vert.x 106 | 107 | .vertx 108 | .tmp 109 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | .github @smallrye/reactive-operators 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, email 4 | (on the SmallRye mailing list), or any other method with the owners of this repository before making a change. 5 | 6 | ## Issues 7 | 8 | * Make sure you provide a reproducer for your issue 9 | * Details about your environment matters - don't forget them. This include where is the application deployed 10 | (bare metal, containers...), Java version... 11 | * Details about your build environment matters (Maven version, Java version) 12 | 13 | 14 | ## Pull Request Process 15 | 16 | * Make sure your pull request includes a nice summary 17 | * Please indicate any breaking change or change that need to be reflected in the documentation 18 | * Make sure the build pass before submitting your PR -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Implementation of the MicroProfile Reactive Streams Operator specification 2 | 3 | ----- 4 | 5 | **IMPORTANT**: This repository is in _maintenance_ mode. 6 | No new features will be implemented. 7 | 8 | Another implementation of MicroProfile Reactive Streams Operators is available in [Mutiny](https://smallrye.io/smallrye-mutiny). 9 | It is recommended to switch to this implementation. 10 | 11 | Reactive Converters have been migrated to https://github.com/smallrye/smallrye-reactive-utils. 12 | 13 | If you have any questions, send a message to https://groups.google.com/forum/#!forum/smallrye. 14 | 15 | ----- 16 | 17 | **Documentation:** https://www.smallrye.io/smallrye-reactive-streams-operators/ 18 | 19 | [![Build Status](https://github.com/smallrye/smallrye-reactive-streams-operators/workflows/SmallRye%20Build/badge.svg?branch=master)]( https://github.com/smallrye/smallrye-reactive-streams-operators/actions?query=workflow%3A%22SmallRye+Build%22) 20 | [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=smallrye_smallrye-reactive-streams-operators&metric=alert_status)](https://sonarcloud.io/dashboard?id=smallrye_smallrye-reactive-streams-operators) 21 | [![License](https://img.shields.io/github/license/smallrye/smallrye-fault-tolerance.svg)](http://www.apache.org/licenses/LICENSE-2.0) 22 | [![Maven](https://img.shields.io/maven-central/v/io.smallrye.reactive/smallrye-reactive-streams-operators?color=green)]() 23 | 24 | ## Getting started 25 | 26 | Check the [Getting Started section](https://www.smallrye.io/smallrye-reactive-streams-operators/#_getting_started) 27 | from the documentation. 28 | 29 | You can also look at the: 30 | 31 | * [Quickstart project](examples/quickstart) 32 | * [Quickstart project with Vert.x](examples/quickstart-vertx) 33 | * [Quickstart project with Camel](examples/quickstart-camel) 34 | 35 | 36 | ## Built With 37 | 38 | * RX Java 2 39 | * Eclipse Vert.x (optional) 40 | 41 | 42 | ## How to build 43 | 44 | ```bash 45 | mvn clean install 46 | ``` 47 | 48 | To collect the code coverage: 49 | 50 | ```bash 51 | mvn clean verify -Pcoverage 52 | # to generate the report 53 | cd implementation 54 | mvn jacoco:report -Djacoco.dataFile=target/jacoco.exec -Pcoverage 55 | ``` 56 | 57 | The code coverage combines unit tests and TCK. The report is generated in the `target/site/jacoco/index.html` 58 | 59 | ## How to contribute 60 | 61 | Just open a pull request. Makes sure to run the tests and the TCK before opening the PR. Don't forget that documentation 62 | and tests are as important as the code (if not more). 63 | 64 | Please read [the contribution guidelines](CONTRIBUTING.md) for details, and the process for submitting pull requests. 65 | 66 | ## Sponsors 67 | 68 | The project is sponsored by Red Hat. 69 | 70 | ## License 71 | 72 | This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details. 73 | 74 | -------------------------------------------------------------------------------- /cdi/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.reactive 7 | smallrye-reactive-streams-operators-project 8 | 1.0.14-SNAPSHOT 9 | 10 | 11 | smallrye-reactive-streams-operators-cdi 12 | 13 | 14 | 15 | ${project.groupId} 16 | smallrye-reactive-streams-operators 17 | ${project.version} 18 | 19 | 20 | jakarta.enterprise 21 | jakarta.enterprise.cdi-api 22 | provided 23 | 24 | 25 | org.jboss.weld.se 26 | weld-se-core 27 | ${version.weld.core} 28 | test 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-surefire-plugin 38 | 39 | 40 | default-test 41 | 42 | test 43 | 44 | 45 | none:none 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | coverage 56 | 57 | @{jacocoArgLine} 58 | 59 | 60 | 61 | 62 | 63 | org.jacoco 64 | jacoco-maven-plugin 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /cdi/src/main/java/io/smallrye/reactive/streams/cdi/ReactiveEngineProvider.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.cdi; 2 | 3 | import java.util.Iterator; 4 | import java.util.ServiceLoader; 5 | 6 | import javax.enterprise.context.ApplicationScoped; 7 | import javax.enterprise.inject.Produces; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.spi.ReactiveStreamsEngine; 10 | 11 | public class ReactiveEngineProvider { 12 | 13 | /** 14 | * @return the reactive stream engine. It uses {@link ServiceLoader#load(Class)} to find an implementation from the 15 | * Classpath. 16 | * @throws IllegalStateException if no implementations are found. 17 | */ 18 | @Produces 19 | @ApplicationScoped 20 | public ReactiveStreamsEngine getEngine() { 21 | Iterator iterator = ServiceLoader.load(ReactiveStreamsEngine.class).iterator(); 22 | if (iterator.hasNext()) { 23 | return iterator.next(); 24 | } 25 | throw new IllegalStateException("No implementation of the " 26 | + ReactiveStreamsEngine.class.getName() + " found in the Classpath"); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /cdi/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /cdi/src/test/java/io/smallrye/reactive/streams/cdi/MyBean.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.cdi; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | import java.util.stream.Collectors; 5 | 6 | import javax.enterprise.context.ApplicationScoped; 7 | import javax.inject.Inject; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.eclipse.microprofile.reactive.streams.operators.spi.ReactiveStreamsEngine; 11 | 12 | @ApplicationScoped 13 | public class MyBean { 14 | 15 | @Inject 16 | private ReactiveStreamsEngine engine; 17 | 18 | public Integer sum() throws ExecutionException, InterruptedException { 19 | return ReactiveStreams.of(1, 2, 3).collect(Collectors.summingInt(i -> i)).run(engine).toCompletableFuture().get(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /cdi/src/test/java/io/smallrye/reactive/streams/cdi/ReactiveEngineProviderTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.cdi; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.concurrent.ExecutionException; 6 | 7 | import org.jboss.weld.environment.se.Weld; 8 | import org.jboss.weld.environment.se.WeldContainer; 9 | import org.junit.After; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | 13 | /** 14 | * Check that beans can access the engine. 15 | */ 16 | public class ReactiveEngineProviderTest { 17 | 18 | private Weld weld; 19 | private WeldContainer container; 20 | 21 | @Before 22 | public void setUp() { 23 | weld = new Weld(); 24 | weld.addBeanClasses(MyBean.class); 25 | } 26 | 27 | @Test 28 | public void testThatABeanCanAccessTheEngine() throws ExecutionException, InterruptedException { 29 | container = weld.initialize(); 30 | MyBean myBean = container.getBeanManager().createInstance().select(MyBean.class).get(); 31 | int result = myBean.sum(); 32 | assertThat(result).isEqualTo(1 + 2 + 3); 33 | } 34 | 35 | @After 36 | public void tearDown() { 37 | if (container != null) { 38 | container.close(); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /cdi/src/test/resources/log4j2-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /doc/assets/images/collect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/collect.png -------------------------------------------------------------------------------- /doc/assets/images/concat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/concat.png -------------------------------------------------------------------------------- /doc/assets/images/converters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/converters.png -------------------------------------------------------------------------------- /doc/assets/images/distinct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/distinct.png -------------------------------------------------------------------------------- /doc/assets/images/dropWhile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/dropWhile.png -------------------------------------------------------------------------------- /doc/assets/images/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/empty.png -------------------------------------------------------------------------------- /doc/assets/images/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/example.png -------------------------------------------------------------------------------- /doc/assets/images/failed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/failed.png -------------------------------------------------------------------------------- /doc/assets/images/filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/filter.png -------------------------------------------------------------------------------- /doc/assets/images/findFirst.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/findFirst.png -------------------------------------------------------------------------------- /doc/assets/images/flatMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/flatMap.png -------------------------------------------------------------------------------- /doc/assets/images/flatMapCompletionStage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/flatMapCompletionStage.png -------------------------------------------------------------------------------- /doc/assets/images/flatMapIterable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/flatMapIterable.png -------------------------------------------------------------------------------- /doc/assets/images/flatMapRsPublisher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/flatMapRsPublisher.png -------------------------------------------------------------------------------- /doc/assets/images/forEach.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/forEach.png -------------------------------------------------------------------------------- /doc/assets/images/fromCompletionStage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/fromCompletionStage.png -------------------------------------------------------------------------------- /doc/assets/images/fromCompletionStageNullable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/fromCompletionStageNullable.png -------------------------------------------------------------------------------- /doc/assets/images/fromIterable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/fromIterable.png -------------------------------------------------------------------------------- /doc/assets/images/generate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/generate.png -------------------------------------------------------------------------------- /doc/assets/images/identity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/identity.png -------------------------------------------------------------------------------- /doc/assets/images/ignore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/ignore.png -------------------------------------------------------------------------------- /doc/assets/images/iterate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/iterate.png -------------------------------------------------------------------------------- /doc/assets/images/limit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/limit.png -------------------------------------------------------------------------------- /doc/assets/images/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/map.png -------------------------------------------------------------------------------- /doc/assets/images/of-many.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/of-many.png -------------------------------------------------------------------------------- /doc/assets/images/of-single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/of-single.png -------------------------------------------------------------------------------- /doc/assets/images/ofNullable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/ofNullable.png -------------------------------------------------------------------------------- /doc/assets/images/onComplete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/onComplete.png -------------------------------------------------------------------------------- /doc/assets/images/onError.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/onError.png -------------------------------------------------------------------------------- /doc/assets/images/onErrorResume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/onErrorResume.png -------------------------------------------------------------------------------- /doc/assets/images/onErrorResumeWith.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/onErrorResumeWith.png -------------------------------------------------------------------------------- /doc/assets/images/onErrorResumeWithRsPublisher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/onErrorResumeWithRsPublisher.png -------------------------------------------------------------------------------- /doc/assets/images/onTerminate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/onTerminate.png -------------------------------------------------------------------------------- /doc/assets/images/peek.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/peek.png -------------------------------------------------------------------------------- /doc/assets/images/reduce-identity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/reduce-identity.png -------------------------------------------------------------------------------- /doc/assets/images/reduce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/reduce.png -------------------------------------------------------------------------------- /doc/assets/images/skip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/skip.png -------------------------------------------------------------------------------- /doc/assets/images/takeWhile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/takeWhile.png -------------------------------------------------------------------------------- /doc/assets/images/toList.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smallrye/smallrye-reactive-streams-operators/5358b84d4728ee280e3df4965e063e0eb62f9e16/doc/assets/images/toList.png -------------------------------------------------------------------------------- /doc/assets/style/style.css: -------------------------------------------------------------------------------- 1 | h5 { 2 | color: #b1005d; 3 | font-size: 1.3em; 4 | } -------------------------------------------------------------------------------- /doc/docinfo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /doc/execution-model.adoc: -------------------------------------------------------------------------------- 1 | == Execution Model 2 | 3 | SmallRye Reactive Stream Operators provides a way to control on which thread are the different callbacks invoked. By 4 | default it uses the caller thread. 5 | 6 | If you are building a Vert.x application, add the following dependency to your project so enforce the Vert.x execution 7 | model: 8 | 9 | [source,xml,subs=attributes+] 10 | ---- 11 | 12 | io.smallrye 13 | smallrye-reactive-streams-vertx-execution-model 14 | {version} 15 | 16 | ---- 17 | 18 | With this dependency, if you are calling `ReactiveStreams.x` from a Vert.x thread, the same thread is used to call the 19 | different callbacks and pass the result. 20 | 21 | 22 | -------------------------------------------------------------------------------- /doc/index.adoc: -------------------------------------------------------------------------------- 1 | = SmallRye Reactive Streams Operators 2 | Clement Escoffier; 3 | :revnumber: {version} 4 | :revdate: {localdate} 5 | :toc: macro 6 | :toclevels: 4 7 | :toc-title: SmallRye Reactive Streams Operators 8 | :doctype: book 9 | :icons: font 10 | :docinfo1: 11 | 12 | ifndef::ebook-format[:leveloffset: 1] 13 | 14 | ifdef::basebackend-html[toc::[]] 15 | 16 | :numbered: 17 | :sectnums: 18 | :sectnumlevels: 4 19 | 20 | ---- 21 | 22 | *IMPORTANT*: This project is in _maintenance_ mode. 23 | No new features will be implemented. 24 | 25 | Another implementation of MicroProfile Reactive Streams Operators is available in https://smallrye.io/smallrye-mutiny[Mutiny]. 26 | It is recommended to switch to this implementation. 27 | 28 | Reactive Converters have been migrated to https://github.com/smallrye/smallrye-reactive-utils. 29 | 30 | If you have any questions, send a message to the https://groups.google.com/forum/#!forum/smallrye[smallrye group]. 31 | 32 | ---- 33 | 34 | include::./intro.adoc[] 35 | include::./getting-started.adoc[] 36 | include::./operators.adoc[] 37 | include::./execution-model.adoc[] 38 | -------------------------------------------------------------------------------- /doc/intro.adoc: -------------------------------------------------------------------------------- 1 | 2 | SmallRye Reactive Stream Operators is an implementation of the Eclipse MicroProfile Reactive Stream Operators 3 | specification (version **{spec-version}**). 4 | 5 | The link:microprofile-reactive-streams-operators-spec.html[MicroProfile Reactive Stream Operators specification] 6 | define a set of operators for Reactive Streams. You can: 7 | 8 | * Create Reactive Streams 9 | * Process the data transiting in the streams 10 | * Accumulate results 11 | 12 | The idea behind the specification is to provide the equivalent of `java.util.stream` however, for Reactive Stream, so, 13 | inherently asynchronous, supporting back-pressure and with error and completion signals propagation. The following code 14 | snippet shows how close the API is: 15 | 16 | [source, java, indent=0] 17 | ---- 18 | include::../examples/snippets/src/main/java/io/smallrye/reactive/operators/snippets/Comparison.java[tag=snippet] 19 | ---- 20 | 21 | The SmallRye implementation is based on https://github.com/ReactiveX/RxJava[RX Java 2]. 22 | 23 | * The Javadoc of the specification is available link:spec-api/index.html[here]. 24 | * The Javadoc of SmallRye Reactive Streams Operators is available link:apidocs/index.html[here]. 25 | 26 | The code is released under the Apache Software License 2.0 and is available on 27 | https://github.com/smallrye/smallrye-reactive-streams-operators[Github]. 28 | 29 | -------------------------------------------------------------------------------- /examples/quickstart-camel/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.reactive 7 | smallrye-reactive-streams-operators-quickstart-camel 8 | 1.0.14-SNAPSHOT 9 | 10 | 11 | 1.8 12 | 1.8 13 | 14 | 3.8.0 15 | 16 | true 17 | 18 | 19 | 20 | 21 | io.smallrye.reactive 22 | smallrye-reactive-streams-operators 23 | 1.0.14-SNAPSHOT 24 | 25 | 26 | org.apache.camel 27 | camel-reactive-streams 28 | ${camel.version} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.apache.maven.plugins 37 | maven-deploy-plugin 38 | 2.8.2 39 | 40 | true 41 | 42 | 43 | 44 | org.apache.maven.plugins 45 | maven-install-plugin 46 | 47 | true 48 | 49 | 50 | 51 | org.sonatype.plugins 52 | nexus-staging-maven-plugin 53 | 54 | true 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /examples/quickstart-camel/src/main/java/io/smallrye/reactive/operators/quickstart/QuickStart.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.operators.quickstart; 2 | 3 | import org.apache.camel.CamelContext; 4 | import org.apache.camel.component.reactive.streams.api.CamelReactiveStreams; 5 | import org.apache.camel.component.reactive.streams.api.CamelReactiveStreamsService; 6 | import org.apache.camel.impl.DefaultCamelContext; 7 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 8 | import org.reactivestreams.Subscriber; 9 | 10 | import java.io.File; 11 | import java.nio.file.Files; 12 | 13 | public class QuickStart { 14 | 15 | public static void main(String[] args) throws Exception { 16 | CamelContext context = new DefaultCamelContext(); 17 | CamelReactiveStreamsService camel = CamelReactiveStreams.get(context); 18 | Subscriber subscriber = camel 19 | .subscriber("file:./target?fileName=values.txt&fileExist=append", String.class); 20 | 21 | ReactiveStreams.of("hello", "from", "smallrye", "reactive", "stream", "operators", 22 | "using", "Apache", "Camel") 23 | .map(String::toUpperCase) // Transform the words 24 | .filter(s -> s.length() > 4) // Filter items 25 | .peek(System.out::println) 26 | .map(s -> s + " ") 27 | .to(subscriber) 28 | .run(); 29 | context.start(); 30 | 31 | // Just wait until it's done. 32 | Thread.sleep(1000); 33 | 34 | Files.readAllLines(new File("target/values.txt").toPath()) 35 | .forEach(s -> System.out.println("File >> " + s)); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /examples/quickstart-vertx/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.reactive 7 | smallrye-reactive-streams-operators-quickstart-vertx 8 | 1.0.14-SNAPSHOT 9 | 10 | 11 | 1.8 12 | 1.8 13 | 3.9.4 14 | 15 | true 16 | 17 | 18 | 19 | 20 | io.smallrye.reactive 21 | smallrye-reactive-streams-operators 22 | 1.0.14-SNAPSHOT 23 | 24 | 25 | io.vertx 26 | vertx-core 27 | ${vertx.version} 28 | 29 | 30 | io.vertx 31 | vertx-rx-java2 32 | ${vertx.version} 33 | 34 | 35 | io.smallrye.reactive 36 | smallrye-reactive-streams-vertx-execution-model 37 | 1.0.14-SNAPSHOT 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-deploy-plugin 47 | 2.8.2 48 | 49 | true 50 | 51 | 52 | 53 | org.apache.maven.plugins 54 | maven-install-plugin 55 | 56 | true 57 | 58 | 59 | 60 | org.sonatype.plugins 61 | nexus-staging-maven-plugin 62 | 63 | true 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /examples/quickstart-vertx/src/main/java/io/smallrye/reactive/operators/quickstart/DataGenerator.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.operators.quickstart; 2 | 3 | import io.vertx.core.json.JsonObject; 4 | import io.vertx.reactivex.core.AbstractVerticle; 5 | 6 | import java.security.SecureRandom; 7 | import java.util.Random; 8 | 9 | public class DataGenerator extends AbstractVerticle { 10 | 11 | private static final int DELAY = 100; 12 | private static final int BOUND = 25; 13 | private Random random = new SecureRandom(); 14 | 15 | @Override 16 | public void start() { 17 | vertx.setPeriodic(DELAY, x -> 18 | vertx.eventBus().send("data", new JsonObject().put("value", random.nextInt(BOUND)))); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /examples/quickstart-vertx/src/main/java/io/smallrye/reactive/operators/quickstart/DataProcessor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.operators.quickstart; 2 | 3 | import io.vertx.core.Future; 4 | import io.vertx.core.json.JsonObject; 5 | import io.vertx.reactivex.core.AbstractVerticle; 6 | import io.vertx.reactivex.core.eventbus.Message; 7 | import io.vertx.reactivex.core.eventbus.MessageConsumer; 8 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 9 | 10 | public class DataProcessor extends AbstractVerticle { 11 | 12 | private static final int PORT = 8080; 13 | 14 | @Override 15 | public void start(Future done) { 16 | vertx.createHttpServer() 17 | .requestHandler(request -> { 18 | // Consume messages from the Vert.x event bus 19 | MessageConsumer consumer = vertx.eventBus().consumer("data"); 20 | // Wrap the stream and manipulate the data 21 | ReactiveStreams.fromPublisher(consumer.toFlowable()) 22 | .limit(5) // Take only 5 messages 23 | .map(Message::body) // Extract the body 24 | .map(json -> json.getInteger("value")) // Extract the value 25 | .peek(i -> System.out.println("Got value: " + i)) // Print it 26 | .reduce(0, (acc, value) -> acc + value) 27 | .run() // Begin to receive items 28 | .whenComplete((res, err) -> { 29 | // When the 5 items has been consumed, write the result to the 30 | // HTTP response: 31 | if (err != null) { 32 | request.response().setStatusCode(500).end(err.getMessage()); 33 | } else { 34 | request.response().end("Result is: " + res); 35 | } 36 | }); 37 | }) 38 | .listen(PORT, ar -> done.handle(ar.mapEmpty())); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/quickstart-vertx/src/main/java/io/smallrye/reactive/operators/quickstart/QuickStart.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.operators.quickstart; 2 | 3 | import io.vertx.reactivex.core.Vertx; 4 | 5 | public class QuickStart { 6 | 7 | public static void main(String[] args) { 8 | Vertx vertx = Vertx.vertx(); 9 | vertx.deployVerticle(DataGenerator.class.getName()); 10 | vertx.deployVerticle(DataProcessor.class.getName()); 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /examples/quickstart/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.reactive 7 | smallrye-reactive-streams-operators-quickstart 8 | 1.0.14-SNAPSHOT 9 | 10 | 11 | 1.8 12 | 1.8 13 | 14 | true 15 | 16 | 17 | 18 | 19 | io.smallrye.reactive 20 | smallrye-reactive-streams-operators 21 | 1.0.14-SNAPSHOT 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | org.apache.maven.plugins 30 | maven-deploy-plugin 31 | 2.8.2 32 | 33 | true 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-install-plugin 39 | 40 | true 41 | 42 | 43 | 44 | org.sonatype.plugins 45 | nexus-staging-maven-plugin 46 | 47 | true 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /examples/quickstart/src/main/java/io/smallrye/reactive/operators/quickstart/QuickStart.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.operators.quickstart; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 4 | 5 | public class QuickStart { 6 | 7 | public static void main(String[] args) { 8 | // Create a stream of words 9 | ReactiveStreams.of("hello", "from", "smallrye", "reactive", "stream", "operators") 10 | .map(String::toUpperCase) // Transform the words 11 | .filter(s -> s.length() > 4) // Filter items 12 | .forEach(word -> System.out.println(">> " + word)) // Terminal operation 13 | .run(); // Run it (create the streams, subscribe to it...) 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /examples/snippets/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.reactive 7 | smallrye-reactive-streams-operators-snippets 8 | 1.0.14-SNAPSHOT 9 | 10 | 11 | 12 | 1.8 13 | 1.8 14 | 15 | true 16 | 17 | 18 | 19 | 20 | 21 | io.smallrye.reactive 22 | smallrye-reactive-streams-operators 23 | 1.0.14-SNAPSHOT 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | org.apache.maven.plugins 32 | maven-deploy-plugin 33 | 2.8.2 34 | 35 | true 36 | 37 | 38 | 39 | org.apache.maven.plugins 40 | maven-install-plugin 41 | 42 | true 43 | 44 | 45 | 46 | org.sonatype.plugins 47 | nexus-staging-maven-plugin 48 | 49 | true 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /examples/snippets/src/main/java/io/smallrye/reactive/operators/snippets/Comparison.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.operators.snippets; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 4 | 5 | import java.util.stream.Stream; 6 | 7 | public class Comparison { 8 | 9 | public static void main(String[] args) { 10 | comparison(); 11 | } 12 | 13 | private static void comparison() { 14 | // tag::snippet[] 15 | // java.util.stream version: 16 | Stream.of("hello", "world") 17 | .filter(word -> word.length() <= 5) 18 | .map(String::toUpperCase) 19 | .findFirst() 20 | .ifPresent(s -> System.out.println("Regular Java stream result: " + s)); 21 | // reactive stream operator version: 22 | ReactiveStreams.of("hello", "world") 23 | .filter(word -> word.length() <= 5) 24 | .map(String::toUpperCase) 25 | .findFirst() 26 | .run() // Run the stream (start publishing) 27 | // Retrieve the result asynchronously, using a CompletionStage 28 | .thenAccept(res -> res 29 | .ifPresent(s -> System.out.println("Reactive Stream result: " + s))); 30 | // end::snippet[] 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /examples/snippets/src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/snippets/src/main/resources/log4j2.yaml: -------------------------------------------------------------------------------- 1 | Configuration: 2 | status: info 3 | 4 | Appenders: 5 | Console: 6 | name: Console 7 | target: SYSTEM_OUT 8 | PatternLayout: 9 | Pattern: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" 10 | 11 | Loggers: 12 | Root: 13 | level: warn 14 | AppenderRef: 15 | ref: Console 16 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/Operator.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Predicate; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | public class Operator implements Predicate { 9 | private Class clazz; 10 | 11 | Operator(Class clazz) { 12 | this.clazz = Objects.requireNonNull(clazz); 13 | } 14 | 15 | public boolean test(Stage s) { 16 | return clazz.isAssignableFrom(s.getClass()); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/ProcessingStage.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import java.util.function.Function; 4 | 5 | import io.reactivex.Flowable; 6 | 7 | /** 8 | * Defines a processing stage - so a stream transformation. 9 | * 10 | * @param type of the received items 11 | * @param type of the emitted items 12 | * 13 | * @author Clement Escoffier 14 | */ 15 | @FunctionalInterface 16 | public interface ProcessingStage extends Function, Flowable> { 17 | 18 | /** 19 | * Adapts the streams. 20 | * 21 | * @param source the input stream, must not be {@code null} 22 | * @return the adapted stream, must not be {@code null} 23 | */ 24 | Flowable apply(Flowable source); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/ProcessingStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 4 | 5 | import io.smallrye.reactive.streams.Engine; 6 | 7 | /** 8 | * Factory to create {@link ProcessingStage} instances. 9 | * 10 | * @author Clement Escoffier 11 | */ 12 | @FunctionalInterface 13 | public interface ProcessingStageFactory { 14 | 15 | /** 16 | * Creates the instance. 17 | * 18 | * @param engine the reactive engine 19 | * @param stage the stage 20 | * @param input data 21 | * @param output data 22 | * @return the created processing stage, should never be {@code null} 23 | */ 24 | ProcessingStage create(Engine engine, T stage); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/ProcessorOperator.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 4 | 5 | import io.smallrye.reactive.streams.Engine; 6 | 7 | public class ProcessorOperator extends Operator { 8 | 9 | private ProcessingStageFactory factory; 10 | 11 | public ProcessorOperator(Class clazz, ProcessingStageFactory factory) { 12 | super(clazz); 13 | this.factory = factory; 14 | } 15 | 16 | public ProcessingStage create(Engine engine, T stage) { 17 | return factory.create(engine, stage); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/PublisherOperator.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 4 | 5 | import io.smallrye.reactive.streams.Engine; 6 | 7 | public class PublisherOperator extends Operator { 8 | 9 | private PublisherStageFactory factory; 10 | 11 | public PublisherOperator(Class clazz, PublisherStageFactory factory) { 12 | super(clazz); 13 | this.factory = factory; 14 | } 15 | 16 | public PublisherStage create(Engine engine, T stage) { 17 | return factory.create(engine, stage); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/PublisherStage.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import io.reactivex.Flowable; 6 | 7 | /** 8 | * Specialization of the {@link ProcessingStage} for data sources (publishers). 9 | * 10 | * @author Clement Escoffier 11 | */ 12 | public interface PublisherStage extends Supplier> { 13 | 14 | /** 15 | * @return the publisher. 16 | */ 17 | Flowable get(); 18 | } 19 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/PublisherStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 4 | 5 | import io.smallrye.reactive.streams.Engine; 6 | 7 | /** 8 | * Factory to create {@link PublisherStage} instances. 9 | * 10 | * @author Clement Escoffier 11 | */ 12 | @FunctionalInterface 13 | public interface PublisherStageFactory { 14 | 15 | /** 16 | * Creates the instance. 17 | * 18 | * @param engine the reactive engine 19 | * @param stage the stage 20 | * @param output data 21 | * @return the created processing stage, should never be {@code null} 22 | */ 23 | PublisherStage create(Engine engine, T stage); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/TerminalOperator.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 4 | 5 | import io.smallrye.reactive.streams.Engine; 6 | 7 | public class TerminalOperator extends Operator { 8 | 9 | private TerminalStageFactory factory; 10 | 11 | public TerminalOperator(Class clazz, TerminalStageFactory factory) { 12 | super(clazz); 13 | this.factory = factory; 14 | } 15 | 16 | public TerminalStage create(Engine engine, T stage) { 17 | return factory.create(engine, stage); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/TerminalStage.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import java.util.concurrent.CompletionStage; 4 | import java.util.function.Function; 5 | 6 | import io.reactivex.Flowable; 7 | 8 | /** 9 | * Defines a terminal stage - so a stream subscription and observation. 10 | * 11 | * @author Clement Escoffier 12 | */ 13 | @FunctionalInterface 14 | public interface TerminalStage extends Function, CompletionStage> { 15 | 16 | /** 17 | * Creates the {@link CompletionStage} called when the embedded logic has completed or failed. 18 | * 19 | * @param flowable the observed / subscribed stream 20 | * @return the asynchronous result 21 | */ 22 | CompletionStage apply(Flowable flowable); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/operators/TerminalStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.operators; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 4 | 5 | import io.smallrye.reactive.streams.Engine; 6 | 7 | /** 8 | * Factory to create {@link TerminalStage} instances. 9 | * 10 | * @author Clement Escoffier 11 | */ 12 | @FunctionalInterface 13 | public interface TerminalStageFactory { 14 | 15 | /** 16 | * Creates the instance. 17 | * 18 | * @param engine the reactive engine, must not be {@code null} 19 | * @param stage the stage, must not be {@code null} 20 | * @param incoming data 21 | * @param computed result 22 | * @return the terminal stage, must not be {@code null} 23 | */ 24 | TerminalStage create(Engine engine, T stage); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/spi/ExecutionModel.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.spi; 2 | 3 | import java.util.function.UnaryOperator; 4 | 5 | import io.reactivex.Flowable; 6 | 7 | @FunctionalInterface 8 | public interface ExecutionModel extends UnaryOperator { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/spi/Transformer.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.spi; 2 | 3 | import java.util.Iterator; 4 | import java.util.ServiceLoader; 5 | 6 | import io.reactivex.Flowable; 7 | 8 | public class Transformer { 9 | 10 | private final ExecutionModel model; 11 | 12 | private static final Transformer INSTANCE; 13 | 14 | static { 15 | INSTANCE = new Transformer(); 16 | } 17 | 18 | private Transformer() { 19 | ServiceLoader loader = ServiceLoader.load(ExecutionModel.class); 20 | Iterator iterator = loader.iterator(); 21 | if (iterator.hasNext()) { 22 | model = iterator.next(); 23 | } else { 24 | model = i -> i; 25 | } 26 | } 27 | 28 | /** 29 | * Calls the model. 30 | * 31 | * @param flowable the flowable 32 | * @param the type of data 33 | * @return the decorated flowable if needed 34 | */ 35 | @SuppressWarnings("unchecked") 36 | public static Flowable apply(Flowable flowable) { 37 | return INSTANCE.model.apply(flowable); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/CancelStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.concurrent.CompletableFuture; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | import org.reactivestreams.Subscriber; 8 | import org.reactivestreams.Subscription; 9 | 10 | import io.reactivex.Flowable; 11 | import io.smallrye.reactive.streams.Engine; 12 | import io.smallrye.reactive.streams.operators.TerminalStage; 13 | import io.smallrye.reactive.streams.operators.TerminalStageFactory; 14 | 15 | /** 16 | * Implementation of {@link Stage.Cancel}. It subscribes and disposes the stream immediately. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class CancelStageFactory implements TerminalStageFactory { 21 | 22 | @Override 23 | public TerminalStage create(Engine engine, Stage.Cancel stage) { 24 | Objects.requireNonNull(stage); 25 | return (Flowable flow) -> { 26 | flow.subscribe(new Subscriber() { 27 | 28 | @Override 29 | public void onSubscribe(Subscription s) { 30 | s.cancel(); 31 | } 32 | 33 | @Override 34 | public void onNext(I in) { 35 | // Do nothing. 36 | } 37 | 38 | @Override 39 | public void onError(Throwable t) { 40 | // Do nothing. 41 | } 42 | 43 | @Override 44 | public void onComplete() { 45 | // Do nothing. 46 | } 47 | }); 48 | return CompletableFuture.completedFuture(null); 49 | }; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/CollectStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.concurrent.CompletableFuture; 5 | import java.util.concurrent.CompletionStage; 6 | import java.util.stream.Collector; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 9 | 10 | import io.reactivex.Flowable; 11 | import io.reactivex.plugins.RxJavaPlugins; 12 | import io.smallrye.reactive.streams.Engine; 13 | import io.smallrye.reactive.streams.operators.TerminalStage; 14 | import io.smallrye.reactive.streams.operators.TerminalStageFactory; 15 | import io.smallrye.reactive.streams.utils.FlowableCollector; 16 | 17 | /** 18 | * Implement the {@link Stage.Collect} stage. It accumulates the result in a {@link Collector} and 19 | * redeems the last result. 20 | * 21 | * @author Clement Escoffier 22 | */ 23 | public class CollectStageFactory implements TerminalStageFactory { 24 | 25 | @SuppressWarnings("unchecked") 26 | @Override 27 | public TerminalStage create(Engine engine, Stage.Collect stage) { 28 | Collector collector = (Collector) Objects.requireNonNull(stage).getCollector(); 29 | Objects.requireNonNull(collector); 30 | return new CollectStage<>(collector); 31 | } 32 | 33 | private static class CollectStage implements TerminalStage { 34 | 35 | private final Collector collector; 36 | 37 | CollectStage(Collector collector) { 38 | this.collector = collector; 39 | } 40 | 41 | @Override 42 | public CompletionStage apply(Flowable source) { 43 | CompletableFuture future = new CompletableFuture<>(); 44 | Flowable flow = source.compose(f -> RxJavaPlugins.onAssembly(new FlowableCollector<>(f, collector))); 45 | //noinspection ResultOfMethodCallIgnored 46 | flow 47 | .firstElement() 48 | .subscribe( 49 | future::complete, 50 | future::completeExceptionally); 51 | return future; 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/ConcatStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.spi.Graph; 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | import io.reactivex.Flowable; 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.PublisherStage; 11 | import io.smallrye.reactive.streams.operators.PublisherStageFactory; 12 | import io.smallrye.reactive.streams.utils.CancellablePublisher; 13 | 14 | /** 15 | * Implementation of the {@link Stage.Concat} stage. Because both streams can emits on different thread, 16 | * this operators takes care to called the user on a Vert.x context if the caller used one, otherwise it 17 | * uses the current thread. 18 | * 19 | * @author Clement Escoffier 20 | */ 21 | public class ConcatStageFactory implements PublisherStageFactory { 22 | 23 | @Override 24 | public PublisherStage create(Engine engine, Stage.Concat stage) { 25 | Objects.requireNonNull(engine); 26 | Objects.requireNonNull(stage); 27 | Graph g1 = stage.getFirst(); 28 | Graph g2 = stage.getSecond(); 29 | return new ConcatStage<>(engine, g1, g2); 30 | } 31 | 32 | private class ConcatStage implements PublisherStage { 33 | private final Engine engine; 34 | private final Graph first; 35 | private final Graph second; 36 | 37 | ConcatStage(Engine engine, Graph g1, Graph g2) { 38 | this.engine = Objects.requireNonNull(engine); 39 | this.first = Objects.requireNonNull(g1); 40 | this.second = Objects.requireNonNull(g2); 41 | } 42 | 43 | @Override 44 | public Flowable get() { 45 | CancellablePublisher cancellable = new CancellablePublisher<>(engine.buildPublisher(second)); 46 | return Flowable.concat(engine.buildPublisher(first), cancellable) 47 | .doOnCancel(cancellable::cancelIfNotSubscribed) 48 | .doOnTerminate(cancellable::cancelIfNotSubscribed); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/CoupledStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.spi.Graph; 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | import org.eclipse.microprofile.reactive.streams.operators.spi.SubscriberWithCompletionStage; 8 | import org.reactivestreams.Publisher; 9 | 10 | import io.reactivex.Flowable; 11 | import io.smallrye.reactive.streams.Engine; 12 | import io.smallrye.reactive.streams.operators.ProcessingStage; 13 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 14 | import io.smallrye.reactive.streams.utils.CouplingProcessor; 15 | 16 | /** 17 | * Implementation of the {@link Stage.Coupled} stage. 18 | * 19 | * @author Clement Escoffier 20 | */ 21 | public class CoupledStageFactory implements ProcessingStageFactory { 22 | @Override 23 | public ProcessingStage create(Engine engine, Stage.Coupled stage) { 24 | Graph source = Objects.requireNonNull(stage.getPublisher()); 25 | Graph sink = Objects.requireNonNull(stage.getSubscriber()); 26 | 27 | Publisher publisher = engine.buildPublisher(source); 28 | SubscriberWithCompletionStage subscriber = engine.buildSubscriber(sink); 29 | 30 | return upstream -> Flowable.fromPublisher( 31 | new CouplingProcessor<>(upstream, subscriber.getSubscriber(), publisher)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/DistinctStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 6 | 7 | import io.reactivex.Flowable; 8 | import io.smallrye.reactive.streams.Engine; 9 | import io.smallrye.reactive.streams.operators.ProcessingStage; 10 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 11 | 12 | /** 13 | * Implementation of the {@link Stage.Distinct} stage. 14 | * 15 | * @author Clement Escoffier 16 | */ 17 | public class DistinctStageFactory implements ProcessingStageFactory { 18 | 19 | @SuppressWarnings("unchecked") 20 | @Override 21 | public ProcessingStage create(Engine engine, Stage.Distinct stage) { 22 | Objects.requireNonNull(stage); 23 | return source -> (Flowable) source.distinct(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/DropWhileStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Predicate; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | import io.reactivex.Flowable; 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.ProcessingStage; 11 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 12 | import io.smallrye.reactive.streams.utils.Casts; 13 | 14 | /** 15 | * Implementation of the {@link Stage.DropWhile} stage. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class DropWhileStageFactory implements ProcessingStageFactory { 20 | 21 | @Override 22 | public ProcessingStage create(Engine engine, Stage.DropWhile stage) { 23 | Predicate predicate = Casts.cast(stage.getPredicate()); 24 | return Casts.cast(new TakeWhile<>(predicate)); 25 | } 26 | 27 | private static class TakeWhile implements ProcessingStage { 28 | private final Predicate predicate; 29 | 30 | TakeWhile(Predicate predicate) { 31 | this.predicate = Objects.requireNonNull(predicate); 32 | } 33 | 34 | @Override 35 | public Flowable apply(Flowable source) { 36 | return source.skipWhile(predicate::test); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FailedPublisherStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 6 | 7 | import io.reactivex.Flowable; 8 | import io.smallrye.reactive.streams.Engine; 9 | import io.smallrye.reactive.streams.operators.PublisherStage; 10 | import io.smallrye.reactive.streams.operators.PublisherStageFactory; 11 | 12 | /** 13 | * Implementation of the {@link Stage.Failed} stage. It just returns a flowable marked as failed. 14 | * 15 | * @author Clement Escoffier 16 | */ 17 | public class FailedPublisherStageFactory implements PublisherStageFactory { 18 | 19 | @Override 20 | public PublisherStage create(Engine engine, Stage.Failed stage) { 21 | Throwable error = Objects.requireNonNull(Objects.requireNonNull(stage).getError()); 22 | return () -> Flowable.error(error); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FilterStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Predicate; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | import io.reactivex.Flowable; 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.ProcessingStage; 11 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 12 | 13 | /** 14 | * Implementation of {@link Stage.Filter} stage. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class FilterStageFactory implements ProcessingStageFactory { 19 | 20 | @SuppressWarnings("unchecked") 21 | @Override 22 | public ProcessingStage create(Engine engine, Stage.Filter stage) { 23 | Objects.requireNonNull(stage); 24 | Predicate predicate = Objects.requireNonNull(stage.getPredicate()); 25 | return source -> (Flowable) source.filter(predicate::test); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FindFirstStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.Optional; 5 | import java.util.concurrent.CompletableFuture; 6 | 7 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 8 | 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.TerminalStage; 11 | import io.smallrye.reactive.streams.operators.TerminalStageFactory; 12 | 13 | /** 14 | * Implementation of the {@link Stage.FindFirst} stage. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class FindFirstStageFactory implements TerminalStageFactory { 19 | 20 | private static final TerminalStage> INSTANCE = source -> { 21 | CompletableFuture> future = new CompletableFuture<>(); 22 | //noinspection ResultOfMethodCallIgnored 23 | source.map(Optional::of).first(Optional.empty()) 24 | .subscribe( 25 | future::complete, future::completeExceptionally); 26 | return future; 27 | }; 28 | 29 | @SuppressWarnings("unchecked") 30 | @Override 31 | public TerminalStage create(Engine engine, Stage.FindFirst stage) { 32 | Objects.requireNonNull(stage); // Not really useful here as it conveys no parameters, so just here for symmetry 33 | return (TerminalStage) INSTANCE; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FlatMapCompletionStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static io.smallrye.reactive.streams.utils.CompletionStageToPublisher.fromCompletionStage; 4 | 5 | import java.util.Objects; 6 | import java.util.concurrent.CompletionStage; 7 | import java.util.function.Function; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 10 | 11 | import io.reactivex.Flowable; 12 | import io.smallrye.reactive.streams.Engine; 13 | import io.smallrye.reactive.streams.operators.ProcessingStage; 14 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 15 | import io.smallrye.reactive.streams.utils.Casts; 16 | 17 | /** 18 | * Implementation of the {@link Stage.FlatMapCompletionStage} stage. 19 | * 20 | * @author Clement Escoffier 21 | */ 22 | public class FlatMapCompletionStageFactory 23 | implements ProcessingStageFactory { 24 | 25 | @Override 26 | public ProcessingStage create(Engine engine, 27 | Stage.FlatMapCompletionStage stage) { 28 | Function> mapper = Casts.cast( 29 | Objects.requireNonNull(stage).getMapper()); 30 | return new FlatMapCompletionStage<>(mapper); 31 | } 32 | 33 | private static class FlatMapCompletionStage implements ProcessingStage { 34 | private final Function> mapper; 35 | 36 | private FlatMapCompletionStage(Function> mapper) { 37 | this.mapper = Objects.requireNonNull(mapper); 38 | } 39 | 40 | @Override 41 | public Flowable apply(Flowable source) { 42 | return source.flatMap((I item) -> { 43 | if (item == null) { 44 | // Throw an NPE to be compliant with the reactive stream spec. 45 | throw new NullPointerException(); 46 | } 47 | CompletionStage result = mapper.apply(item); 48 | if (result == null) { 49 | // Throw an NPE to be compliant with the reactive stream spec. 50 | throw new NullPointerException(); 51 | } 52 | return fromCompletionStage(result, false); 53 | }, 1); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FlatMapIterableStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Function; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | import io.reactivex.Flowable; 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.ProcessingStage; 11 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 12 | import io.smallrye.reactive.streams.utils.Casts; 13 | 14 | /** 15 | * @author Clement Escoffier 16 | */ 17 | public class FlatMapIterableStageFactory implements ProcessingStageFactory { 18 | 19 | @Override 20 | public ProcessingStage create(Engine engine, Stage.FlatMapIterable stage) { 21 | Function> mapper = Casts.cast(stage.getMapper()); 22 | return new FlatMapIterable<>(mapper); 23 | } 24 | 25 | private static class FlatMapIterable implements ProcessingStage { 26 | private final Function> mapper; 27 | 28 | private FlatMapIterable(Function> mapper) { 29 | this.mapper = Objects.requireNonNull(mapper); 30 | } 31 | 32 | @Override 33 | public Flowable apply(Flowable source) { 34 | return source.concatMapIterable(mapper::apply); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FlatMapStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Function; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Graph; 7 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 8 | import org.reactivestreams.Subscriber; 9 | 10 | import io.reactivex.Flowable; 11 | import io.smallrye.reactive.streams.Engine; 12 | import io.smallrye.reactive.streams.operators.ProcessingStage; 13 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 14 | import io.smallrye.reactive.streams.utils.Casts; 15 | import io.smallrye.reactive.streams.utils.DelegatingSubscriber; 16 | 17 | /** 18 | * Implementation of the {@link Stage.FlatMap} stage. Be aware it behaves as a RX `concatMap`. 19 | * 20 | * @author Clement Escoffier 21 | */ 22 | public class FlatMapStageFactory implements ProcessingStageFactory { 23 | 24 | @Override 25 | public ProcessingStage create(Engine engine, Stage.FlatMap stage) { 26 | Function mapper = Casts.cast(stage.getMapper()); 27 | return new FlatMapStage<>(engine, mapper); 28 | } 29 | 30 | private static class FlatMapStage implements ProcessingStage { 31 | private final Engine engine; 32 | private final Function mapper; 33 | 34 | private FlatMapStage(Engine engine, Function mapper) { 35 | this.mapper = Objects.requireNonNull(mapper); 36 | this.engine = engine; 37 | } 38 | 39 | @Override 40 | public Flowable apply(Flowable source) { 41 | return source 42 | .concatMap((I item) -> { 43 | Graph graph = mapper.apply(item); 44 | Flowable publisher = Flowable.fromPublisher( 45 | Objects.requireNonNull(engine.buildPublisher(Objects.requireNonNull(graph)))); 46 | 47 | return (Subscriber delegate) -> { 48 | // Required because RX FlatMap subscriber does not enforce the reactive stream spec. 49 | Subscriber facade = new DelegatingSubscriber<>(delegate); 50 | publisher.subscribe(facade); 51 | }; 52 | 53 | }); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FromCompletionStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static io.smallrye.reactive.streams.utils.CompletionStageToPublisher.fromCompletionStage; 4 | 5 | import java.util.Objects; 6 | import java.util.concurrent.CompletionStage; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 9 | 10 | import io.reactivex.Flowable; 11 | import io.smallrye.reactive.streams.Engine; 12 | import io.smallrye.reactive.streams.operators.PublisherStage; 13 | import io.smallrye.reactive.streams.operators.PublisherStageFactory; 14 | import io.smallrye.reactive.streams.utils.Casts; 15 | 16 | public class FromCompletionStageFactory implements PublisherStageFactory { 17 | 18 | @Override 19 | public PublisherStage create(Engine engine, Stage.FromCompletionStage stage) { 20 | Objects.requireNonNull(stage); 21 | return () -> { 22 | CompletionStage cs = Casts.cast(Objects.requireNonNull(stage.getCompletionStage())); 23 | return Flowable.fromPublisher(fromCompletionStage(cs, false)); 24 | }; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FromCompletionStageNullableFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static io.smallrye.reactive.streams.utils.CompletionStageToPublisher.fromCompletionStage; 4 | 5 | import java.util.Objects; 6 | import java.util.concurrent.CompletionStage; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 9 | 10 | import io.reactivex.Flowable; 11 | import io.smallrye.reactive.streams.Engine; 12 | import io.smallrye.reactive.streams.operators.PublisherStage; 13 | import io.smallrye.reactive.streams.operators.PublisherStageFactory; 14 | import io.smallrye.reactive.streams.utils.Casts; 15 | 16 | public class FromCompletionStageNullableFactory implements PublisherStageFactory { 17 | 18 | @Override 19 | public PublisherStage create(Engine engine, Stage.FromCompletionStageNullable stage) { 20 | Objects.requireNonNull(stage); 21 | return () -> { 22 | CompletionStage cs = Casts.cast(Objects.requireNonNull(stage.getCompletionStage())); 23 | return Flowable.fromPublisher(fromCompletionStage(cs, true)); 24 | }; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FromIterableStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 6 | 7 | import io.reactivex.Flowable; 8 | import io.smallrye.reactive.streams.Engine; 9 | import io.smallrye.reactive.streams.operators.PublisherStage; 10 | import io.smallrye.reactive.streams.operators.PublisherStageFactory; 11 | 12 | /** 13 | * Implementation of the {@link Stage.Of} stage. 14 | * 15 | * @author Clement Escoffier 16 | */ 17 | public class FromIterableStageFactory implements PublisherStageFactory { 18 | 19 | @SuppressWarnings("unchecked") 20 | @Override 21 | public PublisherStage create(Engine engine, Stage.Of stage) { 22 | Iterable elements = (Iterable) Objects.requireNonNull(Objects.requireNonNull(stage).getElements()); 23 | return () -> Flowable.fromIterable(elements); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/FromPublisherStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 6 | import org.reactivestreams.Publisher; 7 | 8 | import io.reactivex.Flowable; 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.PublisherStage; 11 | import io.smallrye.reactive.streams.operators.PublisherStageFactory; 12 | 13 | /** 14 | * Implementation of the {@link Stage.PublisherStage} stage. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class FromPublisherStageFactory implements PublisherStageFactory { 19 | 20 | @SuppressWarnings("unchecked") 21 | @Override 22 | public PublisherStage create(Engine engine, Stage.PublisherStage stage) { 23 | Publisher publisher = (Publisher) Objects.requireNonNull(Objects.requireNonNull(stage.getRsPublisher())); 24 | return () -> Flowable.fromPublisher(publisher); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/LimitStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 4 | 5 | import io.reactivex.Flowable; 6 | import io.smallrye.reactive.streams.Engine; 7 | import io.smallrye.reactive.streams.operators.ProcessingStage; 8 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 9 | 10 | /** 11 | * Implementation of the {@link Stage.Limit} stage. 12 | * 13 | * @author Clement Escoffier 14 | */ 15 | public class LimitStageFactory implements ProcessingStageFactory { 16 | 17 | @Override 18 | public ProcessingStage create(Engine engine, Stage.Limit stage) { 19 | long limit = stage.getLimit(); 20 | return source -> (Flowable) source.limit(limit); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/MapStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Function; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | import io.smallrye.reactive.streams.Engine; 9 | import io.smallrye.reactive.streams.operators.ProcessingStage; 10 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 11 | import io.smallrye.reactive.streams.utils.Casts; 12 | 13 | /** 14 | * Implementation of the {@link Stage.Map} stage. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class MapStageFactory implements ProcessingStageFactory { 19 | 20 | @Override 21 | public ProcessingStage create(Engine engine, Stage.Map stage) { 22 | Function mapper = Casts.cast(stage.getMapper()); 23 | Objects.requireNonNull(mapper); 24 | return source -> source.map(mapper::apply); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/OnCompleteStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 6 | 7 | import io.reactivex.Flowable; 8 | import io.smallrye.reactive.streams.Engine; 9 | import io.smallrye.reactive.streams.operators.ProcessingStage; 10 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 11 | 12 | /** 13 | * Implementation of the {@link Stage.OnComplete} stage. 14 | * 15 | * @author Clement Escoffier 16 | */ 17 | public class OnCompleteStageFactory implements ProcessingStageFactory { 18 | 19 | @SuppressWarnings("unchecked") 20 | @Override 21 | public ProcessingStage create(Engine engine, Stage.OnComplete stage) { 22 | Runnable runnable = Objects.requireNonNull(stage).getAction(); 23 | Objects.requireNonNull(runnable); 24 | return source -> (Flowable) source.doOnComplete(runnable::run); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/OnErrorResumeStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Function; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | import io.reactivex.Flowable; 9 | import io.reactivex.plugins.RxJavaPlugins; 10 | import io.smallrye.reactive.streams.Engine; 11 | import io.smallrye.reactive.streams.operators.ProcessingStage; 12 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 13 | import io.smallrye.reactive.streams.utils.recovery.OnErrorReturn; 14 | 15 | /** 16 | * Implementation of the {@link Stage.OnErrorResume} stage. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class OnErrorResumeStageFactory implements ProcessingStageFactory { 21 | 22 | @SuppressWarnings("unchecked") 23 | @Override 24 | public ProcessingStage create(Engine engine, Stage.OnErrorResume stage) { 25 | Function function = (Function) Objects.requireNonNull(stage).getFunction(); 26 | Objects.requireNonNull(function); 27 | return source -> (Flowable) RxJavaPlugins.onAssembly(new OnErrorReturn<>(source, function)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/OnErrorResumeWithStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Function; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Graph; 7 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 8 | 9 | import io.reactivex.Flowable; 10 | import io.reactivex.plugins.RxJavaPlugins; 11 | import io.smallrye.reactive.streams.Engine; 12 | import io.smallrye.reactive.streams.operators.ProcessingStage; 13 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 14 | import io.smallrye.reactive.streams.utils.recovery.OnErrorResumeWith; 15 | 16 | /** 17 | * Implementation of the {@link Stage.OnErrorResumeWith} stage. 18 | * 19 | * @author Clement Escoffier 20 | */ 21 | public class OnErrorResumeWithStageFactory implements ProcessingStageFactory { 22 | 23 | @SuppressWarnings("unchecked") 24 | @Override 25 | public ProcessingStage create(Engine engine, Stage.OnErrorResumeWith stage) { 26 | Function function = Objects.requireNonNull(stage).getFunction(); 27 | Objects.requireNonNull(function); 28 | 29 | return source -> (Flowable) RxJavaPlugins.onAssembly( 30 | new OnErrorResumeWith<>(source, (Throwable err) -> { 31 | Graph graph = function.apply(err); 32 | return Flowable.fromPublisher( 33 | Objects.requireNonNull(engine.buildPublisher(Objects.requireNonNull(graph)))); 34 | })); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/OnErrorStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Consumer; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | import io.reactivex.Flowable; 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.ProcessingStage; 11 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 12 | 13 | /** 14 | * Implementation of the {@link Stage.OnError} stage. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class OnErrorStageFactory implements ProcessingStageFactory { 19 | 20 | @SuppressWarnings("unchecked") 21 | @Override 22 | public ProcessingStage create(Engine engine, Stage.OnError stage) { 23 | Consumer consumer = Objects.requireNonNull(stage).getConsumer(); 24 | Objects.requireNonNull(consumer); 25 | return source -> (Flowable) source.doOnError(consumer::accept); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/OnTerminateStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 6 | 7 | import io.reactivex.Flowable; 8 | import io.smallrye.reactive.streams.Engine; 9 | import io.smallrye.reactive.streams.operators.ProcessingStage; 10 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 11 | 12 | /** 13 | * Implementation of the {@link Stage.OnTerminate} stage. 14 | * 15 | * @author Clement Escoffier 16 | */ 17 | public class OnTerminateStageFactory implements ProcessingStageFactory { 18 | 19 | @SuppressWarnings("unchecked") 20 | @Override 21 | public ProcessingStage create(Engine engine, Stage.OnTerminate stage) { 22 | Runnable runnable = Objects.requireNonNull(stage).getAction(); 23 | Objects.requireNonNull(runnable); 24 | // Interesting issue when using onTerminate, the TCK fails because the issue is reported twice 25 | // First, the onComplete "part" is called, throws an exception, and then call the doOnError part 26 | // which throws another exception. 27 | // Anyway, we should also configure the cancellation callback. 28 | return source -> (Flowable) source 29 | .doOnError(t -> runnable.run()) 30 | .doOnComplete(runnable::run) 31 | .doOnCancel(runnable::run); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/PeekStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Consumer; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | import io.reactivex.Flowable; 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.ProcessingStage; 11 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 12 | 13 | /** 14 | * Implementation of the {@link Stage.Peek} stage. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class PeekStageFactory implements ProcessingStageFactory { 19 | 20 | @SuppressWarnings("unchecked") 21 | @Override 22 | public ProcessingStage create(Engine engine, Stage.Peek stage) { 23 | Consumer consumer = (Consumer) Objects.requireNonNull(stage) 24 | .getConsumer(); 25 | Objects.requireNonNull(consumer); 26 | return source -> (Flowable) source.doOnNext(consumer::accept); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/ProcessorStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 6 | import org.reactivestreams.Processor; 7 | 8 | import io.reactivex.Flowable; 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.ProcessingStage; 11 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 12 | import io.smallrye.reactive.streams.utils.Casts; 13 | 14 | /** 15 | * Implementation of the {@link Stage.ProcessorStage} stage ({@code via} operators). 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class ProcessorStageFactory implements ProcessingStageFactory { 20 | 21 | @Override 22 | public ProcessingStage create(Engine engine, Stage.ProcessorStage stage) { 23 | Processor processor = Casts.cast(Objects.requireNonNull( 24 | Objects.requireNonNull(stage).getRsProcessor())); 25 | 26 | return source -> Flowable.defer(() -> { 27 | Flowable flowable = Flowable.fromPublisher(processor); 28 | source.safeSubscribe(processor); 29 | return flowable; 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/SkipStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 4 | 5 | import io.reactivex.Flowable; 6 | import io.smallrye.reactive.streams.Engine; 7 | import io.smallrye.reactive.streams.operators.ProcessingStage; 8 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 9 | 10 | /** 11 | * Implementation of the {@link Stage.Skip} stage. 12 | * 13 | * @author Clement Escoffier 14 | */ 15 | public class SkipStageFactory implements ProcessingStageFactory { 16 | 17 | @Override 18 | public ProcessingStage create(Engine engine, Stage.Skip stage) { 19 | long skip = stage.getSkip(); 20 | return source -> (Flowable) source.skip(skip); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/SubscriberStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.concurrent.CompletionStage; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | import org.reactivestreams.Subscriber; 8 | 9 | import io.reactivex.Flowable; 10 | import io.smallrye.reactive.streams.Engine; 11 | import io.smallrye.reactive.streams.operators.TerminalStage; 12 | import io.smallrye.reactive.streams.operators.TerminalStageFactory; 13 | import io.smallrye.reactive.streams.utils.WrappedSubscriber; 14 | 15 | /** 16 | * Implementation of the {@link Stage.SubscriberStage} stage. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class SubscriberStageFactory implements TerminalStageFactory { 21 | 22 | @SuppressWarnings("unchecked") 23 | @Override 24 | public TerminalStage create(Engine engine, Stage.SubscriberStage stage) { 25 | Subscriber subscriber = (Subscriber) Objects.requireNonNull(stage).getRsSubscriber(); 26 | Objects.requireNonNull(subscriber); 27 | return (TerminalStage) new SubscriberStage<>(subscriber); 28 | } 29 | 30 | private static class SubscriberStage implements TerminalStage { 31 | 32 | private final Subscriber subscriber; 33 | 34 | SubscriberStage(Subscriber subscriber) { 35 | this.subscriber = subscriber; 36 | } 37 | 38 | @Override 39 | public CompletionStage apply(Flowable source) { 40 | WrappedSubscriber wrapped = new WrappedSubscriber<>(subscriber); 41 | source.safeSubscribe(wrapped); 42 | return wrapped.future(); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/stages/TakeWhileStageFactory.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Predicate; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 7 | 8 | import io.reactivex.Flowable; 9 | import io.smallrye.reactive.streams.Engine; 10 | import io.smallrye.reactive.streams.operators.ProcessingStage; 11 | import io.smallrye.reactive.streams.operators.ProcessingStageFactory; 12 | 13 | /** 14 | * Implementation of the {@link Stage.TakeWhile} stage. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class TakeWhileStageFactory implements ProcessingStageFactory { 19 | 20 | @SuppressWarnings("unchecked") 21 | @Override 22 | public ProcessingStage create(Engine engine, Stage.TakeWhile stage) { 23 | Predicate predicate = (Predicate) Objects.requireNonNull(stage.getPredicate()); 24 | return source -> (Flowable) source.takeWhile(predicate::test); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/CancellablePublisher.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.Objects; 4 | import java.util.concurrent.atomic.AtomicBoolean; 5 | 6 | import org.reactivestreams.Publisher; 7 | import org.reactivestreams.Subscriber; 8 | 9 | /** 10 | * Wrapped a source publisher and make it cancellable on demand. The cancellation happens if 11 | * no-one subscribed to the source publisher. This class is required for the 12 | * {@link io.smallrye.reactive.streams.stages.ConcatStageFactory} to enforce the reactive 13 | * streams rules. 14 | * 15 | * @author Clement Escoffier 16 | */ 17 | public class CancellablePublisher implements Publisher { 18 | private final Publisher source; 19 | private final AtomicBoolean subscribed = new AtomicBoolean(); 20 | 21 | public CancellablePublisher(Publisher delegate) { 22 | this.source = delegate; 23 | } 24 | 25 | @Override 26 | public void subscribe(Subscriber subscriber) { 27 | Objects.requireNonNull(subscriber); 28 | if (subscribed.compareAndSet(false, true)) { 29 | source.subscribe(subscriber); 30 | } else { 31 | subscriber.onSubscribe(new EmptySubscription()); 32 | subscriber.onError(new IllegalStateException("Multicast not supported")); 33 | } 34 | } 35 | 36 | public void cancelIfNotSubscribed() { 37 | if (subscribed.compareAndSet(false, true)) { 38 | source.subscribe(new CancellationSubscriber<>()); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/CancellationSubscriber.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.Objects; 4 | 5 | import org.reactivestreams.Subscriber; 6 | import org.reactivestreams.Subscription; 7 | 8 | /** 9 | * @author Clement Escoffier 10 | */ 11 | public class CancellationSubscriber implements Subscriber { 12 | 13 | @Override 14 | public void onSubscribe(Subscription s) { 15 | Objects.requireNonNull(s).cancel(); 16 | } 17 | 18 | @Override 19 | public void onNext(T t) { 20 | // Just check for null value. 21 | Objects.requireNonNull(t); 22 | } 23 | 24 | @Override 25 | public void onError(Throwable t) { 26 | // Ignored. 27 | Objects.requireNonNull(t); 28 | } 29 | 30 | @Override 31 | public void onComplete() { 32 | // Ignored. 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/Casts.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.concurrent.CompletionStage; 4 | import java.util.function.Function; 5 | import java.util.function.Predicate; 6 | 7 | import org.reactivestreams.Processor; 8 | 9 | import io.smallrye.reactive.streams.operators.ProcessingStage; 10 | 11 | /** 12 | * Cosmetic cast / generic / erasure fixes. 13 | *

14 | * At some point this class should disappear... 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | @SuppressWarnings("unchecked") 19 | public class Casts { 20 | 21 | private Casts() { 22 | // Avoid direct instantiation. 23 | } 24 | 25 | public static Function cast(Function fun) { 26 | return (Function) fun; 27 | } 28 | 29 | public static Predicate cast(Predicate p) { 30 | return (Predicate) p; 31 | } 32 | 33 | public static ProcessingStage cast(ProcessingStage p) { 34 | return (ProcessingStage) p; 35 | } 36 | 37 | public static Processor cast(Processor p) { 38 | return (Processor) p; 39 | } 40 | 41 | public static CompletionStage cast(CompletionStage cs) { 42 | return (CompletionStage) cs; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/CollectorSubscriber.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.function.BiConsumer; 4 | import java.util.function.Function; 5 | 6 | import org.reactivestreams.Subscriber; 7 | import org.reactivestreams.Subscription; 8 | 9 | import io.reactivex.internal.subscriptions.DeferredScalarSubscription; 10 | import io.reactivex.internal.subscriptions.SubscriptionHelper; 11 | import io.reactivex.plugins.RxJavaPlugins; 12 | 13 | final class CollectorSubscriber extends DeferredScalarSubscription 14 | implements Subscriber { 15 | 16 | private static final long serialVersionUID = 2129956429647866525L; 17 | 18 | private final transient BiConsumer accumulator; 19 | 20 | private final transient Function finisher; 21 | 22 | private transient A intermediate; 23 | 24 | private transient Subscription subscription; 25 | 26 | private boolean done; 27 | 28 | CollectorSubscriber(Subscriber actual, 29 | A initialValue, BiConsumer accumulator, Function finisher) { 30 | super(actual); 31 | this.intermediate = initialValue; 32 | this.accumulator = accumulator; 33 | this.finisher = finisher; 34 | } 35 | 36 | @Override 37 | public void onSubscribe(Subscription s) { 38 | if (SubscriptionHelper.validate(this.subscription, s)) { 39 | this.subscription = s; 40 | 41 | downstream.onSubscribe(this); 42 | 43 | s.request(Long.MAX_VALUE); 44 | } 45 | } 46 | 47 | @Override 48 | public void onNext(T t) { 49 | if (!done) { 50 | try { 51 | accumulator.accept(intermediate, t); 52 | } catch (Exception ex) { 53 | subscription.cancel(); 54 | onError(ex); 55 | } 56 | } 57 | } 58 | 59 | @Override 60 | public void onError(Throwable t) { 61 | if (done) { 62 | RxJavaPlugins.onError(t); 63 | } else { 64 | done = true; 65 | intermediate = null; 66 | downstream.onError(t); 67 | } 68 | } 69 | 70 | @Override 71 | public void onComplete() { 72 | if (!done) { 73 | R r; 74 | 75 | try { 76 | r = finisher.apply(intermediate); 77 | } catch (Exception ex) { 78 | onError(ex); 79 | return; 80 | } 81 | 82 | intermediate = null; 83 | complete(r); 84 | } 85 | } 86 | 87 | @Override 88 | public void cancel() { 89 | super.cancel(); 90 | subscription.cancel(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/CompletionStageToPublisher.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.Objects; 4 | import java.util.concurrent.CompletionStage; 5 | 6 | import io.reactivex.Flowable; 7 | import io.reactivex.processors.AsyncProcessor; 8 | 9 | public class CompletionStageToPublisher { 10 | 11 | private CompletionStageToPublisher() { 12 | // Avoid direct instantiation. 13 | } 14 | 15 | public static Flowable fromCompletionStage(CompletionStage future, boolean acceptNullValue) { 16 | AsyncProcessor processor = AsyncProcessor.create(); 17 | 18 | Objects.requireNonNull(future).whenComplete((T v, Throwable e) -> { 19 | if (e != null) { 20 | processor.onError(e); 21 | } else if (v != null) { 22 | processor.onNext(v); 23 | processor.onComplete(); 24 | } else { 25 | if (acceptNullValue) { 26 | processor.onComplete(); 27 | } else { 28 | processor.onError(new NullPointerException("Redeemed value is `null`")); 29 | } 30 | } 31 | }); 32 | 33 | return processor; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/CouplingProcessor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import org.reactivestreams.Publisher; 4 | import org.reactivestreams.Subscriber; 5 | 6 | public class CouplingProcessor implements Publisher { 7 | 8 | private final SubscriptionObserver controller; 9 | private final Publisher publisher; 10 | 11 | public CouplingProcessor(Publisher source, Subscriber subscriber, Publisher publisher) { 12 | controller = new SubscriptionObserver<>(source, subscriber); 13 | this.publisher = publisher; 14 | controller.run(); 15 | } 16 | 17 | @Override 18 | public synchronized void subscribe(Subscriber subscriber) { 19 | SubscriptionObserver observer = new SubscriptionObserver<>(this.publisher, subscriber); 20 | controller.setObserver(observer); 21 | observer.setObserver(controller); 22 | observer.run(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/DefaultSubscriberWithCompletionStage.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.concurrent.CompletionStage; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.CompletionSubscriber; 6 | import org.eclipse.microprofile.reactive.streams.operators.spi.SubscriberWithCompletionStage; 7 | import org.reactivestreams.Processor; 8 | import org.reactivestreams.Subscriber; 9 | 10 | public class DefaultSubscriberWithCompletionStage implements SubscriberWithCompletionStage { 11 | private final CompletionSubscriber subscriber; 12 | 13 | public DefaultSubscriberWithCompletionStage(Processor processor, CompletionStage result) { 14 | subscriber = CompletionSubscriber.of(processor, result); 15 | } 16 | 17 | @Override 18 | public CompletionStage getCompletion() { 19 | return subscriber.getCompletion(); 20 | } 21 | 22 | @Override 23 | public Subscriber getSubscriber() { 24 | return subscriber; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/DelegatingSubscriber.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.Objects; 4 | 5 | import org.reactivestreams.Subscriber; 6 | import org.reactivestreams.Subscription; 7 | 8 | /** 9 | * A subscriber delegating to another subscriber and enforcing that parameters are not {@code null} 10 | * 11 | * @author Clement Escoffier 12 | */ 13 | public class DelegatingSubscriber implements Subscriber { 14 | private final Subscriber delegate; 15 | 16 | public DelegatingSubscriber(Subscriber delegate) { 17 | this.delegate = delegate; 18 | } 19 | 20 | @Override 21 | public void onSubscribe(Subscription s) { 22 | Objects.requireNonNull(s); 23 | delegate.onSubscribe(s); 24 | } 25 | 26 | @Override 27 | public void onNext(O out) { 28 | Objects.requireNonNull(out); 29 | delegate.onNext(out); 30 | } 31 | 32 | @Override 33 | public void onError(Throwable t) { 34 | Objects.requireNonNull(t); 35 | delegate.onError(t); 36 | } 37 | 38 | @Override 39 | public void onComplete() { 40 | delegate.onComplete(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/EmptySubscription.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import org.reactivestreams.Subscription; 4 | 5 | /** 6 | * A {@link Subscription implementation} ignoring everything. 7 | * 8 | * @author Clement Escoffier 9 | */ 10 | public class EmptySubscription implements Subscription { 11 | @Override 12 | public void request(long n) { 13 | // Ignored. 14 | } 15 | 16 | @Override 17 | public void cancel() { 18 | // Ignored. 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/FlowableCollector.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.function.BiConsumer; 4 | import java.util.function.Function; 5 | import java.util.stream.Collector; 6 | 7 | import org.reactivestreams.Publisher; 8 | import org.reactivestreams.Subscriber; 9 | 10 | import io.reactivex.Flowable; 11 | import io.reactivex.internal.subscriptions.EmptySubscription; 12 | 13 | /** 14 | * Collect elements of the upstream with the help of the Collector'subscription callback functions. 15 | * 16 | * @param the upstream value type 17 | * @param the accumulated type 18 | * @param the result type 19 | */ 20 | public final class FlowableCollector extends Flowable { 21 | 22 | private final Publisher source; 23 | 24 | private final Collector collector; 25 | 26 | public FlowableCollector(Publisher source, Collector collector) { 27 | this.source = source; 28 | this.collector = collector; 29 | } 30 | 31 | @Override 32 | protected void subscribeActual(Subscriber s) { 33 | A initialValue; 34 | BiConsumer accumulator; 35 | Function finisher; 36 | 37 | try { 38 | initialValue = collector.supplier().get(); 39 | accumulator = collector.accumulator(); 40 | finisher = collector.finisher(); 41 | } catch (Exception ex) { 42 | source.subscribe(new CancellationSubscriber<>()); 43 | EmptySubscription.error(ex, s); 44 | return; 45 | } 46 | 47 | source.subscribe(new CollectorSubscriber<>(s, initialValue, accumulator, finisher)); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/WrappedProcessor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.Objects; 4 | import java.util.concurrent.atomic.AtomicBoolean; 5 | 6 | import org.reactivestreams.Processor; 7 | import org.reactivestreams.Publisher; 8 | import org.reactivestreams.Subscriber; 9 | import org.reactivestreams.Subscription; 10 | 11 | /** 12 | * Processor wrapping a publisher and subscriber, and connect them 13 | */ 14 | public class WrappedProcessor implements Processor { 15 | private final Subscriber subscriber; 16 | private final Publisher publisher; 17 | private final AtomicBoolean subscribed = new AtomicBoolean(false); 18 | 19 | public WrappedProcessor(Subscriber subscriber, Publisher publisher) { 20 | this.subscriber = subscriber; 21 | this.publisher = publisher; 22 | } 23 | 24 | @Override 25 | public void subscribe(Subscriber subscriber) { 26 | publisher.subscribe(subscriber); 27 | } 28 | 29 | @Override 30 | public void onSubscribe(Subscription subscription) { 31 | if (!subscribed.compareAndSet(false, true)) { 32 | subscription.cancel(); 33 | } else { 34 | subscriber.onSubscribe(subscription); 35 | } 36 | } 37 | 38 | @Override 39 | public void onNext(T item) { 40 | subscriber.onNext(item); 41 | } 42 | 43 | @Override 44 | public void onError(Throwable throwable) { 45 | subscriber.onError(Objects.requireNonNull(throwable)); 46 | } 47 | 48 | @Override 49 | public void onComplete() { 50 | subscriber.onComplete(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/WrappedSubscriber.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.Objects; 4 | import java.util.concurrent.CancellationException; 5 | import java.util.concurrent.CompletableFuture; 6 | import java.util.concurrent.CompletionStage; 7 | import java.util.concurrent.atomic.AtomicBoolean; 8 | 9 | import org.reactivestreams.Subscriber; 10 | import org.reactivestreams.Subscription; 11 | 12 | /** 13 | * @author Clement Escoffier 14 | */ 15 | public class WrappedSubscriber implements Subscriber { 16 | 17 | private final CompletableFuture future = new CompletableFuture<>(); 18 | private final Subscriber source; 19 | private final AtomicBoolean subscribed = new AtomicBoolean(false); 20 | 21 | public WrappedSubscriber(Subscriber delegate) { 22 | this.source = delegate; 23 | } 24 | 25 | public CompletionStage future() { 26 | return future; 27 | } 28 | 29 | @Override 30 | public void onSubscribe(Subscription subscription) { 31 | Objects.requireNonNull(subscription); 32 | if (subscribed.compareAndSet(false, true)) { 33 | source.onSubscribe( 34 | new WrappedSubscription(subscription, () -> future.completeExceptionally(new CancellationException()))); 35 | } else { 36 | subscription.cancel(); 37 | } 38 | } 39 | 40 | @Override 41 | public void onNext(T item) { 42 | source.onNext(Objects.requireNonNull(item)); 43 | } 44 | 45 | @Override 46 | public void onError(Throwable throwable) { 47 | future.completeExceptionally(Objects.requireNonNull(throwable)); 48 | source.onError(throwable); 49 | } 50 | 51 | @Override 52 | public void onComplete() { 53 | future.complete(null); 54 | source.onComplete(); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/WrappedSubscription.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import java.util.Objects; 4 | 5 | import org.reactivestreams.Subscription; 6 | 7 | /** 8 | * @author Clement Escoffier 9 | */ 10 | public class WrappedSubscription implements Subscription { 11 | 12 | private final Subscription subscription; 13 | private final Runnable cancellationHandler; 14 | 15 | WrappedSubscription(Subscription subscription, Runnable onCancellation) { 16 | this.subscription = Objects.requireNonNull(subscription); 17 | this.cancellationHandler = onCancellation; 18 | } 19 | 20 | @Override 21 | public void request(long n) { 22 | subscription.request(n); 23 | } 24 | 25 | @Override 26 | public void cancel() { 27 | if (cancellationHandler != null) { 28 | cancellationHandler.run(); 29 | } 30 | subscription.cancel(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/recovery/OnErrorResumeWith.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils.recovery; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Function; 5 | 6 | import org.reactivestreams.Publisher; 7 | import org.reactivestreams.Subscriber; 8 | 9 | import io.reactivex.Flowable; 10 | import io.reactivex.internal.fuseable.HasUpstreamPublisher; 11 | 12 | public class OnErrorResumeWith extends Flowable implements HasUpstreamPublisher { 13 | 14 | /** 15 | * The upstream source Publisher. 16 | */ 17 | private final Flowable source; 18 | 19 | private final Function> nextSupplier; 20 | 21 | public OnErrorResumeWith(Flowable source, 22 | Function> nextSupplier) { 23 | this.source = Objects.requireNonNull(source, "source is null"); 24 | this.nextSupplier = nextSupplier; 25 | } 26 | 27 | @Override 28 | public final Publisher source() { 29 | return source; 30 | } 31 | 32 | @Override 33 | protected void subscribeActual(Subscriber s) { 34 | OnErrorResumeWithSubscriber parent = new OnErrorResumeWithSubscriber<>(s, nextSupplier); 35 | s.onSubscribe(parent.arbiter()); 36 | source.subscribe(parent); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/recovery/OnErrorResumeWithSubscriber.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils.recovery; 2 | 3 | import java.util.function.Function; 4 | 5 | import org.reactivestreams.Publisher; 6 | import org.reactivestreams.Subscriber; 7 | import org.reactivestreams.Subscription; 8 | 9 | import io.reactivex.FlowableSubscriber; 10 | import io.reactivex.internal.subscriptions.EmptySubscription; 11 | import io.reactivex.internal.subscriptions.SubscriptionArbiter; 12 | import io.reactivex.plugins.RxJavaPlugins; 13 | 14 | public class OnErrorResumeWithSubscriber implements FlowableSubscriber { 15 | private final Subscriber actual; 16 | private final Function> nextSupplier; 17 | private final SubscriptionArbiter arbiter; 18 | 19 | private boolean once; 20 | 21 | private boolean done; 22 | 23 | OnErrorResumeWithSubscriber(Subscriber actual, 24 | Function> nextSupplier) { 25 | this.actual = actual; 26 | this.nextSupplier = nextSupplier; 27 | this.arbiter = new SubscriptionArbiter(false); 28 | } 29 | 30 | @Override 31 | public void onSubscribe(Subscription s) { 32 | if (!(s instanceof EmptySubscription)) { 33 | arbiter.setSubscription(s); 34 | } 35 | // else the subscription has already been cancelled, and so we must not subscribe to 36 | // be compliant with Reactive Streams. 37 | } 38 | 39 | @Override 40 | public void onNext(T t) { 41 | if (done) { 42 | return; 43 | } 44 | actual.onNext(t); 45 | if (!once) { 46 | arbiter.produced(1L); 47 | } 48 | } 49 | 50 | @Override 51 | public void onError(Throwable t) { 52 | if (once) { 53 | if (done) { 54 | RxJavaPlugins.onError(t); 55 | } else { 56 | actual.onError(t); 57 | } 58 | return; 59 | } 60 | once = true; 61 | 62 | Publisher p; 63 | 64 | try { 65 | p = nextSupplier.apply(t); 66 | } catch (Exception e) { 67 | actual.onError(e); 68 | return; 69 | } 70 | 71 | if (p == null) { 72 | NullPointerException npe = new NullPointerException("Publisher is null"); 73 | npe.initCause(t); 74 | actual.onError(npe); 75 | return; 76 | } 77 | 78 | p.subscribe(this); 79 | } 80 | 81 | @Override 82 | public void onComplete() { 83 | if (done) { 84 | return; 85 | } 86 | done = true; 87 | once = true; 88 | actual.onComplete(); 89 | } 90 | 91 | Subscription arbiter() { 92 | return arbiter; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/recovery/OnErrorReturn.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils.recovery; 2 | 3 | import java.util.function.Function; 4 | 5 | import org.reactivestreams.Publisher; 6 | import org.reactivestreams.Subscriber; 7 | 8 | import io.reactivex.Flowable; 9 | import io.reactivex.internal.fuseable.HasUpstreamPublisher; 10 | 11 | public class OnErrorReturn extends Flowable implements HasUpstreamPublisher { 12 | 13 | /** 14 | * The upstream source Publisher. 15 | */ 16 | private final Flowable source; 17 | 18 | private final Function valueSupplier; 19 | 20 | public OnErrorReturn(Flowable source, Function valueSupplier) { 21 | this.source = source; 22 | this.valueSupplier = valueSupplier; 23 | } 24 | 25 | @Override 26 | public final Publisher source() { 27 | return source; 28 | } 29 | 30 | @Override 31 | protected void subscribeActual(Subscriber s) { 32 | source.subscribe(new OnErrorReturnSubscriber<>(s, valueSupplier)); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /implementation/src/main/java/io/smallrye/reactive/streams/utils/recovery/OnErrorReturnSubscriber.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils.recovery; 2 | 3 | import java.util.Objects; 4 | import java.util.function.Function; 5 | 6 | import org.reactivestreams.Subscriber; 7 | 8 | import io.reactivex.internal.subscribers.SinglePostCompleteSubscriber; 9 | 10 | public class OnErrorReturnSubscriber extends SinglePostCompleteSubscriber { 11 | 12 | private static final long serialVersionUID = 1111111L; 13 | private final transient Function valueSupplier; 14 | 15 | OnErrorReturnSubscriber(Subscriber actual, 16 | Function valueSupplier) { 17 | super(actual); 18 | this.valueSupplier = valueSupplier; 19 | } 20 | 21 | @Override 22 | public void onNext(T t) { 23 | produced++; 24 | downstream.onNext(t); 25 | } 26 | 27 | @Override 28 | public void onError(Throwable t) { 29 | T v; 30 | try { 31 | v = Objects.requireNonNull(valueSupplier.apply(t), "The valueSupplier returned a null value"); 32 | } catch (Exception ex) { 33 | 34 | downstream.onError(ex); 35 | return; 36 | } 37 | complete(v); 38 | } 39 | 40 | @Override 41 | public void onComplete() { 42 | downstream.onComplete(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /implementation/src/main/resources/META-INF/services/org.eclipse.microprofile.reactive.streams.operators.spi.ReactiveStreamsEngine: -------------------------------------------------------------------------------- 1 | io.smallrye.reactive.streams.Engine -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/DistinctStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.List; 6 | import java.util.Objects; 7 | import java.util.concurrent.ExecutionException; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link DistinctStageFactory}. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class DistinctStageFactoryTest extends StageTestBase { 21 | 22 | private final DistinctStageFactory factory = new DistinctStageFactory(); 23 | 24 | @Test 25 | public void create() throws ExecutionException, InterruptedException { 26 | Flowable flowable = Flowable.fromArray(1, 2, 1, 4, 3, 2, 5, 3, 6, 6, 4, 8, 7, 4, 5, 6, 7, 8, 9, 9, 10) 27 | .subscribeOn(Schedulers.computation()); 28 | 29 | List list = ReactiveStreams.fromPublisher(flowable) 30 | .filter(i -> i < 4) 31 | .distinct() 32 | .map(this::asString) 33 | .toList() 34 | .run().toCompletableFuture().get(); 35 | 36 | assertThat(list).containsExactly("1", "2", "3"); 37 | } 38 | 39 | private String asString(int i) { 40 | return Objects.toString(i); 41 | } 42 | 43 | @Test(expected = NullPointerException.class) 44 | public void createWithoutStage() { 45 | factory.create(null, null); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/DropWhileStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.List; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | /** 15 | * Checks the behavior of the {@link DropWhileStageFactory} class. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class DropWhileStageFactoryTest extends StageTestBase { 20 | 21 | private final DropWhileStageFactory factory = new DropWhileStageFactory(); 22 | 23 | @Test 24 | public void create() throws ExecutionException, InterruptedException { 25 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 26 | .subscribeOn(Schedulers.computation()); 27 | List list = ReactiveStreams.fromPublisher(flowable).dropWhile(i -> i < 6).toList().run() 28 | .toCompletableFuture().get(); 29 | assertThat(list).hasSize(5).containsExactly(6, 7, 8, 9, 10); 30 | } 31 | 32 | @Test(expected = NullPointerException.class) 33 | public void createWithoutStage() { 34 | factory.create(null, null); 35 | } 36 | 37 | @Test(expected = NullPointerException.class) 38 | public void createWithoutPredicate() { 39 | factory.create(null, () -> null); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/FailedPublisherStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import org.junit.Test; 4 | 5 | import io.reactivex.subscribers.TestSubscriber; 6 | import io.smallrye.reactive.streams.operators.PublisherStage; 7 | 8 | /** 9 | * Checks the behavior of {@link FailedPublisherStageFactory}. 10 | * 11 | * @author Clement Escoffier 12 | */ 13 | public class FailedPublisherStageFactoryTest extends StageTestBase { 14 | 15 | private final FailedPublisherStageFactory factory = new FailedPublisherStageFactory(); 16 | 17 | @Test 18 | public void createWithError() { 19 | Exception failure = new Exception("Boom"); 20 | PublisherStage boom = factory.create(null, () -> failure); 21 | TestSubscriber test = boom.get().test(); 22 | test.assertError(failure); 23 | } 24 | 25 | @Test(expected = NullPointerException.class) 26 | public void createWithoutError() { 27 | factory.create(null, () -> null); 28 | } 29 | 30 | @Test(expected = NullPointerException.class) 31 | public void createWithoutStage() { 32 | factory.create(null, null); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/FilterStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.List; 6 | import java.util.concurrent.ExecutionException; 7 | import java.util.function.Predicate; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link FilterStageFactory} class. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class FilterStageFactoryTest extends StageTestBase { 21 | 22 | private final FilterStageFactory factory = new FilterStageFactory(); 23 | 24 | @Test 25 | public void create() throws ExecutionException, InterruptedException { 26 | Predicate even = i -> i % 2 == 0; 27 | 28 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 29 | .subscribeOn(Schedulers.computation()); 30 | List list = ReactiveStreams.fromPublisher(flowable).filter(even).toList().run() 31 | .toCompletableFuture().get(); 32 | assertThat(list).hasSize(5).containsExactly(2, 4, 6, 8, 10); 33 | } 34 | 35 | @Test(expected = NullPointerException.class) 36 | public void createWithoutStage() { 37 | factory.create(null, null); 38 | } 39 | 40 | @Test(expected = NullPointerException.class) 41 | public void createWithoutPredicate() { 42 | factory.create(null, () -> null); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/FindFirstStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Optional; 6 | 7 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 8 | import org.junit.Test; 9 | 10 | import io.reactivex.Flowable; 11 | import io.reactivex.schedulers.Schedulers; 12 | 13 | /** 14 | * Checks the behavior of the {@link FindFirstStageFactory}. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class FindFirstStageFactoryTest extends StageTestBase { 19 | 20 | private final FindFirstStageFactory factory = new FindFirstStageFactory(); 21 | 22 | @Test 23 | public void create() { 24 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 25 | .subscribeOn(Schedulers.computation()); 26 | 27 | Optional optional = ReactiveStreams.fromPublisher(flowable).filter(i -> i > 5) 28 | .findFirst().run().toCompletableFuture().join(); 29 | 30 | assertThat(optional).contains(6); 31 | } 32 | 33 | @Test(expected = NullPointerException.class) 34 | public void createWithoutStage() { 35 | factory.create(null, null); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/FlatMapIterableStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | import java.util.Objects; 8 | import java.util.concurrent.*; 9 | 10 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 11 | import org.junit.After; 12 | import org.junit.Test; 13 | 14 | import io.reactivex.Flowable; 15 | import io.reactivex.schedulers.Schedulers; 16 | 17 | /** 18 | * Checks the behavior of the {@link FlatMapIterableStageFactory}. 19 | * 20 | * @author Clement Escoffier 21 | */ 22 | public class FlatMapIterableStageFactoryTest extends StageTestBase { 23 | 24 | private final FlatMapIterableStageFactory factory = new FlatMapIterableStageFactory(); 25 | 26 | private final ExecutorService executor = Executors.newSingleThreadExecutor(); 27 | 28 | @After 29 | public void cleanup() { 30 | executor.shutdown(); 31 | } 32 | 33 | @Test 34 | public void create() throws ExecutionException, InterruptedException { 35 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 36 | .subscribeOn(Schedulers.computation()); 37 | 38 | List list = ReactiveStreams.fromPublisher(flowable) 39 | .filter(i -> i < 4) 40 | .flatMapIterable(this::duplicate) 41 | .flatMapCompletionStage(this::asString) 42 | .toList() 43 | .run().toCompletableFuture().get(); 44 | 45 | assertThat(list).containsExactly("1", "1", "2", "2", "3", "3"); 46 | } 47 | 48 | private List duplicate(int i) { 49 | return Arrays.asList(i, i); 50 | } 51 | 52 | private CompletionStage asString(int i) { 53 | CompletableFuture cf = new CompletableFuture<>(); 54 | executor.submit(() -> cf.complete(Objects.toString(i))); 55 | return cf; 56 | } 57 | 58 | @Test(expected = NullPointerException.class) 59 | public void createWithoutStage() { 60 | factory.create(null, null); 61 | } 62 | 63 | @Test(expected = NullPointerException.class) 64 | public void createWithoutFunction() { 65 | factory.create(null, () -> null); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/FlatMapStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.List; 6 | import java.util.Objects; 7 | import java.util.concurrent.*; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.PublisherBuilder; 10 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 11 | import org.junit.After; 12 | import org.junit.Test; 13 | 14 | import io.reactivex.Flowable; 15 | import io.reactivex.schedulers.Schedulers; 16 | 17 | /** 18 | * Checks the behavior of the {@link FlatMapStageFactory}. 19 | * 20 | * @author Clement Escoffier 21 | */ 22 | public class FlatMapStageFactoryTest extends StageTestBase { 23 | 24 | private final FlatMapStageFactory factory = new FlatMapStageFactory(); 25 | 26 | private final ExecutorService executor = Executors.newSingleThreadExecutor(); 27 | 28 | @After 29 | public void cleanup() { 30 | executor.shutdown(); 31 | } 32 | 33 | @Test 34 | public void create() throws ExecutionException, InterruptedException { 35 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 36 | .subscribeOn(Schedulers.computation()); 37 | 38 | List list = ReactiveStreams.fromPublisher(flowable) 39 | .filter(i -> i < 4) 40 | .flatMap(this::duplicate) 41 | .flatMapCompletionStage(this::asString) 42 | .toList() 43 | .run().toCompletableFuture().get(); 44 | 45 | assertThat(list).containsExactly("1", "1", "2", "2", "3", "3"); 46 | } 47 | 48 | private PublisherBuilder duplicate(int i) { 49 | return ReactiveStreams.fromPublisher(Flowable.just(i, i).observeOn(Schedulers.computation())); 50 | } 51 | 52 | private CompletionStage asString(int i) { 53 | CompletableFuture cf = new CompletableFuture<>(); 54 | executor.submit(() -> cf.complete(Objects.toString(i))); 55 | return cf; 56 | } 57 | 58 | @Test(expected = NullPointerException.class) 59 | public void createWithoutStage() { 60 | factory.create(null, null); 61 | } 62 | 63 | @Test(expected = NullPointerException.class) 64 | public void createWithoutFunction() { 65 | factory.create(null, () -> null); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/FromIterableStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | import java.util.Optional; 8 | import java.util.concurrent.ExecutionException; 9 | 10 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 11 | import org.junit.Test; 12 | 13 | /** 14 | * Checks the behavior of the {@link FromIterableStageFactory} class. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class FromIterableStageFactoryTest extends StageTestBase { 19 | 20 | private final FromIterableStageFactory factory = new FromIterableStageFactory(); 21 | 22 | @Test 23 | public void create() throws ExecutionException, InterruptedException { 24 | List list = ReactiveStreams.of(1, 2, 3).toList().run().toCompletableFuture().get(); 25 | assertThat(list).containsExactly(1, 2, 3); 26 | 27 | Optional res = ReactiveStreams.of(25).findFirst().run().toCompletableFuture().get(); 28 | assertThat(res).contains(25); 29 | 30 | Optional empty = ReactiveStreams.fromIterable(Collections.emptyList()).findFirst().run().toCompletableFuture().get(); 31 | assertThat(empty).isEmpty(); 32 | } 33 | 34 | @Test(expected = NullPointerException.class) 35 | public void createWithoutStage() { 36 | factory.create(null, null); 37 | } 38 | 39 | @Test(expected = NullPointerException.class) 40 | public void createWithoutFunction() { 41 | factory.create(null, () -> null); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/FromPublisherStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static org.assertj.core.api.Fail.fail; 5 | 6 | import java.util.List; 7 | import java.util.Optional; 8 | import java.util.concurrent.ExecutionException; 9 | 10 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 11 | import org.junit.Test; 12 | 13 | import io.reactivex.Flowable; 14 | 15 | /** 16 | * Checks the behavior of the {@link FromPublisherStageFactory} class. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class FromPublisherStageFactoryTest extends StageTestBase { 21 | 22 | private final FromPublisherStageFactory factory = new FromPublisherStageFactory(); 23 | 24 | @Test 25 | public void create() throws ExecutionException, InterruptedException { 26 | List list = ReactiveStreams.fromPublisher(Flowable.fromArray(1, 2, 3)).toList().run().toCompletableFuture() 27 | .get(); 28 | assertThat(list).containsExactly(1, 2, 3); 29 | 30 | Optional res = ReactiveStreams.fromPublisher(Flowable.just(25)).findFirst().run().toCompletableFuture().get(); 31 | assertThat(res).contains(25); 32 | 33 | Optional empty = ReactiveStreams.fromPublisher(Flowable.empty()).findFirst().run().toCompletableFuture().get(); 34 | assertThat(empty).isEmpty(); 35 | 36 | try { 37 | ReactiveStreams.fromPublisher(Flowable.error(new Exception("Boom"))).findFirst().run() 38 | .toCompletableFuture().get(); 39 | fail("Exception should be thrown"); 40 | } catch (Exception e) { 41 | assertThat(e).hasMessageContaining("Boom"); 42 | } 43 | } 44 | 45 | @Test(expected = NullPointerException.class) 46 | public void createWithoutStage() { 47 | factory.create(null, null); 48 | } 49 | 50 | @Test(expected = NullPointerException.class) 51 | public void createWithoutFunction() { 52 | factory.create(null, () -> null); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/LimitStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.List; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | /** 15 | * Checks the behavior of the {@link LimitStageFactory} class. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class LimitStageFactoryTest extends StageTestBase { 20 | 21 | private final LimitStageFactory factory = new LimitStageFactory(); 22 | 23 | @Test 24 | public void create() throws ExecutionException, InterruptedException { 25 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 26 | .subscribeOn(Schedulers.computation()); 27 | List list = ReactiveStreams.fromPublisher(flowable).limit(5).toList().run() 28 | .toCompletableFuture().get(); 29 | assertThat(list).hasSize(5).containsExactly(1, 2, 3, 4, 5); 30 | } 31 | 32 | @Test(expected = NullPointerException.class) 33 | public void createWithoutStage() { 34 | factory.create(null, null); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/MapStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.List; 6 | import java.util.Objects; 7 | import java.util.concurrent.ExecutionException; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link MapStageFactory}. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class MapStageFactoryTest extends StageTestBase { 21 | 22 | private final MapStageFactory factory = new MapStageFactory(); 23 | 24 | @Test 25 | public void create() throws ExecutionException, InterruptedException { 26 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 27 | .subscribeOn(Schedulers.computation()); 28 | 29 | List list = ReactiveStreams.fromPublisher(flowable) 30 | .filter(i -> i < 4) 31 | .map(this::square) 32 | .map(this::asString) 33 | .toList() 34 | .run().toCompletableFuture().get(); 35 | 36 | assertThat(list).containsExactly("1", "4", "9"); 37 | } 38 | 39 | private Integer square(int i) { 40 | return i * i; 41 | } 42 | 43 | private String asString(int i) { 44 | return Objects.toString(i); 45 | } 46 | 47 | @Test(expected = NullPointerException.class) 48 | public void createWithoutStage() { 49 | factory.create(null, null); 50 | } 51 | 52 | @Test(expected = NullPointerException.class) 53 | public void createWithoutFunction() { 54 | factory.create(null, () -> null); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/OnCompleteStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Objects; 6 | import java.util.concurrent.ExecutionException; 7 | import java.util.concurrent.atomic.AtomicBoolean; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link OnCompleteStageFactory}. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class OnCompleteStageFactoryTest extends StageTestBase { 21 | 22 | private final OnCompleteStageFactory factory = new OnCompleteStageFactory(); 23 | 24 | @Test 25 | public void create() throws ExecutionException, InterruptedException { 26 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 27 | .subscribeOn(Schedulers.computation()); 28 | 29 | AtomicBoolean completed = new AtomicBoolean(); 30 | ReactiveStreams.fromPublisher(flowable) 31 | .filter(i -> i < 4) 32 | .map(this::square) 33 | .onComplete(() -> completed.set(true)) 34 | .map(this::asString) 35 | .toList() 36 | .run().toCompletableFuture().get(); 37 | assertThat(completed).isTrue(); 38 | } 39 | 40 | private Integer square(int i) { 41 | return i * i; 42 | } 43 | 44 | private String asString(int i) { 45 | return Objects.toString(i); 46 | } 47 | 48 | @Test(expected = NullPointerException.class) 49 | public void createWithoutStage() { 50 | factory.create(null, null); 51 | } 52 | 53 | @Test(expected = NullPointerException.class) 54 | public void createWithoutFunction() { 55 | factory.create(null, () -> null); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/OnErrorResumeWithStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | import java.util.concurrent.ExecutionException; 8 | import java.util.concurrent.atomic.AtomicReference; 9 | 10 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 11 | import org.junit.Test; 12 | 13 | import io.reactivex.Flowable; 14 | import io.reactivex.schedulers.Schedulers; 15 | 16 | /** 17 | * Checks the behavior of the {@link OnErrorResumeStageFactory}. 18 | * 19 | * @author Clement Escoffier 20 | */ 21 | public class OnErrorResumeWithStageFactoryTest extends StageTestBase { 22 | 23 | private final OnErrorResumeStageFactory factory = new OnErrorResumeStageFactory(); 24 | 25 | @Test 26 | public void create() throws ExecutionException, InterruptedException { 27 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 28 | .subscribeOn(Schedulers.computation()); 29 | 30 | List list = ReactiveStreams. failed(new Exception("BOOM")) 31 | .onErrorResumeWith(t -> ReactiveStreams.fromPublisher(flowable)) 32 | .toList() 33 | .run().toCompletableFuture().exceptionally(x -> Collections.emptyList()).get(); 34 | 35 | assertThat(list).hasSize(10); 36 | } 37 | 38 | @Test 39 | public void createAndFailAgain() throws ExecutionException, InterruptedException { 40 | AtomicReference error = new AtomicReference<>(); 41 | List list = ReactiveStreams. failed(new RuntimeException("BOOM")) 42 | .onErrorResumeWith(t -> ReactiveStreams.failed(new RuntimeException("Failed"))) 43 | .toList() 44 | .run().toCompletableFuture().exceptionally(x -> { 45 | error.set(x); 46 | return Collections.emptyList(); 47 | }).get(); 48 | 49 | assertThat(list).hasSize(0); 50 | assertThat(error.get()).hasMessage("Failed"); 51 | } 52 | 53 | @Test(expected = NullPointerException.class) 54 | public void createWithoutStage() { 55 | factory.create(null, null); 56 | } 57 | 58 | @Test(expected = NullPointerException.class) 59 | public void createWithoutFunction() { 60 | factory.create(null, () -> null); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/OnErrorStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Collections; 6 | import java.util.Objects; 7 | import java.util.concurrent.ExecutionException; 8 | import java.util.concurrent.atomic.AtomicReference; 9 | 10 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 11 | import org.junit.Test; 12 | 13 | import io.reactivex.Flowable; 14 | import io.reactivex.schedulers.Schedulers; 15 | 16 | /** 17 | * Checks the behavior of the {@link OnErrorStageFactory}. 18 | * 19 | * @author Clement Escoffier 20 | */ 21 | public class OnErrorStageFactoryTest extends StageTestBase { 22 | 23 | private final OnErrorStageFactory factory = new OnErrorStageFactory(); 24 | 25 | @Test 26 | public void create() throws ExecutionException, InterruptedException { 27 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 28 | .subscribeOn(Schedulers.computation()); 29 | 30 | AtomicReference error = new AtomicReference<>(); 31 | ReactiveStreams.fromPublisher(flowable) 32 | .filter(i -> i < 4) 33 | .map(this::squareOrFailed) 34 | .onError(error::set) 35 | .map(this::asString) 36 | .toList() 37 | .run().toCompletableFuture().exceptionally(x -> Collections.emptyList()).get(); 38 | assertThat(error.get()).hasMessage("failed"); 39 | } 40 | 41 | private Integer squareOrFailed(int i) { 42 | if (i == 2) { 43 | throw new RuntimeException("failed"); 44 | } 45 | return i * i; 46 | } 47 | 48 | private String asString(int i) { 49 | return Objects.toString(i); 50 | } 51 | 52 | @Test(expected = NullPointerException.class) 53 | public void createWithoutStage() { 54 | factory.create(null, null); 55 | } 56 | 57 | @Test(expected = NullPointerException.class) 58 | public void createWithoutFunction() { 59 | factory.create(null, () -> null); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/OnTerminateStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Collections; 6 | import java.util.Objects; 7 | import java.util.concurrent.ExecutionException; 8 | import java.util.concurrent.atomic.AtomicBoolean; 9 | 10 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 11 | import org.junit.Test; 12 | 13 | import io.reactivex.Flowable; 14 | import io.reactivex.schedulers.Schedulers; 15 | 16 | /** 17 | * Checks the behavior of the {@link OnTerminateStageFactory}. 18 | * 19 | * @author Clement Escoffier 20 | */ 21 | public class OnTerminateStageFactoryTest extends StageTestBase { 22 | 23 | private final OnTerminateStageFactory factory = new OnTerminateStageFactory(); 24 | 25 | @Test 26 | public void createWithFailure() throws ExecutionException, InterruptedException { 27 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 28 | .subscribeOn(Schedulers.computation()); 29 | 30 | AtomicBoolean error = new AtomicBoolean(); 31 | ReactiveStreams.fromPublisher(flowable) 32 | .filter(i -> i < 4) 33 | .map(this::squareOrFailed) 34 | .onTerminate(() -> error.set(true)) 35 | .map(this::asString) 36 | .toList() 37 | .run().toCompletableFuture().exceptionally(x -> Collections.emptyList()).get(); 38 | assertThat(error).isTrue(); 39 | } 40 | 41 | @Test 42 | public void create() throws ExecutionException, InterruptedException { 43 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 44 | .subscribeOn(Schedulers.computation()); 45 | 46 | AtomicBoolean completed = new AtomicBoolean(); 47 | ReactiveStreams.fromPublisher(flowable) 48 | .filter(i -> i < 4) 49 | .map(this::square) 50 | .onTerminate(() -> completed.set(true)) 51 | .map(this::asString) 52 | .toList() 53 | .run().toCompletableFuture().get(); 54 | assertThat(completed).isTrue(); 55 | } 56 | 57 | private Integer squareOrFailed(int i) { 58 | if (i == 2) { 59 | throw new RuntimeException("failed"); 60 | } 61 | return i * i; 62 | } 63 | 64 | private Integer square(int i) { 65 | return i * i; 66 | } 67 | 68 | private String asString(int i) { 69 | return Objects.toString(i); 70 | } 71 | 72 | @Test(expected = NullPointerException.class) 73 | public void createWithoutStage() { 74 | factory.create(null, null); 75 | } 76 | 77 | @Test(expected = NullPointerException.class) 78 | public void createWithoutFunction() { 79 | factory.create(null, () -> null); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/PeekStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Objects; 8 | import java.util.concurrent.ExecutionException; 9 | 10 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 11 | import org.junit.Test; 12 | 13 | import io.reactivex.Flowable; 14 | import io.reactivex.schedulers.Schedulers; 15 | 16 | /** 17 | * Checks the behavior of the {@link PeekStageFactory}. 18 | * 19 | * @author Clement Escoffier 20 | */ 21 | public class PeekStageFactoryTest extends StageTestBase { 22 | 23 | private final PeekStageFactory factory = new PeekStageFactory(); 24 | 25 | @Test 26 | public void create() throws ExecutionException, InterruptedException { 27 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 28 | .subscribeOn(Schedulers.computation()); 29 | 30 | List squares = new ArrayList<>(); 31 | List strings = new ArrayList<>(); 32 | List list = ReactiveStreams.fromPublisher(flowable) 33 | .filter(i -> i < 4) 34 | .map(this::square) 35 | .peek(squares::add) 36 | .map(this::asString) 37 | .peek(strings::add) 38 | .toList() 39 | .run().toCompletableFuture().get(); 40 | 41 | assertThat(list).containsExactly("1", "4", "9"); 42 | assertThat(squares).containsExactly(1, 4, 9); 43 | assertThat(strings).containsExactly("1", "4", "9"); 44 | } 45 | 46 | private Integer square(int i) { 47 | return i * i; 48 | } 49 | 50 | private String asString(int i) { 51 | return Objects.toString(i); 52 | } 53 | 54 | @Test(expected = NullPointerException.class) 55 | public void createWithoutStage() { 56 | factory.create(null, null); 57 | } 58 | 59 | @Test(expected = NullPointerException.class) 60 | public void createWithoutFunction() { 61 | factory.create(null, () -> null); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/SkipStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.List; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | /** 15 | * Checks the behavior of the {@link SkipStageFactory} class. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class SkipStageFactoryTest extends StageTestBase { 20 | 21 | private final SkipStageFactory factory = new SkipStageFactory(); 22 | 23 | @Test 24 | public void create() throws ExecutionException, InterruptedException { 25 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 26 | .subscribeOn(Schedulers.computation()); 27 | List list = ReactiveStreams.fromPublisher(flowable).skip(5).toList().run() 28 | .toCompletableFuture().get(); 29 | assertThat(list).hasSize(5).containsExactly(6, 7, 8, 9, 10); 30 | } 31 | 32 | @Test(expected = NullPointerException.class) 33 | public void createWithoutStage() { 34 | factory.create(null, null); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/StageTestBase.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | import java.util.stream.IntStream; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.PublisherBuilder; 7 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 8 | 9 | /** 10 | * Creates and disposes the engine. 11 | * 12 | * @author Clement Escoffier 13 | */ 14 | public class StageTestBase { 15 | 16 | PublisherBuilder infiniteStream() { 17 | return ReactiveStreams.fromIterable(() -> { 18 | AtomicInteger value = new AtomicInteger(); 19 | return IntStream.generate(value::incrementAndGet).boxed().iterator(); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/SubscriberStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Optional; 6 | 7 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 8 | import org.eclipse.microprofile.reactive.streams.operators.SubscriberBuilder; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.schedulers.Schedulers; 13 | import io.smallrye.reactive.streams.Engine; 14 | 15 | /** 16 | * Checks the behavior of the {@link SubscriberStageFactory}. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class SubscriberStageFactoryTest extends StageTestBase { 21 | 22 | private final SubscriberStageFactory factory = new SubscriberStageFactory(); 23 | 24 | @Test 25 | public void create() { 26 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 27 | .subscribeOn(Schedulers.computation()); 28 | 29 | SubscriberBuilder> builder = ReactiveStreams. builder().findFirst(); 30 | 31 | Optional optional = ReactiveStreams.fromPublisher(flowable).filter(i -> i > 5) 32 | .to(builder).run().toCompletableFuture().join(); 33 | 34 | assertThat(optional).contains(6); 35 | } 36 | 37 | @Test(expected = NullPointerException.class) 38 | public void createWithoutStage() { 39 | factory.create(new Engine(), null); 40 | } 41 | 42 | @Test(expected = NullPointerException.class) 43 | public void createWithoutSubscriber() { 44 | factory.create(new Engine(), () -> null); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/stages/TakeWhileStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.List; 6 | import java.util.concurrent.ExecutionException; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | /** 15 | * Checks the behavior of the {@link TakeWhileStageFactory} class. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class TakeWhileStageFactoryTest extends StageTestBase { 20 | 21 | private final TakeWhileStageFactory factory = new TakeWhileStageFactory(); 22 | 23 | @Test 24 | public void create() throws ExecutionException, InterruptedException { 25 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 26 | .subscribeOn(Schedulers.computation()); 27 | List list = ReactiveStreams.fromPublisher(flowable).takeWhile(i -> i < 6).toList().run() 28 | .toCompletableFuture().get(); 29 | assertThat(list).hasSize(5).containsExactly(1, 2, 3, 4, 5); 30 | } 31 | 32 | @Test(expected = NullPointerException.class) 33 | public void createWithoutStage() { 34 | factory.create(null, null); 35 | } 36 | 37 | @Test(expected = NullPointerException.class) 38 | public void createWithoutPredicate() { 39 | factory.create(null, () -> null); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/utils/WrappedSubscriberTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | import java.util.concurrent.atomic.AtomicReference; 7 | 8 | import org.junit.Test; 9 | import org.reactivestreams.Subscriber; 10 | import org.reactivestreams.Subscription; 11 | 12 | public class WrappedSubscriberTest { 13 | 14 | @Test 15 | public void checkThatOnSubscribeCanOnlyBeCallOnce() { 16 | AtomicReference subscriptionReference = new AtomicReference<>(); 17 | WrappedSubscriber subscriber = new WrappedSubscriber<>(new Subscriber() { 18 | @Override 19 | public void onSubscribe(Subscription s) { 20 | subscriptionReference.set(s); 21 | } 22 | 23 | @Override 24 | public void onNext(Integer integer) { 25 | 26 | } 27 | 28 | @Override 29 | public void onError(Throwable t) { 30 | 31 | } 32 | 33 | @Override 34 | public void onComplete() { 35 | 36 | } 37 | }); 38 | 39 | AtomicBoolean cancellationReference1 = new AtomicBoolean(); 40 | subscriber.onSubscribe(new Subscription() { 41 | @Override 42 | public void request(long n) { 43 | 44 | } 45 | 46 | @Override 47 | public void cancel() { 48 | cancellationReference1.set(true); 49 | } 50 | }); 51 | 52 | assertThat(cancellationReference1.get()).isFalse(); 53 | assertThat(subscriptionReference.get()).isNotNull(); 54 | 55 | AtomicBoolean cancellationReference2 = new AtomicBoolean(); 56 | subscriber.onSubscribe(new Subscription() { 57 | @Override 58 | public void request(long n) { 59 | 60 | } 61 | 62 | @Override 63 | public void cancel() { 64 | cancellationReference2.set(true); 65 | } 66 | }); 67 | 68 | assertThat(cancellationReference1.get()).isFalse(); 69 | assertThat(cancellationReference2.get()).isTrue(); 70 | assertThat(subscriptionReference.get()).isNotNull(); 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /implementation/src/test/java/io/smallrye/reactive/streams/utils/WrappedSubscriptionTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.utils; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.concurrent.atomic.AtomicBoolean; 6 | 7 | import org.junit.Test; 8 | import org.reactivestreams.Subscription; 9 | 10 | public class WrappedSubscriptionTest { 11 | 12 | @Test 13 | public void testWrappedSubscription() { 14 | Subscription subscription = new Subscription() { 15 | @Override 16 | public void request(long n) { 17 | 18 | } 19 | 20 | @Override 21 | public void cancel() { 22 | 23 | } 24 | }; 25 | 26 | WrappedSubscription wrapped = new WrappedSubscription(subscription, null); 27 | assertThat(wrapped).isNotNull(); 28 | wrapped.request(10); 29 | wrapped.cancel(); 30 | } 31 | 32 | @Test 33 | public void testWrappedSubscriptionWithCompletionCallback() { 34 | Subscription subscription = new Subscription() { 35 | @Override 36 | public void request(long n) { 37 | 38 | } 39 | 40 | @Override 41 | public void cancel() { 42 | 43 | } 44 | }; 45 | AtomicBoolean called = new AtomicBoolean(); 46 | WrappedSubscription wrapped = new WrappedSubscription(subscription, () -> called.set(true)); 47 | assertThat(wrapped).isNotNull(); 48 | wrapped.request(10); 49 | wrapped.cancel(); 50 | assertThat(called).isTrue(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /implementation/src/test/java/tck/ReactiveStreamsEngineImplTck.java: -------------------------------------------------------------------------------- 1 | package tck; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.tck.ReactiveStreamsTck; 4 | import org.reactivestreams.tck.TestEnvironment; 5 | 6 | import io.smallrye.reactive.streams.Engine; 7 | 8 | /** 9 | * Executes the TCK again the implementation. 10 | */ 11 | public class ReactiveStreamsEngineImplTck extends ReactiveStreamsTck { 12 | 13 | public ReactiveStreamsEngineImplTck() { 14 | super(new TestEnvironment(200)); 15 | } 16 | 17 | @Override 18 | protected Engine createEngine() { 19 | return new Engine(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /release/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.reactive 7 | smallrye-reactive-streams-operators-project 8 | 1.0.14-SNAPSHOT 9 | 10 | 11 | smallrye-reactive-streams-operators-release 12 | 13 | Empty Release Project to Avoid Maven Bug 14 | Empty Release Project to Avoid Maven Bug 15 | 16 | pom 17 | 18 | -------------------------------------------------------------------------------- /tck/src/test/java/io/smallrye/reactive/streams/tck/ApplicationEnhancer.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.tck; 2 | 3 | import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor; 4 | import org.jboss.arquillian.core.spi.LoadableExtension; 5 | 6 | /** 7 | * Arquillian extension to add the CDI provider into the application. 8 | */ 9 | public class ApplicationEnhancer implements LoadableExtension { 10 | @Override 11 | public void register(LoadableExtension.ExtensionBuilder extensionBuilder) { 12 | extensionBuilder 13 | .service(ApplicationArchiveProcessor.class, ProducerInjectionProcessor.class); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tck/src/test/java/io/smallrye/reactive/streams/tck/InContainerIT.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.tck; 2 | 3 | import org.eclipse.microprofile.reactive.streams.operators.tck.arquillian.ReactiveStreamsArquillianTck; 4 | 5 | public class InContainerIT extends ReactiveStreamsArquillianTck { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /tck/src/test/java/io/smallrye/reactive/streams/tck/ProducerInjectionProcessor.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.tck; 2 | 3 | import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor; 4 | import org.jboss.arquillian.test.spi.TestClass; 5 | import org.jboss.shrinkwrap.api.Archive; 6 | import org.jboss.shrinkwrap.api.spec.JavaArchive; 7 | 8 | import io.smallrye.reactive.streams.cdi.ReactiveEngineProvider; 9 | 10 | /** 11 | * Just adding the {@link ReactiveEngineProvider} into the application deployment. 12 | */ 13 | public class ProducerInjectionProcessor implements ApplicationArchiveProcessor { 14 | @Override 15 | public void process(Archive applicationArchive, TestClass testClass) { 16 | applicationArchive.as(JavaArchive.class) 17 | .addClass(ReactiveEngineProvider.class); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tck/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension: -------------------------------------------------------------------------------- 1 | io.smallrye.reactive.streams.tck.ApplicationEnhancer -------------------------------------------------------------------------------- /tck/src/test/resources/log4j2-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /vertx-execution-model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | 6 | io.smallrye.reactive 7 | smallrye-reactive-streams-operators-project 8 | 1.0.14-SNAPSHOT 9 | 10 | 11 | smallrye-reactive-streams-vertx-execution-model 12 | 13 | 14 | 15 | 16 | io.vertx 17 | vertx-stack-depchain 18 | ${vertx.version} 19 | pom 20 | import 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ${project.groupId} 29 | smallrye-reactive-streams-operators 30 | ${project.version} 31 | compile 32 | 33 | 34 | 35 | io.vertx 36 | vertx-rx-java2 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-surefire-plugin 45 | 46 | 47 | default-test 48 | 49 | test 50 | 51 | 52 | none:none 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | coverage 63 | 64 | @{jacocoArgLine} 65 | 66 | 67 | 68 | 69 | 70 | org.jacoco 71 | jacoco-maven-plugin 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /vertx-execution-model/src/main/java/io/smallrye/reactive/streams/vertx/VertxExecutionModel.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.vertx; 2 | 3 | import io.reactivex.Flowable; 4 | import io.smallrye.reactive.streams.spi.ExecutionModel; 5 | import io.vertx.reactivex.core.Context; 6 | import io.vertx.reactivex.core.RxHelper; 7 | import io.vertx.reactivex.core.Vertx; 8 | 9 | /** 10 | * An implementation of {@link ExecutionModel} enforcing the Vert.x execution model. 11 | */ 12 | public class VertxExecutionModel implements ExecutionModel { 13 | 14 | @Override 15 | public Flowable apply(Flowable input) { 16 | Context context = Vertx.currentContext(); 17 | if (context != null && context.getDelegate() != null) { 18 | return input.compose(f -> f.observeOn(RxHelper.scheduler(context))); 19 | } 20 | return input; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /vertx-execution-model/src/main/resources/META-INF/services/io.smallrye.reactive.streams.spi.ExecutionModel: -------------------------------------------------------------------------------- 1 | io.smallrye.reactive.streams.vertx.VertxExecutionModel -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/CollectStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.concurrent.Callable; 4 | import java.util.concurrent.CompletionStage; 5 | import java.util.stream.Collectors; 6 | 7 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 8 | import org.junit.Test; 9 | 10 | import io.reactivex.Flowable; 11 | import io.reactivex.schedulers.Schedulers; 12 | 13 | /** 14 | * Checks the behavior of the {@link CollectStageFactory} when running from a Vert.x context 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class CollectStageFactoryTest extends StageTestBase { 19 | 20 | @Test 21 | public void createFromVertxContext() { 22 | Callable> callable = () -> { 23 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 24 | .subscribeOn(Schedulers.computation()) 25 | .map(i -> i + 1); 26 | 27 | return ReactiveStreams.fromPublisher(flowable) 28 | .collect(Collectors.summingInt(value -> value)).run(); 29 | }; 30 | 31 | executeOnEventLoop(callable).assertSuccess(2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11); 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/ConcatStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Arrays; 6 | import java.util.LinkedHashSet; 7 | import java.util.List; 8 | import java.util.concurrent.Callable; 9 | import java.util.concurrent.CompletionStage; 10 | 11 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 12 | import org.junit.Test; 13 | 14 | import io.reactivex.Flowable; 15 | import io.reactivex.schedulers.Schedulers; 16 | 17 | /** 18 | * Checks the behavior of the {@link ConcatStageFactory} class, especially the thread handling when running from a Vert.x 19 | * context. 20 | * 21 | * @author Clement Escoffier 22 | */ 23 | public class ConcatStageFactoryTest extends StageTestBase { 24 | 25 | @Test 26 | public void testConcatenationWhenAllEmissionsAreMadeFromDifferentThreadsButCreationIsOnVertxContext() { 27 | Flowable firstStream = Flowable.fromArray(1, 2, 3).observeOn(Schedulers.io()); 28 | Flowable secondStream = Flowable.fromArray(4, 5, 6).observeOn(Schedulers.computation()); 29 | 30 | LinkedHashSet threads = new LinkedHashSet<>(); 31 | Callable>> callable = () -> ReactiveStreams 32 | .concat(ReactiveStreams.fromPublisher(firstStream), ReactiveStreams.fromPublisher(secondStream)) 33 | .peek(i -> threads.add(Thread.currentThread().getName())) 34 | .toList().run(); 35 | 36 | executeOnEventLoop(callable).assertSuccess(Arrays.asList(1, 2, 3, 4, 5, 6)); 37 | assertThat(threads).hasSize(1).contains(getCapturedThreadName()); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/DistinctStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Objects; 6 | import java.util.concurrent.Callable; 7 | import java.util.concurrent.CompletionStage; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link DistinctStageFactory} when running from the Vert.x context. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class DistinctStageFactoryTest extends StageTestBase { 21 | 22 | @Test 23 | public void createOnVertxContext() { 24 | Flowable flowable = Flowable.fromArray(1, 2, 1, 4, 3, 2, 5, 3, 6, 6, 4, 8, 7, 4, 5, 6, 7, 8, 9, 9, 10) 25 | .subscribeOn(Schedulers.computation()); 26 | 27 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable) 28 | .filter(i -> i < 4) 29 | .distinct() 30 | .map(this::asString) 31 | .toList() 32 | .run(); 33 | 34 | executeOnEventLoop(callable).assertSuccess(Arrays.asList("1", "2", "3")); 35 | } 36 | 37 | private String asString(int i) { 38 | return Objects.toString(i); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/DropWhileStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.CompletionStage; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | /** 15 | * Checks the behavior of the {@link DropWhileStageFactory} class when running from the Vert.x context. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class DropWhileStageFactoryTest extends StageTestBase { 20 | 21 | @Test 22 | public void createFromVertxContext() { 23 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 24 | .subscribeOn(Schedulers.computation()); 25 | 26 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable).dropWhile(i -> i < 6) 27 | .toList().run(); 28 | 29 | executeOnEventLoop(callable).assertSuccess(Arrays.asList(6, 7, 8, 9, 10)); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/FailedPublisherStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Optional; 4 | import java.util.concurrent.Callable; 5 | import java.util.concurrent.CompletionStage; 6 | 7 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 8 | import org.junit.Test; 9 | 10 | import io.reactivex.Flowable; 11 | import io.reactivex.schedulers.Schedulers; 12 | 13 | /** 14 | * Checks the behavior of {@link FailedPublisherStageFactory} when running on the Vert.x Context. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class FailedPublisherStageFactoryTest extends StageTestBase { 19 | 20 | @Test 21 | public void createWithErrorFromVertxContext() { 22 | Exception failure = new Exception("Boom"); 23 | Callable>> callable = () -> ReactiveStreams.fromPublisher(Flowable.just(1) 24 | .observeOn(Schedulers.newThread())) 25 | . flatMap(x -> ReactiveStreams.failed(failure)) 26 | .to(ReactiveStreams. builder().findFirst()).run(); 27 | 28 | executeOnEventLoop(callable).assertFailure("Boom"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/FilterStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.CompletionStage; 7 | import java.util.function.Predicate; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link FilterStageFactory} class when running from the Vert.x Context. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class FilterStageFactoryTest extends StageTestBase { 21 | 22 | @Test 23 | public void createFromVertxContext() { 24 | Predicate even = i -> i % 2 == 0; 25 | 26 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 27 | .subscribeOn(Schedulers.computation()); 28 | 29 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable).filter(even).toList() 30 | .run(); 31 | 32 | executeOnEventLoop(callable).assertSuccess(Arrays.asList(2, 4, 6, 8, 10)); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/FindFirstStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Optional; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 6 | import org.junit.Test; 7 | 8 | import io.reactivex.Flowable; 9 | import io.reactivex.schedulers.Schedulers; 10 | 11 | /** 12 | * Checks the behavior of the {@link FindFirstStageFactory} when running from the Vert.x Context. 13 | * 14 | * @author Clement Escoffier 15 | */ 16 | public class FindFirstStageFactoryTest extends StageTestBase { 17 | 18 | @Test 19 | public void createFromContext() { 20 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 21 | .subscribeOn(Schedulers.computation()); 22 | executeOnEventLoop(() -> ReactiveStreams.fromPublisher(flowable).filter(i -> i > 5) 23 | .findFirst().run()).assertSuccess(Optional.of(6)); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/FlatMapIterableStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Objects; 6 | import java.util.concurrent.CompletableFuture; 7 | import java.util.concurrent.CompletionStage; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link FlatMapIterableStageFactory} when running from the Vert.x Context. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class FlatMapIterableStageFactoryTest extends StageTestBase { 21 | 22 | @Test 23 | public void createFromVertxContext() { 24 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 25 | .subscribeOn(Schedulers.computation()); 26 | 27 | executeOnEventLoop(() -> ReactiveStreams.fromPublisher(flowable) 28 | .filter(i -> i < 4) 29 | .flatMapIterable(this::duplicate) 30 | .flatMapCompletionStage(this::asString) 31 | .toList() 32 | .run()).assertSuccess(Arrays.asList("1", "1", "2", "2", "3", "3")); 33 | } 34 | 35 | private List duplicate(int i) { 36 | return Arrays.asList(i, i); 37 | } 38 | 39 | private CompletionStage asString(int i) { 40 | CompletableFuture cf = new CompletableFuture<>(); 41 | vertx.runOnContext(v -> cf.complete(Objects.toString(i))); 42 | return cf; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/FlatMapStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.Objects; 5 | import java.util.concurrent.CompletableFuture; 6 | import java.util.concurrent.CompletionStage; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.PublisherBuilder; 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link FlatMapStageFactory} when running from the Vert.x Context. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class FlatMapStageFactoryTest extends StageTestBase { 21 | 22 | @Test 23 | public void createFromVertxContext() { 24 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 25 | .subscribeOn(Schedulers.computation()); 26 | 27 | executeOnEventLoop(() -> ReactiveStreams.fromPublisher(flowable) 28 | .filter(i -> i < 4) 29 | .flatMap(this::duplicate) 30 | .flatMapCompletionStage(this::asString) 31 | .toList() 32 | .run()).assertSuccess(Arrays.asList("1", "1", "2", "2", "3", "3")); 33 | } 34 | 35 | private PublisherBuilder duplicate(int i) { 36 | return ReactiveStreams.fromPublisher(Flowable.just(i, i).observeOn(Schedulers.computation())); 37 | } 38 | 39 | private CompletionStage asString(int i) { 40 | CompletableFuture cf = new CompletableFuture<>(); 41 | vertx.runOnContext(v -> cf.complete(Objects.toString(i))); 42 | return cf; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/FromCompletionStageFactoryNullableTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Optional; 4 | import java.util.concurrent.CompletableFuture; 5 | import java.util.concurrent.CompletionStage; 6 | 7 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 8 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 9 | import org.junit.Test; 10 | 11 | /** 12 | * Checks the behavior of the {@link Stage.FromCompletionStageNullable} class when running from the Vert.x Context. 13 | * 14 | * @author Clement Escoffier 15 | */ 16 | public class FromCompletionStageFactoryNullableTest extends StageTestBase { 17 | 18 | @Test 19 | public void createFromAlreadyCompletedFutureFromVertxContext() { 20 | executeOnEventLoop(() -> { 21 | CompletionStage cs = CompletableFuture.completedFuture("hello"); 22 | return ReactiveStreams.fromCompletionStageNullable(cs).findFirst().run().toCompletableFuture(); 23 | }).assertSuccess(Optional.of("hello")); 24 | } 25 | 26 | @Test 27 | public void createFromAlreadyFailedFutureFromVertxContext() { 28 | executeOnEventLoop(() -> { 29 | CompletionStage cs = new CompletableFuture<>(); 30 | ((CompletableFuture) cs).completeExceptionally(new Exception("Expected")); 31 | return ReactiveStreams.fromCompletionStageNullable(cs).findFirst().run(); 32 | }).assertFailure("Expected"); 33 | } 34 | 35 | @Test 36 | public void createFromFutureGoingToBeCompletedFromVertxContext() { 37 | CompletableFuture cf = new CompletableFuture<>(); 38 | 39 | executeOnEventLoop(() -> { 40 | CompletionStage> stage = ReactiveStreams.fromCompletionStageNullable(cf).findFirst().run(); 41 | vertx.setTimer(10, x -> cf.complete("Hello")); 42 | return stage; 43 | }).assertSuccess(Optional.of("Hello")); 44 | } 45 | 46 | @Test 47 | public void createFromFutureGoingToBeFailedFromVertxContext() { 48 | CompletableFuture cf = new CompletableFuture<>(); 49 | 50 | executeOnEventLoop(() -> { 51 | CompletionStage> stage = ReactiveStreams.fromCompletionStageNullable(cf).findFirst().run(); 52 | vertx.setTimer(10, x -> cf.completeExceptionally(new Exception("Expected"))); 53 | return stage; 54 | }).assertFailure("Expected"); 55 | } 56 | 57 | @Test 58 | public void createFromFutureGoingToBeCompletedWithNullFromVertxContext() { 59 | CompletableFuture cf = new CompletableFuture<>(); 60 | 61 | executeOnEventLoop(() -> { 62 | CompletionStage> stage = ReactiveStreams.fromCompletionStageNullable(cf).findFirst().run(); 63 | vertx.setTimer(10, x -> cf.complete(null)); 64 | return stage; 65 | }).assertSuccess(Optional.empty()); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/FromCompletionStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Optional; 4 | import java.util.concurrent.CompletableFuture; 5 | import java.util.concurrent.CompletionStage; 6 | 7 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 8 | import org.eclipse.microprofile.reactive.streams.operators.spi.Stage; 9 | import org.junit.Test; 10 | 11 | /** 12 | * Checks the behavior of the {@link Stage.FromCompletionStage} class when running from the Vert.x Context. 13 | * 14 | * @author Clement Escoffier 15 | */ 16 | public class FromCompletionStageFactoryTest extends StageTestBase { 17 | 18 | @Test 19 | public void createFromAlreadyCompletedFutureFromVertxContext() { 20 | executeOnEventLoop(() -> { 21 | CompletionStage cs = CompletableFuture.completedFuture("hello"); 22 | return ReactiveStreams.fromCompletionStage(cs).findFirst().run().toCompletableFuture(); 23 | }).assertSuccess(Optional.of("hello")); 24 | } 25 | 26 | @Test 27 | public void createFromAlreadyFailedFutureFromVertxContext() { 28 | executeOnEventLoop(() -> { 29 | CompletionStage cs = new CompletableFuture<>(); 30 | ((CompletableFuture) cs).completeExceptionally(new Exception("Expected")); 31 | return ReactiveStreams.fromCompletionStage(cs).findFirst().run(); 32 | }).assertFailure("Expected"); 33 | } 34 | 35 | @Test 36 | public void createFromFutureGoingToBeCompletedFromVertxContext() { 37 | CompletableFuture cf = new CompletableFuture<>(); 38 | 39 | executeOnEventLoop(() -> { 40 | CompletionStage> stage = ReactiveStreams.fromCompletionStage(cf).findFirst().run(); 41 | vertx.setTimer(10, x -> cf.complete("Hello")); 42 | return stage; 43 | }).assertSuccess(Optional.of("Hello")); 44 | } 45 | 46 | @Test 47 | public void createFromFutureGoingToBeFailedFromVertxContext() { 48 | CompletableFuture cf = new CompletableFuture<>(); 49 | 50 | executeOnEventLoop(() -> { 51 | CompletionStage> stage = ReactiveStreams.fromCompletionStage(cf).findFirst().run(); 52 | vertx.setTimer(10, x -> cf.completeExceptionally(new Exception("Expected"))); 53 | return stage; 54 | }).assertFailure("Expected"); 55 | } 56 | 57 | @Test 58 | public void createFromFutureGoingToBeCompletedWithNullFromVertxContext() { 59 | CompletableFuture cf = new CompletableFuture<>(); 60 | 61 | executeOnEventLoop(() -> { 62 | CompletionStage> stage = ReactiveStreams.fromCompletionStage(cf).findFirst().run(); 63 | vertx.setTimer(10, x -> cf.complete(null)); 64 | return stage; 65 | }).assertFailure("Redeemed value is `null`"); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/FromIterableStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Optional; 9 | import java.util.concurrent.ExecutionException; 10 | 11 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 12 | import org.junit.Test; 13 | 14 | /** 15 | * Checks the behavior of the {@link FromIterableStageFactory} class. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class FromIterableStageFactoryTest extends StageTestBase { 20 | 21 | private final FromIterableStageFactory factory = new FromIterableStageFactory(); 22 | 23 | @Test 24 | public void create() throws ExecutionException, InterruptedException { 25 | List list = ReactiveStreams.of(1, 2, 3).toList().run().toCompletableFuture().get(); 26 | assertThat(list).containsExactly(1, 2, 3); 27 | 28 | Optional res = ReactiveStreams.of(25).findFirst().run().toCompletableFuture().get(); 29 | assertThat(res).contains(25); 30 | 31 | Optional empty = ReactiveStreams.fromIterable(Collections.emptyList()).findFirst().run().toCompletableFuture().get(); 32 | assertThat(empty).isEmpty(); 33 | } 34 | 35 | @Test 36 | public void createFromVertxContext() { 37 | 38 | executeOnEventLoop(() -> ReactiveStreams.of(1, 2, 3).toList().run()).assertSuccess(Arrays.asList(1, 2, 3)); 39 | 40 | executeOnEventLoop(() -> ReactiveStreams.of(25).findFirst().run()).assertSuccess(Optional.of(25)); 41 | 42 | executeOnEventLoop(() -> ReactiveStreams.fromIterable(Collections.emptyList()).findFirst().run()) 43 | .assertSuccess(Optional.empty()); 44 | } 45 | 46 | @Test(expected = NullPointerException.class) 47 | public void createWithoutStage() { 48 | factory.create(null, null); 49 | } 50 | 51 | @Test(expected = NullPointerException.class) 52 | public void createWithoutFunction() { 53 | factory.create(null, () -> null); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/FromPublisherStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.Optional; 5 | 6 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 7 | import org.junit.Test; 8 | 9 | import io.reactivex.Flowable; 10 | 11 | /** 12 | * Checks the behavior of the {@link FromPublisherStageFactory} class when running from the Vert.x Context. 13 | * 14 | * @author Clement Escoffier 15 | */ 16 | public class FromPublisherStageFactoryTest extends StageTestBase { 17 | 18 | @Test 19 | public void createFromVertxContext() { 20 | executeOnEventLoop(() -> ReactiveStreams.fromPublisher(Flowable.fromArray(1, 2, 3)).toList().run()) 21 | .assertSuccess(Arrays.asList(1, 2, 3)); 22 | 23 | executeOnEventLoop(() -> ReactiveStreams.fromPublisher(Flowable.just(25)).findFirst().run()) 24 | .assertSuccess(Optional.of(25)); 25 | 26 | executeOnEventLoop(() -> ReactiveStreams.fromPublisher(Flowable.empty()).findFirst().run()) 27 | .assertSuccess(Optional.empty()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/LimitStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.CompletionStage; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | /** 15 | * Checks the behavior of the {@link LimitStageFactory} class when running from the Vert.x Context. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class LimitStageFactoryTest extends StageTestBase { 20 | 21 | @Test 22 | public void createFromVertxContext() { 23 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 24 | .subscribeOn(Schedulers.computation()); 25 | 26 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable).limit(5).toList() 27 | .run(); 28 | 29 | executeOnEventLoop(callable).assertSuccess(Arrays.asList(1, 2, 3, 4, 5)); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/MapStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Objects; 6 | import java.util.concurrent.Callable; 7 | import java.util.concurrent.CompletionStage; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link MapStageFactory} when running from the Vert.x Context. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class MapStageFactoryTest extends StageTestBase { 21 | 22 | @Test 23 | public void createOnVertxContext() { 24 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 25 | .subscribeOn(Schedulers.computation()); 26 | 27 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable) 28 | .filter(i -> i < 4) 29 | .map(this::square) 30 | .map(this::asString) 31 | .toList() 32 | .run(); 33 | 34 | executeOnEventLoop(callable).assertSuccess(Arrays.asList("1", "4", "9")); 35 | } 36 | 37 | private Integer square(int i) { 38 | return i * i; 39 | } 40 | 41 | private String asString(int i) { 42 | return Objects.toString(i); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/OnCompleteStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.*; 6 | import java.util.concurrent.Callable; 7 | import java.util.concurrent.CompletionStage; 8 | import java.util.concurrent.atomic.AtomicBoolean; 9 | 10 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 11 | import org.junit.Test; 12 | 13 | import io.reactivex.Flowable; 14 | import io.reactivex.schedulers.Schedulers; 15 | 16 | /** 17 | * Checks the behavior of the {@link OnCompleteStageFactory} when running from the Vert.x Context. 18 | * 19 | * @author Clement Escoffier 20 | */ 21 | public class OnCompleteStageFactoryTest extends StageTestBase { 22 | 23 | @Test 24 | public void createOnVertxContext() { 25 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 26 | .subscribeOn(Schedulers.computation()); 27 | 28 | AtomicBoolean completed = new AtomicBoolean(); 29 | Set threads = new LinkedHashSet<>(); 30 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable) 31 | .filter(i -> i < 4) 32 | .map(this::square) 33 | .onComplete(() -> { 34 | completed.set(true); 35 | threads.add(Thread.currentThread().getName()); 36 | }) 37 | .map(this::asString) 38 | .toList() 39 | .run(); 40 | 41 | executeOnEventLoop(callable).assertSuccess(Arrays.asList("1", "4", "9")); 42 | assertThat(completed).isTrue(); 43 | assertThat(threads).hasSize(1).containsExactly(getCapturedThreadName()); 44 | } 45 | 46 | private Integer square(int i) { 47 | return i * i; 48 | } 49 | 50 | private String asString(int i) { 51 | return Objects.toString(i); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/OnErrorStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.LinkedHashSet; 6 | import java.util.List; 7 | import java.util.Objects; 8 | import java.util.Set; 9 | import java.util.concurrent.Callable; 10 | import java.util.concurrent.CompletionStage; 11 | import java.util.concurrent.atomic.AtomicReference; 12 | 13 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 14 | import org.junit.Test; 15 | 16 | import io.reactivex.Flowable; 17 | import io.reactivex.schedulers.Schedulers; 18 | 19 | /** 20 | * Checks the behavior of the {@link OnErrorStageFactory} when running from the Vert.x Context. 21 | * 22 | * @author Clement Escoffier 23 | */ 24 | public class OnErrorStageFactoryTest extends StageTestBase { 25 | 26 | @Test 27 | public void createOnVertxContext() { 28 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 29 | .subscribeOn(Schedulers.computation()); 30 | 31 | AtomicReference error = new AtomicReference<>(); 32 | Set threads = new LinkedHashSet<>(); 33 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable) 34 | .filter(i -> i < 4) 35 | .map(this::squareOrFailed) 36 | .onError(err -> { 37 | error.set(err); 38 | threads.add(Thread.currentThread().getName()); 39 | }) 40 | .map(this::asString) 41 | .toList() 42 | .run(); 43 | 44 | executeOnEventLoop(callable).assertFailure("failed"); 45 | assertThat(error.get()).hasMessage("failed"); 46 | assertThat(threads).hasSize(1).containsExactly(getCapturedThreadName()); 47 | } 48 | 49 | private Integer squareOrFailed(int i) { 50 | if (i == 2) { 51 | throw new RuntimeException("failed"); 52 | } 53 | return i * i; 54 | } 55 | 56 | private String asString(int i) { 57 | return Objects.toString(i); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/PeekStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import java.util.*; 6 | import java.util.concurrent.Callable; 7 | import java.util.concurrent.CompletionStage; 8 | 9 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 10 | import org.junit.Test; 11 | 12 | import io.reactivex.Flowable; 13 | import io.reactivex.schedulers.Schedulers; 14 | 15 | /** 16 | * Checks the behavior of the {@link PeekStageFactory} when running from the Vert.x Context. 17 | * 18 | * @author Clement Escoffier 19 | */ 20 | public class PeekStageFactoryTest extends StageTestBase { 21 | 22 | private final PeekStageFactory factory = new PeekStageFactory(); 23 | 24 | @Test 25 | public void createOnVertxContext() { 26 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 27 | .subscribeOn(Schedulers.computation()); 28 | 29 | List squares = new ArrayList<>(); 30 | List strings = new ArrayList<>(); 31 | Set threads = new LinkedHashSet<>(); 32 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable) 33 | .filter(i -> i < 4) 34 | .map(this::square) 35 | .peek(squares::add) 36 | .peek(i -> threads.add(Thread.currentThread().getName())) 37 | .map(this::asString) 38 | .peek(strings::add) 39 | .peek(i -> threads.add(Thread.currentThread().getName())) 40 | .toList() 41 | .run(); 42 | 43 | executeOnEventLoop(callable).assertSuccess(Arrays.asList("1", "4", "9")); 44 | assertThat(squares).containsExactly(1, 4, 9); 45 | assertThat(strings).containsExactly("1", "4", "9"); 46 | assertThat(threads).hasSize(1).containsExactly(getCapturedThreadName()); 47 | } 48 | 49 | private Integer square(int i) { 50 | return i * i; 51 | } 52 | 53 | private String asString(int i) { 54 | return Objects.toString(i); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/ProcessorStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.ProcessorBuilder; 6 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 7 | import org.junit.Test; 8 | import org.reactivestreams.Processor; 9 | 10 | import io.reactivex.Flowable; 11 | import io.reactivex.schedulers.Schedulers; 12 | 13 | /** 14 | * Checks the behavior of the {@link ProcessorStageFactory} when running from the Vert.x Context. 15 | * 16 | * @author Clement Escoffier 17 | */ 18 | public class ProcessorStageFactoryTest extends StageTestBase { 19 | 20 | @Test 21 | public void createWithProcessorsFromVertxContext() { 22 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 23 | .subscribeOn(Schedulers.computation()); 24 | 25 | executeOnEventLoop(() -> ReactiveStreams.fromPublisher(flowable) 26 | .filter(i -> i < 4) 27 | .via(duplicateProcessor()) 28 | .via(asStringProcessor()) 29 | .toList() 30 | .run()).assertSuccess(Arrays.asList("1", "1", "2", "2", "3", "3")); 31 | } 32 | 33 | @Test 34 | public void createWithProcessorBuildersFromVertxContext() { 35 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 36 | .subscribeOn(Schedulers.computation()); 37 | 38 | executeOnEventLoop(() -> ReactiveStreams.fromPublisher(flowable) 39 | .filter(i -> i < 4) 40 | .via(duplicateProcessorBuilder()) 41 | .via(asStringProcessorBuilder()) 42 | .toList() 43 | .run()).assertSuccess(Arrays.asList("1", "1", "2", "2", "3", "3")); 44 | } 45 | 46 | private ProcessorBuilder duplicateProcessorBuilder() { 47 | return ReactiveStreams. builder().flatMapIterable(i -> Arrays.asList(i, i)); 48 | } 49 | 50 | private Processor duplicateProcessor() { 51 | return duplicateProcessorBuilder().buildRs(); 52 | } 53 | 54 | private ProcessorBuilder asStringProcessorBuilder() { 55 | return ReactiveStreams. builder().map(Object::toString); 56 | } 57 | 58 | private Processor asStringProcessor() { 59 | return asStringProcessorBuilder().buildRs(); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/SkipStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.CompletionStage; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | /** 15 | * Checks the behavior of the {@link SkipStageFactory} class when running from the Vert.x Context. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class SkipStageFactoryTest extends StageTestBase { 20 | 21 | @Test 22 | public void createFromVertxContext() { 23 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 24 | .subscribeOn(Schedulers.computation()); 25 | 26 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable).skip(5).toList() 27 | .run(); 28 | 29 | executeOnEventLoop(callable).assertSuccess(Arrays.asList(6, 7, 8, 9, 10)); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/SubscriberStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Optional; 4 | 5 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 6 | import org.eclipse.microprofile.reactive.streams.operators.SubscriberBuilder; 7 | import org.junit.Test; 8 | 9 | import io.reactivex.Flowable; 10 | import io.reactivex.schedulers.Schedulers; 11 | 12 | /** 13 | * Checks the behavior of the {@link SubscriberStageFactory} when running from the Vert.x Context. 14 | * 15 | * @author Clement Escoffier 16 | */ 17 | public class SubscriberStageFactoryTest extends StageTestBase { 18 | 19 | @Test 20 | public void createFromContext() { 21 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 22 | .subscribeOn(Schedulers.computation()); 23 | executeOnEventLoop(() -> { 24 | SubscriberBuilder> builder = ReactiveStreams. builder().findFirst(); 25 | return ReactiveStreams.fromPublisher(flowable).filter(i -> i > 5) 26 | .to(builder).run(); 27 | }).assertSuccess(Optional.of(6)); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /vertx-execution-model/src/test/java/io/smallrye/reactive/streams/stages/TakeWhileStageFactoryTest.java: -------------------------------------------------------------------------------- 1 | package io.smallrye.reactive.streams.stages; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.concurrent.Callable; 6 | import java.util.concurrent.CompletionStage; 7 | 8 | import org.eclipse.microprofile.reactive.streams.operators.ReactiveStreams; 9 | import org.junit.Test; 10 | 11 | import io.reactivex.Flowable; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | /** 15 | * Checks the behavior of the {@link TakeWhileStageFactory} class when running from the Vert.x Context. 16 | * 17 | * @author Clement Escoffier 18 | */ 19 | public class TakeWhileStageFactoryTest extends StageTestBase { 20 | 21 | @Test 22 | public void createFromVertxContext() { 23 | Flowable flowable = Flowable.fromArray(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 24 | .subscribeOn(Schedulers.computation()); 25 | 26 | Callable>> callable = () -> ReactiveStreams.fromPublisher(flowable).takeWhile(i -> i < 6) 27 | .toList().run(); 28 | 29 | executeOnEventLoop(callable).assertSuccess(Arrays.asList(1, 2, 3, 4, 5)); 30 | } 31 | } 32 | --------------------------------------------------------------------------------