Getting started with the Java SignalR SDK

Microsoft has just released a Java SignalR SDK which allows Java and Android clients to access ASP.NET SignalR back ends. The library is open source, and currently it is up to you to build the .jar packages yourself. For your convenience I’ve uploaded my built .jar files. Given that this library as of yet is still fairly undocumented, and I spent quite some time on getting it up and running, I figured I’d provide a short introduction tutorial here. I found the C# SignalR client documentation to be the most useful while figuring out the API as the classes and methods overall seem to correspond. The tests in the GitHub repository are another useful resource. I’ll mainly be focusing on the specific differences in the Java library, and refer you to the original documentation for more elaborate information.

We will create a simple Hub supporting bidirectional communication. A quick and easy way to get a C# back end up and running for the purpose of this tutorial is to self-host a SignalR server in a simple console or WPF application. The following C# code shows a simple hub with one method which can be called by the Java client, SendMessage.

public class MessageHub : Hub
{
	public static event Action<string, string> MessageReceived = delegate { };

	public void SendMessage( string name, string message )
	{
		MessageReceived( name, message );
	}
}

I added a static event handler which can be consumed by the console or WPF front end to display the received message. SendMessage is called from a different thread, so in case you want to update the UI, don’t forget to use a dispatcher!

MessageHub.MessageReceived  += ( name, message ) => _dispatcher.Invoke(
    () => { MessageBox.Content = String.Format( "{0} said {1}", name, message ); } );

Onwards to the client side code! To set up a Java project which can use the SignalR client API, add the ‘signalr-client-sdk.jar’ and ‘gson-2.2.2.jar’ to the project build path. For Android projects the references need to be added differently. Drag the two jars, and the additional ‘signalr-client-sdk-android.jar’ to the libs folder in Eclipse. By doing so they will automatically be added as Android libraries.

As mentioned before, the SignalR Java client follows the same structure as the C# client API, thus setting up a connection is quite similar. However, for Android applications an additional platform component needs to be loaded as shown below; also don’t forget to add internet permission to your manifest file, or you will receive a SocketException when trying to connect.

Platform.loadPlatformComponent( new AndroidPlatformComponent() );
// Change to the IP address and matching port of your SignalR server.
String host = "http://192.168.0.xxx:8080";
HubConnection connection = new HubConnection( host );
HubProxy hub = connection.createHubProxy( "MessageHub" );

This simply configures the connection. Establishing the actual connection is somewhat different than the C# documentation due to limitations of Java. To mimic language support for async in C#, the SignalRFuture class is introduced. Asynchronous operations return an instance of this class, without actually performing any real work yet. What follows is example code of how to start the connection synchronously by calling get() on the SignalRFuture. Don’t forget to cleanly stop() the connection when shutting down the application.

SignalRFuture<Void> awaitConnection = connection.start();
try {
	awaitConnection.get();
} catch (InterruptedException e) {
	// Handle ...
} catch (ExecutionException e) {
	// Handle ...
}

In case your server is up and running, you should now be ready to start listening to and submitting messages. Again, listening to events in C# is more straightforward since it supports lambdas as the C# client API documentation demonstrates.

stockTickerHubProxy.On<Stock>( "UpdateStockPrice", stock => Console.WriteLine(
    "Stock update for {0} new price {1}", stock.Symbol, stock.Price) );

Doing something similar in Java requires elaborate inline anonymous classes, or the creation of a handler class per event you want to listen to. Suppose the server would send a message “context.Clients.All.UpdateStatus( “Online” );”, handling this the ‘C# way’ would like as follows:

hub.on( "UpdateStatus",
    new SubscriptionHandler<String>() {
        @Override
        public void run( String status ) {
           // Since we are updating the UI,
           // we need to use a handler of the UI thread.
           final String fStatus = status;
           handler.post( new Runnable() {
               @Override
               public void run() {
                   statusField.setText( fStatus );
               }
           } );
        }
    }
, String.class );

Therefore, Microsoft has seemingly added a method not available in the C# API to the Java client. Calling hub.subscribe( listener ) where listener is an object implementing corresponding methods for every available incoming event is a much more straightforward way to listen to messages. Under the covers this uses reflection to hook everything up correctly. These methods need to be public!

hub.subscribe( this );
...
public void UpdateStatus( String status )
{
	final String fStatus = status;
	handler.post(new Runnable(){
		@Override
		public void run() {
			statusField.setText( fStatus );
		}});
}

More complex types work as well, as long as it is supported by JSON. I don’t know the specifics, but this will be dependent on the SignalR server and the gson library used by the SignalR Java client. The following code prepares the client to call a new method on the server which you can add to the MessageHub: “public void SendCustomType( CustomType object ) { … }“.

// A simple C# class which can be sent over SignalR.
public class CustomType
{
	public string Name;
	public int Id;
}
// The same type as defined in Java.
public class CustomType
{
	public String Name;
	public int Id;
}

Finally, calling the earlier SendMessage() and the newly added SendCustomType() can be done as follows. As you can see, remote method invocation again returns a SignalRFuture, and a subsequent get() is needed.

try {
    hub.invoke( "SendMessage", "Client", "Hello world!" ).get();
    hub.invoke( "SendCustomType",
        new CustomType() {{ Name = "Universe"; Id = 42; }} ).get();
} catch (InterruptedException e) {
	// Handle ...
} catch (ExecutionException e) {
	// Handle ...
}

