Skip to content

Commit 018b3cd

Browse files
committed
Add Connection#openChannel to return Optional<Channel>
Fixes #431
1 parent 0168ce9 commit 018b3cd

File tree

3 files changed

+172
-1
lines changed

3 files changed

+172
-1
lines changed

src/main/java/com/rabbitmq/client/Connection.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.IOException;
2020
import java.net.InetAddress;
2121
import java.util.Map;
22+
import java.util.Optional;
2223
import java.util.concurrent.ExecutorService;
2324

2425
/**
@@ -117,6 +118,9 @@ public interface Connection extends ShutdownNotifier, Closeable { // rename to A
117118
* Create a new channel, using an internally allocated channel number.
118119
* If <a href="http://www.rabbitmq.com/api-guide.html#recovery">automatic connection recovery</a>
119120
* is enabled, the channel returned by this method will be {@link Recoverable}.
121+
* <p>
122+
* Use {@link #openChannel()} if you want to use an {@link Optional} to deal
123+
* with a {@null} value.
120124
*
121125
* @return a new channel descriptor, or null if none is available
122126
* @throws IOException if an I/O problem is encountered
@@ -125,12 +129,51 @@ public interface Connection extends ShutdownNotifier, Closeable { // rename to A
125129

126130
/**
127131
* Create a new channel, using the specified channel number if possible.
132+
* <p>
133+
* Use {@link #openChannel(int)} if you want to use an {@link Optional} to deal
134+
* with a {@null} value.
135+
*
128136
* @param channelNumber the channel number to allocate
129137
* @return a new channel descriptor, or null if this channel number is already in use
130138
* @throws IOException if an I/O problem is encountered
131139
*/
132140
Channel createChannel(int channelNumber) throws IOException;
133141

142+
/**
143+
* Create a new channel wrapped in an {@link Optional}.
144+
* The channel number is allocated internally.
145+
* <p>
146+
* If <a href="http://www.rabbitmq.com/api-guide.html#recovery">automatic connection recovery</a>
147+
* is enabled, the channel returned by this method will be {@link Recoverable}.
148+
* <p>
149+
* Use {@link #createChannel()} to return directly a {@link Channel} or {@code null}.
150+
*
151+
* @return an {@link Optional} containing the channel;
152+
* never {@code null} but potentially empty if no channel is available
153+
* @throws IOException if an I/O problem is encountered
154+
* @see #createChannel()
155+
* @since 5.6.0
156+
*/
157+
default Optional<Channel> openChannel() throws IOException {
158+
return Optional.ofNullable(createChannel());
159+
}
160+
161+
/**
162+
* Create a new channel, using the specified channel number if possible.
163+
* <p>
164+
* Use {@link #createChannel(int)} to return directly a {@link Channel} or {@code null}.
165+
*
166+
* @param channelNumber the channel number to allocate
167+
* @return an {@link Optional} containing the channel,
168+
* never {@code null} but potentially empty if this channel number is already in use
169+
* @throws IOException if an I/O problem is encountered
170+
* @see #createChannel(int)
171+
* @since 5.6.0
172+
*/
173+
default Optional<Channel> openChannel(int channelNumber) throws IOException {
174+
return Optional.ofNullable(createChannel(channelNumber));
175+
}
176+
134177
/**
135178
* Close this connection and all its channels
136179
* with the {@link com.rabbitmq.client.AMQP#REPLY_SUCCESS} close code

src/test/java/com/rabbitmq/client/test/ClientTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@
6565
DefaultRetryHandlerTest.class,
6666
NioDeadlockOnConnectionClosing.class,
6767
GeneratedClassesTest.class,
68-
RpcTopologyRecordingTest.class
68+
RpcTopologyRecordingTest.class,
69+
ConnectionTest.class
6970
})
7071
public class ClientTests {
7172

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright (c) 2018 Pivotal Software, Inc. All rights reserved.
2+
//
3+
// This software, the RabbitMQ Java client library, is triple-licensed under the
4+
// Mozilla Public License 1.1 ("MPL"), the GNU General Public License version 2
5+
// ("GPL") and the Apache License version 2 ("ASL"). For the MPL, please see
6+
// LICENSE-MPL-RabbitMQ. For the GPL, please see LICENSE-GPL2. For the ASL,
7+
// please see LICENSE-APACHE2.
8+
//
9+
// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
10+
// either express or implied. See the LICENSE file for specific language governing
11+
// rights and limitations of this software.
12+
//
13+
// If you have any questions regarding licensing, please contact us at
14+
15+
16+
package com.rabbitmq.client.test;
17+
18+
import com.rabbitmq.client.Channel;
19+
import com.rabbitmq.client.Connection;
20+
import org.junit.Before;
21+
import org.junit.Test;
22+
import org.junit.runner.RunWith;
23+
import org.junit.runners.Parameterized;
24+
import org.mockito.Mock;
25+
import org.mockito.stubbing.OngoingStubbing;
26+
27+
import java.io.IOException;
28+
import java.util.NoSuchElementException;
29+
import java.util.Optional;
30+
31+
import static org.junit.Assert.*;
32+
import static org.mockito.Mockito.mock;
33+
import static org.mockito.Mockito.when;
34+
import static org.mockito.MockitoAnnotations.initMocks;
35+
36+
@RunWith(Parameterized.class)
37+
public class ConnectionTest {
38+
39+
@Parameterized.Parameter
40+
public TestConfigurator configurator;
41+
@Mock
42+
Connection c = mock(Connection.class);
43+
@Mock
44+
Channel ch = mock(Channel.class);
45+
46+
@Parameterized.Parameters
47+
public static Object[] configurators() {
48+
return new Object[]{new NotNumberedChannelCreationCallback(), new NumberedChannelCreationCallback()};
49+
}
50+
51+
@Before
52+
public void init() {
53+
initMocks(this);
54+
}
55+
56+
@Test
57+
public void openChannelWithNonNullChannelShouldReturnNonEmptyOptional() throws Exception {
58+
configurator.mockAndWhenChannel(c).thenReturn(ch);
59+
configurator.mockAndWhenOptional(c).thenCallRealMethod();
60+
Optional<Channel> optional = configurator.open(c);
61+
assertTrue(optional.isPresent());
62+
assertSame(ch, optional.get());
63+
}
64+
65+
@Test(expected = NoSuchElementException.class)
66+
public void openChannelWithNullChannelShouldReturnEmptyOptional() throws Exception {
67+
configurator.mockAndWhenChannel(c).thenReturn(null);
68+
configurator.mockAndWhenOptional(c).thenCallRealMethod();
69+
Optional<Channel> optional = configurator.open(c);
70+
assertFalse(optional.isPresent());
71+
optional.get();
72+
}
73+
74+
@Test(expected = IOException.class)
75+
public void openChannelShouldPropagateIoException() throws Exception {
76+
configurator.mockAndWhenChannel(c).thenThrow(IOException.class);
77+
configurator.mockAndWhenOptional(c).thenCallRealMethod();
78+
configurator.open(c);
79+
}
80+
81+
interface TestConfigurator {
82+
83+
OngoingStubbing<Channel> mockAndWhenChannel(Connection c) throws IOException;
84+
85+
OngoingStubbing<Optional<Channel>> mockAndWhenOptional(Connection c) throws IOException;
86+
87+
Optional<Channel> open(Connection c) throws IOException;
88+
89+
}
90+
91+
static class NotNumberedChannelCreationCallback implements TestConfigurator {
92+
93+
@Override
94+
public OngoingStubbing<Channel> mockAndWhenChannel(Connection c) throws IOException {
95+
return when(c.createChannel());
96+
}
97+
98+
@Override
99+
public OngoingStubbing<Optional<Channel>> mockAndWhenOptional(Connection c) throws IOException {
100+
return when(c.openChannel());
101+
}
102+
103+
@Override
104+
public Optional<Channel> open(Connection c) throws IOException {
105+
return c.openChannel();
106+
}
107+
}
108+
109+
static class NumberedChannelCreationCallback implements TestConfigurator {
110+
111+
@Override
112+
public OngoingStubbing<Channel> mockAndWhenChannel(Connection c) throws IOException {
113+
return when(c.createChannel(1));
114+
}
115+
116+
@Override
117+
public OngoingStubbing<Optional<Channel>> mockAndWhenOptional(Connection c) throws IOException {
118+
return when(c.openChannel(1));
119+
}
120+
121+
@Override
122+
public Optional<Channel> open(Connection c) throws IOException {
123+
return c.openChannel(1);
124+
}
125+
}
126+
127+
}

0 commit comments

Comments
 (0)