use of org.eclipse.microprofile.reactive.messaging.spi.Connector in project smallrye-reactive-messaging by smallrye.
the class ConnectorAttributeProcessor method process.
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (invoked) {
return true;
}
invoked = true;
Set<? extends Element> annotated = roundEnv.getElementsAnnotatedWith(ConnectorAttributes.class);
Set<? extends Element> others = roundEnv.getElementsAnnotatedWith(ConnectorAttribute.class);
Set<Element> all = new LinkedHashSet<>();
all.addAll(annotated);
all.addAll(others);
for (Element annotatedElement : all) {
String className = annotatedElement.toString();
Connector connector = getConnector(annotatedElement);
ConnectorAttributes annotation = annotatedElement.getAnnotation(ConnectorAttributes.class);
ConnectorAttribute[] attributes;
if (annotation == null) {
attributes = new ConnectorAttribute[] { annotatedElement.getAnnotation(ConnectorAttribute.class) };
} else {
attributes = annotation.value();
}
List<ConnectorAttribute> incomingAttributes = new ArrayList<>();
List<ConnectorAttribute> outgoingAttributes = new ArrayList<>();
List<ConnectorAttribute> commonAttributes = new ArrayList<>();
for (ConnectorAttribute attribute : attributes) {
addAttributeToList(commonAttributes, attribute, ConnectorAttribute.Direction.INCOMING_AND_OUTGOING);
addAttributeToList(incomingAttributes, attribute, ConnectorAttribute.Direction.INCOMING);
addAttributeToList(outgoingAttributes, attribute, ConnectorAttribute.Direction.OUTGOING);
}
validate(commonAttributes);
validate(incomingAttributes);
validate(outgoingAttributes);
ConfigurationClassWriter classWriter = new ConfigurationClassWriter(processingEnv);
ConfigurationDocWriter asciidocWriter = new ConfigurationDocWriter(processingEnv);
ConfigurationMarkdownDocWriter markdownWriter = new ConfigurationMarkdownDocWriter(processingEnv);
try {
classWriter.generateAllClasses(connector, className, commonAttributes, incomingAttributes, outgoingAttributes);
asciidocWriter.generate(connector, commonAttributes, incomingAttributes, outgoingAttributes);
markdownWriter.generate(connector, commonAttributes, incomingAttributes, outgoingAttributes);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return true;
}
use of org.eclipse.microprofile.reactive.messaging.spi.Connector in project helidon by oracle.
the class ChannelRouter method registerConnectorFactory.
/**
* Register connector bean, can be recognized as a bean implementing
* {@link org.eclipse.microprofile.reactive.messaging.spi.IncomingConnectorFactory}
* or {@link org.eclipse.microprofile.reactive.messaging.spi.OutgoingConnectorFactory}
* or both with annotation {@link org.eclipse.microprofile.reactive.messaging.spi.Connector}.
*
* @param bean connector bean
*/
void registerConnectorFactory(Bean<?> bean) {
Class<?> beanType = bean.getBeanClass();
Connector annotation = beanType.getAnnotation(Connector.class);
if (IncomingConnectorFactory.class.isAssignableFrom(beanType) && null != annotation) {
incomingConnectorFactoryList.add(bean);
}
if (OutgoingConnectorFactory.class.isAssignableFrom(beanType) && null != annotation) {
outgoingConnectorFactoryList.add(bean);
}
}
use of org.eclipse.microprofile.reactive.messaging.spi.Connector in project smallrye-reactive-messaging by smallrye.
the class RabbitMQConnector method getSubscriberBuilder.
/**
* Creates a <em>channel</em> 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.
* <p>
* Note that the connection to the <em>transport</em> or <em>broker</em> 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 SubscriberBuilder}, must not be {@code null}.
* @throws IllegalArgumentException if the configuration is invalid.
* @throws NoSuchElementException if the configuration does not contain an expected attribute.
*/
@Override
public SubscriberBuilder<? extends Message<?>, Void> getSubscriberBuilder(final Config config) {
final RabbitMQConnectorOutgoingConfiguration oc = new RabbitMQConnectorOutgoingConfiguration(config);
outgoingChannelStatus.put(oc.getChannel(), ChannelStatus.INITIALISING);
// Create a client
final RabbitMQClient client = RabbitMQClientHelper.createClient(this, oc, clientOptions, credentialsProviders);
final ConnectionHolder holder = new ConnectionHolder(client, oc, getVertx());
final Uni<RabbitMQPublisher> getSender = holder.getOrEstablishConnection().onItem().call(connection -> establishExchange(connection, oc)).onItem().transformToUni(connection -> Uni.createFrom().item(RabbitMQPublisher.create(getVertx(), connection, new RabbitMQPublisherOptions().setReconnectAttempts(oc.getReconnectAttempts()).setReconnectInterval(ofSeconds(oc.getReconnectInterval()).toMillis()).setMaxInternalQueueSize(oc.getMaxOutgoingInternalQueueSize().orElse(Integer.MAX_VALUE))))).onItem().call(RabbitMQPublisher::start).invoke(s -> {
// Add the channel in the opened state
outgoingChannelStatus.put(oc.getChannel(), ChannelStatus.CONNECTED);
}).onFailure().invoke(t -> outgoingChannelStatus.put(oc.getChannel(), ChannelStatus.NOT_CONNECTED)).onFailure().recoverWithNull().memoize().indefinitely().onCancellation().invoke(() -> outgoingChannelStatus.put(oc.getChannel(), ChannelStatus.NOT_CONNECTED));
// Set up a sender based on the publisher we established above
final RabbitMQMessageSender processor = new RabbitMQMessageSender(oc, getSender);
subscriptions.add(processor);
// Return a SubscriberBuilder
return ReactiveStreams.<Message<?>>builder().via(processor).onError(t -> {
log.error(oc.getChannel(), t);
outgoingChannelStatus.put(oc.getChannel(), ChannelStatus.NOT_CONNECTED);
}).ignore();
}
use of org.eclipse.microprofile.reactive.messaging.spi.Connector in project smallrye-reactive-messaging by smallrye.
the class RabbitMQConnector method getPublisherBuilder.
/**
* Creates a <em>channel</em> 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 IncomingConnectorFactory} to use.
*
* <p>
* Note that the connection to the <em>transport</em> or <em>broker</em> is generally postponed until the
* subscription occurs.
*
* @param config the configuration, must not be {@code null}, must contain the {@link #CHANNEL_NAME_ATTRIBUTE}
* attribute.
* @return the created {@link PublisherBuilder}, will not be {@code null}.
* @throws IllegalArgumentException if the configuration is invalid.
* @throws NoSuchElementException if the configuration does not contain an expected attribute.
*/
@Override
public PublisherBuilder<? extends Message<?>> getPublisherBuilder(final Config config) {
final RabbitMQConnectorIncomingConfiguration ic = new RabbitMQConnectorIncomingConfiguration(config);
incomingChannelStatus.put(ic.getChannel(), ChannelStatus.INITIALISING);
// Create a client
final RabbitMQClient client = RabbitMQClientHelper.createClient(this, ic, clientOptions, credentialsProviders);
final ConnectionHolder holder = new ConnectionHolder(client, ic, getVertx());
final RabbitMQFailureHandler onNack = createFailureHandler(ic);
final RabbitMQAckHandler onAck = createAckHandler(ic);
// Ensure we set the queue up
Uni<RabbitMQClient> uniQueue = holder.getOrEstablishConnection().onItem().call(connection -> establishQueue(connection, ic)).onItem().call(connection -> establishDLQ(connection, ic)).onItem().invoke(connection -> incomingChannelStatus.put(ic.getChannel(), ChannelStatus.CONNECTED));
// Once the queue is set up, set yp a consumer
final Integer interval = ic.getReconnectInterval();
final Integer attempts = ic.getReconnectAttempts();
Multi<? extends Message<?>> multi = uniQueue.onItem().transformToUni(connection -> client.basicConsumer(ic.getQueueName(), new QueueOptions().setAutoAck(ic.getAutoAcknowledgement()).setMaxInternalQueueSize(ic.getMaxIncomingInternalQueueSize()).setKeepMostRecent(ic.getKeepMostRecent()))).onItem().transformToMulti(consumer -> getStreamOfMessages(consumer, holder, ic, onNack, onAck)).plug(m -> {
if (attempts > 0) {
return m.onFailure().invoke(log::retrieveMessagesRetrying).onFailure().retry().withBackOff(ofSeconds(1), ofSeconds(interval)).atMost(attempts).onFailure().invoke(t -> {
incomingChannelStatus.put(ic.getChannel(), ChannelStatus.NOT_CONNECTED);
log.retrieveMessagesNoMoreRetrying(t);
});
}
return m;
});
if (Boolean.TRUE.equals(ic.getBroadcast())) {
multi = multi.broadcast().toAllSubscribers();
}
return ReactiveStreams.fromPublisher(multi);
}
use of org.eclipse.microprofile.reactive.messaging.spi.Connector in project smallrye-reactive-messaging by smallrye.
the class ConfigurationDocWriterTest method test.
@Test
public void test() throws IOException {
ProcessingEnvironment pe = mock(ProcessingEnvironment.class);
ConfigurationDocWriter writer = new ConfigurationDocWriter(pe);
List<ConnectorAttribute> attributes = new ArrayList<>();
attributes.add(new ConnectorAttributeLiteral("a", "desc-a", "string", true, ConnectorAttribute.Direction.INCOMING));
attributes.add(new ConnectorAttributeLiteral("b", "desc-b", "int", false, ConnectorAttribute.Direction.INCOMING));
attributes.add(new ConnectorAttributeLiteral("c", "desc-c", "boolean", true, ConnectorAttribute.Direction.INCOMING).setAlias("alias-c"));
attributes.add(new ConnectorAttributeLiteral("d", "desc-d", "string", false, ConnectorAttribute.Direction.INCOMING).setDefaultValue("d"));
attributes.add(new ConnectorAttributeLiteral("e", "desc-e", "string", false, ConnectorAttribute.Direction.INCOMING).setDefaultValue("e").setAlias("alias-e"));
attributes.add(new ConnectorAttributeLiteral("f", "desc-f", "string", true, ConnectorAttribute.Direction.INCOMING).setAlias("alias-f"));
Connector connector = ConnectorLiteral.of("my-connector");
ByteArrayOutputStream boas = new ByteArrayOutputStream();
try (PrintWriter pw = new PrintWriter(boas)) {
writer.generateDocumentation(connector, "Incoming", attributes, Collections.emptyList(), pw);
pw.flush();
}
String content = boas.toString("UTF-8");
assertThat(content).isNotEmpty();
boas = new ByteArrayOutputStream();
try (PrintWriter pw = new PrintWriter(boas)) {
writer.generateDocumentation(connector, "Outgoing", attributes, Collections.emptyList(), pw);
pw.flush();
}
content = boas.toString("UTF-8");
assertThat(content).isNotEmpty();
}
Aggregations