Closed shark300 closed 4 years ago
Are you certain that this code ...
.where("type")
.exists();
...is correctly represented by this JSON?
"arguments":{"type": null}}
Could you please run your Spring code to create the exchange and binding, then export your RabbitMQ definitions to see what JSON is produce (attach it to your response)? Or, provide a complete set of code I can clone, compile and run to see how Spring does it. That would speed up diagnosis greatly as it would save me the time of figuring out how to get the Spring code running.
Maybe yes, but I can't figure out how to configure it on UI too. If I leave empty, it causes an empty String not "undefined" on UI.
@shark300 please see this comment. Thanks.
Yes, sure.
We only spend time investigating behaviors that can be reproduced with 3.8.9
.
OK, this turned out to be a different arguments
value (a binding one, not the queue one).
These curl
commands work as expected:
curl -u guest:guest --location --request POST http://localhost:15672/api/bindings/%2F/e/he.1/q/cq.1/ --header 'Content-Type: application/json' --data-raw '{"routing_key":"", "arguments":{}}'
curl -u guest:guest --location --request POST http://localhost:15672/api/bindings/%2F/e/he.1/q/cq.1/ --header 'Content-Type: application/json' --data-raw '{"routing_key":"", "arguments":{"type": "blue"}}'
This does not create a binding:
curl -u guest:guest --location --request POST http://localhost:15672/api/bindings/%2F/e/he.1/q/cq.1/ --header 'Content-Type: application/json' --data-raw '{"routing_key":"", "arguments":{"type": null}}'
and the node logs an exception, {error,null_not_allowed}
.
There is no way to tell a headers exchange match on an absence of a value, the closest option is to match on "one of the values" using the "x-match" => "any"
argument (as opposed to "x-match" => "all"
). So this limitation makes sense to me.
The plugin could report validation failure better, e.g. with a 400
response.
@michaelklishin @lukebakken
I'm trying to figure out Spring and RabbitMQ internal operation, and as I see, Spring works great. If I configure headers exchange with exists() method, it will create (somehow) a working binding and I can't do that with UI.
.where("type")
.exists();
match: no match:
Unfortunately, I can not configure on UI:
empty string on UI: "undefined" string on UI:
Last but not least, I configured Spring like this:
.where("type")
.matches("undefined")
I've got a same result as I expected.
I've tried to export working configuration by this command: rabbitmqctl export_definitions C:\Temp\definitions.file.json (I have configured a local server RabbitMQ 3.8.9, Erlang 23.1.2) but there is no argument have been exported (or imported as well):
So to recap, I really don't know how, but Spring can configure "existing" operation on headers exchange, and it works. Management UI can't reproduce that, and I can't export this configurations too.
I've created a quick sample project too.
A traffic capture would tell you exactly what your Spring code does. Are you sure that it uses the HTTP API to set up the bindings, for example? In any case, matching on null
will not achieve what you likely want. Headers exchanges cannot match on absence of a key.
If there is no argument in the definitions, it means that it's skipped by this Spring code. That would explain why it does not fail validation. The solution to replicate this via the HTTP API would be the same: skip the null value. I have demonstrated above using curl
that it works as expected.
@michaelklishin Good catch, Spring is using AMQP to declare exchanges/queues/bindings; even so, it should be configurable on RabbitMQ UI without Spring Admin. Thank you for your tips. I've captured the traffic by Wireshark.
What exactly should be configurable in the management UI? There is a way to configure arguments but null
values are explicitly unsupported and I explained why. Any Web UI form, at least in the current interface, has to worry about blank fields that were never touched by the user, especially because of the declaration property equivalence requirement.
I am not convinced that there is any reason for us to remove the validation; we won't do it because of a single reported case: much more demand for this change should emerge first.
@michaelklishin I see your point, but unfortunately, I can't configure RabbitMQ exchanges on our staging environments via AMQP (for security reason). I have to open a support ticket for configuring our RabbitMQ bindings but our support teams can't do that on UI or via import_definitions. Due to this there is no way for us to configure headers exchange argument "exists". As I see, although there is a way to configure it headers arguments via AMQP, but it should be configurable on UI too.
Hi @michaelklishin Do you have any news about this issue? If not, we will develop a migration tool for our support team. This tool can use native AMQP to modify headers's binding instead of calling REST API or importing JSON.
rabbitmq-plugins list
When a binding is created by Spring, arguments could be undefined, but it is not possible to configure on UI or by REST.