27
27
import java .util .Map ;
28
28
import java .util .Map .Entry ;
29
29
import java .util .concurrent .TimeoutException ;
30
+ import java .util .function .Function ;
30
31
31
32
import com .rabbitmq .client .impl .MethodArgumentReader ;
32
33
import com .rabbitmq .client .impl .MethodArgumentWriter ;
@@ -58,6 +59,27 @@ public class RpcClient {
58
59
private final int _timeout ;
59
60
/** NO_TIMEOUT value must match convention on {@link BlockingCell#uninterruptibleGet(int)} */
60
61
protected final static int NO_TIMEOUT = -1 ;
62
+ /** Whether to publish RPC requests with the mandatory flag or not. */
63
+ private final boolean _useMandatory ;
64
+
65
+ public final static Function <Object , Response > DEFAULT_REPLY_HANDLER = reply -> {
66
+ if (reply instanceof ShutdownSignalException ) {
67
+ ShutdownSignalException sig = (ShutdownSignalException ) reply ;
68
+ ShutdownSignalException wrapper =
69
+ new ShutdownSignalException (sig .isHardError (),
70
+ sig .isInitiatedByApplication (),
71
+ sig .getReason (),
72
+ sig .getReference ());
73
+ wrapper .initCause (sig );
74
+ throw wrapper ;
75
+ } else if (reply instanceof UnroutableRpcRequestException ) {
76
+ throw (UnroutableRpcRequestException ) reply ;
77
+ } else {
78
+ return (Response ) reply ;
79
+ }
80
+ };
81
+
82
+ private final Function <Object , Response > _replyHandler ;
61
83
62
84
/** Map from request correlation ID to continuation BlockingCell */
63
85
private final Map <String , BlockingCell <Object >> _continuationMap = new HashMap <String , BlockingCell <Object >>();
@@ -67,6 +89,46 @@ public class RpcClient {
67
89
/** Consumer attached to our reply queue */
68
90
private DefaultConsumer _consumer ;
69
91
92
+ /**
93
+ * Construct a {@link RpcClient} with the passed-in {@link RpcClientParams}.
94
+ *
95
+ * @param params
96
+ * @throws IOException
97
+ * @see RpcClientParams
98
+ * @since 5.6.0
99
+ */
100
+ public RpcClient (RpcClientParams params ) throws
101
+ IOException {
102
+ _channel = params .getChannel ();
103
+ _exchange = params .getExchange ();
104
+ _routingKey = params .getRoutingKey ();
105
+ _replyTo = params .getReplyTo ();
106
+ if (params .getTimeout () < NO_TIMEOUT ) {
107
+ throw new IllegalArgumentException ("Timeout argument must be NO_TIMEOUT(-1) or non-negative." );
108
+ }
109
+ _timeout = params .getTimeout ();
110
+ _useMandatory = params .shouldUseMandatory ();
111
+ _replyHandler = params .getReplyHandler ();
112
+ _correlationId = 0 ;
113
+
114
+ _consumer = setupConsumer ();
115
+ if (_useMandatory ) {
116
+ this ._channel .addReturnListener (returnMessage -> {
117
+ synchronized (_continuationMap ) {
118
+ String replyId = returnMessage .getProperties ().getCorrelationId ();
119
+ BlockingCell <Object > blocker = _continuationMap .remove (replyId );
120
+ if (blocker == null ) {
121
+ // Entry should have been removed if request timed out,
122
+ // log a warning nevertheless.
123
+ LOGGER .warn ("No outstanding request for correlation ID {}" , replyId );
124
+ } else {
125
+ blocker .set (new UnroutableRpcRequestException (returnMessage ));
126
+ }
127
+ }
128
+ });
129
+ }
130
+ }
131
+
70
132
/**
71
133
* Construct a new RpcClient that will communicate on the given channel, sending
72
134
* requests to the given exchange with the given routing key.
@@ -78,18 +140,16 @@ public class RpcClient {
78
140
* @param replyTo the queue where the server should put the reply
79
141
* @param timeout milliseconds before timing out on wait for response
80
142
* @throws IOException if an error is encountered
143
+ * @deprecated use {@link RpcClient#RpcClient(RpcClientParams)} instead, will be removed in 6.0.0
81
144
*/
145
+ @ Deprecated
82
146
public RpcClient (Channel channel , String exchange , String routingKey , String replyTo , int timeout ) throws
83
147
IOException {
84
- _channel = channel ;
85
- _exchange = exchange ;
86
- _routingKey = routingKey ;
87
- _replyTo = replyTo ;
88
- if (timeout < NO_TIMEOUT ) throw new IllegalArgumentException ("Timeout arguument must be NO_TIMEOUT(-1) or non-negative." );
89
- _timeout = timeout ;
90
- _correlationId = 0 ;
91
-
92
- _consumer = setupConsumer ();
148
+ this (new RpcClientParams ()
149
+ .channel (channel ).exchange (exchange ).routingKey (routingKey )
150
+ .replyTo (replyTo ).timeout (timeout )
151
+ .useMandatory (false )
152
+ );
93
153
}
94
154
95
155
/**
@@ -106,7 +166,9 @@ public RpcClient(Channel channel, String exchange, String routingKey, String rep
106
166
* @param routingKey the routing key
107
167
* @param replyTo the queue where the server should put the reply
108
168
* @throws IOException if an error is encountered
169
+ * @deprecated use {@link RpcClient#RpcClient(RpcClientParams)} instead, will be removed in 6.0.0
109
170
*/
171
+ @ Deprecated
110
172
public RpcClient (Channel channel , String exchange , String routingKey , String replyTo ) throws IOException {
111
173
this (channel , exchange , routingKey , replyTo , NO_TIMEOUT );
112
174
}
@@ -123,7 +185,9 @@ public RpcClient(Channel channel, String exchange, String routingKey, String rep
123
185
* @param exchange the exchange to connect to
124
186
* @param routingKey the routing key
125
187
* @throws IOException if an error is encountered
188
+ * @deprecated use {@link RpcClient#RpcClient(RpcClientParams)} instead, will be removed in 6.0.0
126
189
*/
190
+ @ Deprecated
127
191
public RpcClient (Channel channel , String exchange , String routingKey ) throws IOException {
128
192
this (channel , exchange , routingKey , "amq.rabbitmq.reply-to" , NO_TIMEOUT );
129
193
}
@@ -142,7 +206,9 @@ public RpcClient(Channel channel, String exchange, String routingKey) throws IOE
142
206
* @param routingKey the routing key
143
207
* @param timeout milliseconds before timing out on wait for response
144
208
* @throws IOException if an error is encountered
209
+ * @deprecated use {@link RpcClient#RpcClient(RpcClientParams)} instead, will be removed in 6.0.0
145
210
*/
211
+ @ Deprecated
146
212
public RpcClient (Channel channel , String exchange , String routingKey , int timeout ) throws IOException {
147
213
this (channel , exchange , routingKey , "amq.rabbitmq.reply-to" , timeout );
148
214
}
@@ -213,7 +279,7 @@ public void handleDelivery(String consumerTag,
213
279
public void publish (AMQP .BasicProperties props , byte [] message )
214
280
throws IOException
215
281
{
216
- _channel .basicPublish (_exchange , _routingKey , props , message );
282
+ _channel .basicPublish (_exchange , _routingKey , _useMandatory , props , message );
217
283
}
218
284
219
285
public Response doCall (AMQP .BasicProperties props , byte [] message )
@@ -242,18 +308,7 @@ public Response doCall(AMQP.BasicProperties props, byte[] message, int timeout)
242
308
_continuationMap .remove (replyId );
243
309
throw ex ;
244
310
}
245
- if (reply instanceof ShutdownSignalException ) {
246
- ShutdownSignalException sig = (ShutdownSignalException ) reply ;
247
- ShutdownSignalException wrapper =
248
- new ShutdownSignalException (sig .isHardError (),
249
- sig .isInitiatedByApplication (),
250
- sig .getReason (),
251
- sig .getReference ());
252
- wrapper .initCause (sig );
253
- throw wrapper ;
254
- } else {
255
- return (Response ) reply ;
256
- }
311
+ return _replyHandler .apply (reply );
257
312
}
258
313
259
314
public byte [] primitiveCall (AMQP .BasicProperties props , byte [] message )
0 commit comments