-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Add MessagePack support for Java SignalR Client #23532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Outdated
Show resolved
Hide resolved
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Outdated
Show resolved
Hide resolved
|
||
private Object readValue(MessageUnpacker unpacker, Class<?> itemType) throws IOException { | ||
// This shouldn't ever get called with itemType == null, but we return anyways to avoid NullPointerExceptions | ||
if (itemType == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I even account for itemType being null? In theory it should never happen (would indicate that a function took an argument of type null, or returned something of type null, which shouldn't be possible) but the test InvocationBinder returns null:
Line 286 in 0d15648
private Class<?> returnType = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this happen given a protocol violation by the server?
If so, we should at the very least log an error and fail the corresponding client-to-server invocation or skip the corresponding server-to-client invocation. Closing the entire HubConnection with an error might be even better.
If this actually cannot happen short of memory corruption or similar, just assert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could happen if the server provides an InvocationBinder that returns null
from getReturnType(invocationId)
when sending a StreamItem (or if the client does the same when sending an invocation)
int length; | ||
Object item = null; | ||
|
||
switch(valueType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't account for the MessagePack data being malformed - if the user passes a Map when the function expects a String, this should just throw a MessagePackException. The C# client appears to do the same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this surface to the HubConnection user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A call to ParseMessages
would throw a RuntimeException w/ "Error reading messagepack data" - JSONHubProtocol does the same:
aspnetcore/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/JsonHubProtocol.java
Lines 175 to 177 in 0d15648
} catch (IOException ex) { | |
throw new RuntimeException("Error reading JSON.", ex); | |
} |
While the C# Client's method is TryParseMessages
, so it just returns false if it runs into issues.
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Outdated
Show resolved
Hide resolved
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Outdated
Show resolved
Hide resolved
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Outdated
Show resolved
Hide resolved
...ignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/CancelInvocationMessage.java
Show resolved
Hide resolved
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Outdated
Show resolved
Hide resolved
Yes, otherwise it kinda defeats the purpose. |
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Outdated
Show resolved
Hide resolved
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Outdated
Show resolved
Hide resolved
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Outdated
Show resolved
Hide resolved
👀 |
7073c17
to
90926f5
Compare
From today's meeting: Next step is to convert the abstraction to use Lines 62 to 66 in e3501dd
|
6b4388a
to
15df263
Compare
Current state - I've converted everything to use ByteBuffer. Json is still working, but MsgPack fails immediately on parsing the first message - on inspection, the length header looks malformed. The payload is 36 bytes - first byte 0x1c (28), second byte 0xc2 (false), 3rd byte 0x96 (6-length array - this appears to be the first byte of the message). Will look into what's happening when I get back to this next week |
@@ -136,7 +136,7 @@ Transport getTransport() { | |||
} | |||
|
|||
this.baseUrl = url; | |||
this.protocol = new JsonHubProtocol(); | |||
this.protocol = new MessagePackHubProtocol(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BrennanConroy @halter73 should this just be a param to the HubConnection constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll want a method on the builder similar to
public withHubProtocol(protocol: IHubProtocol): HubConnectionBuilder { |
and yes, the protocol will be passed to the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to default it to JsonHubProtocol :D
Current issue: The ByteBuffer received here is ReadOnly: aspnetcore/src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java Line 167 in c934d3e
Figuring out why |
src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java
Outdated
Show resolved
Hide resolved
String handshakeResponseString = payload.substring(0, handshakeLength - 1); | ||
// The handshake will always be a UTF8 Json string, so we can convert the ByteBuffer to that to read the beginning of the payload | ||
String payloadStr = new String(payload.array(), StandardCharsets.UTF_8); | ||
int handshakeLength = payloadStr.indexOf(RECORD_SEPARATOR) + 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we find the index from the original payload first, then make a string once with the known size?
src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubConnection.java
Outdated
Show resolved
Hide resolved
src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HubProtocol.java
Outdated
Show resolved
Hide resolved
src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/JsonHubProtocol.java
Outdated
Show resolved
Hide resolved
src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Utils.java
Outdated
Show resolved
Hide resolved
src/SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/Utils.java
Outdated
Show resolved
Hide resolved
...SignalR/clients/java/signalr/src/main/java/com/microsoft/signalr/MessagePackHubProtocol.java
Show resolved
Hide resolved
/azp run |
d244b67
to
5a2357e
Compare
...gnalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HttpHubConnectionBuilder.java
Outdated
Show resolved
Hide resolved
...gnalR/clients/java/signalr/src/main/java/com/microsoft/signalr/HttpHubConnectionBuilder.java
Outdated
Show resolved
Hide resolved
@BrennanConroy @halter73 just pushed 6e53284, any other concerns? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File issues for followup work?
Resolves #21644
Things to call out in docs:
HubConnection.on()
,HubConnection.invoke()
, orHubConnection.stream()
. You can get a Type w/ something likenew TypeReference<ArrayList<Integer>>() { }).getType()
. The exception is primitives, for which you should use, e.g.,int.class
. The methods mentioned are generic, but have no generic parameter, so must be invoked with the syntaxHubConnection.<ArrayList<Integer>>invoke(Type, ...)
Todo: