FluxMessageChannelSpec() { this.channel = new FluxMessageChannel(); }
@Override public void subscribeTo(Publisher<Message<?>> publisher) { ConnectableFlux<?> connectableFlux = Flux.from(publisher) .handle((message, sink) -> sink.next(send(message))) .onErrorContinue((throwable, o) -> logger.warn("Error during processing event: " + o, throwable) ) .doOnComplete(() -> this.publishers.remove(publisher)) .publish(); this.publishers.put(publisher, connectableFlux); if (!this.subscribers.isEmpty()) { connectableFlux.connect(); } }
/** * Populate a {@link FluxMessageChannel} to the {@link IntegrationFlowBuilder} chain * and subscribe it to the provided {@link Publisher}. * @param publisher the {@link Publisher} to subscribe to. * @return new {@link IntegrationFlowBuilder}. */ public static IntegrationFlowBuilder from(Publisher<Message<?>> publisher) { FluxMessageChannel reactiveChannel = new FluxMessageChannel(); reactiveChannel.subscribeTo(publisher); return from((MessageChannel) reactiveChannel); }
@Test public void testReactiveStreamsConsumerFluxMessageChannel() throws InterruptedException { FluxMessageChannel testChannel = new FluxMessageChannel(); testChannel.send(testMessage); testChannel.send(testMessage); testChannel.send(testMessage2);
@Test public void testReactiveStreamsConsumerViaConsumerEndpointFactoryBean() throws Exception { FluxMessageChannel testChannel = new FluxMessageChannel(); testChannel.send(testMessage); testChannel.send(testMessage); testChannel.send(testMessage2); testChannel.send(testMessage2);
@Bean public MessageChannel fluxResultChannel() { return new FluxMessageChannel(); }
/** * Populate a {@link FluxMessageChannel} to start a reactive processing for upstream data, * wrap it to a {@link Flux}, apply provided {@link Function} via {@link Flux#transform(Function)} * and emit the result to one more {@link FluxMessageChannel}, subscribed in the downstream flow. * @param fluxFunction the {@link Function} to process data reactive manner. * @param <I> the input payload type. * @param <O> the output type. * @return the current {@link IntegrationFlowDefinition}. */ @SuppressWarnings("unchecked") public <I, O> B fluxTransform(Function<? super Flux<Message<I>>, ? extends Publisher<O>> fluxFunction) { if (!(this.currentMessageChannel instanceof FluxMessageChannel)) { channel(new FluxMessageChannel()); } Publisher<Message<I>> upstream = (Publisher<Message<I>>) this.currentMessageChannel; Flux<Message<O>> result = Transformers.transformWithFunction(upstream, fluxFunction); FluxMessageChannel downstream = new FluxMessageChannel(); downstream.subscribeTo((Flux<Message<?>>) (Flux<?>) result); this.currentMessageChannel = downstream; return addComponent(this.currentMessageChannel); }
@Override public void subscribeTo(Publisher<Message<?>> publisher) { ConnectableFlux<?> connectableFlux = Flux.from(publisher) .handle((message, sink) -> sink.next(send(message))) .onErrorContinue((throwable, o) -> logger.warn("Error during processing event: " + o, throwable) ) .doOnComplete(() -> this.publishers.remove(publisher)) .publish(); this.publishers.put(publisher, connectableFlux); if (!this.subscribers.isEmpty()) { connectableFlux.connect(); } }
@Bean public MessageChannel fluxChannel() { return new FluxMessageChannel(); }
/** * Populate a {@link FluxMessageChannel} to the {@link IntegrationFlowBuilder} chain * and subscribe it to the provided {@link Publisher}. * @param publisher the {@link Publisher} to subscribe to. * @return new {@link IntegrationFlowBuilder}. */ public static IntegrationFlowBuilder from(Publisher<Message<?>> publisher) { FluxMessageChannel reactiveChannel = new FluxMessageChannel(); reactiveChannel.subscribeTo(publisher); return from((MessageChannel) reactiveChannel); }
@Bean public MessageChannel fluxMessageChannel() { return new FluxMessageChannel(); }
/** * Populate a {@link FluxMessageChannel} to start a reactive processing for upstream data, * wrap it to a {@link Flux}, apply provided {@link Function} via {@link Flux#transform(Function)} * and emit the result to one more {@link FluxMessageChannel}, subscribed in the downstream flow. * @param fluxFunction the {@link Function} to process data reactive manner. * @param <I> the input payload type. * @param <O> the output type. * @return the current {@link IntegrationFlowDefinition}. */ @SuppressWarnings("unchecked") public <I, O> B fluxTransform(Function<? super Flux<Message<I>>, ? extends Publisher<O>> fluxFunction) { if (!(this.currentMessageChannel instanceof FluxMessageChannel)) { channel(new FluxMessageChannel()); } Publisher<Message<I>> upstream = (Publisher<Message<I>>) this.currentMessageChannel; Flux<Message<O>> result = Transformers.transformWithFunction(upstream, fluxFunction); FluxMessageChannel downstream = new FluxMessageChannel(); downstream.subscribeTo((Flux<Message<?>>) (Flux<?>) result); this.currentMessageChannel = downstream; return addComponent(this.currentMessageChannel); }
/** * Represent an Integration Flow as a Reactive Streams {@link Publisher} bean. * @param <T> the expected {@code payload} type * @return the Reactive Streams {@link Publisher} */ @SuppressWarnings("unchecked") public <T> Publisher<Message<T>> toReactivePublisher() { MessageChannel channelForPublisher = this.currentMessageChannel; Publisher<Message<T>> publisher; if (channelForPublisher instanceof Publisher) { publisher = (Publisher<Message<T>>) channelForPublisher; } else { if (channelForPublisher != null && this.integrationComponents.size() > 1 && !(channelForPublisher instanceof MessageChannelReference) && !(channelForPublisher instanceof FixedSubscriberChannelPrototype)) { publisher = MessageChannelReactiveUtils.toPublisher(channelForPublisher); } else { MessageChannel reactiveChannel = new FluxMessageChannel(); publisher = (Publisher<Message<T>>) reactiveChannel; channel(reactiveChannel); } } this.implicitChannel = false; get(); return new PublisherIntegrationFlow<>(this.integrationComponents, publisher); }
FluxMessageChannelSpec() { this.channel = new FluxMessageChannel(); }
@Bean public MessageChannel fluxResultChannel() { return new FluxMessageChannel(); }
@Test public void splitStreamReactive() { Message<?> message = new GenericMessage<>(Stream.of("x", "y", "z")); FluxMessageChannel replyChannel = new FluxMessageChannel(); DefaultMessageSplitter splitter = new DefaultMessageSplitter(); splitter.setOutputChannel(replyChannel); splitter.handleMessage(message); Flux<String> testFlux = Flux.from(replyChannel) .map(Message::getPayload) .cast(String.class); StepVerifier.create(testFlux) .expectNext("x", "y", "z") .then(() -> ((Subscriber<?>) TestUtils.getPropertyValue(replyChannel, "subscribers", List.class).get(0)) .onComplete()) .verifyComplete(); }
@Test public void splitArrayPayloadReactive() { Message<?> message = new GenericMessage<>(new String[] { "x", "y", "z" }); FluxMessageChannel replyChannel = new FluxMessageChannel(); DefaultMessageSplitter splitter = new DefaultMessageSplitter(); splitter.setOutputChannel(replyChannel); splitter.handleMessage(message); Flux<String> testFlux = Flux.from(replyChannel) .map(Message::getPayload) .cast(String.class); StepVerifier.create(testFlux) .expectNext("x", "y", "z") .then(() -> ((Subscriber<?>) TestUtils.getPropertyValue(replyChannel, "subscribers", List.class).get(0)) .onComplete()) .verifyComplete(); }
@Test public void splitFluxReactive() { Message<?> message = new GenericMessage<>(Flux.just("x", "y", "z")); FluxMessageChannel replyChannel = new FluxMessageChannel(); DefaultMessageSplitter splitter = new DefaultMessageSplitter(); splitter.setOutputChannel(replyChannel); splitter.handleMessage(message); Flux<String> testFlux = Flux.from(replyChannel) .map(Message::getPayload) .cast(String.class); StepVerifier.create(testFlux) .expectNext("x", "y", "z") .then(() -> ((Subscriber<?>) TestUtils.getPropertyValue(replyChannel, "subscribers", List.class).get(0)) .onComplete()) .verifyComplete(); }
@Test public void testFileSplitterReactive() { FluxMessageChannel outputChannel = new FluxMessageChannel(); FileSplitter splitter = new FileSplitter(true, true); splitter.setApplySequence(true); splitter.setOutputChannel(outputChannel); splitter.handleMessage(new GenericMessage<>(file)); StepVerifier.create(outputChannel) .assertNext(m -> { assertThat(m, hasHeaderKey(IntegrationMessageHeaderAccessor.SEQUENCE_SIZE)); assertThat(m, hasHeader(FileHeaders.MARKER, "START")); assertThat(m, hasPayload(instanceOf(FileSplitter.FileMarker.class))); FileMarker fileMarker = (FileSplitter.FileMarker) m.getPayload(); assertEquals(FileMarker.Mark.START, fileMarker.getMark()); assertEquals(file.getAbsolutePath(), fileMarker.getFilePath()); }) .expectNextCount(2) .assertNext(m -> { assertThat(m, hasHeader(FileHeaders.MARKER, "END")); assertThat(m, hasPayload(instanceOf(FileSplitter.FileMarker.class))); FileMarker fileMarker = (FileSplitter.FileMarker) m.getPayload(); assertEquals(FileMarker.Mark.END, fileMarker.getMark()); assertEquals(file.getAbsolutePath(), fileMarker.getFilePath()); assertEquals(2, fileMarker.getLineCount()); }) .then(() -> ((Subscriber<?>) TestUtils.getPropertyValue(outputChannel, "subscribers", List.class).get(0)) .onComplete()) .verifyComplete(); }
@Bean public FluxMessageChannel resultChannel() { return new FluxMessageChannel(); }