@Override protected Object handleRequestMessage(Message<?> requestMessage) { org.springframework.amqp.core.Message amqpMessage = MappingUtils.mapMessage(requestMessage, this.messageConverter, getHeaderMapper(), getDefaultDeliveryMode(), isHeadersMappedLast()); addDelayProperty(requestMessage, amqpMessage); RabbitMessageFuture future = this.template.sendAndReceive(generateExchangeName(requestMessage), generateRoutingKey(requestMessage), amqpMessage); future.addCallback(new FutureCallback(requestMessage)); CorrelationData correlationData = generateCorrelationData(requestMessage); if (correlationData != null && future.getConfirm() != null) { future.getConfirm().addCallback(new CorrelationCallback(correlationData, future)); } return null; }
@Override protected void doStop() { this.template.stop(); super.doStop(); }
@Test public void testAsyncDelayExpression() { ConnectionFactory connectionFactory = mock(ConnectionFactory.class); AsyncRabbitTemplate amqpTemplate = spy(new AsyncRabbitTemplate(new RabbitTemplate(connectionFactory), new SimpleMessageListenerContainer(connectionFactory), "replyTo")); amqpTemplate.setTaskScheduler(mock(TaskScheduler.class)); AsyncAmqpOutboundGateway gateway = new AsyncAmqpOutboundGateway(amqpTemplate); willAnswer( invocation -> amqpTemplate.new RabbitMessageFuture("foo", invocation.getArgument(2))) .given(amqpTemplate).sendAndReceive(anyString(), anyString(), any(Message.class)); gateway.setExchangeName("foo"); gateway.setRoutingKey("bar"); gateway.setDelayExpressionString("42"); gateway.setBeanFactory(mock(BeanFactory.class)); gateway.setOutputChannel(new NullChannel()); gateway.afterPropertiesSet(); gateway.start(); ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class); gateway.handleMessage(new GenericMessage<>("foo")); verify(amqpTemplate).sendAndReceive(eq("foo"), eq("bar"), captor.capture()); assertThat(captor.getValue().getMessageProperties().getDelay(), equalTo(42)); }
public AsyncAmqpOutboundGateway(AsyncRabbitTemplate template) { Assert.notNull(template, "AsyncRabbitTemplate cannot be null"); this.template = template; this.messageConverter = template.getMessageConverter(); Assert.notNull(this.messageConverter, "the template's message converter cannot be null"); setConnectionFactory(this.template.getConnectionFactory()); setAsync(true); }
container.afterPropertiesSet(); container.start(); AsyncRabbitTemplate asyncTemplate = new AsyncRabbitTemplate(template, container); asyncTemplate.setEnableConfirms(true); asyncTemplate.setMandatory(true); asyncTemplate.setReceiveTimeout(10); assertThat(error.getPayload(), instanceOf(MessagingException.class)); assertThat(error.getPayload().getCause(), instanceOf(AmqpReplyTimeoutException.class)); asyncTemplate.setReceiveTimeout(30000); receiver.setMessageListener(messageListener); willReturn(future).given(asyncTemplate).sendAndReceive(anyString(), anyString(), any(org.springframework.amqp.core.Message.class)); DirectFieldAccessor dfa = new DirectFieldAccessor(future); assertEquals("nacknack", nack.getNackReason()); asyncTemplate.stop(); receiver.stop(); ccf.destroy();
@Test public void testMessage1ArgDirect() throws Exception { this.latch.set(new CountDownLatch(1)); ListenableFuture<Message> future1 = this.asyncDirectTemplate.sendAndReceive(getFooMessage()); ListenableFuture<Message> future2 = this.asyncDirectTemplate.sendAndReceive(getFooMessage()); this.latch.get().countDown(); Message reply1 = checkMessageResult(future1, "FOO"); assertEquals(Address.AMQ_RABBITMQ_REPLY_TO, reply1.getMessageProperties().getConsumerQueue()); Message reply2 = checkMessageResult(future2, "FOO"); assertEquals(Address.AMQ_RABBITMQ_REPLY_TO, reply2.getMessageProperties().getConsumerQueue()); this.latch.set(null); waitForZeroInUseConsumers(); assertThat(TestUtils .getPropertyValue(this.asyncDirectTemplate, "directReplyToContainer.consumerCount", Integer.class), equalTo(2)); this.asyncDirectTemplate.stop(); this.asyncDirectTemplate.start(); assertThat(TestUtils .getPropertyValue(this.asyncDirectTemplate, "directReplyToContainer.consumerCount", Integer.class), equalTo(0)); }
@Test public void testConvert1ArgDirect() throws Exception { this.latch.set(new CountDownLatch(1)); ListenableFuture<String> future1 = this.asyncDirectTemplate.convertSendAndReceive("foo"); ListenableFuture<String> future2 = this.asyncDirectTemplate.convertSendAndReceive("bar"); this.latch.get().countDown(); checkConverterResult(future1, "FOO"); checkConverterResult(future2, "BAR"); this.latch.set(null); waitForZeroInUseConsumers(); assertThat(TestUtils .getPropertyValue(this.asyncDirectTemplate, "directReplyToContainer.consumerCount", Integer.class), equalTo(2)); final String missingQueue = UUID.randomUUID().toString(); this.asyncDirectTemplate.convertSendAndReceive("", missingQueue, "foo"); // send to nowhere this.asyncDirectTemplate.stop(); // should clear the inUse channel map waitForZeroInUseConsumers(); this.asyncDirectTemplate.start(); this.asyncDirectTemplate.setReceiveTimeout(1); this.asyncDirectTemplate.convertSendAndReceive("", missingQueue, "foo"); // send to nowhere waitForZeroInUseConsumers(); this.asyncDirectTemplate.setReceiveTimeout(10000); this.asyncDirectTemplate.convertSendAndReceive("", missingQueue, "foo").cancel(true); waitForZeroInUseConsumers(); }
@Override public <C> RabbitConverterFuture<C> convertSendAndReceive(String exchange, String routingKey, Object object, MessagePostProcessor messagePostProcessor) { return convertSendAndReceive(exchange, routingKey, object, messagePostProcessor, null); }
@Test @DirtiesContext public void testMessageWithConfirmDirect() throws Exception { this.asyncDirectTemplate.setEnableConfirms(true); RabbitMessageFuture future = this.asyncDirectTemplate .sendAndReceive(new SimpleMessageConverter().toMessage("sleep", new MessageProperties())); ListenableFuture<Boolean> confirm = future.getConfirm(); assertNotNull(confirm); assertTrue(confirm.get(10, TimeUnit.SECONDS)); checkMessageResult(future, "SLEEP"); }
@Test @DirtiesContext public void testStopCancelled() throws Exception { this.asyncTemplate.setReceiveTimeout(5000); RabbitConverterFuture<String> future = this.asyncTemplate.convertSendAndReceive("noReply"); TheCallback callback = new TheCallback(); future.addCallback(callback); assertEquals(1, TestUtils.getPropertyValue(this.asyncTemplate, "pending", Map.class).size()); this.asyncTemplate.stop(); // Second stop() to be sure that it is idempotent this.asyncTemplate.stop(); try { future.get(10, TimeUnit.SECONDS); fail("Expected CancellationException"); } catch (CancellationException e) { assertEquals("AsyncRabbitTemplate was stopped while waiting for reply", future.getNackCause()); } assertEquals(0, TestUtils.getPropertyValue(this.asyncTemplate, "pending", Map.class).size()); assertTrue(callback.latch.await(10, TimeUnit.SECONDS)); assertTrue(future.isCancelled()); assertNull(TestUtils.getPropertyValue(this.asyncTemplate, "taskScheduler")); /* * Test there's no harm if the reply is received after the cancel. This * should never happen because the container is stopped before canceling * and the future is removed from the pending map. */ future.set("foo"); assertNull(callback.result); }
@Override public <C> RabbitConverterFuture<C> convertSendAndReceiveAsType(String exchange, String routingKey, Object object, ParameterizedTypeReference<C> responseType) { return convertSendAndReceiveAsType(exchange, routingKey, object, null, responseType); }
@Bean public AsyncRabbitTemplate asyncRabbitTemplate(ConnectionFactory rabbitConnectionFactory) { return new AsyncRabbitTemplate(rabbitConnectionFactory, "", "", "asyncReplies"); }
@Test @DirtiesContext public void testConvertWithConfirmDirect() throws Exception { this.asyncDirectTemplate.setEnableConfirms(true); RabbitConverterFuture<String> future = this.asyncDirectTemplate.convertSendAndReceive("sleep"); ListenableFuture<Boolean> confirm = future.getConfirm(); assertNotNull(confirm); assertTrue(confirm.get(10, TimeUnit.SECONDS)); checkConverterResult(future, "SLEEP"); }
@Test @DirtiesContext public void testReturn() throws Exception { this.asyncTemplate.setMandatory(true); ListenableFuture<String> future = this.asyncTemplate.convertSendAndReceive(this.requests.getName() + "x", "foo"); try { future.get(10, TimeUnit.SECONDS); fail("Expected exception"); } catch (ExecutionException e) { assertThat(e.getCause(), instanceOf(AmqpMessageReturnedException.class)); assertEquals(this.requests.getName() + "x", ((AmqpMessageReturnedException) e.getCause()).getRoutingKey()); } }
@Test @DirtiesContext public void testReceiveTimeout() throws Exception { this.asyncTemplate.setReceiveTimeout(500); ListenableFuture<String> future = this.asyncTemplate.convertSendAndReceive("noReply"); TheCallback callback = new TheCallback(); future.addCallback(callback); assertEquals(1, TestUtils.getPropertyValue(this.asyncTemplate, "pending", Map.class).size()); try { future.get(10, TimeUnit.SECONDS); fail("Expected ExecutionException"); } catch (ExecutionException e) { assertThat(e.getCause(), instanceOf(AmqpReplyTimeoutException.class)); } assertEquals(0, TestUtils.getPropertyValue(this.asyncTemplate, "pending", Map.class).size()); assertTrue(callback.latch.await(10, TimeUnit.SECONDS)); assertThat(callback.ex, instanceOf(AmqpReplyTimeoutException.class)); }
@Override protected void doStart() { super.doStart(); this.template.start(); }
@Override public synchronized void start() { if (!this.running) { if (this.internalTaskScheduler) { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setThreadNamePrefix(getBeanName() == null ? "asyncTemplate-" : (getBeanName() + "-")); scheduler.afterPropertiesSet(); this.taskScheduler = scheduler; } if (this.container != null) { this.container.start(); } if (this.directReplyToContainer != null) { this.directReplyToContainer.setTaskScheduler(this.taskScheduler); this.directReplyToContainer.start(); } } this.running = true; }
@Override public <C> RabbitConverterFuture<C> convertSendAndReceive(String exchange, String routingKey, Object object, MessagePostProcessor messagePostProcessor) { return convertSendAndReceive(exchange, routingKey, object, messagePostProcessor, null); }
@Test @DirtiesContext public void testMessageWithConfirm() throws Exception { this.asyncTemplate.setEnableConfirms(true); RabbitMessageFuture future = this.asyncTemplate .sendAndReceive(new SimpleMessageConverter().toMessage("sleep", new MessageProperties())); ListenableFuture<Boolean> confirm = future.getConfirm(); assertNotNull(confirm); assertTrue(confirm.get(10, TimeUnit.SECONDS)); checkMessageResult(future, "SLEEP"); }
@Override public <C> RabbitConverterFuture<C> convertSendAndReceiveAsType(String exchange, String routingKey, Object object, ParameterizedTypeReference<C> responseType) { return convertSendAndReceiveAsType(exchange, routingKey, object, null, responseType); }