From 2445135472b31c3d6ec3d2b710d5ee398309c222 Mon Sep 17 00:00:00 2001 From: Julien Ponge Date: Fri, 23 Sep 2022 15:55:58 +0200 Subject: [PATCH 1/3] New library to expose Vert.x ReadStream as Flow.Publisher --- ...vertx-based-reactive-streams-publishers.md | 27 +++ mkdocs.yml | 1 + mutiny-zero-vertx-publishers/pom.xml | 70 +++++++ mutiny-zero-vertx-publishers/revapi.json | 46 +++++ .../vertxpublishers/NoopSubscription.java | 15 ++ .../zero/vertxpublishers/PublisherBase.java | 29 +++ .../SuppliedFutureStreamPublisher.java | 38 ++++ .../SuppliedStreamPublisher.java | 33 ++++ .../zero/vertxpublishers/VertxPublisher.java | 43 +++++ .../UrbanObservatoryHttpClient.java | 67 +++++++ .../vertxpublishers/VertxPublisherTest.java | 175 ++++++++++++++++++ .../tck/VertxPublisherTckTest.java | 51 +++++ pom.xml | 3 + 13 files changed, 598 insertions(+) create mode 100644 docs/vertx-based-reactive-streams-publishers.md create mode 100644 mutiny-zero-vertx-publishers/pom.xml create mode 100644 mutiny-zero-vertx-publishers/revapi.json create mode 100644 mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/NoopSubscription.java create mode 100644 mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/PublisherBase.java create mode 100644 mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/SuppliedFutureStreamPublisher.java create mode 100644 mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/SuppliedStreamPublisher.java create mode 100644 mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/VertxPublisher.java create mode 100644 mutiny-zero-vertx-publishers/src/test/java/docsamples/UrbanObservatoryHttpClient.java create mode 100644 mutiny-zero-vertx-publishers/src/test/java/mutiny/zero/vertxpublishers/VertxPublisherTest.java create mode 100644 mutiny-zero-vertx-publishers/src/test/java/mutiny/zero/vertxpublishers/tck/VertxPublisherTckTest.java diff --git a/docs/vertx-based-reactive-streams-publishers.md b/docs/vertx-based-reactive-streams-publishers.md new file mode 100644 index 0000000..33d9586 --- /dev/null +++ b/docs/vertx-based-reactive-streams-publishers.md @@ -0,0 +1,27 @@ +# Vert.x-based Reactive Streams Publishers + +The `mutiny-zero-vertx-publishers` library (Maven coordinates `io.smallrye.reactive:mutiny-zero-vertx-publishers`) allows creating _Reactive Streams_ publishers from [Vert.x](https://vertx.io/) streams. + +This library acts as a thin adapter between Vert.x `ReadStream` and `java.util.concurrent.Flow.Publisher` and uses _Mutiny Zero_ to expose _Reactive Streams_ compliant publishers. + +## API overview + +The entry point is the `mutiny.zero.vertxpublishers.VertxPublisher` interface that exposes 2 static factory methods. + +- `Publisher fromSupplier(Supplier> streamSupplier)` is to be used when some Vert.x API returns a `ReadStream`. +- `Publisher fromFuture(Supplier>> futureStreamSupplier)` is to be used when some Vert.x API asynchronously returns a `ReadStream` through a `Future`. + +The factory methods use suppliers so that the `ReadStream` instances to be adapted are on a per-subscriber basis. + +## Sample usage + +The following example makes HTTP requests to the [Newcastle University Urban Observatory API](https://api.usb.urbanobservatory.ac.uk/) using the Vert.x HTTP client: + +```java linenums="1" +--8<-- "mutiny-zero-vertx-publishers/src/test/java/docsamples/UrbanObservatoryHttpClient.java" +``` + +A new HTTP connection is issued everytime the publisher is being subscribed. +In this example the subscriber controls demand by requesting a new Vert.x `Buffer` every 500ms. + +If you run this program then you will see the JSON response being progressively printed to the standard console in chunks, every 500 milliseconds. diff --git a/mkdocs.yml b/mkdocs.yml index a4f7f6c..5cb8034 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -7,6 +7,7 @@ nav: - 'quick-start.md' - Javadoc: './apidocs/index.html' - 'flow-adapters.md' + - 'vertx-based-reactive-streams-publishers.md' theme: name: material diff --git a/mutiny-zero-vertx-publishers/pom.xml b/mutiny-zero-vertx-publishers/pom.xml new file mode 100644 index 0000000..a9a88e0 --- /dev/null +++ b/mutiny-zero-vertx-publishers/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + + io.smallrye.reactive + mutiny-zero-parent + 0.5.0-SNAPSHOT + + + mutiny-zero-vertx-publishers + SmallRye Mutiny Zero Vert.x-based publishers + jar + Support making publishers from Vert.x streams + + + + io.smallrye.reactive + mutiny-zero + ${project.version} + + + io.vertx + vertx-core + ${vertx.version} + + + + org.junit.jupiter + junit-jupiter + test + + + org.awaitility + awaitility + test + + + io.smallrye.reactive + mutiny + test + + + + org.reactivestreams + reactive-streams-tck-flow + test + + + + + org.testng + testng + test + + + org.junit.support + testng-engine + test + + + ch.qos.logback + logback-classic + test + + + + \ No newline at end of file diff --git a/mutiny-zero-vertx-publishers/revapi.json b/mutiny-zero-vertx-publishers/revapi.json new file mode 100644 index 0000000..000ec75 --- /dev/null +++ b/mutiny-zero-vertx-publishers/revapi.json @@ -0,0 +1,46 @@ +[ + { + "extension": "revapi.java", + "id": "java", + "configuration": { + "missing-classes": { + "behavior": "report", + "ignoreMissingAnnotations": false + } + } + }, + { + "extension": "revapi.filter", + "configuration": { + "elements": { + "include": [ + { + "matcher": "java-package", + "match": "mutiny.zero.flow.adapters" + } + ] + } + } + }, + { + "extension": "revapi.differences", + "id": "breaking-changes", + "configuration": { + "criticality": "highlight", + "minSeverity": "POTENTIALLY_BREAKING", + "minCriticality": "documented", + "differences": [] + } + }, + { + "extension": "revapi.reporter.json", + "configuration": { + "minSeverity": "POTENTIALLY_BREAKING", + "minCriticality": "documented", + "output": "target/compatibility.json", + "indent": true, + "append": false, + "keepEmptyFile": true + } + } +] \ No newline at end of file diff --git a/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/NoopSubscription.java b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/NoopSubscription.java new file mode 100644 index 0000000..93c0d6e --- /dev/null +++ b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/NoopSubscription.java @@ -0,0 +1,15 @@ +package mutiny.zero.vertxpublishers; + +import java.util.concurrent.Flow; + +class NoopSubscription implements Flow.Subscription { + @Override + public void request(long n) { + // Nothing + } + + @Override + public void cancel() { + // Nothing + } +} diff --git a/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/PublisherBase.java b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/PublisherBase.java new file mode 100644 index 0000000..a9511e9 --- /dev/null +++ b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/PublisherBase.java @@ -0,0 +1,29 @@ +package mutiny.zero.vertxpublishers; + +import java.util.concurrent.Flow; + +import io.vertx.core.streams.ReadStream; +import mutiny.zero.BackpressureStrategy; +import mutiny.zero.TubeConfiguration; +import mutiny.zero.ZeroPublisher; + +abstract class PublisherBase implements Flow.Publisher { + + protected void adapt(Flow.Subscriber subscriber, ReadStream stream) { + TubeConfiguration conf = new TubeConfiguration().withBackpressureStrategy(BackpressureStrategy.ERROR); + Flow.Publisher publisher = ZeroPublisher.create(conf, tube -> { + stream.pause(); + stream.handler(tube::send); + stream.exceptionHandler(tube::fail); + stream.endHandler(v -> tube.complete()); + tube.whenCancelled(() -> { + stream.pause(); + stream.handler(null); + stream.exceptionHandler(null); + stream.endHandler(null); + }); + tube.whenRequested(stream::fetch); + }); + publisher.subscribe(subscriber); + } +} diff --git a/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/SuppliedFutureStreamPublisher.java b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/SuppliedFutureStreamPublisher.java new file mode 100644 index 0000000..7811633 --- /dev/null +++ b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/SuppliedFutureStreamPublisher.java @@ -0,0 +1,38 @@ +package mutiny.zero.vertxpublishers; + +import java.util.concurrent.Flow; +import java.util.function.Supplier; + +import io.vertx.core.Future; +import io.vertx.core.streams.ReadStream; + +class SuppliedFutureStreamPublisher extends PublisherBase { + + private final Supplier>> futureStreamSupplier; + + SuppliedFutureStreamPublisher(Supplier>> futureStreamSupplier) { + this.futureStreamSupplier = futureStreamSupplier; + } + + @Override + public void subscribe(Flow.Subscriber subscriber) { + Future> future; + try { + future = futureStreamSupplier.get(); + } catch (Throwable err) { + subscriber.onSubscribe(new NoopSubscription()); + subscriber.onError(err); + return; + } + if (future == null) { + subscriber.onSubscribe(new NoopSubscription()); + subscriber.onError(new NullPointerException("The future cannot be null")); + } else { + future.onSuccess(stream -> adapt(subscriber, stream)); + future.onFailure(err -> { + subscriber.onSubscribe(new NoopSubscription()); + subscriber.onError(err); + }); + } + } +} diff --git a/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/SuppliedStreamPublisher.java b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/SuppliedStreamPublisher.java new file mode 100644 index 0000000..c653521 --- /dev/null +++ b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/SuppliedStreamPublisher.java @@ -0,0 +1,33 @@ +package mutiny.zero.vertxpublishers; + +import java.util.concurrent.Flow; +import java.util.function.Supplier; + +import io.vertx.core.streams.ReadStream; + +class SuppliedStreamPublisher extends PublisherBase { + + private final Supplier> streamSupplier; + + SuppliedStreamPublisher(Supplier> streamSupplier) { + this.streamSupplier = streamSupplier; + } + + @Override + public void subscribe(Flow.Subscriber subscriber) { + ReadStream stream; + try { + stream = streamSupplier.get(); + } catch (Throwable err) { + subscriber.onSubscribe(new NoopSubscription()); + subscriber.onError(err); + return; + } + if (stream == null) { + subscriber.onSubscribe(new NoopSubscription()); + subscriber.onError(new NullPointerException("The stream cannot be null")); + } else { + adapt(subscriber, stream); + } + } +} diff --git a/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/VertxPublisher.java b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/VertxPublisher.java new file mode 100644 index 0000000..3534d19 --- /dev/null +++ b/mutiny-zero-vertx-publishers/src/main/java/mutiny/zero/vertxpublishers/VertxPublisher.java @@ -0,0 +1,43 @@ +package mutiny.zero.vertxpublishers; + +import static java.util.Objects.requireNonNull; + +import java.util.concurrent.Flow.Publisher; +import java.util.function.Supplier; + +import io.vertx.core.Future; +import io.vertx.core.streams.ReadStream; + +/** + * Expose Vert.x streams as Reactive Streams compliant publishers. + */ +public interface VertxPublisher { + + /** + * Create a publisher from a Vert.x stream supplier. + * The supplier is called for each new publisher subscription. + * + * @param streamSupplier the {@link ReadStream} supplier, cannot be {@code null}, cannot return {@code null}, must not throw + * an exception + * @param the elements type + * @return the new {@link Publisher} + */ + static Publisher fromSupplier(Supplier> streamSupplier) { + requireNonNull(streamSupplier, "The stream supplier cannot be null"); + return new SuppliedStreamPublisher<>(streamSupplier); + } + + /** + * Create a publisher from a Vert.x future stream supplier. + * The supplier is called for each new publisher subscription. + * + * @param futureStreamSupplier the {@link Future} {@link ReadStream} supplier, cannot be {@code null}, cannot return + * {@code null}, must not throw an exception + * @param the elements type + * @return the new {@link Publisher} + */ + static Publisher fromFuture(Supplier>> futureStreamSupplier) { + requireNonNull(futureStreamSupplier, "The future supplier cannot be null"); + return new SuppliedFutureStreamPublisher<>(futureStreamSupplier); + } +} diff --git a/mutiny-zero-vertx-publishers/src/test/java/docsamples/UrbanObservatoryHttpClient.java b/mutiny-zero-vertx-publishers/src/test/java/docsamples/UrbanObservatoryHttpClient.java new file mode 100644 index 0000000..3d7ddf2 --- /dev/null +++ b/mutiny-zero-vertx-publishers/src/test/java/docsamples/UrbanObservatoryHttpClient.java @@ -0,0 +1,67 @@ +package docsamples; + +import java.nio.charset.StandardCharsets; +import java.util.concurrent.Executors; +import java.util.concurrent.Flow; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import io.vertx.core.Vertx; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpClient; +import io.vertx.core.http.HttpClientRequest; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.RequestOptions; +import mutiny.zero.vertxpublishers.VertxPublisher; + +public class UrbanObservatoryHttpClient { + + public static void main(String[] args) { + + Vertx vertx = Vertx.vertx(); + ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); + + RequestOptions opts = new RequestOptions() + .setSsl(true) + .setHost("api.usb.urbanobservatory.ac.uk") + .setPort(443) + .setMethod(HttpMethod.GET) + .addHeader("Accept", "application/json") + .setURI("/api/v2.0a/sensors/entity"); + + HttpClient httpClient = vertx.createHttpClient(); + + Flow.Publisher publisher = VertxPublisher.fromFuture(() -> httpClient + .request(opts) + .compose(HttpClientRequest::send)); + + publisher.subscribe(new Flow.Subscriber<>() { + + private Flow.Subscription subscription; + + @Override + public void onSubscribe(Flow.Subscription s) { + System.out.println("======================================"); + this.subscription = s; + s.request(1L); + } + + @Override + public void onNext(Buffer buffer) { + System.out.print(buffer.toString(StandardCharsets.UTF_8)); + executor.schedule(() -> subscription.request(1L), 500, TimeUnit.MILLISECONDS); + } + + @Override + public void onError(Throwable t) { + System.out.println("======================================"); + t.printStackTrace(); + } + + @Override + public void onComplete() { + System.out.println("======================================"); + } + }); + } +} diff --git a/mutiny-zero-vertx-publishers/src/test/java/mutiny/zero/vertxpublishers/VertxPublisherTest.java b/mutiny-zero-vertx-publishers/src/test/java/mutiny/zero/vertxpublishers/VertxPublisherTest.java new file mode 100644 index 0000000..157762b --- /dev/null +++ b/mutiny-zero-vertx-publishers/src/test/java/mutiny/zero/vertxpublishers/VertxPublisherTest.java @@ -0,0 +1,175 @@ +package mutiny.zero.vertxpublishers; + +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.*; + +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.concurrent.Flow; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import org.junit.jupiter.api.*; + +import io.smallrye.mutiny.Multi; +import io.smallrye.mutiny.helpers.test.AssertSubscriber; +import io.vertx.core.Future; +import io.vertx.core.Vertx; +import io.vertx.core.buffer.Buffer; + +@DisplayName("Vert.x publisher tests") +class VertxPublisherTest { + + @Nested + @DisplayName("Regular tests") + class RegularTests { + + Vertx vertx; + + @BeforeEach + void prepare() { + vertx = Vertx.vertx(); + } + + @AfterEach + void cleanup() { + AtomicBoolean closed = new AtomicBoolean(); + vertx.close(ar -> closed.set(true)); + await().atMost(5, TimeUnit.SECONDS).untilTrue(closed); + } + + @Test + @DisplayName("Test using a periodic stream") + void periodicStream() throws InterruptedException { + Flow.Publisher publisher = VertxPublisher.fromSupplier(() -> vertx.periodicStream(50)); + + AssertSubscriber sub = AssertSubscriber.create(); + Multi.createFrom().publisher(publisher) + .onItem().transform(ignored -> "tick") + .select().first(10) + .subscribe().withSubscriber(sub); + + Thread.sleep(250); + sub.assertHasNotReceivedAnyItem(); + sub.request(2); + Thread.sleep(500); + sub.assertItems("tick", "tick"); + sub.request(1); + Thread.sleep(500); + sub.assertItems("tick", "tick", "tick"); + sub.cancel(); + } + + @Test + @DisplayName("Test using a TCP stream") + void netServer() throws InterruptedException { + AtomicBoolean ready = new AtomicBoolean(); + AtomicInteger port = new AtomicInteger(); + + vertx.createNetServer().connectHandler(socket -> { + AtomicLong counter = new AtomicLong(); + vertx.setPeriodic(100, tick -> { + socket.write("[ tick :: " + counter.getAndIncrement() + " ]\n"); + }); + }).listen(0).onSuccess(server -> { + port.set(server.actualPort()); + ready.set(true); + }); + + await().atMost(5, TimeUnit.SECONDS).untilTrue(ready); + + Flow.Publisher publisher = VertxPublisher + .fromFuture(() -> vertx.createNetClient().connect(port.get(), "localhost")); + + AssertSubscriber sub = AssertSubscriber.create(); + Multi.createFrom().publisher(publisher) + .onItem().transform(buffer -> buffer.toString(StandardCharsets.UTF_8)) + .subscribe().withSubscriber(sub); + + Thread.sleep(1000); + sub.assertHasNotReceivedAnyItem(); + sub.request(10); + Thread.sleep(1000); + + List items = sub.getItems(); + int firstBatchCount = items.size(); + assertTrue(firstBatchCount > 2); + assertEquals("[ tick :: 0 ]\n", items.get(0)); + assertEquals("[ tick :: 1 ]\n", items.get(1)); + + Thread.sleep(250); + assertEquals(firstBatchCount, sub.getItems().size()); + + sub.request(1); + Thread.sleep(500); + assertEquals(firstBatchCount + 1, sub.getItems().size()); + + sub.cancel(); + } + } + + @Nested + @DisplayName("Null and throwable cases") + class NullsAndThrowables { + + @Test + @DisplayName("Reject a null supplier") + void rejectNullSupplier() { + NullPointerException exception = assertThrows(NullPointerException.class, () -> VertxPublisher.fromSupplier(null)); + assertEquals("The stream supplier cannot be null", exception.getMessage()); + } + + @Test + @DisplayName("Reject a null future supplier") + void rejectNullFutureSupplier() { + NullPointerException exception = assertThrows(NullPointerException.class, () -> VertxPublisher.fromFuture(null)); + assertEquals("The future supplier cannot be null", exception.getMessage()); + } + + @Test + @DisplayName("Handle null returning supplier") + void handleNullReturningSupplier() { + AssertSubscriber sub = AssertSubscriber.create(Long.MAX_VALUE); + VertxPublisher.fromSupplier(() -> null).subscribe(sub); + sub.assertFailedWith(NullPointerException.class, "The stream cannot be null"); + } + + @Test + @DisplayName("Handle null returning future supplier") + void handleNullReturningFutureSupplier() { + AssertSubscriber sub = AssertSubscriber.create(Long.MAX_VALUE); + VertxPublisher.fromFuture(() -> null).subscribe(sub); + sub.assertFailedWith(NullPointerException.class, "The future cannot be null"); + } + + @Test + @DisplayName("Handle failed futures") + void handleFailedFutures() { + AssertSubscriber sub = AssertSubscriber.create(Long.MAX_VALUE); + VertxPublisher.fromFuture(() -> Future.failedFuture(new RuntimeException("Yolo"))).subscribe(sub); + sub.assertFailedWith(RuntimeException.class, "Yolo"); + } + + @Test + @DisplayName("Handle exception throwing suppliers") + void handleThrowingSuppliers() { + AssertSubscriber sub = AssertSubscriber.create(Long.MAX_VALUE); + VertxPublisher.fromSupplier(() -> { + throw new RuntimeException("Yolo"); + }).subscribe(sub); + sub.assertFailedWith(RuntimeException.class, "Yolo"); + } + + @Test + @DisplayName("Handle exception throwing future suppliers") + void handleThrowingFutureSuppliers() { + AssertSubscriber sub = AssertSubscriber.create(Long.MAX_VALUE); + VertxPublisher.fromFuture(() -> { + throw new RuntimeException("Yolo"); + }).subscribe(sub); + sub.assertFailedWith(RuntimeException.class, "Yolo"); + } + } +} diff --git a/mutiny-zero-vertx-publishers/src/test/java/mutiny/zero/vertxpublishers/tck/VertxPublisherTckTest.java b/mutiny-zero-vertx-publishers/src/test/java/mutiny/zero/vertxpublishers/tck/VertxPublisherTckTest.java new file mode 100644 index 0000000..a141eb6 --- /dev/null +++ b/mutiny-zero-vertx-publishers/src/test/java/mutiny/zero/vertxpublishers/tck/VertxPublisherTckTest.java @@ -0,0 +1,51 @@ +package mutiny.zero.vertxpublishers.tck; + +import static org.awaitility.Awaitility.await; + +import java.util.concurrent.Flow; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.reactivestreams.tck.TestEnvironment; +import org.reactivestreams.tck.flow.FlowPublisherVerification; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; + +import io.smallrye.mutiny.Multi; +import io.vertx.core.Vertx; +import mutiny.zero.vertxpublishers.VertxPublisher; + +public class VertxPublisherTckTest extends FlowPublisherVerification { + + public VertxPublisherTckTest() { + super(new TestEnvironment()); + } + + Vertx vertx; + + @BeforeMethod + @Override + public void setUp() throws Exception { + super.setUp(); + vertx = Vertx.vertx(); + } + + @AfterMethod + public void tearDown() { + AtomicBoolean closed = new AtomicBoolean(); + vertx.close(ar -> closed.set(true)); + await().atMost(5, TimeUnit.SECONDS).untilTrue(closed); + } + + @Override + public Flow.Publisher createFlowPublisher(long elements) { + // Wrapping in a Multi to limit to the TCK-requested number of elements + return Multi.createFrom().publisher(VertxPublisher.fromSupplier(() -> vertx.periodicStream(25))) + .select().first(elements); + } + + @Override + public Flow.Publisher createFailedFlowPublisher() { + return null; + } +} diff --git a/pom.xml b/pom.xml index 5ab64c3..d144119 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,7 @@ mutiny-zero mutiny-zero-flow-adapters + mutiny-zero-vertx-publishers mutiny-zero-reactive-streams-junit5-tck @@ -62,6 +63,8 @@ 1.0.4 2.0.0-milestone2 + 4.3.3 + 4.2.0 3.23.1 From fa8222d160a546e7974122a15b08a902cc2ae93d Mon Sep 17 00:00:00 2001 From: Julien Ponge Date: Fri, 23 Sep 2022 16:05:06 +0200 Subject: [PATCH 2/3] Fix bad package reference --- mutiny-zero-vertx-publishers/revapi.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mutiny-zero-vertx-publishers/revapi.json b/mutiny-zero-vertx-publishers/revapi.json index 000ec75..ba3b628 100644 --- a/mutiny-zero-vertx-publishers/revapi.json +++ b/mutiny-zero-vertx-publishers/revapi.json @@ -16,7 +16,7 @@ "include": [ { "matcher": "java-package", - "match": "mutiny.zero.flow.adapters" + "match": "mutiny.zero.vertxpublishers" } ] } From 5a4697bac7d20d198eca66d3681a1fd0fe17a7e8 Mon Sep 17 00:00:00 2001 From: Julien Ponge Date: Fri, 23 Sep 2022 16:10:02 +0200 Subject: [PATCH 3/3] Missing module-info --- mutiny-zero-vertx-publishers/src/main/java/module-info.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 mutiny-zero-vertx-publishers/src/main/java/module-info.java diff --git a/mutiny-zero-vertx-publishers/src/main/java/module-info.java b/mutiny-zero-vertx-publishers/src/main/java/module-info.java new file mode 100644 index 0000000..d83028b --- /dev/null +++ b/mutiny-zero-vertx-publishers/src/main/java/module-info.java @@ -0,0 +1,5 @@ +module mutiny.zero.vertxpublishers { + exports mutiny.zero.vertxpublishers; + requires mutiny.zero; + requires io.vertx.core; +} \ No newline at end of file