'Channel shutdown: channel error: reply-code=406, reply-text=PRECONDITION_FAILED - reply consumer already set

I'm running multiple tests with spring-amqp, spring-rabbit. My Maven parent is spring-boot-starter-parent:1.2.3.RELEASE which pulls:

spring-rabbit:1.4.3.RELEASE
    spring-amqp:1.4.3.RELEASE
    amqp-client:3.4.2

At a certain point one of the tests fails with this error and I don't see the reason:

Executing callback on RabbitMQ Channel: Cached Rabbit Channel: AMQChannel(amqp://[email protected]:5672/,2119)
Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - reply consumer already set, class-id=60, method-id=20)
Detected closed channel on exception.  Re-initializing: null

If I change to spring-boot-starter-parent:1.3.1.RELEASE all tests are passed.

Digging down in the different versions, it seems I can still reproduce the failed test with

spring-rabbit:1.5.0.M1
    spring-amqp:1.5.0.M1
    amqp-client:3.5.5

but all tests are passing with

spring-rabbit:1.5.0.RELEASE
    spring-amqp:1.5.0.RELEASE
    amqp-client:3.5.5

Is there any relevant change between 1.5.0.M1 and 1.5.0.RELEASE that could answer this? I tried to browse GitHub compare but didn't help.

1st update:

I could narrow down the issue. In the tests I call sendAndReceive() to a queue inside a HystrixCommand (from Netflix). This HystrixCommand uses a smaller (2s) timeout then the default reply timeout (5s) in RabbitTemplate.

A service is listening on that declared queue and returns the answer.

I have a certain test to do a sendAndReceive() to a non-existing queue. When that special test is executed the HystrixCommand times out.

The next test executing sendAndReceive() to the declared queue gives the channel error.

@SpringBootApplication
public class SpringAmqpTestApplication implements CommandLineRunner {

    public static final String QUEUE_NAME = "Spring-AMQP-Test";
    private static final String NONEXISTENT_QUEUE_NAME = UUID.randomUUID().toString() + "@" + System.currentTimeMillis();

    public static void main( String[] args ) {
        SpringApplication.run( SpringAmqpTestApplication.class, args );
    }

    @Autowired
    AmqpTemplate amqpTemplate;

    @Override
    public void run( String... args ) throws Exception {
        sendAndReceive( QUEUE_NAME );

        sendAndReceive( NONEXISTENT_QUEUE_NAME );

        sendAndReceive( QUEUE_NAME );
    }

    private void sendAndReceive( String routingKey ) {
        CustomHystrixCommand customHystrixCommand = new CustomHystrixCommand( amqpTemplate, routingKey );
        String answer = customHystrixCommand.execute();
        System.err.println( "< sendAndReceive(): " + answer );
    }
}

My HystrixCommand is fairly simple:

public class CustomHystrixCommand extends HystrixCommand<String> {

    private String routingKey;

    AmqpTemplate amqpTemplate;

    public CustomHystrixCommand( AmqpTemplate amqpTemplate, String routingKey ) {
        super( HystrixCommandGroupKey.Factory.asKey( "" ), 2000 );
        this.amqpTemplate = amqpTemplate;
        this.routingKey = routingKey;
    }

    @Override
    protected String run() throws Exception {
        String request = UUID.randomUUID().toString();
        MessageProperties messageProperties = new MessageProperties();
        Message message = new Message( request.getBytes(), messageProperties );
        Message answer = amqpTemplate.sendAndReceive( "", routingKey, message );
        return "OK answer";
    }

    @Override
    protected String getFallback() {
        return "getFallback()";
    }

}

With spring-boot-starter-parent:1.2.3.RELEASE my logs are:

< sendAndReceive(): OK answer
< sendAndReceive(): getFallback()
2016-01-27 11:47:42.266 ERROR 15007 --- [pool-1-thread-1] o.s.a.r.c.CachingConnectionFactory       : Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - reply consumer already set, class-id=60, method-id=20)
< sendAndReceive(): getFallback()

while with spring-boot-starter-parent:1.3.1.RELEASE:

< sendAndReceive(): OK answer
< sendAndReceive(): getFallback()
< sendAndReceive(): OK answer

Thanks for any help / explanation.



Solution 1:[1]

I am not aware of any changes (but haven't looked) but, in any case, 1.5.0.M1 is a pre-release milestone and 1.5.0.RELEASE is a release. Milestones should never be used when the actual release is available. The current release is 1.5.3.RELEASE.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Gary Russell