├── .gitignore
├── LICENSE
├── README.md
├── pom.xml
└── src
└── main
└── java
└── com
└── clevercloud
├── annotations
└── NonEmpty.java
└── rabbitmq
├── NoRabbitMQConnectionException.java
├── RabbitMQAutoChannel.java
├── RabbitMQAutoConnection.java
├── Watchable.java
└── WatcherThread.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | .idea/
3 | *.iml
4 |
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | Helper to automatically handle reconnections automatically in a pool of rabbitmq servers.
294 | Copyright (C) 2013 Clever Cloud, SAS
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | rabbitmq-autoreconnect-java
2 | ===========================
3 |
4 | Helper to automatically handle reconnections automatically in a pool of rabbitmq servers.
5 |
6 | To use it, simply instantiate RammitMQAutoConnection instead of using a ConnectionFactory with newConnection.
7 | Everything will be automatic.
8 |
9 | Maven configuration:
10 |
11 | ```
12 |
13 | Clever Cloud
14 | Clever Cloud's repository
15 | http://maven.clever-cloud.com
16 | default
17 |
18 | ```
19 |
20 | ```
21 |
22 | com.clevercloud
23 | rabbitmq-autoreconnect
24 | 1.7
25 |
26 | ```
27 |
28 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.clevercloud
5 | rabbitmq-autoreconnect
6 | 1.7
7 |
8 | rabbitmq-autoreconnect
9 | Helper to automatically handle reconnections automatically in a pool of rabbitmq servers.
10 | http://maven.apache.org
11 |
12 |
13 |
14 |
15 | GNU General Public License, version 2
16 | http://www.gnu.org/licenses/gpl-2.0.html
17 | repo
18 |
19 |
20 |
21 |
22 | https://github.com/CleverCloud/rabbitmq-autoreconnect-java
23 |
24 |
25 | jar
26 |
27 |
28 | ${project.build.directory}/endorsed
29 | UTF-8
30 |
31 |
32 |
33 |
34 | com.rabbitmq
35 | amqp-client
36 | 3.2.4
37 |
38 |
39 | com.google.code.findbugs
40 | jsr305
41 | 2.0.1
42 |
43 |
44 | log4j
45 | log4j
46 | 1.2.17
47 |
48 |
49 | commons-logging
50 | commons-logging
51 | 1.1.1
52 |
53 |
54 |
55 |
56 |
57 |
58 | org.apache.maven.plugins
59 | maven-compiler-plugin
60 | 2.3.2
61 |
62 | 1.6
63 | 1.6
64 |
65 | ${endorsed.dir}
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/main/java/com/clevercloud/annotations/NonEmpty.java:
--------------------------------------------------------------------------------
1 | package com.clevercloud.annotations;
2 |
3 | import javax.annotation.meta.TypeQualifier;
4 | import javax.annotation.meta.TypeQualifierValidator;
5 | import javax.annotation.meta.When;
6 | import java.lang.annotation.Documented;
7 | import java.lang.annotation.Retention;
8 | import java.lang.annotation.RetentionPolicy;
9 | import java.util.Collection;
10 |
11 | /**
12 | * @author Marc-Antoine Perennou
13 | */
14 |
15 | @Documented
16 | @TypeQualifier
17 | @Retention(RetentionPolicy.RUNTIME)
18 | public @interface NonEmpty {
19 | When when() default When.ALWAYS;
20 |
21 | static class Checker implements TypeQualifierValidator {
22 |
23 | public When forConstantValue(NonEmpty qualifierqualifierArgument,
24 | Object value) {
25 | if (value != null && value instanceof Collection && ((Collection) value).isEmpty())
26 | return When.NEVER;
27 | return When.ALWAYS;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/clevercloud/rabbitmq/NoRabbitMQConnectionException.java:
--------------------------------------------------------------------------------
1 | package com.clevercloud.rabbitmq;
2 |
3 | /**
4 | * @author Marc-Antoine Perennou
5 | */
6 |
7 | public class NoRabbitMQConnectionException extends RuntimeException {
8 |
9 | public NoRabbitMQConnectionException() {
10 | super("Couldn't connect to rabbitmq server");
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/clevercloud/rabbitmq/RabbitMQAutoChannel.java:
--------------------------------------------------------------------------------
1 | package com.clevercloud.rabbitmq;
2 |
3 | import com.rabbitmq.client.*;
4 | import org.apache.commons.logging.Log;
5 | import org.apache.commons.logging.LogFactory;
6 |
7 | import java.io.IOException;
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 | import java.util.concurrent.TimeoutException;
13 |
14 |
15 | /**
16 | * @author Marc-Antoine Perennou
17 | */
18 |
19 | public class RabbitMQAutoChannel implements Channel, Watchable {
20 | private static final Log logger = LogFactory.getLog(RabbitMQAutoChannel.class);
21 |
22 | private RabbitMQAutoConnection connection;
23 | private Integer channelNumber;
24 |
25 | private Channel channel;
26 |
27 | private List returnListeners;
28 | private List flowListeners;
29 | private List confirmListeners;
30 | private List shutdownListeners;
31 |
32 | private Consumer defaultConsumer;
33 | private Map consumers;
34 |
35 | private WatcherThread watcher;
36 |
37 | public RabbitMQAutoChannel(RabbitMQAutoConnection connection) {
38 | this.connection = connection;
39 |
40 | this.returnListeners = new ArrayList();
41 | this.flowListeners = new ArrayList();
42 | this.confirmListeners = new ArrayList();
43 | this.shutdownListeners = new ArrayList();
44 |
45 | this.consumers = new HashMap();
46 |
47 | this.watcher = new WatcherThread(this, this.connection.getInterval());
48 | this.watcher.start();
49 | }
50 |
51 | public RabbitMQAutoChannel(RabbitMQAutoConnection connection, Integer channelNumber) {
52 | this(connection);
53 | this.channelNumber = channelNumber;
54 | }
55 |
56 | private boolean isConnected() {
57 | return this.channel != null && this.channel.isOpen();
58 | }
59 |
60 | @Override
61 | public void watch() {
62 | this.checkChannel();
63 | }
64 |
65 | private synchronized void checkChannel() {
66 | if (this.isConnected())
67 | return;
68 |
69 | for (int tries = 0; (this.connection.getTries() == RabbitMQAutoConnection.NO_TRIES_LIMIT || tries < this.connection.getTries()) && !this.isConnected(); ++tries) {
70 | if (this.connection.isVerbose())
71 | logger.info("Attempting to " + ((this.channel != null) ? "re" : "") + "create channel to the rabbitmq server.");
72 |
73 | try {
74 | this.channel = (this.channelNumber == null) ? this.connection.createRawChannel() : this.connection.createRawChannel(this.channelNumber);
75 | for (ReturnListener listener : this.returnListeners) {
76 | this.channel.addReturnListener(listener);
77 | }
78 | for (FlowListener listener : this.flowListeners) {
79 | this.channel.addFlowListener(listener);
80 | }
81 | for (ConfirmListener listener : this.confirmListeners) {
82 | this.channel.addConfirmListener(listener);
83 | }
84 | for (ShutdownListener listener : this.shutdownListeners) {
85 | this.channel.addShutdownListener(listener);
86 | }
87 | this.channel.setDefaultConsumer(this.defaultConsumer);
88 | for (Map.Entry entry : this.consumers.entrySet()) {
89 | BasicConsumer c = entry.getValue();
90 | this.channel.basicConsume(entry.getKey(), c.autoack, c.consumerTag, c.noLocal, c.exclusive, c.arguments, c.consumer);
91 | }
92 | } catch (IOException ignored) {
93 | }
94 |
95 | try {
96 | Thread.sleep(this.connection.getInterval());
97 | } catch (InterruptedException ignored) {
98 | }
99 | }
100 | if (this.isConnected()) {
101 | if (this.connection.isVerbose())
102 | logger.info("Created channel to the rabbitmq server.");
103 | } else
104 | throw new NoRabbitMQConnectionException();
105 | }
106 |
107 | public Channel getChannel() {
108 | this.checkChannel();
109 | return this.channel;
110 | }
111 |
112 | /**
113 | * Retrieve this channel's channel number.
114 | *
115 | * @return the channel number
116 | */
117 | @Override
118 | public int getChannelNumber() {
119 | return this.getChannel().getChannelNumber();
120 | }
121 |
122 | /**
123 | * Retrieve the connection which carries this channel.
124 | *
125 | * @return the underlying {@link com.rabbitmq.client.Connection}
126 | */
127 | @Override
128 | public Connection getConnection() {
129 | return this.getChannel().getConnection();
130 | }
131 |
132 | /**
133 | * Close this channel with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code
134 | * and message 'OK'.
135 | *
136 | * @throws java.io.IOException if an error is encountered
137 | */
138 | @Override
139 | public void close() throws IOException {
140 | this.watcher.cancel();
141 | this.getChannel().close();
142 | }
143 |
144 | /**
145 | * Close this channel.
146 | *
147 | * @param closeCode the close code (See under "Reply Codes" in the AMQP specification)
148 | * @param closeMessage a message indicating the reason for closing the connection
149 | * @throws java.io.IOException if an error is encountered
150 | */
151 | @Override
152 | public void close(int closeCode, String closeMessage) throws IOException {
153 | this.watcher.cancel();
154 | this.getChannel().close(closeCode, closeMessage);
155 | }
156 |
157 | /**
158 | * Set flow on the channel
159 | *
160 | * @param active if true, the server is asked to start sending. If false, the server is asked to stop sending.
161 | * @throws java.io.IOException
162 | */
163 | @Override
164 | public AMQP.Channel.FlowOk flow(boolean active) throws IOException {
165 | return this.getChannel().flow(active);
166 | }
167 |
168 | /**
169 | * Return the current Channel.Flow settings.
170 | */
171 | @Override
172 | public AMQP.Channel.FlowOk getFlow() {
173 | return this.getChannel().getFlow();
174 | }
175 |
176 | /**
177 | * Abort this channel with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code
178 | * and message 'OK'.
179 | *
180 | * Forces the channel to close and waits for the close operation to complete.
181 | * Any encountered exceptions in the close operation are silently discarded.
182 | */
183 | @Override
184 | public void abort() throws IOException {
185 | this.watcher.cancel();
186 | this.getChannel().abort();
187 | }
188 |
189 | /**
190 | * Abort this channel.
191 | *
192 | * Forces the channel to close and waits for the close operation to complete.
193 | * Any encountered exceptions in the close operation are silently discarded.
194 | */
195 | @Override
196 | public void abort(int closeCode, String closeMessage) throws IOException {
197 | this.watcher.cancel();
198 | this.getChannel().abort(closeCode, closeMessage);
199 | }
200 |
201 | /**
202 | * Add a {@link com.rabbitmq.client.ReturnListener}.
203 | *
204 | * @param listener the listener to add
205 | */
206 | @Override
207 | public void addReturnListener(ReturnListener listener) {
208 | this.getChannel().addReturnListener(listener);
209 | this.returnListeners.add(listener);
210 | }
211 |
212 | /**
213 | * Remove a {@link com.rabbitmq.client.ReturnListener}.
214 | *
215 | * @param listener the listener to remove
216 | * @return true if the listener was found and removed,
217 | * false otherwise
218 | */
219 | @Override
220 | public boolean removeReturnListener(ReturnListener listener) {
221 | this.returnListeners.remove(listener);
222 | return this.getChannel().removeReturnListener(listener);
223 | }
224 |
225 | /**
226 | * Remove all {@link com.rabbitmq.client.ReturnListener}s.
227 | */
228 | @Override
229 | public void clearReturnListeners() {
230 | this.returnListeners.clear();
231 | this.getChannel().clearReturnListeners();
232 | }
233 |
234 | /**
235 | * Add a {@link com.rabbitmq.client.FlowListener}.
236 | *
237 | * @param listener the listener to add
238 | */
239 | @Override
240 | public void addFlowListener(FlowListener listener) {
241 | this.getChannel().addFlowListener(listener);
242 | this.flowListeners.add(listener);
243 | }
244 |
245 | /**
246 | * Remove a {@link com.rabbitmq.client.FlowListener}.
247 | *
248 | * @param listener the listener to remove
249 | * @return true if the listener was found and removed,
250 | * false otherwise
251 | */
252 | @Override
253 | public boolean removeFlowListener(FlowListener listener) {
254 | this.flowListeners.remove(listener);
255 | return this.getChannel().removeFlowListener(listener);
256 | }
257 |
258 | /**
259 | * Remove all {@link com.rabbitmq.client.FlowListener}s.
260 | */
261 | @Override
262 | public void clearFlowListeners() {
263 | this.flowListeners.clear();
264 | this.getChannel().clearFlowListeners();
265 | }
266 |
267 | /**
268 | * Add a {@link com.rabbitmq.client.ConfirmListener}.
269 | *
270 | * @param listener the listener to add
271 | */
272 | @Override
273 | public void addConfirmListener(ConfirmListener listener) {
274 | this.getChannel().addConfirmListener(listener);
275 | this.confirmListeners.add(listener);
276 | }
277 |
278 | /**
279 | * Remove a {@link com.rabbitmq.client.ConfirmListener}.
280 | *
281 | * @param listener the listener to remove
282 | * @return true if the listener was found and removed,
283 | * false otherwise
284 | */
285 | @Override
286 | public boolean removeConfirmListener(ConfirmListener listener) {
287 | this.confirmListeners.remove(listener);
288 | return this.getChannel().removeConfirmListener(listener);
289 | }
290 |
291 | /**
292 | * Remove all {@link com.rabbitmq.client.ConfirmListener}s.
293 | */
294 | @Override
295 | public void clearConfirmListeners() {
296 | this.confirmListeners.clear();
297 | this.getChannel().clearConfirmListeners();
298 | }
299 |
300 | /**
301 | * Get the current default consumer. @see setDefaultConsumer for rationale.
302 | *
303 | * @return an interface to the current default consumer.
304 | */
305 | @Override
306 | public Consumer getDefaultConsumer() {
307 | return this.getChannel().getDefaultConsumer();
308 | }
309 |
310 | /**
311 | * Set the current default consumer.
312 | *
313 | * Under certain circumstances it is possible for a channel to receive a
314 | * message delivery which does not match any consumer which is currently
315 | * set up via basicConsume(). This will occur after the following sequence
316 | * of events:
317 | *
318 | * ctag = basicConsume(queue, consumer); // i.e. with explicit acks
319 | * // some deliveries take place but are not acked
320 | * basicCancel(ctag);
321 | * basicRecover(false);
322 | *
323 | * Since requeue is specified to be false in the basicRecover, the spec
324 | * states that the message must be redelivered to "the original recipient"
325 | * - i.e. the same channel / consumer-tag. But the consumer is no longer
326 | * active.
327 | *
328 | * In these circumstances, you can register a default consumer to handle
329 | * such deliveries. If no default consumer is registered an
330 | * IllegalStateException will be thrown when such a delivery arrives.
331 | *
332 | * Most people will not need to use this.
333 | *
334 | * @param consumer the consumer to use, or null indicating "don't use one".
335 | */
336 | @Override
337 | public void setDefaultConsumer(Consumer consumer) {
338 | this.defaultConsumer = consumer;
339 | this.getChannel().setDefaultConsumer(consumer);
340 | }
341 |
342 | /**
343 | * Request specific "quality of service" settings.
344 | *
345 | * These settings impose limits on the amount of data the server
346 | * will deliver to consumers before requiring acknowledgements.
347 | * Thus they provide a means of consumer-initiated flow control.
348 | *
349 | * @param prefetchSize maximum amount of content (measured in
350 | * octets) that the server will deliver, 0 if unlimited
351 | * @param prefetchCount maximum number of messages that the server
352 | * will deliver, 0 if unlimited
353 | * @param global true if the settings should be applied to the
354 | * entire connection rather than just the current channel
355 | * @throws java.io.IOException if an error is encountered
356 | * @see com.rabbitmq.client.AMQP.Basic.Qos
357 | */
358 | @Override
359 | public void basicQos(int prefetchSize, int prefetchCount, boolean global) throws IOException {
360 | try {
361 | this.getChannel().basicQos(prefetchSize, prefetchCount, global);
362 | } catch (IOException connectionReset) {
363 | this.getChannel().basicQos(prefetchSize, prefetchCount, global);
364 | }
365 | }
366 |
367 | /**
368 | * Request a specific prefetchCount "quality of service" settings
369 | * for this channel.
370 | *
371 | * @param prefetchCount maximum number of messages that the server
372 | * will deliver, 0 if unlimited
373 | * @throws java.io.IOException if an error is encountered
374 | * @see #basicQos(int, int, boolean)
375 | */
376 | @Override
377 | public void basicQos(int prefetchCount) throws IOException {
378 | try {
379 | this.getChannel().basicQos(prefetchCount);
380 | } catch (IOException connectionReset) {
381 | this.getChannel().basicQos(prefetchCount);
382 | }
383 | }
384 |
385 | /**
386 | * Publish a message
387 | *
388 | * @param exchange the exchange to publish the message to
389 | * @param routingKey the routing key
390 | * @param props other properties for the message - routing headers etc
391 | * @param body the message body
392 | * @throws java.io.IOException if an error is encountered
393 | * @see com.rabbitmq.client.AMQP.Basic.Publish
394 | */
395 | @Override
396 | public void basicPublish(String exchange, String routingKey, AMQP.BasicProperties props, byte[] body) throws IOException {
397 | try {
398 | this.getChannel().basicPublish(exchange, routingKey, props, body);
399 | } catch (IOException connectionReset) {
400 | this.getChannel().basicPublish(exchange, routingKey, props, body);
401 | }
402 | }
403 |
404 | /**
405 | * Publish a message
406 | *
407 | * @param exchange the exchange to publish the message to
408 | * @param routingKey the routing key
409 | * @param mandatory true if the 'mandatory' flag is to be set
410 | * @param props other properties for the message - routing headers etc
411 | * @param body the message body
412 | * @throws java.io.IOException if an error is encountered
413 | * @see com.rabbitmq.client.AMQP.Basic.Publish
414 | */
415 | @Override
416 | public void basicPublish(String exchange, String routingKey, boolean mandatory, AMQP.BasicProperties props, byte[] body) throws IOException {
417 | try {
418 | this.getChannel().basicPublish(exchange, routingKey, mandatory, props, body);
419 | } catch (IOException connectionReset) {
420 | this.getChannel().basicPublish(exchange, routingKey, mandatory, props, body);
421 | }
422 | }
423 |
424 | /**
425 | * Publish a message
426 | *
427 | * @param exchange the exchange to publish the message to
428 | * @param routingKey the routing key
429 | * @param mandatory true if the 'mandatory' flag is to be set
430 | * @param immediate true if the 'immediate' flag is to be
431 | * set. Note that the RabbitMQ server does not support this flag.
432 | * @param props other properties for the message - routing headers etc
433 | * @param body the message body
434 | * @throws java.io.IOException if an error is encountered
435 | * @see com.rabbitmq.client.AMQP.Basic.Publish
436 | */
437 | @Override
438 | public void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, AMQP.BasicProperties props, byte[] body) throws IOException {
439 | try {
440 | this.getChannel().basicPublish(exchange, routingKey, mandatory, immediate, props, body);
441 | } catch (IOException connectionReset) {
442 | this.getChannel().basicPublish(exchange, routingKey, mandatory, immediate, props, body);
443 | }
444 | }
445 |
446 | /**
447 | * Actively declare a non-autodelete, non-durable exchange with no extra arguments
448 | *
449 | * @param exchange the name of the exchange
450 | * @param type the exchange type
451 | * @return a declaration-confirm method to indicate the exchange was successfully declared
452 | * @throws java.io.IOException if an error is encountered
453 | * @see com.rabbitmq.client.AMQP.Exchange.Declare
454 | * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk
455 | */
456 | @Override
457 | public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type) throws IOException {
458 | try {
459 | return this.getChannel().exchangeDeclare(exchange, type);
460 | } catch (IOException connectionReset) {
461 | return this.getChannel().exchangeDeclare(exchange, type);
462 | }
463 | }
464 |
465 | /**
466 | * Actively declare a non-autodelete exchange with no extra arguments
467 | *
468 | * @param exchange the name of the exchange
469 | * @param type the exchange type
470 | * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart)
471 | * @return a declaration-confirm method to indicate the exchange was successfully declared
472 | * @throws java.io.IOException if an error is encountered
473 | * @see com.rabbitmq.client.AMQP.Exchange.Declare
474 | * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk
475 | */
476 | @Override
477 | public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable) throws IOException {
478 | try {
479 | return this.getChannel().exchangeDeclare(exchange, type, durable);
480 | } catch (IOException connectionReset) {
481 | return this.getChannel().exchangeDeclare(exchange, type, durable);
482 | }
483 | }
484 |
485 | /**
486 | * Declare an exchange.
487 | *
488 | * @param exchange the name of the exchange
489 | * @param type the exchange type
490 | * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart)
491 | * @param autoDelete true if the server should delete the exchange when it is no longer in use
492 | * @param arguments other properties (construction arguments) for the exchange
493 | * @return a declaration-confirm method to indicate the exchange was successfully declared
494 | * @throws java.io.IOException if an error is encountered
495 | * @see com.rabbitmq.client.AMQP.Exchange.Declare
496 | * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk
497 | */
498 | @Override
499 | public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, Map arguments) throws IOException {
500 | try {
501 | return this.getChannel().exchangeDeclare(exchange, type, durable, autoDelete, arguments);
502 | } catch (IOException connectionReset) {
503 | return this.getChannel().exchangeDeclare(exchange, type, durable, autoDelete, arguments);
504 | }
505 | }
506 |
507 | /**
508 | * Declare an exchange, via an interface that allows the complete set of
509 | * arguments.
510 | *
511 | * @param exchange the name of the exchange
512 | * @param type the exchange type
513 | * @param durable true if we are declaring a durable exchange (the exchange will survive a server restart)
514 | * @param autoDelete true if the server should delete the exchange when it is no longer in use
515 | * @param internal true if the exchange is internal, i.e. can't be directly
516 | * published to by a client.
517 | * @param arguments other properties (construction arguments) for the exchange
518 | * @return a declaration-confirm method to indicate the exchange was successfully declared
519 | * @throws java.io.IOException if an error is encountered
520 | * @see com.rabbitmq.client.AMQP.Exchange.Declare
521 | * @see com.rabbitmq.client.AMQP.Exchange.DeclareOk
522 | */
523 | @Override
524 | public AMQP.Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete, boolean internal, Map arguments) throws IOException {
525 | try {
526 | return this.getChannel().exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments);
527 | } catch (IOException connectionReset) {
528 | return this.getChannel().exchangeDeclare(exchange, type, durable, autoDelete, internal, arguments);
529 | }
530 | }
531 |
532 | /**
533 | * Declare an exchange passively; that is, check if the named exchange exists.
534 | *
535 | * @param name check the existence of an exchange named this
536 | * @throws java.io.IOException the server will raise a 404 channel exception if the named exchange does not exist.
537 | */
538 | @Override
539 | public AMQP.Exchange.DeclareOk exchangeDeclarePassive(String name) throws IOException {
540 | try {
541 | return this.getChannel().exchangeDeclarePassive(name);
542 | } catch (IOException connectionReset) {
543 | return this.getChannel().exchangeDeclarePassive(name);
544 | }
545 | }
546 |
547 | /**
548 | * Delete an exchange
549 | *
550 | * @param exchange the name of the exchange
551 | * @param ifUnused true to indicate that the exchange is only to be deleted if it is unused
552 | * @return a deletion-confirm method to indicate the exchange was successfully deleted
553 | * @throws java.io.IOException if an error is encountered
554 | * @see com.rabbitmq.client.AMQP.Exchange.Delete
555 | * @see com.rabbitmq.client.AMQP.Exchange.DeleteOk
556 | */
557 | @Override
558 | public AMQP.Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) throws IOException {
559 | try {
560 | return this.getChannel().exchangeDelete(exchange, ifUnused);
561 | } catch (IOException connectionReset) {
562 | return this.getChannel().exchangeDelete(exchange, ifUnused);
563 | }
564 | }
565 |
566 | /**
567 | * Delete an exchange, without regard for whether it is in use or not
568 | *
569 | * @param exchange the name of the exchange
570 | * @return a deletion-confirm method to indicate the exchange was successfully deleted
571 | * @throws java.io.IOException if an error is encountered
572 | * @see com.rabbitmq.client.AMQP.Exchange.Delete
573 | * @see com.rabbitmq.client.AMQP.Exchange.DeleteOk
574 | */
575 | @Override
576 | public AMQP.Exchange.DeleteOk exchangeDelete(String exchange) throws IOException {
577 | try {
578 | return this.getChannel().exchangeDelete(exchange);
579 | } catch (IOException connectionReset) {
580 | return this.getChannel().exchangeDelete(exchange);
581 | }
582 | }
583 |
584 | /**
585 | * Bind an exchange to an exchange, with no extra arguments.
586 | *
587 | * @param destination the name of the exchange to which messages flow across the binding
588 | * @param source the name of the exchange from which messages flow across the binding
589 | * @param routingKey the routine key to use for the binding
590 | * @return a binding-confirm method if the binding was successfully created
591 | * @throws java.io.IOException if an error is encountered
592 | * @see com.rabbitmq.client.AMQP.Exchange.Bind
593 | * @see com.rabbitmq.client.AMQP.Exchange.BindOk
594 | */
595 | @Override
596 | public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey) throws IOException {
597 | try {
598 | return this.getChannel().exchangeBind(destination, source, routingKey);
599 | } catch (IOException connectionReset) {
600 | return this.getChannel().exchangeBind(destination, source, routingKey);
601 | }
602 | }
603 |
604 | /**
605 | * Bind an exchange to an exchange.
606 | *
607 | * @param destination the name of the exchange to which messages flow across the binding
608 | * @param source the name of the exchange from which messages flow across the binding
609 | * @param routingKey the routine key to use for the binding
610 | * @param arguments other properties (binding parameters)
611 | * @return a binding-confirm method if the binding was successfully created
612 | * @throws java.io.IOException if an error is encountered
613 | * @see com.rabbitmq.client.AMQP.Exchange.Bind
614 | * @see com.rabbitmq.client.AMQP.Exchange.BindOk
615 | */
616 | @Override
617 | public AMQP.Exchange.BindOk exchangeBind(String destination, String source, String routingKey, Map arguments) throws IOException {
618 | try {
619 | return this.getChannel().exchangeBind(destination, source, routingKey, arguments);
620 | } catch (IOException connectionReset) {
621 | return this.getChannel().exchangeBind(destination, source, routingKey, arguments);
622 | }
623 | }
624 |
625 | /**
626 | * Unbind an exchange from an exchange, with no extra arguments.
627 | *
628 | * @param destination the name of the exchange to which messages flow across the binding
629 | * @param source the name of the exchange from which messages flow across the binding
630 | * @param routingKey the routine key to use for the binding
631 | * @return a binding-confirm method if the binding was successfully created
632 | * @throws java.io.IOException if an error is encountered
633 | * @see com.rabbitmq.client.AMQP.Exchange.Bind
634 | * @see com.rabbitmq.client.AMQP.Exchange.BindOk
635 | */
636 | @Override
637 | public AMQP.Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey) throws IOException {
638 | try {
639 | return this.getChannel().exchangeUnbind(destination, source, routingKey);
640 | } catch (IOException connectionReset) {
641 | return this.getChannel().exchangeUnbind(destination, source, routingKey);
642 | }
643 | }
644 |
645 | /**
646 | * Unbind an exchange from an exchange.
647 | *
648 | * @param destination the name of the exchange to which messages flow across the binding
649 | * @param source the name of the exchange from which messages flow across the binding
650 | * @param routingKey the routine key to use for the binding
651 | * @param arguments other properties (binding parameters)
652 | * @return a binding-confirm method if the binding was successfully created
653 | * @throws java.io.IOException if an error is encountered
654 | * @see com.rabbitmq.client.AMQP.Exchange.Bind
655 | * @see com.rabbitmq.client.AMQP.Exchange.BindOk
656 | */
657 | @Override
658 | public AMQP.Exchange.UnbindOk exchangeUnbind(String destination, String source, String routingKey, Map arguments) throws IOException {
659 | try {
660 | return this.getChannel().exchangeUnbind(destination, source, routingKey, arguments);
661 | } catch (IOException connectionReset) {
662 | return this.getChannel().exchangeUnbind(destination, source, routingKey, arguments);
663 | }
664 | }
665 |
666 | /**
667 | * Actively declare a server-named exclusive, autodelete, non-durable queue.
668 | * The name of the new queue is held in the "queue" field of the {@link com.rabbitmq.client.AMQP.Queue.DeclareOk} result.
669 | *
670 | * @return a declaration-confirm method to indicate the queue was successfully declared
671 | * @throws java.io.IOException if an error is encountered
672 | * @see com.rabbitmq.client.AMQP.Queue.Declare
673 | * @see com.rabbitmq.client.AMQP.Queue.DeclareOk
674 | */
675 | @Override
676 | public AMQP.Queue.DeclareOk queueDeclare() throws IOException {
677 | try {
678 | return this.getChannel().queueDeclare();
679 | } catch (IOException connectionReset) {
680 | return this.getChannel().queueDeclare();
681 | }
682 | }
683 |
684 | /**
685 | * Declare a queue
686 | *
687 | * @param queue the name of the queue
688 | * @param durable true if we are declaring a durable queue (the queue will survive a server restart)
689 | * @param exclusive true if we are declaring an exclusive queue (restricted to this connection)
690 | * @param autoDelete true if we are declaring an autodelete queue (server will delete it when no longer in use)
691 | * @param arguments other properties (construction arguments) for the queue
692 | * @return a declaration-confirm method to indicate the queue was successfully declared
693 | * @throws java.io.IOException if an error is encountered
694 | * @see com.rabbitmq.client.AMQP.Queue.Declare
695 | * @see com.rabbitmq.client.AMQP.Queue.DeclareOk
696 | */
697 | @Override
698 | public AMQP.Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map arguments) throws IOException {
699 | try {
700 | return this.getChannel().queueDeclare(queue, durable, exclusive, autoDelete, arguments);
701 | } catch (IOException connectionReset) {
702 | return this.getChannel().queueDeclare(queue, durable, exclusive, autoDelete, arguments);
703 | }
704 | }
705 |
706 | /**
707 | * Declare a queue passively; i.e., check if it exists. In AMQP
708 | * 0-9-1, all arguments aside from nowait are ignored; and sending
709 | * nowait makes this method a no-op, so we default it to false.
710 | *
711 | * @param queue the name of the queue
712 | * @return a declaration-confirm method to indicate the queue exists
713 | * @throws java.io.IOException if an error is encountered,
714 | * including if the queue does not exist and if the queue is
715 | * exclusively owned by another connection.
716 | * @see com.rabbitmq.client.AMQP.Queue.Declare
717 | * @see com.rabbitmq.client.AMQP.Queue.DeclareOk
718 | */
719 | @Override
720 | public AMQP.Queue.DeclareOk queueDeclarePassive(String queue) throws IOException {
721 | try {
722 | return this.getChannel().queueDeclarePassive(queue);
723 | } catch (IOException connectionReset) {
724 | return this.getChannel().queueDeclarePassive(queue);
725 | }
726 | }
727 |
728 | /**
729 | * Delete a queue, without regard for whether it is in use or has messages on it
730 | *
731 | * @param queue the name of the queue
732 | * @return a deletion-confirm method to indicate the queue was successfully deleted
733 | * @throws java.io.IOException if an error is encountered
734 | * @see com.rabbitmq.client.AMQP.Queue.Delete
735 | * @see com.rabbitmq.client.AMQP.Queue.DeleteOk
736 | */
737 | @Override
738 | public AMQP.Queue.DeleteOk queueDelete(String queue) throws IOException {
739 | try {
740 | return this.getChannel().queueDelete(queue);
741 | } catch (IOException connectionReset) {
742 | return this.getChannel().queueDelete(queue);
743 | }
744 | }
745 |
746 | /**
747 | * Delete a queue
748 | *
749 | * @param queue the name of the queue
750 | * @param ifUnused true if the queue should be deleted only if not in use
751 | * @param ifEmpty true if the queue should be deleted only if empty
752 | * @return a deletion-confirm method to indicate the queue was successfully deleted
753 | * @throws java.io.IOException if an error is encountered
754 | * @see com.rabbitmq.client.AMQP.Queue.Delete
755 | * @see com.rabbitmq.client.AMQP.Queue.DeleteOk
756 | */
757 | @Override
758 | public AMQP.Queue.DeleteOk queueDelete(String queue, boolean ifUnused, boolean ifEmpty) throws IOException {
759 | try {
760 | return this.getChannel().queueDelete(queue, ifUnused, ifEmpty);
761 | } catch (IOException connectionReset) {
762 | return this.getChannel().queueDelete(queue, ifUnused, ifEmpty);
763 | }
764 | }
765 |
766 | /**
767 | * Bind a queue to an exchange, with no extra arguments.
768 | *
769 | * @param queue the name of the queue
770 | * @param exchange the name of the exchange
771 | * @param routingKey the routine key to use for the binding
772 | * @return a binding-confirm method if the binding was successfully created
773 | * @throws java.io.IOException if an error is encountered
774 | * @see com.rabbitmq.client.AMQP.Queue.Bind
775 | * @see com.rabbitmq.client.AMQP.Queue.BindOk
776 | */
777 | @Override
778 | public AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey) throws IOException {
779 | try {
780 | return this.getChannel().queueBind(queue, exchange, routingKey);
781 | } catch (IOException connectionReset) {
782 | return this.getChannel().queueBind(queue, exchange, routingKey);
783 | }
784 | }
785 |
786 | /**
787 | * Bind a queue to an exchange.
788 | *
789 | * @param queue the name of the queue
790 | * @param exchange the name of the exchange
791 | * @param routingKey the routine key to use for the binding
792 | * @param arguments other properties (binding parameters)
793 | * @return a binding-confirm method if the binding was successfully created
794 | * @throws java.io.IOException if an error is encountered
795 | * @see com.rabbitmq.client.AMQP.Queue.Bind
796 | * @see com.rabbitmq.client.AMQP.Queue.BindOk
797 | */
798 | @Override
799 | public AMQP.Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map arguments) throws IOException {
800 | try {
801 | return this.getChannel().queueBind(queue, exchange, routingKey, arguments);
802 | } catch (IOException connectionReset) {
803 | return this.getChannel().queueBind(queue, exchange, routingKey, arguments);
804 | }
805 | }
806 |
807 | /**
808 | * Unbinds a queue from an exchange, with no extra arguments.
809 | *
810 | * @param queue the name of the queue
811 | * @param exchange the name of the exchange
812 | * @param routingKey the routine key to use for the binding
813 | * @return an unbinding-confirm method if the binding was successfully deleted
814 | * @throws java.io.IOException if an error is encountered
815 | * @see com.rabbitmq.client.AMQP.Queue.Unbind
816 | * @see com.rabbitmq.client.AMQP.Queue.UnbindOk
817 | */
818 | @Override
819 | public AMQP.Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey) throws IOException {
820 | try {
821 | return this.getChannel().queueUnbind(queue, exchange, routingKey);
822 | } catch (IOException connectionReset) {
823 | return this.getChannel().queueUnbind(queue, exchange, routingKey);
824 | }
825 | }
826 |
827 | /**
828 | * Unbind a queue from an exchange.
829 | *
830 | * @param queue the name of the queue
831 | * @param exchange the name of the exchange
832 | * @param routingKey the routine key to use for the binding
833 | * @param arguments other properties (binding parameters)
834 | * @return an unbinding-confirm method if the binding was successfully deleted
835 | * @throws java.io.IOException if an error is encountered
836 | * @see com.rabbitmq.client.AMQP.Queue.Unbind
837 | * @see com.rabbitmq.client.AMQP.Queue.UnbindOk
838 | */
839 | @Override
840 | public AMQP.Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, Map arguments) throws IOException {
841 | try {
842 | return this.getChannel().queueUnbind(queue, exchange, routingKey, arguments);
843 | } catch (IOException connectionReset) {
844 | return this.getChannel().queueUnbind(queue, exchange, routingKey, arguments);
845 | }
846 | }
847 |
848 | /**
849 | * Purges the contents of the given queue.
850 | *
851 | * @param queue the name of the queue
852 | * @return a purge-confirm method if the purge was executed succesfully
853 | * @throws java.io.IOException if an error is encountered
854 | * @see com.rabbitmq.client.AMQP.Queue.Purge
855 | * @see com.rabbitmq.client.AMQP.Queue.PurgeOk
856 | */
857 | @Override
858 | public AMQP.Queue.PurgeOk queuePurge(String queue) throws IOException {
859 | try {
860 | return this.getChannel().queuePurge(queue);
861 | } catch (IOException connectionReset) {
862 | return this.getChannel().queuePurge(queue);
863 | }
864 | }
865 |
866 | /**
867 | * Retrieve a message from a queue using {@link com.rabbitmq.client.AMQP.Basic.Get}
868 | *
869 | * @param queue the name of the queue
870 | * @param autoAck true if the server should consider messages
871 | * acknowledged once delivered; false if the server should expect
872 | * explicit acknowledgements
873 | * @return a {@link com.rabbitmq.client.GetResponse} containing the retrieved message data
874 | * @throws java.io.IOException if an error is encountered
875 | * @see com.rabbitmq.client.AMQP.Basic.Get
876 | * @see com.rabbitmq.client.AMQP.Basic.GetOk
877 | * @see com.rabbitmq.client.AMQP.Basic.GetEmpty
878 | */
879 | @Override
880 | public GetResponse basicGet(String queue, boolean autoAck) throws IOException {
881 | try {
882 | return this.getChannel().basicGet(queue, autoAck);
883 | } catch (IOException connectionReset) {
884 | return this.getChannel().basicGet(queue, autoAck);
885 | }
886 | }
887 |
888 | /**
889 | * Acknowledge one or several received
890 | * messages. Supply the deliveryTag from the {@link com.rabbitmq.client.AMQP.Basic.GetOk}
891 | * or {@link com.rabbitmq.client.AMQP.Basic.Deliver} method
892 | * containing the received message being acknowledged.
893 | *
894 | * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver}
895 | * @param multiple true to acknowledge all messages up to and
896 | * including the supplied delivery tag; false to acknowledge just
897 | * the supplied delivery tag.
898 | * @throws java.io.IOException if an error is encountered
899 | * @see com.rabbitmq.client.AMQP.Basic.Ack
900 | */
901 | @Override
902 | public void basicAck(long deliveryTag, boolean multiple) throws IOException {
903 | try {
904 | this.getChannel().basicAck(deliveryTag, multiple);
905 | } catch (IOException connectionReset) {
906 | this.getChannel().basicAck(deliveryTag, multiple);
907 | }
908 | }
909 |
910 | /**
911 | * Reject one or several received messages.
912 | *
913 | * Supply the deliveryTag from the {@link com.rabbitmq.client.AMQP.Basic.GetOk}
914 | * or {@link com.rabbitmq.client.AMQP.Basic.GetOk} method containing the message to be rejected.
915 | *
916 | * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver}
917 | * @param multiple true to reject all messages up to and including
918 | * the supplied delivery tag; false to reject just the supplied
919 | * delivery tag.
920 | * @param requeue true if the rejected message(s) should be requeued rather
921 | * than discarded/dead-lettered
922 | * @throws java.io.IOException if an error is encountered
923 | * @see com.rabbitmq.client.AMQP.Basic.Nack
924 | */
925 | @Override
926 | public void basicNack(long deliveryTag, boolean multiple, boolean requeue) throws IOException {
927 | try {
928 | this.getChannel().basicNack(deliveryTag, multiple, requeue);
929 | } catch (IOException connectionReset) {
930 | this.getChannel().basicNack(deliveryTag, multiple, requeue);
931 | }
932 | }
933 |
934 | /**
935 | * Reject a message. Supply the deliveryTag from the {@link com.rabbitmq.client.AMQP.Basic.GetOk}
936 | * or {@link com.rabbitmq.client.AMQP.Basic.Deliver} method
937 | * containing the received message being rejected.
938 | *
939 | * @param deliveryTag the tag from the received {@link com.rabbitmq.client.AMQP.Basic.GetOk} or {@link com.rabbitmq.client.AMQP.Basic.Deliver}
940 | * @param requeue true if the rejected message should be requeued rather than discarded/dead-lettered
941 | * @throws java.io.IOException if an error is encountered
942 | * @see com.rabbitmq.client.AMQP.Basic.Reject
943 | */
944 | @Override
945 | public void basicReject(long deliveryTag, boolean requeue) throws IOException {
946 | try {
947 | this.getChannel().basicReject(deliveryTag, requeue);
948 | } catch (IOException connectionReset) {
949 | this.getChannel().basicReject(deliveryTag, requeue);
950 | }
951 | }
952 |
953 | /**
954 | * Start a non-nolocal, non-exclusive consumer, with
955 | * explicit acknowledgement and a server-generated consumerTag.
956 | *
957 | * @param queue the name of the queue
958 | * @param callback an interface to the consumer object
959 | * @return the consumerTag generated by the server
960 | * @throws java.io.IOException if an error is encountered
961 | * @see com.rabbitmq.client.AMQP.Basic.Consume
962 | * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk
963 | * @see #basicAck
964 | * @see #basicConsume(String, boolean, String, boolean, boolean, java.util.Map, com.rabbitmq.client.Consumer)
965 | */
966 | @Override
967 | public String basicConsume(String queue, Consumer callback) throws IOException {
968 | String ret;
969 | try {
970 | ret = this.getChannel().basicConsume(queue, callback);
971 | } catch (IOException connectionReset) {
972 | ret = this.getChannel().basicConsume(queue, callback);
973 | }
974 | this.consumers.put(queue, new BasicConsumer(callback));
975 | return ret;
976 | }
977 |
978 | /**
979 | * Start a non-nolocal, non-exclusive consumer, with
980 | * a server-generated consumerTag.
981 | *
982 | * @param queue the name of the queue
983 | * @param autoAck true if the server should consider messages
984 | * acknowledged once delivered; false if the server should expect
985 | * explicit acknowledgements
986 | * @param callback an interface to the consumer object
987 | * @return the consumerTag generated by the server
988 | * @throws java.io.IOException if an error is encountered
989 | * @see com.rabbitmq.client.AMQP.Basic.Consume
990 | * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk
991 | * @see #basicConsume(String, boolean, String, boolean, boolean, java.util.Map, com.rabbitmq.client.Consumer)
992 | */
993 | @Override
994 | public String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException {
995 | String ret;
996 | try {
997 | ret = this.getChannel().basicConsume(queue, autoAck, callback);
998 | } catch (IOException connectionReset) {
999 | ret = this.getChannel().basicConsume(queue, autoAck, callback);
1000 | }
1001 | this.consumers.put(queue, new BasicConsumer(callback, autoAck));
1002 | return ret;
1003 | }
1004 |
1005 | /**
1006 | * Start a non-nolocal, non-exclusive consumer.
1007 | *
1008 | * @param queue the name of the queue
1009 | * @param autoAck true if the server should consider messages
1010 | * acknowledged once delivered; false if the server should expect
1011 | * explicit acknowledgements
1012 | * @param consumerTag a client-generated consumer tag to establish context
1013 | * @param callback an interface to the consumer object
1014 | * @return the consumerTag associated with the new consumer
1015 | * @throws java.io.IOException if an error is encountered
1016 | * @see com.rabbitmq.client.AMQP.Basic.Consume
1017 | * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk
1018 | * @see #basicConsume(String, boolean, String, boolean, boolean, java.util.Map, com.rabbitmq.client.Consumer)
1019 | */
1020 | @Override
1021 | public String basicConsume(String queue, boolean autoAck, String consumerTag, Consumer callback) throws IOException {
1022 | String ret;
1023 | try {
1024 | ret = this.getChannel().basicConsume(queue, autoAck, consumerTag, callback);
1025 | } catch (IOException connectionReset) {
1026 | ret = this.getChannel().basicConsume(queue, autoAck, consumerTag, callback);
1027 | }
1028 | this.consumers.put(queue, new BasicConsumer(callback, autoAck, consumerTag));
1029 | return ret;
1030 | }
1031 |
1032 | /**
1033 | * Start a consumer. Calls the consumer's {@link com.rabbitmq.client.Consumer#handleConsumeOk}
1034 | * method.
1035 | *
1036 | * @param queue the name of the queue
1037 | * @param autoAck true if the server should consider messages
1038 | * acknowledged once delivered; false if the server should expect
1039 | * explicit acknowledgements
1040 | * @param consumerTag a client-generated consumer tag to establish context
1041 | * @param noLocal true if the server should not deliver to this consumer
1042 | * messages published on this channel's connection
1043 | * @param exclusive true if this is an exclusive consumer
1044 | * @param callback an interface to the consumer object
1045 | * @param arguments a set of arguments for the consume
1046 | * @return the consumerTag associated with the new consumer
1047 | * @throws java.io.IOException if an error is encountered
1048 | * @see com.rabbitmq.client.AMQP.Basic.Consume
1049 | * @see com.rabbitmq.client.AMQP.Basic.ConsumeOk
1050 | */
1051 | @Override
1052 | public String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, Consumer callback) throws IOException {
1053 | String ret;
1054 | try {
1055 | ret = this.getChannel().basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, callback);
1056 | } catch (IOException connectionReset) {
1057 | ret = this.getChannel().basicConsume(queue, autoAck, consumerTag, noLocal, exclusive, arguments, callback);
1058 | }
1059 | this.consumers.put(queue, new BasicConsumer(callback, autoAck, consumerTag, noLocal, exclusive, arguments));
1060 | return ret;
1061 | }
1062 |
1063 | /**
1064 | * Cancel a consumer. Calls the consumer's {@link com.rabbitmq.client.Consumer#handleCancelOk}
1065 | * method.
1066 | *
1067 | * @param consumerTag a client- or server-generated consumer tag to establish context
1068 | * @throws java.io.IOException if an error is encountered, or if the consumerTag is unknown
1069 | * @see com.rabbitmq.client.AMQP.Basic.Cancel
1070 | * @see com.rabbitmq.client.AMQP.Basic.CancelOk
1071 | */
1072 | @Override
1073 | public void basicCancel(String consumerTag) throws IOException {
1074 | try {
1075 | this.getChannel().basicCancel(consumerTag);
1076 | } catch (IOException connectionReset) {
1077 | this.getChannel().basicCancel(consumerTag);
1078 | }
1079 | }
1080 |
1081 | /**
1082 | * Ask the broker to resend unacknowledged messages. In 0-8
1083 | * basic.recover is asynchronous; in 0-9-1 it is synchronous, and
1084 | * the new, deprecated method basic.recover_async is asynchronous.
1085 | *
1086 | * Equivalent to calling basicRecover(true), messages
1087 | * will be requeued and possibly delivered to a different consumer.
1088 | *
1089 | * @see #basicRecover(boolean)
1090 | */
1091 | @Override
1092 | public AMQP.Basic.RecoverOk basicRecover() throws IOException {
1093 | try {
1094 | return this.getChannel().basicRecover();
1095 | } catch (IOException connectionReset) {
1096 | return this.getChannel().basicRecover();
1097 | }
1098 | }
1099 |
1100 | /**
1101 | * Ask the broker to resend unacknowledged messages. In 0-8
1102 | * basic.recover is asynchronous; in 0-9-1 it is synchronous, and
1103 | * the new, deprecated method basic.recover_async is asynchronous.
1104 | *
1105 | * @param requeue If true, messages will be requeued and possibly
1106 | * delivered to a different consumer. If false, messages will be
1107 | * redelivered to the same consumer.
1108 | */
1109 | @Override
1110 | public AMQP.Basic.RecoverOk basicRecover(boolean requeue) throws IOException {
1111 | try {
1112 | return this.getChannel().basicRecover(requeue);
1113 | } catch (IOException connectionReset) {
1114 | return this.getChannel().basicRecover(requeue);
1115 | }
1116 | }
1117 |
1118 | /**
1119 | * Ask the broker to resend unacknowledged messages. In 0-8
1120 | * basic.recover is asynchronous; in 0-9-1 it is synchronous, and
1121 | * the new, deprecated method basic.recover_async is asynchronous
1122 | * and deprecated.
1123 | *
1124 | * @param requeue If true, messages will be requeued and possibly
1125 | * delivered to a different consumer. If false, messages will be
1126 | * redelivered to the same consumer.
1127 | */
1128 | @Override
1129 | public void basicRecoverAsync(boolean requeue) throws IOException {
1130 | try {
1131 | this.getChannel().basicRecoverAsync(requeue);
1132 | } catch (IOException connectionReset) {
1133 | this.getChannel().basicRecoverAsync(requeue);
1134 | }
1135 | }
1136 |
1137 | /**
1138 | * Enables TX mode on this channel.
1139 | *
1140 | * @return a transaction-selection method to indicate the transaction was successfully initiated
1141 | * @throws java.io.IOException if an error is encountered
1142 | * @see com.rabbitmq.client.AMQP.Tx.Select
1143 | * @see com.rabbitmq.client.AMQP.Tx.SelectOk
1144 | */
1145 | @Override
1146 | public AMQP.Tx.SelectOk txSelect() throws IOException {
1147 | try {
1148 | return this.getChannel().txSelect();
1149 | } catch (IOException connectionReset) {
1150 | return this.getChannel().txSelect();
1151 | }
1152 | }
1153 |
1154 | /**
1155 | * Commits a TX transaction on this channel.
1156 | *
1157 | * @return a transaction-commit method to indicate the transaction was successfully committed
1158 | * @throws java.io.IOException if an error is encountered
1159 | * @see com.rabbitmq.client.AMQP.Tx.Commit
1160 | * @see com.rabbitmq.client.AMQP.Tx.CommitOk
1161 | */
1162 | @Override
1163 | public AMQP.Tx.CommitOk txCommit() throws IOException {
1164 | try {
1165 | return this.getChannel().txCommit();
1166 | } catch (IOException connectionReset) {
1167 | return this.getChannel().txCommit();
1168 | }
1169 | }
1170 |
1171 | /**
1172 | * Rolls back a TX transaction on this channel.
1173 | *
1174 | * @return a transaction-rollback method to indicate the transaction was successfully rolled back
1175 | * @throws java.io.IOException if an error is encountered
1176 | * @see com.rabbitmq.client.AMQP.Tx.Rollback
1177 | * @see com.rabbitmq.client.AMQP.Tx.RollbackOk
1178 | */
1179 | @Override
1180 | public AMQP.Tx.RollbackOk txRollback() throws IOException {
1181 | try {
1182 | return this.getChannel().txRollback();
1183 | } catch (IOException connectionReset) {
1184 | return this.getChannel().txRollback();
1185 | }
1186 | }
1187 |
1188 | /**
1189 | * Enables publisher acknowledgements on this channel.
1190 | *
1191 | * @throws java.io.IOException if an error is encountered
1192 | * @see com.rabbitmq.client.AMQP.Confirm.Select
1193 | */
1194 | @Override
1195 | public AMQP.Confirm.SelectOk confirmSelect() throws IOException {
1196 | try {
1197 | return this.getChannel().confirmSelect();
1198 | } catch (IOException connectionReset) {
1199 | return this.getChannel().confirmSelect();
1200 | }
1201 | }
1202 |
1203 | /**
1204 | * When in confirm mode, returns the sequence number of the next
1205 | * message to be published.
1206 | *
1207 | * @return the sequence number of the next message to be published
1208 | */
1209 | @Override
1210 | public long getNextPublishSeqNo() {
1211 | return this.getChannel().getNextPublishSeqNo();
1212 | }
1213 |
1214 | /**
1215 | * Wait until all messages published since the last call have been
1216 | * either ack'd or nack'd by the broker. Note, when called on a
1217 | * non-Confirm channel, waitForConfirms throws an IllegalStateException.
1218 | *
1219 | * @return whether all the messages were ack'd (and none were nack'd)
1220 | * @throws IllegalStateException
1221 | */
1222 | @Override
1223 | public boolean waitForConfirms() throws InterruptedException {
1224 | return this.getChannel().waitForConfirms();
1225 | }
1226 |
1227 | /**
1228 | * Wait until all messages published since the last call have been
1229 | * either ack'd or nack'd by the broker; or until timeout elapses.
1230 | * If the timeout expires a TimeoutException is thrown. When
1231 | * called on a non-Confirm channel, waitForConfirms throws an
1232 | * IllegalStateException.
1233 | *
1234 | * @return whether all the messages were ack'd (and none were nack'd)
1235 | * @throws IllegalStateException
1236 | */
1237 | @Override
1238 | public boolean waitForConfirms(long timeout) throws InterruptedException, TimeoutException {
1239 | return this.getChannel().waitForConfirms(timeout);
1240 | }
1241 |
1242 | /**
1243 | * Wait until all messages published since the last call have
1244 | * been either ack'd or nack'd by the broker. If any of the
1245 | * messages were nack'd, waitForConfirmsOrDie will throw an
1246 | * IOException. When called on a non-Confirm channel, it will
1247 | * throw an IllegalStateException.
1248 | *
1249 | * @throws IllegalStateException
1250 | */
1251 | @Override
1252 | public void waitForConfirmsOrDie() throws IOException, InterruptedException {
1253 | try {
1254 | this.getChannel().waitForConfirmsOrDie();
1255 | } catch (IOException connectionReset) {
1256 | this.getChannel().waitForConfirmsOrDie();
1257 | }
1258 | }
1259 |
1260 | /**
1261 | * Wait until all messages published since the last call have
1262 | * been either ack'd or nack'd by the broker; or until timeout elapses.
1263 | * If the timeout expires a TimeoutException is thrown. If any of the
1264 | * messages were nack'd, waitForConfirmsOrDie will throw an
1265 | * IOException. When called on a non-Confirm channel, it will
1266 | * throw an IllegalStateException.
1267 | *
1268 | * @throws IllegalStateException
1269 | */
1270 | @Override
1271 | public void waitForConfirmsOrDie(long timeout) throws IOException, InterruptedException, TimeoutException {
1272 | try {
1273 | this.getChannel().waitForConfirmsOrDie(timeout);
1274 | } catch (IOException connectionReset) {
1275 | this.getChannel().waitForConfirmsOrDie(timeout);
1276 | }
1277 | }
1278 |
1279 | /**
1280 | * Asynchronously send a method over this channel.
1281 | *
1282 | * @param method method to transmit over this channel.
1283 | * @throws java.io.IOException Problem transmitting method.
1284 | */
1285 | @Override
1286 | public void asyncRpc(Method method) throws IOException {
1287 | try {
1288 | this.getChannel().asyncRpc(method);
1289 | } catch (IOException connectionReset) {
1290 | this.getChannel().asyncRpc(method);
1291 | }
1292 | }
1293 |
1294 | /**
1295 | * Synchronously send a method over this channel.
1296 | *
1297 | * @param method method to transmit over this channel.
1298 | * @return command response to method. Caller should cast as appropriate.
1299 | * @throws java.io.IOException Problem transmitting method.
1300 | */
1301 | @Override
1302 | public Command rpc(Method method) throws IOException {
1303 | try {
1304 | return this.getChannel().rpc(method);
1305 | } catch (IOException connectionReset) {
1306 | return this.getChannel().rpc(method);
1307 | }
1308 | }
1309 |
1310 | /**
1311 | * Add shutdown listener.
1312 | * If the component is already closed, handler is fired immediately
1313 | *
1314 | * @param listener {@link com.rabbitmq.client.ShutdownListener} to the component
1315 | */
1316 | @Override
1317 | public void addShutdownListener(ShutdownListener listener) {
1318 | this.getChannel().addShutdownListener(listener);
1319 | this.shutdownListeners.add(listener);
1320 | }
1321 |
1322 | /**
1323 | * Remove shutdown listener for the component.
1324 | *
1325 | * @param listener {@link com.rabbitmq.client.ShutdownListener} to be removed
1326 | */
1327 | @Override
1328 | public void removeShutdownListener(ShutdownListener listener) {
1329 | this.shutdownListeners.remove(listener);
1330 | this.getChannel().removeShutdownListener(listener);
1331 | }
1332 |
1333 | /**
1334 | * Get the shutdown reason object
1335 | *
1336 | * @return ShutdownSignalException if component is closed, null otherwise
1337 | */
1338 | @Override
1339 | public ShutdownSignalException getCloseReason() {
1340 | return this.getChannel().getCloseReason();
1341 | }
1342 |
1343 | /**
1344 | * Protected API - notify the listeners attached to the component
1345 | *
1346 | * @see com.rabbitmq.client.ShutdownListener
1347 | */
1348 | @Override
1349 | public void notifyListeners() {
1350 | this.getChannel().notifyListeners();
1351 | }
1352 |
1353 | /**
1354 | * Determine whether the component is currently open.
1355 | * Will return false if we are currently closing.
1356 | * Checking this method should be only for information,
1357 | * because of the race conditions - state can change after the call.
1358 | * Instead just execute and try to catch ShutdownSignalException
1359 | * and IOException
1360 | *
1361 | * @return true when component is open, false otherwise
1362 | */
1363 | @Override
1364 | public boolean isOpen() {
1365 | return this.getChannel().isOpen();
1366 | }
1367 |
1368 | private class BasicConsumer {
1369 |
1370 | private Consumer consumer;
1371 | private boolean autoack;
1372 | private String consumerTag;
1373 | private boolean noLocal;
1374 | private boolean exclusive;
1375 | private Map arguments;
1376 |
1377 | public BasicConsumer(Consumer consumer, boolean autoack, String consumerTag, boolean noLocal, boolean exclusive, Map arguments) {
1378 | this.consumer = consumer;
1379 | this.autoack = autoack;
1380 | this.consumerTag = consumerTag;
1381 | this.noLocal = noLocal;
1382 | this.exclusive = exclusive;
1383 | this.arguments = arguments;
1384 | }
1385 |
1386 | public BasicConsumer(Consumer consumer, boolean autoack, String consumerTag) {
1387 | this(consumer, autoack, consumerTag, false, false, null);
1388 | }
1389 |
1390 | public BasicConsumer(Consumer consumer, boolean autoack) {
1391 | this(consumer, autoack, "");
1392 | }
1393 |
1394 | public BasicConsumer(Consumer consumer) {
1395 | this(consumer, true);
1396 | }
1397 | }
1398 | }
1399 |
--------------------------------------------------------------------------------
/src/main/java/com/clevercloud/rabbitmq/RabbitMQAutoConnection.java:
--------------------------------------------------------------------------------
1 | package com.clevercloud.rabbitmq;
2 |
3 | import com.clevercloud.annotations.NonEmpty;
4 | import com.rabbitmq.client.*;
5 | import org.apache.commons.logging.Log;
6 | import org.apache.commons.logging.LogFactory;
7 |
8 | import javax.annotation.Nonnull;
9 | import javax.net.ssl.SSLContext;
10 | import java.io.IOException;
11 | import java.net.InetAddress;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.Map;
15 | import java.util.Random;
16 |
17 |
18 | public class RabbitMQAutoConnection implements Connection, Watchable {
19 |
20 | private static final Log logger = LogFactory.getLog(RabbitMQAutoConnection.class);
21 |
22 |
23 | /**
24 | * Retry until success
25 | */
26 | public static final long NO_TRIES_LIMIT = -1;
27 |
28 | /**
29 | * Default interval before two reconnection attempts
30 | */
31 | public static final long DEFAULT_INTERVAL = 500;
32 |
33 | /**
34 | * Default maximal number of tries to reconnect
35 | */
36 | public static final long DEFAULT_TRIES = NO_TRIES_LIMIT;
37 |
38 | private Connection connection;
39 |
40 | private List hosts;
41 | private ConnectionFactory factory;
42 |
43 | private long interval;
44 | private long tries;
45 |
46 | private boolean verbose;
47 |
48 | private List shutdownListeners;
49 | private List blockedListeners;
50 |
51 |
52 | private Random random;
53 |
54 | private WatcherThread watcher;
55 |
56 | /*
57 | * With SSL
58 | */
59 |
60 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, int port, String login, String password, SSLContext context, long interval, long tries) {
61 | this(hosts,port, login, password, null, context, interval, tries);
62 | }
63 |
64 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, int port, String login, String password, String vhost, SSLContext context, long interval, long tries) {
65 | this.hosts = hosts;
66 |
67 | this.factory = new ConnectionFactory();
68 | factory.setPort(port);
69 | factory.setUsername(login);
70 | factory.setPassword(password);
71 | if(vhost != null)
72 | factory.setVirtualHost(vhost);
73 | if (context != null)
74 | factory.useSslProtocol(context);
75 |
76 | this.interval = interval;
77 | this.tries = tries;
78 |
79 | this.verbose = false;
80 |
81 | this.shutdownListeners = new ArrayList();
82 | this.blockedListeners = new ArrayList();
83 |
84 |
85 | this.random = new Random();
86 |
87 | this.watcher = new WatcherThread(this, this.interval);
88 | this.watcher.start();
89 | }
90 |
91 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, String login, String password, SSLContext context, long interval, long tries) {
92 | this(hosts, ConnectionFactory.USE_DEFAULT_PORT, login, password, context, interval, tries);
93 | }
94 |
95 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, String login, String password, String vhost, SSLContext context, long interval, long tries) {
96 | this(hosts, ConnectionFactory.USE_DEFAULT_PORT, login, password, vhost, context, interval, tries);
97 | }
98 |
99 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, int port, String login, String password, SSLContext context) {
100 | this(hosts, port, login, password, context, DEFAULT_INTERVAL, DEFAULT_TRIES);
101 | }
102 |
103 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, int port, String login, String password, String vhost, SSLContext context) {
104 | this(hosts, port, login, password, vhost, context, DEFAULT_INTERVAL, DEFAULT_TRIES);
105 | }
106 |
107 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, String login, String password, SSLContext context) {
108 | this(hosts, login, password, context, DEFAULT_INTERVAL, DEFAULT_TRIES);
109 | }
110 |
111 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, String login, String password, String vhost, SSLContext context) {
112 | this(hosts, login, password, vhost, context, DEFAULT_INTERVAL, DEFAULT_TRIES);
113 | }
114 |
115 | /*
116 | * Without SSL
117 | */
118 |
119 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, int port, String login, String password, long interval, long tries) {
120 | this(hosts, port, login, password, ConnectionFactory.DEFAULT_VHOST, interval, tries);
121 | }
122 |
123 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, int port, String login, String password, String vhost, long interval, long tries) {
124 | this(hosts, port, login, password, vhost, null, interval, tries);
125 | }
126 |
127 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, String login, String password, String vhost, long interval, long tries) {
128 | this(hosts, ConnectionFactory.USE_DEFAULT_PORT, login, password, vhost, interval, tries);
129 | }
130 |
131 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, String login, String password, long interval, long tries) {
132 | this(hosts, ConnectionFactory.USE_DEFAULT_PORT, login, password, interval, tries);
133 | }
134 |
135 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, int port, String login, String password, String vhost) {
136 | this(hosts, port, login, password, vhost, DEFAULT_INTERVAL, DEFAULT_TRIES);
137 | }
138 |
139 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, int port, String login, String password) {
140 | this(hosts, port, login, password, DEFAULT_INTERVAL, DEFAULT_TRIES);
141 | }
142 |
143 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, String login, String password, String vhost) {
144 | this(hosts, login, password, vhost, DEFAULT_INTERVAL, DEFAULT_TRIES);
145 | }
146 |
147 | public RabbitMQAutoConnection(@Nonnull @NonEmpty List hosts, String login, String password) {
148 | this(hosts, login, password, DEFAULT_INTERVAL, DEFAULT_TRIES);
149 | }
150 |
151 | public void setVerbose(boolean verbose) {
152 | this.verbose = verbose;
153 | }
154 |
155 | public boolean isVerbose() {
156 | return this.verbose;
157 | }
158 |
159 | public long getTries() {
160 | return tries;
161 | }
162 |
163 | public long getInterval() {
164 | return interval;
165 | }
166 |
167 | private boolean isConnected() {
168 | return this.connection != null && this.connection.isOpen();
169 | }
170 |
171 | @Override
172 | public void watch() {
173 | this.checkConnection();
174 | }
175 |
176 | private synchronized void checkConnection() {
177 | if (this.isConnected())
178 | return;
179 |
180 | for (int tries = 0; (this.tries == NO_TRIES_LIMIT || tries < this.tries) && !this.isConnected(); ++tries) {
181 | if (this.verbose)
182 | logger.info("Attempting to " + ((this.connection != null) ? "re" : "") + "connect to the rabbitmq server.");
183 |
184 | this.factory.setHost(this.hosts.get(this.random.nextInt(this.hosts.size())));
185 |
186 | try {
187 | this.connection = this.factory.newConnection(); // TODO: call newConnection with null, Address[] ?
188 | for (ShutdownListener shutdownListener : shutdownListeners) {
189 | this.connection.addShutdownListener(shutdownListener);
190 | }
191 |
192 | for (BlockedListener blockedListener : blockedListeners) {
193 | this.connection.addBlockedListener(blockedListener);
194 | }
195 |
196 | } catch (IOException ignored) {
197 | }
198 |
199 | try {
200 | Thread.sleep(this.interval);
201 | } catch (InterruptedException ignored) {
202 | }
203 | }
204 |
205 | if (this.isConnected()) {
206 | if (this.verbose)
207 | logger.info("Connected to the rabbitmq server.");
208 | } else
209 | throw new NoRabbitMQConnectionException();
210 | }
211 |
212 | public Connection getConnection() {
213 | this.checkConnection();
214 | return this.connection;
215 | }
216 |
217 | /**
218 | * Retrieve the host.
219 | *
220 | * @return the hostname of the peer we're connected to.
221 | */
222 | @Override
223 | public InetAddress getAddress() {
224 | return this.getConnection().getAddress();
225 | }
226 |
227 | /**
228 | * Retrieve the port number.
229 | *
230 | * @return the port number of the peer we're connected to.
231 | */
232 | @Override
233 | public int getPort() {
234 | return this.getConnection().getPort();
235 | }
236 |
237 | /**
238 | * Get the negotiated maximum channel number. Usable channel
239 | * numbers range from 1 to this number, inclusive.
240 | *
241 | * @return the maximum channel number permitted for this connection.
242 | */
243 | @Override
244 | public int getChannelMax() {
245 | return this.getConnection().getChannelMax();
246 | }
247 |
248 | /**
249 | * Get the negotiated maximum frame size.
250 | *
251 | * @return the maximum frame size, in octets; zero if unlimited
252 | */
253 | @Override
254 | public int getFrameMax() {
255 | return this.getConnection().getFrameMax();
256 | }
257 |
258 | /**
259 | * Get the negotiated heartbeat interval.
260 | *
261 | * @return the heartbeat interval, in seconds; zero if none
262 | */
263 | @Override
264 | public int getHeartbeat() {
265 | return this.getConnection().getHeartbeat();
266 | }
267 |
268 | /**
269 | * Get a copy of the map of client properties sent to the server
270 | *
271 | * @return a copy of the map of client properties
272 | */
273 | @Override
274 | public Map getClientProperties() {
275 | return this.getConnection().getClientProperties();
276 | }
277 |
278 | /**
279 | * Retrieve the server properties.
280 | *
281 | * @return a map of the server properties. This typically includes the product name and version of the server.
282 | */
283 | @Override
284 | public Map getServerProperties() {
285 | return this.getConnection().getServerProperties();
286 | }
287 |
288 | public Channel createRawChannel() throws IOException {
289 | return this.getConnection().createChannel();
290 | }
291 |
292 | public Channel createRawChannel(int channelNumber) throws IOException {
293 | return this.getConnection().createChannel(channelNumber);
294 | }
295 |
296 | /**
297 | * Create a new channel, using an internally allocated channel number.
298 | *
299 | * @return a new channel descriptor, or null if none is available
300 | * @throws IOException if an I/O problem is encountered
301 | */
302 | @Override
303 | public Channel createChannel() throws IOException {
304 | return new RabbitMQAutoChannel(this);
305 | }
306 |
307 | /**
308 | * Create a new channel, using the specified channel number if possible.
309 | *
310 | * @param channelNumber the channel number to allocate
311 | * @return a new channel descriptor, or null if this channel number is already in use
312 | * @throws IOException if an I/O problem is encountered
313 | */
314 | @Override
315 | public Channel createChannel(int channelNumber) throws IOException {
316 | return new RabbitMQAutoChannel(this, channelNumber);
317 | }
318 |
319 | /**
320 | * Close this connection and all its channels
321 | * with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code
322 | * and message 'OK'.
323 | *
324 | * Waits for all the close operations to complete.
325 | *
326 | * @throws IOException if an I/O problem is encountered
327 | */
328 | @Override
329 | public void close() throws IOException {
330 | this.watcher.cancel();
331 | this.getConnection().close();
332 | }
333 |
334 | /**
335 | * Close this connection and all its channels.
336 | *
337 | * Waits for all the close operations to complete.
338 | *
339 | * @param closeCode the close code (See under "Reply Codes" in the AMQP specification)
340 | * @param closeMessage a message indicating the reason for closing the connection
341 | * @throws IOException if an I/O problem is encountered
342 | */
343 | @Override
344 | public void close(int closeCode, String closeMessage) throws IOException {
345 | this.watcher.cancel();
346 | this.getConnection().close(closeCode, closeMessage);
347 | }
348 |
349 | /**
350 | * Close this connection and all its channels
351 | * with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code
352 | * and message 'OK'.
353 | *
354 | * This method behaves in a similar way as {@link #close()}, with the only difference
355 | * that it waits with a provided timeout for all the close operations to
356 | * complete. When timeout is reached the socket is forced to close.
357 | *
358 | * @param timeout timeout (in milliseconds) for completing all the close-related
359 | * operations, use -1 for infinity
360 | * @throws IOException if an I/O problem is encountered
361 | */
362 | @Override
363 | public void close(int timeout) throws IOException {
364 | this.watcher.cancel();
365 | this.getConnection().close(timeout);
366 | }
367 |
368 | /**
369 | * Close this connection and all its channels.
370 | *
371 | * Waits with the given timeout for all the close operations to complete.
372 | * When timeout is reached the socket is forced to close.
373 | *
374 | * @param closeCode the close code (See under "Reply Codes" in the AMQP specification)
375 | * @param closeMessage a message indicating the reason for closing the connection
376 | * @param timeout timeout (in milliseconds) for completing all the close-related
377 | * operations, use -1 for infinity
378 | * @throws IOException if an I/O problem is encountered
379 | */
380 | @Override
381 | public void close(int closeCode, String closeMessage, int timeout) throws IOException {
382 | this.watcher.cancel();
383 | this.getConnection().close(closeCode, closeMessage, timeout);
384 | }
385 |
386 | /**
387 | * Abort this connection and all its channels
388 | * with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code
389 | * and message 'OK'.
390 | *
391 | * Forces the connection to close.
392 | * Any encountered exceptions in the close operations are silently discarded.
393 | */
394 | @Override
395 | public void abort() {
396 | this.watcher.cancel();
397 | this.getConnection().abort();
398 | }
399 |
400 | /**
401 | * Abort this connection and all its channels.
402 | *
403 | * Forces the connection to close and waits for all the close operations to complete.
404 | * Any encountered exceptions in the close operations are silently discarded.
405 | *
406 | * @param closeCode the close code (See under "Reply Codes" in the AMQP specification)
407 | * @param closeMessage a message indicating the reason for closing the connection
408 | */
409 | @Override
410 | public void abort(int closeCode, String closeMessage) {
411 | this.watcher.cancel();
412 | this.getConnection().abort(closeCode, closeMessage);
413 | }
414 |
415 | /**
416 | * Abort this connection and all its channels
417 | * with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code
418 | * and message 'OK'.
419 | *
420 | * This method behaves in a similar way as {@link #abort()}, with the only difference
421 | * that it waits with a provided timeout for all the close operations to
422 | * complete. When timeout is reached the socket is forced to close.
423 | *
424 | * @param timeout timeout (in milliseconds) for completing all the close-related
425 | * operations, use -1 for infinity
426 | */
427 | @Override
428 | public void abort(int timeout) {
429 | this.watcher.cancel();
430 | this.getConnection().abort(timeout);
431 | }
432 |
433 | /**
434 | * Abort this connection and all its channels.
435 | *
436 | * Forces the connection to close and waits with the given timeout
437 | * for all the close operations to complete. When timeout is reached
438 | * the socket is forced to close.
439 | * Any encountered exceptions in the close operations are silently discarded.
440 | *
441 | * @param closeCode the close code (See under "Reply Codes" in the AMQP specification)
442 | * @param closeMessage a message indicating the reason for closing the connection
443 | * @param timeout timeout (in milliseconds) for completing all the close-related
444 | * operations, use -1 for infinity
445 | */
446 | @Override
447 | public void abort(int closeCode, String closeMessage, int timeout) {
448 | this.watcher.cancel();
449 | this.getConnection().abort(closeCode, closeMessage, timeout);
450 | }
451 |
452 | /**
453 | * Add shutdown listener.
454 | * If the component is already closed, handler is fired immediately
455 | *
456 | * @param listener {@link com.rabbitmq.client.ShutdownListener} to the component
457 | */
458 | @Override
459 | public void addShutdownListener(ShutdownListener listener) {
460 | this.getConnection().addShutdownListener(listener);
461 | this.shutdownListeners.add(listener);
462 | }
463 |
464 | /**
465 | * Remove shutdown listener for the component.
466 | *
467 | * @param listener {@link com.rabbitmq.client.ShutdownListener} to be removed
468 | */
469 | @Override
470 | public void removeShutdownListener(ShutdownListener listener) {
471 | this.shutdownListeners.remove(listener);
472 | this.connection.removeShutdownListener(listener);
473 | }
474 |
475 | /**
476 | * Get the shutdown reason object
477 | *
478 | * @return ShutdownSignalException if component is closed, null otherwise
479 | */
480 | @Override
481 | public ShutdownSignalException getCloseReason() {
482 | return this.getConnection().getCloseReason();
483 | }
484 |
485 | /**
486 | * Protected API - notify the listeners attached to the component
487 | *
488 | * @see com.rabbitmq.client.ShutdownListener
489 | */
490 | @Override
491 | public void notifyListeners() {
492 | this.getConnection().notifyListeners();
493 | }
494 |
495 | /**
496 | * Determine whether the component is currently open.
497 | * Will return false if we are currently closing.
498 | * Checking this method should be only for information,
499 | * because of the race conditions - state can change after the call.
500 | * Instead just execute and try to catch ShutdownSignalException
501 | * and IOException
502 | *
503 | * @return true when component is open, false otherwise
504 | */
505 | @Override
506 | public boolean isOpen() {
507 | return this.getConnection().isOpen();
508 | }
509 |
510 | @Override
511 | public void addBlockedListener(BlockedListener listener) {
512 | this.blockedListeners.add(listener);
513 | this.getConnection().addBlockedListener(listener);
514 | }
515 |
516 | @Override
517 | public boolean removeBlockedListener(BlockedListener listener) {
518 | this.blockedListeners.remove(listener);
519 | return this.getConnection().removeBlockedListener(listener);
520 | }
521 |
522 | @Override
523 | public void clearBlockedListeners() {
524 | this.blockedListeners.clear();
525 | this.getConnection().clearBlockedListeners();
526 | }
527 |
528 | }
529 |
530 |
531 |
--------------------------------------------------------------------------------
/src/main/java/com/clevercloud/rabbitmq/Watchable.java:
--------------------------------------------------------------------------------
1 | package com.clevercloud.rabbitmq;
2 |
3 | /**
4 | * @author Marc-Antoine Perennou
5 | */
6 |
7 | public interface Watchable {
8 |
9 | void watch();
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/clevercloud/rabbitmq/WatcherThread.java:
--------------------------------------------------------------------------------
1 | package com.clevercloud.rabbitmq;
2 |
3 | /**
4 | * @author Marc-Antoine Perennou
5 | */
6 |
7 | public class WatcherThread extends Thread {
8 |
9 | private Watchable watchable;
10 | private long interval;
11 | private boolean run;
12 |
13 | public WatcherThread(Watchable watchable, long interval) {
14 | this.watchable = watchable;
15 | this.interval = interval;
16 | this.run = true;
17 | }
18 |
19 | @Override
20 | public void run() {
21 | while (this.run) {
22 | this.watchable.watch();
23 | try {
24 | Thread.sleep(this.interval);
25 | } catch (InterruptedException ignored) {
26 | }
27 | }
28 | }
29 |
30 | public void cancel() {
31 | this.run = false;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------