Skip to content

Commit 28ab2dc

Browse files
committed
docs: add mandatory property documentation
1 parent 03c5ce4 commit 28ab2dc

File tree

4 files changed

+103
-74
lines changed

4 files changed

+103
-74
lines changed

docs/docs/reactive-commons/2-sending-a-domain-event.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,15 @@ Where name is the event name, eventId is an unique event identifier and data is
2626
public interface DomainEventBus {
2727
<T> Publisher<Void> emit(DomainEvent<T> event);
2828

29+
<T> Publisher<Void> emit(String domain, DomainEvent<T> event);
30+
2931
Publisher<Void> emit(CloudEvent event);
32+
33+
Publisher<Void> emit(String domain, CloudEvent event);
34+
35+
Publisher<Void> emit(RawMessage event);
36+
37+
Publisher<Void> emit(String domain, RawMessage event);
3038
}
3139
```
3240

docs/docs/reactive-commons/3-sending-a-command.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,21 @@ Where name is the command name, commandId is an unique command identifier and da
2525
```java
2626
public interface DirectAsyncGateway {
2727

28-
<T> Mono<Void> sendCommand(Command<T> command, String targetName);
28+
<T> Mono<Void> sendCommand(Command<T> command, String targetName);
2929

30-
<T> Mono<Void> sendCommand(Command<T> command, String targetName, long delayMillis);
30+
<T> Mono<Void> sendCommand(Command<T> command, String targetName, long delayMillis);
3131

3232
<T> Mono<Void> sendCommand(Command<T> command, String targetName, String domain); // Send to specific domain
3333

3434
<T> Mono<Void> sendCommand(Command<T> command, String targetName, long delayMillis, String domain); // Send to specific domain with delay
3535

3636
Mono<Void> sendCommand(CloudEvent command, String targetName); // Send with CloudEvent format
3737

38-
Mono<Void> sendCommand(CloudEvent command, String targetName, String domain); // Send with CloudEvent format to an specific domain
38+
Mono<Void> sendCommand(CloudEvent command, String targetName, long delayMillis); // Send with CloudEvent format and delay
39+
40+
Mono<Void> sendCommand(CloudEvent command, String targetName, String domain); // Send with CloudEvent format to specific domain
41+
42+
Mono<Void> sendCommand(CloudEvent command, String targetName, long delayMillis, String domain);
3943
}
4044
```
4145

@@ -44,7 +48,7 @@ You can send a CloudEvent or a Command\<T> to a target application. You also can
4448

4549
## Enabling autoconfiguration
4650

47-
To send Commands you should enable the respecting spring boot autoconfiguration using the `@EnableDomainEventBus` annotation
51+
To send Commands you should enable the respecting spring boot autoconfiguration using the `@EnableDirectAsyncGateway` annotation
4852
For example:
4953

5054
```java

