Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected exchange type: headers #408

Closed
SergiusSidorov opened this issue Apr 25, 2016 · 5 comments
Closed

Unexpected exchange type: headers #408

SergiusSidorov opened this issue Apr 25, 2016 · 5 comments

Comments

@SergiusSidorov
Copy link

SergiusSidorov commented Apr 25, 2016

Hi!

When I try to bind queue to headers exchange through annotation @RabbitListener -> bindings -> @QueueBinding, I receive exception: Unexpected exchange type: headers

I inspect class RabbitListenerAnnotationBeanPostProcessor and found next code:

if (exchangeType.equals(ExchangeTypes.DIRECT)) {
    exchange = new DirectExchange(exchangeName,
            resolveExpressionAsBoolean(bindingExchange.durable()),
            resolveExpressionAsBoolean(bindingExchange.autoDelete()));
    actualBinding = new Binding(queueName, DestinationType.QUEUE, exchangeName, resolvedKey, null);
}
else if (exchangeType.equals(ExchangeTypes.FANOUT)) {
    exchange = new FanoutExchange(exchangeName,
            resolveExpressionAsBoolean(bindingExchange.durable()),
            resolveExpressionAsBoolean(bindingExchange.autoDelete()));
    actualBinding = new Binding(queueName, DestinationType.QUEUE, exchangeName, "", null);
}
else if (exchangeType.equals(ExchangeTypes.TOPIC)) {
    exchange = new TopicExchange(exchangeName,
            resolveExpressionAsBoolean(bindingExchange.durable()),
            resolveExpressionAsBoolean(bindingExchange.autoDelete()));
    actualBinding = new Binding(queueName, DestinationType.QUEUE, exchangeName, resolvedKey, null);
}
else {
    throw new BeanInitializationException("Unexpected exchange type: " + exchangeType);
}

i.e. binding to headers exchange not supported in annotation @RabbitListener.
Why?

@artembilan
Copy link
Member

Well, pay attention, please, to the @RabbitListener with bindings configurations.
We found it as already enough complicated.
And from other hand see the HeadersExchange description and its binding logic in the HeadersExchangeMapConfigurer. For example:

BindingBuilder.bind(new Queue("q"))
                .to(new HeadersExchange("t"))
                .where("foo")
                .matches("bar");

But there are other configuration logical branches.

So, we decided do not allow HeadersExchange from the annotation configuration and let end-users to do their sophisticated solutions with standard BindingBuilder and @Bean combinations:

@Bean
public DirectExchange e1() {
    return new DirectExchange("e1", false, true);
}

@Bean
public Queue q1() {
    return new Queue("q1", false, false, true);
}

@Bean
public Binding b1() {
    return BindingBuilder.bind(q1()).to(e1()).with("k1");
}

Ultimately, the @RabbitListener is just for listener's method on the queue. And from big height it shouldn't know anything about bindings.

Hope that is clear

@garyrussell
Copy link
Contributor

The javadocs document this limitation.

None of the exchanges declared by the @QueueBinding annotations support an arguments map - it's a bit awkward to build a map using annotations.

Since the headers exchange requires arguments for the header mapping and x-match argument, we couldn't support it without adding argument support, hence it's not currently supported.

The work around (and for any exchange requiring arguments) is to use external @Bean definitions.

We can revisit this if you feel strongly about it - if so, open a JIRA Issue and we'll take a look.

We'd need to add something like

Argument[] arguments default {}

Where Argument would be an annotation, something like:

  {  @Argument(name="x-match", value="all",
     @Argument(name="foo", value="bar",
     @Argument(name="baz", value="qux" }

Now I see it laid out like that, it doesn't look like it would be too bad; however, if you configured queue arguments as well, the annotation could get very unwieldy, very quickly, and hard to read - hence my original thought that such configuration would be better done as @Beans.

@SergiusSidorov
Copy link
Author

The idea with the array of arguments looks great. In my opinion, this solution looks complete (all type of exchanges will be supported).
Write bindings on annotations isn't very nice solution. But this has a right to exist. Especially since it is already there for other types of exchanges.

@garyrussell
Copy link
Contributor

@artembilan
Copy link
Member

The PR #409 has been merged 54a613a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants