io.smallrye.reactive.messaging.connector.OutboundConnector Maven / Gradle / Ivy
package io.smallrye.reactive.messaging.connector;
import java.util.NoSuchElementException;
import java.util.concurrent.Flow.Subscriber;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.reactive.messaging.Message;
import org.eclipse.microprofile.reactive.messaging.spi.Connector;
import org.eclipse.microprofile.reactive.messaging.spi.ConnectorFactory;
/**
* SPI used to implement a connector managing a sink of messages for a specific transport. For example, to
* handle dispatch messages to Kafka, the reactive messaging extension would implement a {@code bean}
* implementing this interface. This bean is called for every {@code stream} that needs to be created for this
* specific transport (so Kafka in this example). These streams are connected to methods annotated with
* {@link org.eclipse.microprofile.reactive.messaging.Outgoing}.
*
* The factory is called to create a {@code subscriber} for each configured transport. The configuration is done
* using MicroProfile Config. The following snippet gives an example for a hypothetical Kafka connector:
*
*
* mp.messaging.outgoing.my-channel.connector=acme.kafka
* mp.messaging.outgoing.my-channel.topic=my-topic
* mp.messaging.connector.acme.kafka.bootstrap.servers=localhost:9092
* ...
*
*
* The configuration keys are structured as follows: {@code mp.messaging.[incoming|outgoing].channel-name.attribute} or
* {@code mp.messaging.[connector].connector-name.attribute}.
* Channel names are not expected to contain {@code .} so the first occurrence of a {@code .} in the channel-name portion
* of a property terminates the channel name and precedes the attribute name.
* For connector attributes, the longest string, inclusive of {@code .}s, that matches a loadable
* connector is used as a {@code connector-name}. The remainder, after a {@code .} separator, is the attribute name.
* Configuration keys that begin
* {@code mp.messaging.incoming} are not used for {@link OutboundConnector} configuration.
*
* The {@code channel-name} segment in the configuration key corresponds to the name of the channel used in the
* {@code Outgoing} annotation:
*
*
* @Outgoing("my-channel")
* public CompletionStage<String> produce(String s) {
* // ...
* }
*
*
* The set of attributes depend on the connector and transport layer (For example, bootstrap.servers is Kafka specific).
* The {@code connector} attribute indicates the name of the connector.
* It will be matched to the value returned by the {@link Connector} qualifier
* used on the relevant {@link OutboundConnector} bean implementation.
* This is how a reactive messaging implementation looks for the specific {@link OutboundConnector} required for
* a channel.
* Any {@code mp.messaging.connector} attributes for the channel's connector are also included in the set
* of relevant attributes. Where an attribute is present for both a channel and its connector the value of the channel
* specific attribute will take precedence.
* In the previous configuration, the smallrye reactive messaging would need to find the
* {@link OutboundConnector} implementation qualified with the {@link Connector} qualifier with the value
* {@code acme.kafka} to create the {@code my-channel} subscriber. Note that if
* the connector cannot be found, the deployment must be failed with a
* {@link jakarta.enterprise.inject.spi.DeploymentException}.
*
* The {@link #getSubscriber(Config)} is called for every channel that needs to be created. The
* {@link Config} object passed to the method contains a subset of the global configuration, and with the prefixes
* removed. So for the previous configuration, it would be:
*
*
* bootstrap.servers = localhost:9092
* topic = my-topic
*
*
* So the connector implementation can retrieve the value with {@link Config#getValue(String, Class)} and
* {@link Config#getOptionalValue(String, Class)}.
*
* If the configuration is invalid, the {@link #getSubscriber(Config)} method must throw an
* {@link IllegalArgumentException}, caught by smallrye reactive messaging implementation and triggering a failure in the
* deployment.
*
* This class is specific to SmallRye and is uses internally instead of
* {@link org.eclipse.microprofile.reactive.messaging.spi.OutgoingConnectorFactory}. Instead of a
* {@link org.eclipse.microprofile.reactive.streams.operators.SubscriberBuilder}, it returns a
* {@link Subscriber}.
*/
public interface OutboundConnector extends ConnectorFactory {
/**
* Creates a channel for the given configuration. The channel's configuration is associated with a
* specific {@code connector}, using the {@link Connector} qualifier's parameter indicating a key to
* which {@link org.eclipse.microprofile.reactive.messaging.Outgoing} to use.
*
* Note that the connection to the transport or broker is generally postponed until the
* subscription.
*
* @param config the configuration, never {@code null}, must contain the {@link #CHANNEL_NAME_ATTRIBUTE}
* attribute.
* @return the created {@link Subscriber}, must not be {@code null}.
* @throws IllegalArgumentException if the configuration is invalid.
* @throws NoSuchElementException if the configuration does not contain an expected attribute.
*/
Subscriber extends Message>> getSubscriber(Config config);
}