Quiz: Advanced Techniques
Test your knowledge on WebFlux, Redis, RabbitMQ, Scheduling, and WebSockets.
30 questions - Click on each question to reveal the answer.
Questions 1-10: Reactive Programming (WebFlux)
Question 1: What is the difference between Spring MVC and WebFlux?
Answer:
| Spring MVC | WebFlux |
|---|---|
| Blocking | Non-blocking |
| 1 thread/request | Event loop |
| Servlet API | Reactive Streams |
| Tomcat, Jetty | Netty |
| Vertical scalability | Horizontal scalability |
Question 2: What is the difference between Mono and Flux?
Answer:
Mono: 0 or 1 elementFlux: 0 to N elements
Mono<User> user = userRepository.findById(1L);
Flux<User> users = userRepository.findAll();
Question 3: What are common Mono/Flux operators?
Answer:
| Operator | Description |
|---|---|
map | Synchronous transformation |
flatMap | Async transformation |
filter | Filtering |
zip | Combine |
onErrorReturn | Error fallback |
switchIfEmpty | Empty fallback |
timeout | Time limit |
retry | Retry |
Question 4: How to write a reactive controller?
Answer:
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserRepository repository;
@GetMapping
public Flux<User> getAll() {
return repository.findAll();
}
@GetMapping("/{id}")
public Mono<ResponseEntity<User>> getById(@PathVariable Long id) {
return repository.findById(id)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Mono<User> create(@RequestBody User user) {
return repository.save(user);
}
}
Question 5: What is R2DBC?
Answer: Reactive Relational Database Connectivity - non-blocking access to relational databases.
public interface UserRepository extends ReactiveCrudRepository<User, Long> {
Flux<User> findByEmail(String email);
}
Replaces blocking JPA/JDBC in reactive applications.
Question 6: How to use WebClient?
Answer:
@Service
public class ExternalApiService {
private final WebClient webClient;
public Mono<Data> fetchData(String id) {
return webClient.get()
.uri("/data/{id}", id)
.retrieve()
.bodyToMono(Data.class)
.timeout(Duration.ofSeconds(5))
.retry(3);
}
}
Question 7: Why never call block() in production?
Answer: block() blocks the thread, negating the benefits of reactive:
- Blocks the event loop
- Reduces throughput
- Can cause deadlocks
Use only in tests.
Question 8: How to test reactive code?
Answer:
@Test
void shouldFindUser() {
Mono<User> userMono = userService.findById(1L);
StepVerifier.create(userMono)
.assertNext(user -> {
assertThat(user.getName()).isEqualTo("John");
})
.verifyComplete();
}
@Test
void shouldHandleError() {
Mono<User> userMono = userService.findById(999L);
StepVerifier.create(userMono)
.expectError(NotFoundException.class)
.verify();
}
Question 9: When to use WebFlux?
Answer:
- High concurrency (thousands of connections)
- Data streaming
- Real-time applications
- Integrations with many external calls
Avoid if: untrained team, blocking libraries, simple CRUD.
Question 10: How to handle errors reactively?
Answer:
return userRepository.findById(id)
.switchIfEmpty(Mono.error(new NotFoundException("User not found")))
.onErrorReturn(new User("Fallback"))
.onErrorResume(e -> {
log.error("Error: {}", e.getMessage());
return Mono.empty();
});
Questions 11-17: Caching with Redis
Question 11: How to configure Spring Cache with Redis?
Answer:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
@Configuration
@EnableCaching
public class CacheConfig { }
Question 12: How to use @Cacheable?
Answer:
@Cacheable(value = "users", key = "#id")
public User findById(Long id) {
log.info("Fetching from DB");
return userRepository.findById(id).orElseThrow();
}
// First call: DB
// Subsequent calls: cache
Question 13: What is the difference between @Cacheable, @CachePut, and @CacheEvict?
Answer:
| Annotation | Behavior |
|---|---|
@Cacheable | Reads from cache or executes and caches |
@CachePut | Always executes and updates the cache |
@CacheEvict | Removes from cache |
@CachePut(value = "users", key = "#user.id")
public User update(User user) { }
@CacheEvict(value = "users", key = "#id")
public void delete(Long id) { }
@CacheEvict(value = "users", allEntries = true)
public void clearCache() { }
Question 14: How to configure cache TTL?
Answer:
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30))
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
Question 15: How to use RedisTemplate directly?
Answer:
@Service
public class SessionService {
private final RedisTemplate<String, Object> redisTemplate;
public void saveSession(String token, UserSession session) {
redisTemplate.opsForValue().set(
"session:" + token,
session,
Duration.ofHours(1)
);
}
public UserSession getSession(String token) {
return (UserSession) redisTemplate.opsForValue()
.get("session:" + token);
}
}
Question 16: How to handle Redis unavailability?
Answer:
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
@Override
public CacheErrorHandler errorHandler() {
return new SimpleCacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException ex, Cache cache, Object key) {
log.warn("Cache error: {}", ex.getMessage());
// Continue without cache
}
};
}
}
Question 17: When to cache?
Answer:
- Frequently read, rarely modified data
- Expensive computations
- External API calls
- Reference data (countries, categories)
Avoid: real-time data, sensitive personal data.
Questions 18-23: Messaging with RabbitMQ
Question 18: How to configure RabbitMQ with Spring?
Answer:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
Question 19: What are the types of RabbitMQ exchanges?
Answer:
| Type | Routing |
|---|---|
| Direct | Exact routing key |
| Fanout | Broadcast to all queues |
| Topic | Pattern matching (*.error, order.#) |
| Headers | Based on headers |
Question 20: How to send a message?
Answer:
@Service
public class OrderProducer {
private final RabbitTemplate rabbitTemplate;
public void sendOrderEvent(OrderEvent event) {
rabbitTemplate.convertAndSend(
"order.exchange", // exchange
"order.created", // routing key
event // message
);
}
}
Question 21: How to receive a message?
Answer:
@Component
public class OrderListener {
@RabbitListener(queues = "order.queue")
public void handleOrder(OrderEvent event) {
log.info("Received: {}", event);
processOrder(event);
}
}
Question 22: What is a Dead Letter Queue?
Answer: Queue that receives failed messages (rejected, expired, max retries):
@Bean
public Queue orderQueue() {
return QueueBuilder.durable("order.queue")
.withArgument("x-dead-letter-exchange", "dlx.exchange")
.withArgument("x-dead-letter-routing-key", "dlq")
.build();
}
Allows analyzing and reprocessing errors.
Question 23: How to ensure message delivery?
Answer:
- Publisher confirms: exchange confirmation
- Consumer acks: processing confirmation
- Persistent messages: survives restart
- Durable queues: persistent queues
@RabbitListener(queues = "order.queue", ackMode = "MANUAL")
public void handle(OrderEvent event, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) {
try {
process(event);
channel.basicAck(tag, false);
} catch (Exception e) {
channel.basicNack(tag, false, false);
}
}
Questions 24-27: Scheduled Tasks
Question 24: How to enable scheduling?
Answer:
@SpringBootApplication
@EnableScheduling
public class Application { }
Question 25: What are the options for @Scheduled?
Answer:
// Every 5 seconds
@Scheduled(fixedRate = 5000)
// 5 seconds after completion
@Scheduled(fixedDelay = 5000)
// Cron expression
@Scheduled(cron = "0 0 6 * * *") // Every day at 6 AM
// With initial delay
@Scheduled(fixedRate = 5000, initialDelay = 10000)
Question 26: How to write a Cron expression?
Answer:
┌───────────── second (0-59)
│ ┌───────────── minute (0-59)
│ │ ┌───────────── hour (0-23)
│ │ │ ┌───────────── day of month (1-31)
│ │ │ │ ┌───────────── month (1-12)
│ │ │ │ │ ┌───────────── day of week (0-7)
* * * * * *
Examples:
0 0 * * * *: every hour0 0 9 * * MON-FRI: 9 AM on weekdays0 */15 * * * *: every 15 minutes
Question 27: How to run a method asynchronously?
Answer:
@EnableAsync
@Configuration
public class AsyncConfig { }
@Service
public class EmailService {
@Async
public CompletableFuture<Boolean> sendEmail(String to) {
// Executed in another thread
return CompletableFuture.completedFuture(true);
}
}
Questions 28-30: WebSockets
Question 28: How to configure WebSocket with STOMP?
Answer:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic", "/queue");
registry.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws").withSockJS();
}
}
Question 29: How to send and receive WebSocket messages?
Answer:
@Controller
public class ChatController {
@MessageMapping("/chat.send")
@SendTo("/topic/messages")
public ChatMessage send(ChatMessage message) {
return message;
}
}
// Programmatic sending
@Service
public class NotificationService {
private final SimpMessagingTemplate template;
public void notifyUser(String userId, Notification notif) {
template.convertAndSendToUser(userId, "/queue/notifications", notif);
}
}
Question 30: When to use WebSocket vs REST?
Answer:
| WebSocket | REST |
|---|---|
| Bidirectional communication | Request-Response |
| Real-time | Static data |
| Chat, notifications | CRUD, API |
| Persistent connection | Short connections |
| Games, trading | Traditional applications |
Score
| Score | Level |
|---|---|
| 27-30 | Excellent - Mastered advanced techniques |
| 21-26 | Good - Some revisions needed |
| 15-20 | Average - Review the chapters |
| Less than 15 | Needs improvement |