Initial Java Client(#2521)

This commit is contained in:
Mikael Mengistu 2018-06-21 16:12:32 -07:00 committed by GitHub
parent 8a69fb7f51
commit 6b3437deb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 277 additions and 4 deletions

View File

@ -13,4 +13,6 @@ repositories {
dependencies {
testImplementation group: 'junit', name: 'junit', version: '4.12'
compile "org.java-websocket:Java-WebSocket:1.3.8"
implementation 'com.google.code.gson:gson:2.8.5'
}

View File

@ -0,0 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public interface Action<T> {
void invoke(T param);
}

View File

@ -0,0 +1,33 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import com.google.gson.JsonArray;
import java.net.URISyntaxException;
import java.util.Scanner;
public class Chat {
public static void main(String[] args) throws URISyntaxException, InterruptedException {
System.out.println("Enter the URL of the SignalR Chat you want to join");
Scanner reader = new Scanner(System.in); // Reading from System.in
String input;
input = reader.nextLine();
HubConnection hubConnection = new HubConnection(input);
hubConnection.On("Send", (message) -> {
String newMessage = ((JsonArray) message).get(0).getAsString();
System.out.println("REGISTERED HANDLER: " + newMessage);
});
//This is a blocking call
hubConnection.start();
while (!input.equals("leave")){
// Scans the next token of the input as an int.
input = reader.nextLine();
hubConnection.send("Send", input);
}
hubConnection.stop();
}
}

View File

@ -0,0 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public class DefaultJsonProtocolHandShakeMessage {
String protocol = "json";
int version = 1;
}

View File

@ -1,8 +1,99 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.URISyntaxException;
import java.util.HashMap;
public class HubConnection {
public boolean methodToTest(){
return true;
private String _url;
private ITransport _transport;
private OnReceiveCallBack callback;
private HashMap<String, Action> handlers = new HashMap<>();
private JsonParser jsonParser = new JsonParser();
private static final String RECORD_SEPARATOR = "\u001e";
public Boolean connected = false;
public HubConnection(String url) {
_url = url;
callback = (payload) -> {
String[] messages = payload.split(RECORD_SEPARATOR);
for (String splitMessage : messages) {
// Empty handshake response "{}". We can ignore it
if (splitMessage.length() == 2) {
continue;
}
processMessage(splitMessage);
}
};
try {
_transport = new WebSocketTransport(_url);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
private void processMessage(String message) {
JsonObject jsonMessage = jsonParser.parse(message).getAsJsonObject();
String messageType = jsonMessage.get("type").toString();
switch(messageType) {
case "1":
//Invocation Message
String target = jsonMessage.get("target").getAsString();
if (handlers.containsKey(target)) {
handlers.get(target).invoke(jsonMessage.get("arguments"));
}
break;
case "2":
//Stream item
//Don't care yet
break;
case "3":
//Completion
//Don't care yet
break;
case "4":
//Stream invocation
//Don't care yet;
break;
case "5":
//Cancel invocation
//Don't care yet
break;
case "6":
//Ping
//Don't care yet
break;
case "7":
// Close message
//Don't care yet;
break;
}
}
public void start() throws InterruptedException {
_transport.setOnReceive(this.callback);
_transport.start();
connected = true;
}
public void stop(){
_transport.stop();
connected = false;
}
public void send(String method, Object arg1) {
InvocationMessage message = new InvocationMessage(method, new Object[]{ arg1 });
_transport.send(message);
}
public void On(String target, Action callback) {
handlers.put(target, callback);
}
}

View File

@ -0,0 +1,10 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public interface ITransport {
void start() throws InterruptedException;
void send(InvocationMessage invocationMessage);
void setOnReceive(OnReceiveCallBack callback);
void onReceive(String message);
void stop();
}

View File

@ -0,0 +1,38 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
public class InvocationMessage {
private int type = 1;
String invocationId;
String target;
Object[] arguments;
public InvocationMessage(String target, Object[] args) {
this.target = target;
arguments = args;
}
public String getInvocationId() {
return invocationId;
}
public void setInvocationId(String invocationId) {
this.invocationId = invocationId;
}
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
public Object getArguments() {
return arguments;
}
public void setArguments(Object[] arguments) {
this.arguments = arguments;
}
}

View File

@ -0,0 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import com.google.gson.JsonObject;
public interface OnReceiveCallBack {
void invoke(String message);
}

View File

@ -0,0 +1,79 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import com.google.gson.Gson;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import java.net.URI;
import java.net.URISyntaxException;
public class WebSocketTransport implements ITransport {
private static final String RECORD_SEPARATOR = "\u001e";
private WebSocketClient _webSocket;
private OnReceiveCallBack onReceiveCallBack;
private URI _url;
public WebSocketTransport(String url) throws URISyntaxException {
// To Do: Format the incoming URL for a websocket connection.
_url = new URI(url);
_webSocket = createWebSocket();
}
@Override
public void start() throws InterruptedException {
_webSocket.connectBlocking();
_webSocket.send(createHandshakeMessage() + RECORD_SEPARATOR);
}
@Override
public void send(InvocationMessage invocationMessage) {
Gson gson = new Gson();
String message = gson.toJson(invocationMessage) + RECORD_SEPARATOR;
_webSocket.send(message);
}
@Override
public void setOnReceive(OnReceiveCallBack callback) {
this.onReceiveCallBack = callback;
}
@Override
public void onReceive(String message) {
this.onReceiveCallBack.invoke(message);
}
private String createHandshakeMessage() {
Gson gson = new Gson();
return gson.toJson(new DefaultJsonProtocolHandShakeMessage());
}
@Override
public void stop() {
_webSocket.closeConnection(0, "HubConnection Stopped");
}
private WebSocketClient createWebSocket() {
return new WebSocketClient(_url) {
@Override
public void onOpen(ServerHandshake handshakedata) {
System.out.println("Connected to " + _url);
}
@Override
public void onMessage(String message) {
onReceive(message);
}
@Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("Connection Closed");
}
@Override
public void onError(Exception ex) {
System.out.println("Error: " + ex.getMessage());
}
};
}
}

View File

@ -6,9 +6,8 @@ import org.junit.Test;
import static org.junit.Assert.*;
public class HubConnectionTest {
// Coming soon!
@Test
public void testEmptyCollection() {
HubConnection hubConnection = new HubConnection();
assertTrue(hubConnection.methodToTest());
}
}