Skip to content

14.2.3 Sending fire-and-forget messages

Imagine that you’re on a starship that has just come under attack from an enemy vessel. You sound a ship-wide “red alert” so that all hands are in battle mode. You don’t need to wait for a response from the ship’s computers affirming the alert status, nor do you have time to wait for and read any kind of response in this situation. You set the alert and then move on to more critical matters.

This is an example of fire-and-forget. Although you may not forget that you’re at red alert, given the circumstances, it’s more important that you deal with the battle crisis than it is for you to handle a response from setting the alert.

To simulate this scenario, we’ll create an RSocket server that handles alert statuses but doesn’t return anything. First, we’ll need to define a class that defines the request payload, such as the Alert class in the following code listing.

Listing 14.6 A model class representing an alert

java
package rsocket;

import java.time.Instant;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Alert {

  private Level level;
  private String orderedBy;
  private Instant orderedAt;

  public static enum Level {
    YELLOW, ORANGE, RED, BLACK
  }
}

The Alert object captures the alert level, who ordered the alert, and a timestamp for when the alert was ordered (defined as an Instant). Again, we’re using Lombok for constructors and accessor methods in the interest of keeping the listing short.

On the server side, the AlertController in the following listing will handle Alert messages.

Listing 14.7 An RSocket controller to handle alert updates

java
package rsocket;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.stereotype.Controller;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

@Controller
@Slf4j
public class AlertController {

  @MessageMapping("alert")
  public Mono<Void> setAlert(Mono<Alert> alertMono) {
    return alertMono
        .doOnNext(alert -> {
          log.info(alert.getLevel() + " alert"
          + " ordered by " + alert.getOrderedBy()
          + " at " + alert.getOrderedAt());
        })
        .thenEmpty(Mono.empty());
  }
}

The setAlert() method handles Alert messages on the "alert" route. To keep things simple (albeit useless in an actual battle situation), it logs only the alerts. But what’s important is that it returns a Mono<Void>, indicating that there is no response, and, therefore, this handler method supports the fire-and-forget model.

In the client, the code isn’t much different from the request-response or requeststream models, as shown here:

java
RSocketRequester tcp = requesterBuilder.tcp("localhost", 7000);
tcp
  .route("alert")
  .data(new Alert(
    Alert.Level.RED, "Craig", Instant.now()))
  .send()
  .subscribe();
log.info("Alert sent");

Notice, however, that instead of calling retrieveMono() or retrieveFlux(), the client merely calls send() with no expectation of a response.

Now let’s take a look at how to handle the channel communication model in which both the server and the client send multiple messages to each other.

Released under the MIT License.