Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit cd33755

Browse files
[Java] Make public API look like RxJava (#3103)
1 parent b63c381 commit cd33755

File tree

6 files changed

+112
-98
lines changed

6 files changed

+112
-98
lines changed

.vscode/launch.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"cwd": "${workspaceFolder}/clients/java/",
99
"console": "externalTerminal",
1010
"stopOnEntry": false,
11-
"mainClass": "com.microsoft.aspnet.signalr.sample.Chat",
11+
"mainClass": "com.microsoft.signalr.sample.Chat",
1212
"args": ""
1313
},
1414
{

clients/java/signalr/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ dependencies {
3333
testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.3.1'
3434
implementation 'com.google.code.gson:gson:2.8.5'
3535
implementation 'com.squareup.okhttp3:okhttp:3.11.0'
36+
implementation 'io.reactivex.rxjava2:rxjava:2.2.2'
3637
}
3738

3839
spotless {

clients/java/signalr/src/main/java/com/microsoft/signalr/HttpHubConnectionBuilder.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
import java.util.concurrent.CompletableFuture;
77
import java.util.function.Supplier;
88

9+
import io.reactivex.Single;
10+
911
public class HttpHubConnectionBuilder {
1012
private String url;
1113
private Transport transport;
1214
private Logger logger;
1315
private HttpClient httpClient;
1416
private boolean skipNegotiate;
15-
private Supplier<CompletableFuture<String>> accessTokenProvider;
17+
private Single<String> accessTokenProvider;
1618

1719
HttpHubConnectionBuilder(String url) {
1820
this.url = url;
@@ -39,7 +41,7 @@ public HttpHubConnectionBuilder shouldSkipNegotiate(boolean skipNegotiate) {
3941
return this;
4042
}
4143

42-
public HttpHubConnectionBuilder withAccessTokenProvider(Supplier<CompletableFuture<String>> accessTokenProvider) {
44+
public HttpHubConnectionBuilder withAccessTokenProvider(Single<String> accessTokenProvider) {
4345
this.accessTokenProvider = accessTokenProvider;
4446
return this;
4547
}

clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java

+41-48
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@
99
import java.util.List;
1010
import java.util.Map;
1111
import java.util.concurrent.CompletableFuture;
12-
import java.util.concurrent.ExecutionException;
1312
import java.util.concurrent.atomic.AtomicInteger;
1413
import java.util.concurrent.locks.Lock;
1514
import java.util.concurrent.locks.ReentrantLock;
1615
import java.util.function.Consumer;
17-
import java.util.function.Supplier;
16+
17+
import io.reactivex.Completable;
18+
import io.reactivex.Single;
1819

1920
public class HubConnection {
2021
private static final String RECORD_SEPARATOR = "\u001e";
@@ -32,13 +33,13 @@ public class HubConnection {
3233
private Logger logger;
3334
private List<Consumer<Exception>> onClosedCallbackList;
3435
private boolean skipNegotiate;
35-
private Supplier<CompletableFuture<String>> accessTokenProvider;
36+
private Single<String> accessTokenProvider;
3637
private Map<String, String> headers = new HashMap<>();
3738
private ConnectionState connectionState = null;
3839
private HttpClient httpClient;
3940
private String stopError;
4041

41-
HubConnection(String url, Transport transport, boolean skipNegotiate, Logger logger, HttpClient httpClient, Supplier<CompletableFuture<String>> accessTokenProvider) {
42+
HubConnection(String url, Transport transport, boolean skipNegotiate, Logger logger, HttpClient httpClient, Single<String> accessTokenProvider) {
4243
if (url == null || url.isEmpty()) {
4344
throw new IllegalArgumentException("A valid url is required.");
4445
}
@@ -49,7 +50,7 @@ public class HubConnection {
4950
if (accessTokenProvider != null) {
5051
this.accessTokenProvider = accessTokenProvider;
5152
} else {
52-
this.accessTokenProvider = () -> CompletableFuture.completedFuture(null);
53+
this.accessTokenProvider = Single.just("");
5354
}
5455

5556
if (httpClient != null) {
@@ -153,14 +154,11 @@ private CompletableFuture<NegotiateResponse> handleNegotiate(String url) {
153154
}
154155

155156
if (negotiateResponse.getAccessToken() != null) {
156-
this.accessTokenProvider = () -> CompletableFuture.completedFuture(negotiateResponse.getAccessToken());
157+
this.accessTokenProvider = Single.just(negotiateResponse.getAccessToken());
157158
String token = "";
158-
try {
159-
// We know the future is already completed in this case
160-
// It's fine to call get() on it.
161-
token = this.accessTokenProvider.get().get();
162-
} catch (InterruptedException | ExecutionException e) {
163-
}
159+
// We know the Single is non blocking in this case
160+
// It's fine to call blockingGet() on it.
161+
token = this.accessTokenProvider.blockingGet();
164162
this.headers.put("Authorization", "Bearer " + token);
165163
}
166164

@@ -179,20 +177,21 @@ public HubConnectionState getConnectionState() {
179177

180178
/**
181179
* Starts a connection to the server.
182-
* @return A completable future that completes when the connection has been established.
180+
* @return A Completable that completes when the connection has been established.
183181
*/
184-
public CompletableFuture<Void> start() {
182+
public Completable start() {
185183
if (hubConnectionState != HubConnectionState.DISCONNECTED) {
186-
return CompletableFuture.completedFuture(null);
184+
return Completable.complete();
187185
}
188186

189187
handshakeReceived = false;
190-
CompletableFuture<Void> tokenFuture = accessTokenProvider.get()
191-
.thenAccept((token) -> {
192-
if (token != null) {
193-
this.headers.put("Authorization", "Bearer " + token);
194-
}
195-
});
188+
CompletableFuture<Void> tokenFuture = new CompletableFuture<>();
189+
accessTokenProvider.subscribe(token -> {
190+
if (token != null && !token.isEmpty()) {
191+
this.headers.put("Authorization", "Bearer " + token);
192+
}
193+
tokenFuture.complete(null);
194+
});
196195

197196
stopError = null;
198197
CompletableFuture<String> negotiate = null;
@@ -202,7 +201,7 @@ public CompletableFuture<Void> start() {
202201
negotiate = tokenFuture.thenCompose((v) -> CompletableFuture.completedFuture(baseUrl));
203202
}
204203

205-
return negotiate.thenCompose((url) -> {
204+
return Completable.fromFuture(negotiate.thenCompose(url -> {
206205
logger.log(LogLevel.Debug, "Starting HubConnection.");
207206
if (transport == null) {
208207
transport = new WebSocketTransport(headers, httpClient, logger);
@@ -211,27 +210,21 @@ public CompletableFuture<Void> start() {
211210
transport.setOnReceive(this.callback);
212211
transport.setOnClose((message) -> stopConnection(message));
213212

214-
try {
215-
return transport.start(url).thenCompose((future) -> {
216-
String handshake = HandshakeProtocol.createHandshakeRequestMessage(
217-
new HandshakeRequestMessage(protocol.getName(), protocol.getVersion()));
218-
return transport.send(handshake).thenRun(() -> {
219-
hubConnectionStateLock.lock();
220-
try {
221-
hubConnectionState = HubConnectionState.CONNECTED;
222-
connectionState = new ConnectionState(this);
223-
logger.log(LogLevel.Information, "HubConnection started.");
224-
} finally {
225-
hubConnectionStateLock.unlock();
226-
}
227-
});
213+
return transport.start(url).thenCompose((future) -> {
214+
String handshake = HandshakeProtocol.createHandshakeRequestMessage(
215+
new HandshakeRequestMessage(protocol.getName(), protocol.getVersion()));
216+
return transport.send(handshake).thenRun(() -> {
217+
hubConnectionStateLock.lock();
218+
try {
219+
hubConnectionState = HubConnectionState.CONNECTED;
220+
connectionState = new ConnectionState(this);
221+
logger.log(LogLevel.Information, "HubConnection started.");
222+
} finally {
223+
hubConnectionStateLock.unlock();
224+
}
228225
});
229-
} catch (RuntimeException e) {
230-
throw e;
231-
} catch (Exception e) {
232-
throw new RuntimeException(e);
233-
}
234-
});
226+
});
227+
}));
235228
}
236229

237230
private CompletableFuture<String> startNegotiate(String url, int negotiateAttempts) {
@@ -268,7 +261,7 @@ private CompletableFuture<String> startNegotiate(String url, int negotiateAttemp
268261
/**
269262
* Stops a connection to the server.
270263
* @param errorMessage An error message if the connected needs to be stopped because of an error.
271-
* @return A completable future that completes when the connection has been stopped.
264+
* @return A Completable that completes when the connection has been stopped.
272265
*/
273266
private CompletableFuture<Void> stop(String errorMessage) {
274267
hubConnectionStateLock.lock();
@@ -292,10 +285,10 @@ private CompletableFuture<Void> stop(String errorMessage) {
292285

293286
/**
294287
* Stops a connection to the server.
295-
* @return A completable future that completes when the connection has been stopped.
288+
* @return A Completable that completes when the connection has been stopped.
296289
*/
297-
public CompletableFuture<Void> stop() {
298-
return stop(null);
290+
public Completable stop() {
291+
return Completable.fromFuture(stop(null));
299292
}
300293

301294
private void stopConnection(String errorMessage) {
@@ -344,7 +337,7 @@ public void send(String method, Object... args) throws Exception {
344337
sendHubMessage(invocationMessage);
345338
}
346339

347-
public <T> CompletableFuture<T> invoke(Class<T> returnType, String method, Object... args) throws Exception {
340+
public <T> Single<T> invoke(Class<T> returnType, String method, Object... args) throws Exception {
348341
String id = connectionState.getNextInvocationId();
349342
InvocationMessage invocationMessage = new InvocationMessage(id, method, args);
350343

@@ -372,7 +365,7 @@ public <T> CompletableFuture<T> invoke(Class<T> returnType, String method, Objec
372365
// where the map doesn't have the future yet when the response is returned
373366
sendHubMessage(invocationMessage);
374367

375-
return future;
368+
return Single.fromFuture(future);
376369
}
377370

378371
private void sendHubMessage(HubMessage message) throws Exception {

0 commit comments

Comments
 (0)