docs/docs/reactive-commons/4-making-an-async-query.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public interface DirectAsyncGateway {
3333
<R extends CloudEvent> Mono<R> requestReply(CloudEvent query, String targetName, Class<R> type); // Query with CloudEvent format
3434

3535
<R extends CloudEvent> Mono<R> requestReply(CloudEvent query, String targetName, Class<R> type, String domain); // Query with CloudEvent format to specific domain
36+
37+
<T> Mono<Void> reply(T response, From from); // Reply to a query
3638
}
3739
```
3840

docs/docs/reactive-commons/9-configuration-properties.md

Lines changed: 85 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ Resultado:
307307

308308
### Ventajas
309309

310-
- Detección temprana de errores de enrutamiento: Evita que mensajes críticos “desaparezcan” sin rastro lo que facilita
310+
- Detección temprana de errores de enrutamiento: Evita que mensajes críticos “desaparezcan” sin rastro lo que facilita
311311
la identificación de configuraciones erróneas en bindings o patrones.
312312
- Integridad y fiabilidad: Garantiza que cada mensaje encuentre un consumidor o, en su defecto, regrese al productor
313313
para un manejo alternativo (colas DLQ, logs, base de datos).
@@ -320,8 +320,8 @@ Aunque esta propiedad no evita problemas de rendimiento o degradación del clús
320320
pérdida de mensajes no enrutados y para detectar errores de configuración en el enrutamiento.
321321

322322
Cuando mandatory está activo, en condiciones normales (todas las rutas existen) no hay prácticamente impacto. En
323-
situaciones anómalas, habrá un tráfico adicional de retorno por cada mensaje no enrutable. Esto supone carga extra
324-
tanto para RabbitMQ (que debe enviar de vuelta el mensaje al productor) como para la aplicación emisora (que debe
323+
situaciones anómalas, habrá un tráfico adicional de retorno por cada mensaje no enrutable. Esto supone carga extra
324+
tanto para RabbitMQ (que debe enviar de vuelta el mensaje al productor) como para la aplicación emisora (que debe
325325
procesar el mensaje devuelto).
326326

327327
### Implementación
@@ -347,6 +347,7 @@ package sample;
347347
import co.com.mypackage.usecase.MyUseCase;
348348
import lombok.RequiredArgsConstructor;
349349
import lombok.extern.java.Log;
350+
import org.reactivecommons.async.rabbit.communications.MyOutboundMessage;
350351
import org.reactivecommons.async.rabbit.communications.UnroutableMessageHandler;
351352
import org.springframework.stereotype.Component;
352353
import reactor.core.publisher.Mono;
@@ -362,7 +363,7 @@ public class ResendUnroutableMessageHandler implements UnroutableMessageHandler
362363
private final MyUseCase useCase;
363364
364365
@Override
365-
public Mono<Void> processMessage(OutboundMessageResult result) {
366+
public Mono<Void> processMessage(OutboundMessageResult<MyOutboundMessage> result) {
366367
var returned = result.getOutboundMessage();
367368
log.severe("Unroutable message: exchange=" + returned.getExchange()
368369
+ ", routingKey=" + returned.getRoutingKey()
@@ -376,26 +377,89 @@ public class ResendUnroutableMessageHandler implements UnroutableMessageHandler
376377
}
377378
```
378379

379-
#### Reenviar mensajes no enrutados a una cola
380+
#### Enviar mensajes no enrutados a una cola
380381

381-
Si queremos volver a enviar el mensaje a una cola es importante tener en cuenta que si la cola no existe el mensaje se
382-
perderá, por lo que antes de enviar el mensaje debemos asegurarnos de que la cola esté creada.
382+
Para enviar el mensaje no enrutado a una cola, utilizamos las anotaciones `@EnableDomainEventBus` para
383+
[eventos de dominio](/reactive-commons-java/docs/reactive-commons/sending-a-domain-event), y `@EnableDirectAsyncGateway`
384+
para [comandos](/reactive-commons-java/docs/reactive-commons/sending-a-command) y
385+
[consultas asíncronas](/reactive-commons-java/docs/reactive-commons/making-an-async-query), según corresponda.
383386

384-
En la clase de configuración de RabbitMQ creamos el bean `ReactiveMessageSender` para obtener la conexión al
385-
broker y usamos las propiedades de conexión definidas a través del bean `AsyncRabbitPropsDomainProperties` para indicar
386-
a que broker nos conectamos:
387+
Es importante asegurarse de que la cola exista antes de enviar el mensaje, ya que, de lo contrario, este se perderá.
388+
Por lo tanto, se recomienda verificar o crear la cola previamente para garantizar una entrega exitosa.
387389

