-
Notifications
You must be signed in to change notification settings - Fork 646
Added Route class for preparing #3
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
Conversation
Made Binding extend from Route. Change method String getExchange () to String getExchangeName Change method String getQueue () to String getQueueName
|
Looks interesting. Can you fill in the contributor agreement form at https://support.springsource.com/spring_committer_signup please? Then we can have a proper chat about it. |
|
I did Thank you for registering to be a SpringSource Community Contributor, we appreciate your dedication to the SpringSource community. Your confirmation number is XXXXXXXXX please save this number for your records. Please contact your project lead for information regarding repository access to the project, project roadmaps, etc.. I didn't know what project lead they wanted so I put Mark Fisher, I might have spelled his name incorrectly. |
|
Thanks. Mark Fisher is correct, but you can consider you have made contact. One last thing: is there a JIRA issue associated with this change (I vaguely remember discussing something similar, but it might have been on the rabbitmq mailing list)? |
|
I don't know, I just started coding from the spring-amqp and spring-integration-amqp. The example spring-integration-amqp looked like it was a work in progress and I just wanted to make it such that it used references to beans instead of text strings. |
|
Ben, There's only one commit and three files are .java, so I didn't see any changes to the XSD or namespace parsers. Did you forget to push something? A couple of housekeeping requests (none of which are urgent), can you:
I'll add this stuff to the fork instructions on the main repository page (you are a guinea pig here). Also, if no-one else is using your branch, could you rebase it against the current master in spring-amqp? |
|
The other changes are in the spring-integration-amqp repo. I was trying to minimize the changes in the spring-amqp repo. I will make the rest of the changes tonight, have to get to work. http://git.springsource.org/spring-integration/sandbox/trees/master/spring-integration-amqp |
|
Here is a full example that was extended from the test case in spring-integration-amqp |
|
The route and binding declarations belong in the Spring AMQP namespace (as distinct from the Spring Integration AMQP one). Can we port those changes over as part of this pull request, or would you rather do another one? The spring-rabbit-1.0.xsd we already have in the repo has those elements declared - it just doesn't implement the parser. If you've done that, then let's put it in the right place. If you want to do the two things separately we can handle that - just tidy up the .java and make an independent request from another branch for the namespace changes. |
|
I am not a xml guru. Ahh yes that is better idea. Let me look at it tonight. I was playing around with spring-integration and trying to make rabbit the back end between different systems(.NET talking to JAVA app). We have a bunch of code at work uses spring-integration but now we are adding .NET 3rd party portions and want rabbit to be the broker. |
|
Hi, @bean no mention of 'routes'. What about we get rid of route and have the binding XSD element take queue, exchange, and optional routing key. |
|
I feel like this discussion should move to JIRA, but I'm happy to be having it. Mark: I think there are problems with the fluent API and the XML namespace from a Rabbit angle. The broker team are not convinced by it and we should listen to what they say. One of the points is that "exchange" and "queue" as names for the "source" and "destination" of a binding are restrictive (Rabbit supports bindings from Exchange to Exchange as well, even though AMQP doesn't). They prefer "source" and "destination" (for the message) as names, and I agree, but that possibly makes the strongly typed fluent API harder to implement (don't know I haven't tried it - was going to look after 1.0.0.M2). I don't see why (with other changes in the offing) the fluent API couldn't use a new abstraction with Route as well. The next thing I was going to ask Ben to think about once we got the first draft committed was how to extend it to support binding to an Exchange, and from there to a mult-step route (e.g. e-e-e-e-q). |
|
Don't know what your are trying to say. In that you don't want things in spring-integration-amqp(example route, binding, queue)? Is that correct. No problem with that if that is what you said. First I was inspired by the rabbit-mq documentation example "What happens to messages when a network outage removes the route between an exchange and a bound queue? " The documentation goes and describes routes as the link between an exchange and queue, it is more of an abstract idea , where the binding is the more physical component. I thought the repetition of the term route is was important enough to get its own element. Now the route only has be declared once, and it can be reused to send the messages to multiple queues. |
|
Jira issue sounds fine, I will work on it in my spare time. I am really just trying to make the spring-amqp / spring-integration-amqp easier to use. I am introducing spring-amqp and spring-integration-amqp at work and I don't want my developers making mistakes. The hard coding of the routes, bindings, and exchanges in the spring-integration-amqp will be error prone and I don't want to have to waste a bunch of time when they make mistakes. Anyways that is that , have to get to back to work work. Is there a way to send a private message. I would rather send some of these things by email, but I don't want all my email being spammed across the Internet. |
|
I mentioned it so that we can be consistent - didn't even know about the exchange-to-exchange support in Rabbit. That does require then for some or all the fluent API to move out of spring-amqp and into spring-rabbit. It concerns me that Route in the way we are discussing it being used is not even a first class term in the AMQP specs. Is the use case you show Ben that common as it seems to me to introduce a new term, though it is used in the Rabbit docs and BQL. |
|
Ben: may email is dsyer AT vmware DOT com. The rabbitmq-discuss group is also a good place to chat about design. Mark and I are possibly talking at cross purposes because I think of spring-amqp as meaning spring-rabbit (whereas in fact they are separated at birth, even though there is no other implementation of the APIs right now). I think Route is a useful addition, and I suppose if it has to it could even go in spring-amqp as opposed to spring-rabbit, but happy to let it fall in either for now, and we can refactor later. It's not that we don't want contributions to spring-integration-amqp as well, but these features are more generic, so they belong more here. |
|
Maybe not , another way might be to have binding that can reference another binding and take its routing information. Does that sound better? Don't know how easy it would be to put it in the code though. Abstract binding class maybe , idk , just trying to throw some things out there. |
|
I apologize for being a bit late to the party. I need to read the RabbitMQ discussion about "routes" to make sure I have the context, but I just want to point out my initial reaction here. I personally do not like the term "route" for this abstraction over bindings. If I understand, the main goal is to provide a single, reusable thing instead of requiring repetitive use of two things. Perhaps a better concept would be "address". In fact, this is something that we have used within the framework a bit (e.g. someExchange://someRoutingKey). My other concern is that this seems to go against the whole goal of decoupling Exchanges from Queues. In fact, if I'm not mistaken, the idea of a "route" as something reusable on both the producer and consumer side would only apply to a Direct Exchange or a Topic Exchange that uses exact-matching rather than routing "patterns". |
|
Using address might be a better idea if it fits better within the spring code base. The documentation for rabbit that I was inspired by was the section "Messaging Concepts: Binding and Routing" . |
|
I agree with Ben in that I don't understand the point about coupling queues and exchanges. Also happy to change names. But I take Mark's point about a route (keeping that as a working name for now) having only a fixed routing key if used by a producer, but being empty or a wildcard if used in a binding. That does seem like the design is wrong somewhere. You will have heard me say this before, but maybe we (i.e. Ben) should elaborate in some more detail about the use case, and we can look at the motivation and not the abstract design. |
|
Maybe I haven't been clear. Route was just addition in where multiple bindings needed the same routing information, route isn't need all the time. It is just when I was coding up pub/sub portion of the system I am working on, the usage of having to create bindings for each queue and repeating the same information with no checks when the application started up was error prone. The are queues per subsystem, there is only one sync exchange. There is a common source tree that contains exchanges and routes. So the underlying subsystems uses the parents application context to get routing and exchange information without needing to know the exact routing keys or exchanges. The introduction of the route was also driven by the spring-integration-amqp source. In the current example the strings si.test.exchange and si.test.queue were repeated 3 times. The routing key was repeated twice. |
|
I'm not sure I understood the use case properly. Let's focus on that and leave aside the configuration and abstraction design. It sounds like a fanout exchange (you want to broadcast the sync message to all interested parties) specific to the message type? Which is why I'm lost because a fanout doesn't require a routing key. What are the producer and consumer semantics - how many messages does a producer send, and how many consumers receive it? |
|
I am getting a little confused also. I don't know if you guys want any of the changes, or what you want the changes to be, so I am limbo right now. I don't know what your saying about the exchanges are you not understanding what the different types of exchanges do or the use cases for these changes? |
|
It's not a question of not wanting changes. We are having a discussion about the design of your proposal, and you can contribute to the discussion best by keeping it on track. As far as your question goes: I think I understand what a fanout exchange is, but I'm happy to be corrected if you detect a misconception, especially if it's relevant to your use case. I asked if you were using a fanout because I'm still confused about your application. It still seems like the best way to nail the requirement for an enhancement (or if there is one) to get more detail from you about how you would use it. |
|
Trying to simplify the use case. |
|
I would say if you are really trying to emulate the behavior of a publish-subscribe-channel, then Fanout Exchange is the closest match. Then, the "routing key" is not even relevant, and you would have what you want: a single "address" - in this case, the exchange name. However, I could be missing something. Can you elaborate on the limitations of Fanout Exchange that led you down this path of using Direct Exchanges, which exhibit point-to-point semantics, when you are actually aiming for pub-sub semantics? |
|
Flexibility, because both direct and fanout exchanges can be simulated using topic exchanges. The performance is O(N) right now which isn't bad because we don't have bunch of queues. I see that fanout is better choice for pub/sub but I want to keep it flexible. |
|
The more I think about it. |
|
If I understand correctly, you are asking about an AMQP-backed MessageChannel option as opposed to the channel-adapters. Is that correct? We are planning to do that, and it would be similar to our JMS-backed channels: http://static.springsource.org/spring-integration/reference/htmlsingle/#jms-channel |
|
The jms section would be great down the road. The question is what do to in the mean time. I can see if you don't want the route class I can deal with pulling it out , it makes some steps easier.I just didn't care for the repetition of strings in the unit tests and examples it is just too error prone. I also have pet peeve when writing code. If you end up repeating member names, methods or character string three or more times you should probably re-factor the code. I could write the code to parse bindings,queues,routingkeys and exchanges to allow for the referencing of beans instead of strings or property variables. |
|
I agree that duplication of strings is bad. What I'm trying to understand is why duplication of strings is really necessary in your particular case. The idea about AMQP-backed channels was an attempt to respond to your last question (or at least what I thought you were asking). However, it seems to me that the most important thing for right now is to really get to the bottom of why you have duplication in the first place, and I think the rationale for NOT using Fanout Exchanges is a key part of that discussion. Based on your previous comments, you want to make it so that developers are not aware of exchange types, and I understand that. On the broker, a Fanout Exchange "x" can be defined. Then, developers only need to know that they send to "x". They do not need to know that it's a Fanout Exchange. |
|
The applies to any case of using the spring-amqp and/or spring-integration-amqp. From the current state of the code in both projects it is difficult to leverage basic spring dependency injection without using variable injections or some other work around(abstract beans etc). Even your own example in spring-integration-amqp I have reduce the string declarations to 3 down from 8, the exchange, queue, route are declare once, the rest just reference those declarations. As side note my majors are in theoretical math and computer science. I have a tendency to make everything more abstract and it confuses people sometimes. I would rather write everything in set notation , then explain in words. |
|
Well, I understand the general issue. I guess one issue with using references instead of just names is that it would require someone to create a Queue and/or Exchange instance within the application. The main problem I have with that is that it actually might also require them to know much more about the underlying instance than they really need to. Let me see if I can explain very briefly... If I want to publish a Message to a Fanout Exchange named "x", then the ONLY thing I need to know is "x" is the name. If OTOH, I need to use a reference for any exchange (e.g. for a outbound-channel-adapter), then I need to create that Exchange or Queue instance. At that point, if the instance has already been declared on the broker (the most common case), then I also need to know all of its properties (durable, exclusive, auto-delete, etc), because a declare command requires all of the details. The "publish" and "consume" commands are much simpler in that regard. I think for the majority of users, they will just want to provide the exchange name on the adapter rather than providing a bean definition that matches all of those properties. I tend to see all of those details as "admin" concerns whereas the end-user just needs to know the names and possibly some set of routing keys. |
|
I left in the amqp references to still allow the use of strings for routing keys,exchanges, and routing keys. I didn't pull that out, I added attributes that allow you to reference a queue, binding, route, or exchange but the user can just still use hard coded strings if they would like. I left it in there because of the use case you are describing. I am having a hard time following your point about the not wanting to have the details behind the scenes, and just having strings. All the examples/test cases in the rabbitlib create queues,exchanges,and bindings, none expect that they are already created. All your own code creates them. It is also very similar to a hibernate property hibernate.hbm2ddl.auto and behind the scenes in rabbit all queues,exchanges ,bindings are being mapped to tables, similar to sql database. A production environment you wouldn't want to mess with making the exchanges etc, but in a testing and coding env , I want them to be made, so I don't have to worry about it. I would also want to test the setup exactly how it would appear in the production system, and not have a miss-match from dev/test to production. |
|
What do you want to do guys? I am going the forward and will attempt see how the route class can be substituted for the address class. |
|
re submitting sometime later |
Rabbit can piggy-back confirms - for example, if seq 1, 2, 3 are sent, it is possible to receive ack spring-projects#3 with 'multiple' set. These means 1, 2, and 3 are acked. This worked fine with just one listener. However, if two or more listeners (e.g. rabbit templates) are attached, only the listener for ack spring-projects#3 is notified (regardless of whether all the acks belong to it). The PublisherCallbackChannel maintains two maps: seq-to-listener and listener-to-map(seq-to-correlation). This fixes the problem by first finding all the listeners that have pending confirms at or below the sequence number; and then uses the second map to send the confirms to the appropriate listener.
Rabbit can piggy-back confirms - for example, if seq 1, 2, 3 are sent, it is possible to receive ack spring-projects#3 with 'multiple' set. These means 1, 2, and 3 are acked. This worked fine with just one listener. However, if two or more listeners (e.g. rabbit templates) are attached, only the listener for ack spring-projects#3 is notified (regardless of whether all the acks belong to it). The PublisherCallbackChannel maintains two maps: seq-to-listener and listener-to-map(seq-to-correlation). This fixes the problem by first finding all the listeners that have pending confirms at or below the sequence number; and then uses the second map to send the confirms to the appropriate listener. AMQP-255 Polishing PR Comments
Rabbit can piggy-back confirms - for example, if seq 1, 2, 3 are sent, it is possible to receive ack spring-projects#3 with 'multiple' set. These means 1, 2, and 3 are acked. This worked fine with just one listener. However, if two or more listeners (e.g. rabbit templates) are attached, only the listener for ack spring-projects#3 is notified (regardless of whether all the acks belong to it). The PublisherCallbackChannel maintains two maps: seq-to-listener and listener-to-map(seq-to-correlation). This fixes the problem by first finding all the listeners that have pending confirms at or below the sequence number; and then uses the second map to send the confirms to the appropriate listener. AMQP-255 Polishing PR Comments
Bumps [io.micrometer:micrometer-tracing-bom](https://github.com/micrometer-metrics/tracing-commercial) from 1.0.12 to 1.0.14. - [Commits](https://github.com/micrometer-metrics/tracing-commercial/commits) --- updated-dependencies: - dependency-name: io.micrometer:micrometer-tracing-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Just added route class, to reduce duplication of code and prepare spring-integration-amqp . Also inspired by the rabbitmq describing routes as entity.
Basically I added route and binding elements to the spring-integration-amqp schema.
A route is a generic class to allow reuse in other binding elements and outbound channel adapters.
So it becomes
<amqp:route exchange="si.test.exchange" id="my.route.id" routing-key="inbound.from.si"/>
It can be referenced in both a <amqp:binding > element or amqp:outbound-channel-adapter
Examples:
<amqp:binding queue="inbound.from.si.queue" route="my.route.id"/>
And also
<amqp:outbound-channel-adapter route-ref="my.route.id" channel="toRabbit" amqp-template="amqpTemplate"/>
I also made changes to spring-integration-amqp that it so you can reference queue, exchanges , route and binding elements from the outbound-channel-adapter and inbound-channel adapter.