Spring Boot for NATS enables declarative abstractions for implementing NATS in Spring Boot applications.
TIP: This project is inspired by Spring Kafka and Spring Pulsar and thus tries to closely match their implementation style.
-
Add
nats-spring-boot-starterdependency to yourpom.xmlfile:<dependency> <groupId>dev.all-things.boot</groupId> <artifactId>nats-spring-boot-starter</artifactId> <version>0.1.0</version> </dependency>
-
Add
@EnableNatson your Spring Boot application / configuration class.@EnableNats @Configuration(proxyBeanMethods = false) public class NatsConfiguration { @Bean @ConditionalOnMissingBean public NatsConnectionConfiguration natsConnectionConfiguration() { NatsConnectionConfiguration configuration = new NatsConnectionConfiguration(); configuration.setServers(List.of("nats://0.0.0.0:58811")); configuration.setUsername("local"); configuration.setPassword("dH...yu"); return configuration; } }
-
Create a listener class and annotate listener method with
@NatsListenerand the subject.
-
Simple listener
@Component public class MessageListener { @NatsListener(subject = "zion.neo") public void onMessage(String message) { logger.info("Received message: {}", message); // Hello, Neo } }
-
Listener with reply
@Component public class MessageListener { @NatsListener(subject = "zion.neo", reply = @Reply(subject = "zion.trinity")) public String onMessage(String message) { logger.info("Received message: {}", message); // Hello, Neo return "Hello, Trinity"; // Sent to the subject 'zion.trinity' } }
TIP: Listener methods support
io.nats.client.Message,java.lang.Stringandbyte[]as reply types. However, user needs to explicitly set subject for the reply typeio.nats.client.Messageand the value set via annotation will be ignored. -
Listener with an unspecified reply type
@NatsListener(subject = "matrix.smith", reply = @Reply(subject = "matrix")) public Object onMessageWithGenericReply(final String message) { logger.info("Received message: {}", message); return switch (new Random(System.nanoTime()).nextInt(3)) { case 0 -> "Hello - From The Matrix"; case 1 -> UUID.randomUUID().toString(); default -> "Hello - From The Matrix".getBytes(StandardCharsets.UTF_8); }; }
TIP: A special handler will be created for listener methods with an unspecified return type which may be slightly inefficient. Also, error related to unsupported return types will be thrown at runtime. Use this feature only when necessary.
Certain attributes of the incoming message can be implicitly extracted and injected as parameters to the listener method.
-
@Headerallows single message header to be injected to the annotated parameter.@Headersinjects all message headers asMap<String, String>.@Component public class MessageListener { @NatsListener(subject = "zion.trinity") public void onMessage(Message message, String messageContent, @Header("id") String messageId, @Headers Map<String, String> headers) { logger.info("Received message '{}', content '{}', id '{}', headers '{}'", message, messageContent, messageId, headers); } }
TIP: Headers can also be injected in multi-value format i.e.
Map<String, List<String>.Map<String, String>serves simple use-cases where headers are expected to have single value. -
Unannotated parameters of types
io.nats.client.Message,java.lang.Stringand/orbyte[]are automatically treated as message content and injected accordingly.
- For better performance,
MethodHandle.invokeis used (instead ofMethod.invoke) for invoking the listener methods.
- JDK 17
- Spring Boot 3.2
This project is Open Source software released under the Apache 2.0 license.