388390
```java
389391
package sample;
390392
393+
import com.fasterxml.jackson.core.type.TypeReference;
394+
import com.fasterxml.jackson.databind.JsonNode;
391395
import com.fasterxml.jackson.databind.ObjectMapper;
392-
import org.reactivecommons.async.rabbit.RabbitMQSetupUtils;
393-
import org.reactivecommons.async.rabbit.RabbitMQFactory;
394-
import org.reactivecommons.async.rabbit.communications.ReactiveMessageSender;
396+
import org.reactivecommons.api.domain.Command;
397+
import org.reactivecommons.async.api.DirectAsyncGateway;
398+
import org.reactivecommons.async.impl.config.annotations.EnableDirectAsyncGateway;
399+
import org.reactivecommons.async.rabbit.communications.MyOutboundMessage;
395400
import org.reactivecommons.async.rabbit.communications.UnroutableMessageHandler;
401+
import org.springframework.beans.factory.annotation.Value;
402+
import org.springframework.stereotype.Component;
403+
import reactor.core.publisher.Mono;
404+
import reactor.rabbitmq.OutboundMessage;
405+
import reactor.rabbitmq.OutboundMessageResult;
406+
407+
@Component
408+
@EnableDirectAsyncGateway
409+
public class ResendUnroutableMessageHandler implements UnroutableMessageHandler {
410+
411+
private final ObjectMapper objectMapper;
412+
private final String retryQueueName;
413+
private final DirectAsyncGateway gateway;
414+
415+
public ResendUnroutableMessageHandler(
416+
ObjectMapper objectMapper,
417+
DirectAsyncGateway gateway,
418+
@Value("${adapters.rabbitmq.retry-queue-name}") String retryQueueName) {
419+
this.objectMapper = objectMapper;
420+
this.retryQueueName = retryQueueName;
421+
this.gateway = gateway;
422+
}
423+
424+
public Mono<Void> emitCommand(String name, String commandId, Object data) {
425+
return Mono.from(gateway.sendCommand(
426+
// Connection with broker using the properties defined through the
427+
// AsyncRabbitPropsDomainProperties bean with the "logs" domain
428+
new Command<>(name, commandId, data), retryQueueName, "logs")
429+
);
430+
}
431+
432+
@Override
433+
public Mono<Void> processMessage(OutboundMessageResult<MyOutboundMessage> result) {
434+
OutboundMessage returned = result.getOutboundMessage();
435+
try {
436+
// The unroutable message is a command, so the message body is deserialized to the Command class.
437+
// Use the DomainEvent class for domain events and the AsyncQuery class for asynchronous queries.
438+
Command<JsonNode> command = objectMapper.readValue(returned.getBody(), new TypeReference<>() {
439+
});
440+
441+
// Send the message to the queue
442+
return emitCommand(command.getName(), command.getCommandId(), command.getData())
443+
.doOnError(e -> log.severe("Failed to send the returned message: " + e.getMessage()));
444+
} catch (Exception e) {
445+
log.severe("Error deserializing the returned message: " + e.getMessage());
446+
return Mono.empty();
447+
}
448+
}
449+
}
450+
```
451+
452+
En la clase de configuración de RabbitMQ creamos el bean `UnroutableMessageProcessor` para registrar el handler de mensajes no enrutados.
453+
454+
```java
455+
package sample;
456+
457+
import org.reactivecommons.async.rabbit.communications.UnroutableMessageNotifier;
458+
import org.reactivecommons.async.rabbit.communications.UnroutableMessageProcessor;
396459
import org.reactivecommons.async.rabbit.config.RabbitProperties;
397460
import org.reactivecommons.async.rabbit.config.props.AsyncProps;
398461
import org.reactivecommons.async.rabbit.config.props.AsyncRabbitPropsDomainProperties;
462+
import org.springframework.beans.factory.annotation.Qualifier;
399463
import org.springframework.beans.factory.annotation.Value;
400464
import org.springframework.context.annotation.Bean;
401465
import org.springframework.context.annotation.Configuration;
@@ -411,7 +475,7 @@ public class RabbitMQConfig {
411475
private final Integer retryDelay;
412476
413477
public RabbitMQConfig(@Qualifier("rabbit") RabbitMQConnectionProperties properties,
414-
@Qualifier("rabbitDual") RabbitMQConnectionProperties propertiesLogs,
478+
@Qualifier("rabbitLogs") RabbitMQConnectionProperties propertiesLogs,
415479
@Value("${adapters.rabbitmq.withDLQRetry}") Boolean withDLQRetry,
416480
@Value("${adapters.rabbitmq.maxRetries}") Integer maxRetries,
417481
@Value("${adapters.rabbitmq.retryDelay}") Integer retryDelay) {
@@ -422,6 +486,7 @@ public class RabbitMQConfig {
422486
this.retryDelay = retryDelay;
423487
}
424488
489+
// This bean is used to create the RabbitMQ connection properties for the application
425490
@Bean
426491
@Primary
427492
public AsyncRabbitPropsDomainProperties customDomainProperties() {
@@ -456,64 +521,14 @@ public class RabbitMQConfig {
456521
.build();
457522
}
458523
459-
// This bean is used to create the RabbitMQ connection and the message sender
524+
// This bean is used to register the handler for unroutable messages
460525
@Bean
461-
public ReactiveMessageSender reactiveMessageSender(ReactiveMQFactory providerFactory,
462-
AsyncRabbitPropsDomainProperties properties) {
463-
return providerFactory.createMessageSenderFromProperties(properties.get("app"));
526+
UnroutableMessageProcessor registerUnroutableMessageHandler(UnroutableMessageNotifier unroutableMessageNotifier,
527+
ResendUnroutableMessageHandler handler) {
528+
var factory = new UnroutableMessageProcessor();
529+
unroutableMessageNotifier.listenToUnroutableMessages(handler);
530+
return factory;
464531
}
465532
466533
}
467534
```
468-
469-
Ahora, en el handler de mensajes no enrutados podemos enviar el mensaje a una cola específica:
470-
```java
471-
package sample;
472-
473-
import com.fasterxml.jackson.core.type.TypeReference;
474-
import com.fasterxml.jackson.databind.JsonNode;
475-
import com.fasterxml.jackson.databind.ObjectMapper;
476-
import lombok.extern.java.Log;
477-
import org.reactivecommons.api.domain.Command;
478-
import org.reactivecommons.async.rabbit.communications.ReactiveMessageSender;
479-
import org.reactivecommons.async.rabbit.communications.UnroutableMessageHandler;
480-
import org.springframework.beans.factory.annotation.Value;
481-
import org.springframework.stereotype.Component;
482-
import reactor.core.publisher.Mono;
483-
import reactor.rabbitmq.OutboundMessage;
484-
import reactor.rabbitmq.OutboundMessageResult;
485-
486-
@Log
487-
@Component
488-
public class ResendUnroutableMessageHandler implements UnroutableMessageHandler {
489-
490-
private final ReactiveMessageSender sender;
491-
private final ObjectMapper objectMapper;
492-
private final String retryQueueName;
493-
494-
public ResendUnroutableMessageHandler(ReactiveMessageSender sender,
495-
ObjectMapper objectMapper,
496-
@Value("${adapters.rabbitmq.retry-queue-name}") String retryQueueName) {
497-
this.sender = sender;
498-
this.objectMapper = objectMapper;
499-
this.retryQueueName = retryQueueName;
500-
}
501-
502-
@Override
503-
public Mono<Void> processMessage(OutboundMessageResult result) {
504-
OutboundMessage returned = result.getOutboundMessage();
505-
try {
506-
// The message we get is of command type, so the message body is deserialized to the Command class.
507-
// For domain events the DomainEvent class should be used and for asynchronous queries the AsyncQuery class.
508-
Command<JsonNode> command = objectMapper.readValue(returned.getBody(), new TypeReference<>() {
509-
});
510-
511-
// Send the message to the queue
512-
return sender.sendMessage(command, returned.getExchange(), retryQueueName, returned.getProperties().getHeaders());
513-
} catch (Exception e) {
514-
log.severe("Error deserializing the returned message: " + e.getMessage());
515-
return Mono.empty();
516-
}
517-
}
518-
}
519-
```

0 commit comments

Comments
 (0)