Similarly, you can simply pass custom objects from the server to the client by adding the custom type as a method parameter: “public void SomeMethod( CustomType bleh ) { … }

About these ads
  1. #1 by Anders Bech Mellson on April 1, 2014 - 8:53 am

    Nice write-up, thank you for the tutorial.

  2. #2 by Gadael Sedubun on May 9, 2014 - 12:33 pm

    can you provide the source code for this tutorial?
    kinda confuse how to use this signalR library..

  3. #4 by lal on August 12, 2014 - 7:27 pm

    Thanks for the great tutorial. I m getting following Console message, but event is not firing

    Verbose – serverSentEvents – Found new data:data: {}
    Verbose – serverSentEvents – Trigger onData: {}
    Verbose – HubConnection – Received data:

    I had tried two ways
    Option1
    hub.on( “testMessage”, new SubscriptionHandler1() {
    @Override
    public void run(CustomMessage msg) {
    //semaphore.release();
    Log.d(“result := “, msg.text);
    Toast.makeText(MainActivity.this, msg.text, Toast.LENGTH_LONG).show();
    }
    }, CustomMessage.class);

    Option2
    hub.subscribe(“testMessage”);

    Handler handler = new Handler();
    public void addMessage( CustomMessage msg ) {

    final String fStatus = msg.text;
    handler.post(new Runnable(){
    @Override
    public void run() {

    Toast.makeText(MainActivity.this, fStatus, Toast.LENGTH_LONG).show();

    }});
    }

  4. #7 by windarco on August 26, 2014 - 5:32 pm

    How do I use Java reflection with hub.subscribe(“MessageFromServer”), cause I am struggling to let my android client get triggered by a message send from the server to client.

    • #8 by Steven Jeuris on August 26, 2014 - 5:50 pm

      What do you mean “how do I use Java reflection”? As I stated, reflection is used under the covers by the Java SignalR SDK. You do not need to implement this yourself when using `hub.subscribe`. However you seem to be confusing `hub.on` with `hub.subscribe`. `hub.on` accepts a method name as you seemingly suggest to be “MessageFromServer”. `hub.subscribe` as I described in this post accepts an object which will listen to incoming messages. Messages are automatically coupled to public methods of the object.

  5. #9 by Pairkshit singh shekhawat on August 29, 2014 - 1:19 pm

    Hi I am trying to create chat in android. using your blog. can you tell me what are parameters in hub.invoke method and how to get message in details

  6. #11 by Anil Kumar on October 6, 2014 - 5:29 pm

    i am unable to do connect Signal R with Samsung device can u please tell me Solution while with other device its working fine

  7. #12 by jhansi on October 30, 2014 - 9:15 am

    i am getting negotiation exception

  8. #13 by Bangar Reddy on October 30, 2014 - 9:18 am

    @steven we are some little bit confused by seeing all .net & Android code here. If you have any working android sample can you please share for me.

  9. #14 by Naimul Mefraz Khan on December 9, 2014 - 1:02 am

    hi Steven,

    I have been trying to get the java client working for the past week, can’t get past the NegotiatonException. I have posted a question over at stackoverflow, can you help me with this?

    http://stackoverflow.com/questions/27365362/signalr-java-client-test-integration-android-invalidhttpstatuscodeexception

    P.S. the question is for the client-tests that ship with the git repo itself, I have also tried the method described here (start from scratch), same issue. Below is the pastebin from your code (the connection bit):

    D/javaclient(27057): java.util.concurrent.ExecutionException: microsoft.aspnet.signalr.client.transport.NegotiationException: There was a problem in the negotiation with the server

  10. #15 by Naimul Mefraz Khan on December 9, 2014 - 6:49 pm

    Adding to my answer in case someone else runs into it. It was a crappy mistake on my part, jumped into java client without understanding signalr properly! The Hub class on the server and the Hub proxy name has to be the same. So on the server side the class:

    public class MessageHub : Hub

    And on the client side

    HubProxy hub = connection.createHubProxy( “MessageHub” );

    And voila! Thanks for the blog.

  11. #16 by Hunter on December 11, 2014 - 4:29 am

    Could you help me ~
    How to Get a Value by public SignalRFuture invoke(final Class resultClass, final String method, Object… args)
    ——————————————————
    my code as below:

    Class resultClass = null;
    SignalRFuture str = hub.invoke(resultClass,
    “HelloWorld2″, “123”);
    str.done(new Action() {
    @Override
    public void run(String arg0) throws Exception {
    Log.i(“0.03″, “arg0=” + arg0);// i can’t receive the result
    }
    }).onError(new ErrorCallback() {
    @Override
    public void onError(Throwable error) {
    Log.i(“0.03″, “error=” + error.toString());
    }
    });
    ——————————————————

    by other way, as below:

    hub.on(“receiveHelloWorldReturn”,
    new SubscriptionHandler1() {
    @Override
    public void run(String msg) {
    Log.i(“0.03″, “Result” + msg); // i can receive the result
    }
    }, String.class);
    hub.invoke(“HelloWorldReturn”);

    please help me, how to receive the return value by
    How to Get a Value by public SignalRFuture invoke(final Class resultClass, final String method, Object… args)

  1. Dictionary as query string parameter in SignalR Android Client

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: