Giter Club home page Giter Club logo

javaphoenixchannels's Introduction

Phoenix Channel Client for Java and Android

JavaPhoenixChannels is a Java and Android client library for the Channels API in the Phoenix Framework. Its primary purpose is to ease development of real time messaging apps for Android using an Elixir/Phoenix backend. For more about the Elixir language and the massively scalable and reliable systems you can build with Phoenix, see http://elixir-lang.org and http://www.phoenixframework.org.

Including the Library

  • Add http://dl.bintray.com/eoinsha/java-phoenix-channels as a Maven repository
  • Add JavaPhoenixChannels as an app dependency:
dependencies {
  ...
  compile('com.github.eoinsha:JavaPhoenixChannels:1.0') {
      exclude module: 'groovy-all'
  }

Examples

Example Android App

For a full sample Android chat app, check out the repository at https://github.com/eoinsha/PhoenixChatAndroid

The quick examples below are used with the Phoenix Chat Example

Example using Groovy

import org.phoenixframework.channels.*
def socket = new Socket('ws://localhost:4000/socket/websocket')
socket.connect()
def chan = socket.chan()
chan.join("rooms:lobby", null)
    .receive("ignore", { -> println "IGNORE"})
    .receive("ok", { envelope -> println "JOINED with $envelope" })
chan.on('new:msg', { -> println "NEW MESSAGE: $envelope"})

Example using Java

import org.phoenixframework.channels.*;

Socket socket;
Channel channel;

// To connect with authentication
String authToken = "abc123"
Uri.Builder url = Uri.parse( "ws://localhost:4000/socket/websocket" ).buildUpon();
url.appendQueryParameter( "auth_token", authToken );
socket = new Socket(url.build().toString());
socket.connect();

channel = socket.chan("rooms:lobby", null);

channel.join()
.receive("ignore", new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        System.out.println("IGNORE");
    }
})
.receive("ok", new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        System.out.println("JOINED with " + envelope.toString());
    }
});

channel.on("new:msg", new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        System.out.println("NEW MESSAGE: " + envelope.toString());
    }
});

channel.on(ChannelEvent.CLOSE.getPhxEvent(), new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        System.out.println("CLOSED: " + envelope.toString());
    }
});

channel.on(ChannelEvent.ERROR.getPhxEvent(), new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        System.out.println("ERROR: " + envelope.toString());
    }
});

//Sending a message. This library uses Jackson for JSON serialization
ObjectNode node = new ObjectNode(JsonNodeFactory.instance)
        .put("user", "my_username")
        .put("body", message);

channel.push("new:msg", node);

Contributing

To contribute, see the contribution guidelines and instructions.

javaphoenixchannels's People

Contributors

astjohn avatar bibol avatar bryanjos avatar dbishai avatar eoinsha avatar jpage4500 avatar martinotten avatar mcontagious avatar metalwihen avatar mpearcy avatar papylhomme avatar solidnerd avatar vheathen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

javaphoenixchannels's Issues

Include guide in Readme needs update

Including this library with gradle following instructions in Readme leads to an older version of this project. Maven repository seems out of date for this project.
It imports okhttp 3.4 where websocket part is now deprecated.

Improving tests

I've been thinking about how we can improve the tests here for a while now. It is a bit hard since we have to test against a Phoenix Channel server. One thought I had is maybe embedding a phoenix project in here that we could run and test against only when testing. The other option is mocking responses. Also interested in better ways to write the tests here.

Any thoughts or suggestions?

Socket closes after every Channel.push command

The Server I connect to generates random URLs and once connected I need to join a channel and then maintain the connection. The server uses Phoenix protocol as well which is why I am using this library.

However whenever I do my initiate channel join command and get a return on my callback function, the library closes the socket. I am not able to find a way to keep the socket open long enough to make my any other calls.

Is there a way to prevent the socket from closing after I make the first push/join on the channel?

JavaPhoenixChannels + Okhttp3 v3.8.1

I need use okttp for api calls and use the channels, but on connect throws the next exception

FATAL EXCEPTION: main
Process: com.yetcargo.yetcargotracker.dev, PID: 20196
java.lang.NoSuchMethodError: No virtual method setCallWebSocket(Lokhttp3/Call;)V in class Lokhttp3/internal/Internal; or its super classes (declaration of 'okhttp3.internal.Internal' appears in /data/app/com.yetcargo.yetcargotracker.dev-1/split_lib_dependencies_apk.apk:classes73.dex)
at okhttp3.ws.WebSocketCall.enqueue(WebSocketCall.java:108)
at org.phoenixframework.channels.Socket.connect(Socket.java:204)
at com.yetcargo.yetcargotracker.screens.main.AllwaysThereService.onStartCommand(AllwaysThereService.java:102)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3394)
at android.app.ActivityThread.-wrap21(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1632)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6251)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)

android.system.ErrnoException: sendto failed: EPIPE (Broken pipe)

Hi there,
I connect socket and it throws an exception with the message sendto failed: EPIPE (Broken pipe) after 5 seconds (with master version).
When I use v0.2.0 version, the socket is closed with code 1011. I've seen the meaning of this code

1011 indicates that a server is terminating the connection because
      it encountered an unexpected condition that prevented it from
      fulfilling the request.

I'm following the README sample to create the connection. What could be wrong? We've tested the socket server with iOS and it works.

final String SOCKET_URL_TEMPLATE = "ws://socket.test.com/socket/websocket?token=%s&vsn=2.0.0";
String url = String.format(SOCKET_URL_TEMPLATE, "token_xpto");

socket = new Socket(url);
            socket.onOpen(new ISocketOpenCallback() {
                @Override
                public void onOpen() {
                    Log.d("[SOCKET_TEST]", "socket opened");
//                    this part connects and join the channel, but the error occurs even without this part
//                    simpleChannelConnection();
                }
            });

            socket.onClose(new ISocketCloseCallback() {
                @Override
                public void onClose() {
                    Log.d("[SOCKET_TEST]", "socket closed");
                }
            });

            socket.onError(new IErrorCallback() {
                @Override
                public void onError(String s) {
                    Log.d("[SOCKET_TEST]", "socket error - " + s);
                }
            });

            socket.onMessage(new IMessageCallback() {
                @Override
                public void onMessage(Envelope envelope) {
                    Log.d("[SOCKET_TEST]", "socket message - " + envelope.toString());
                }
            });

            socket.reconectOnFailure(false);
            socket.connect();

Thank you.

Luis

FATAL EXCEPTION: OkHttp Dispatcher

Hi! I've been trying to use Phoenix Channel Client for Android, but get the following error when I try to run my application.

E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
E/AndroidRuntime: Process: com.example.cc.myapplication, PID: 1611
E/AndroidRuntime: java.lang.AbstractMethodError: abstract method "void com.squareup.okhttp.ws.WebSocketListener.onFailure(java.io.IOException, com.squareup.okhttp.Response)"
E/AndroidRuntime: at com.squareup.okhttp.ws.WebSocketCall$1.onFailure(WebSocketCall.java:107)
E/AndroidRuntime: at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:176)
E/AndroidRuntime: at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
E/AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
E/AndroidRuntime: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
E/AndroidRuntime: at java.lang.Thread.run(Thread.java:818)
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
D/: HostConnection::get()
New Host Connection established 0xf04737d0, tid 1611

So far, I've compiled the client into a .jar file using gradle, and added it to my libs folder. When I tried to run the app, it gave me a missing class error for Jackson Node and okhttp. I added them to my dependencies list, but ended up with the above error which I'm not sure how I should proceed with.

This is my dependencies list

dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile files('libs/JavaPhoenixChannels-0.1.0-SNAPSHOT.jar')
compile files('libs/JavaPhoenixChannels-0.1.0-SNAPSHOT-javadoc.jar')
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.0-rc1'
compile 'com.squareup.okhttp:okhttp-ws:2.6.0'
compile 'com.squareup.okhttp:okhttp:2.6.0'
}

So far, my main activity only contains up to the following from your example

import org.phoenixframework.channels.*;

Socket socket;
Channel channel;

socket = new Socket("ws://localhost:4000/socket/websocket");
socket.connect();

channel = socket.chan("rooms:lobby", null);

channel.join()
.receive("ignore", new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        System.out.println("IGNORE");
    }
})
.receive("ok", new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        System.out.println("JOINED with " + envelope.toString());
    }
});

Do you have any advice as to how I should proceed? Let me know if there's any other details I should provide. Thank you!

Internet connection

I test socket using JavaPhoenixChannels.
Steps 1 : open app and make sure app connected internet (via on my case I use Wifi ... )
Steps 2 : Turn off Wifi

Result:
App crash and Log error:

WebSocket connection error
                                                  java.net.UnknownHostException: Unable to resolve host "www.acdefgh.xyz": No address associated with hostname
                                                      at java.net.InetAddress.lookupHostByName(InetAddress.java:434)
                                                      at java.net.InetAddress.getAllByNameImpl(InetAddress.java:259)
                                                      at java.net.InetAddress.getAllByName(InetAddress.java:221)
                                                      at com.squareup.okhttp.Dns$1.lookup(Dns.java:39)
                                                      at com.squareup.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:175)
                                                      at com.squareup.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:141)
                                                      at com.squareup.okhttp.internal.http.RouteSelector.next(RouteSelector.java:83)
                                                      at com.squareup.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:164)
                                                      at com.squareup.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)
                                                      at com.squareup.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
                                                      at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:283)
                                                      at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)
                                                      at com.squareup.okhttp.Call.getResponse(Call.java:286)
                                                      at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:243)
                                                      at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:205)
                                                      at com.squareup.okhttp.Call.access$100(Call.java:35)
                                                      at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:171)
                                                      at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
                                                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
                                                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
                                                      at java.lang.Thread.run(Thread.java:818)

You know, we can check internet on Android SDK, with JavaPhoenixChannels , we can't do that.
So I suggest

  1. I create interface on Socket
   public interface InternetConnection {
        boolean isConnected();
   }

and make sure on Activity, Socket implement

private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, Intent intent) {
            boolean isConnected = NetworkingUntils.isNetworkAvailable(context);
            if (isConnected) {
                if (socket == null) {
                    setUpSocket();
                } else {
                    socket.updateInternetConnection(isConnected);
                }
            } else {
                if (socket != null)
                    socket.disconnect();
                socket = null;
            }
        }
    };

public void updateInternetConnection(final boolean isConnected) {
        if (socket != null) {
            socket.setInternetConnection(new Socket.InternetConnection() {
                @Override
                public boolean isConnected() {
                    return isConnected;
                }
            });
        }
    }

2 . Change isConnect method

private InternetConnection internetConnection;
 /**
     * @return true if the socket connection is connected
     */
    public boolean isConnected() {
        return webSocket != null && internetConnection != null && internetConnection.isConnected();
    }

Result : app don't crash
Please consider internet connection.

I can't download successful version JavaPhoenixChannels 1.0 for androidstudio,and error reporting when i using version 0.2 to disconnection reconnection

hellow ,i want to using JavaPhoenixChannels to android , and i have two problems

first problem

i add

repositories {
        google()
        jcenter()
        maven { url 'http://dl.bintray.com/eoinsha/java-phoenix-channels' }
    }   

but i can't download JavaPhoenixChannels version 1.0

second problem

i successful to connect websocket ,and i try to reconnect with broken line
then something went wrong.
like this

2018-11-28 18:18:30.789 30717-30733/com.ssh.kotlinchat E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
    Process: com.ssh.kotlinchat, PID: 30717
    java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.next(ArrayList.java:831)
        at org.phoenixframework.channels.Socket$PhoenixWSListener.onMessage(Socket.java:82)
        at okhttp3.internal.ws.RealWebSocket$1.onMessage(RealWebSocket.java:62)
        at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:242)
        at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:108)
        at okhttp3.internal.ws.RealWebSocket.readMessage(RealWebSocket.java:97)
        at okhttp3.ws.WebSocketCall.createWebSocket(WebSocketCall.java:152)
        at okhttp3.ws.WebSocketCall.access$000(WebSocketCall.java:41)
        at okhttp3.ws.WebSocketCall$1.onResponse(WebSocketCall.java:97)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:126)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:761)

and it always happen
please help me

Phoenix Socket with okhttp3

I am using the dependency "com.squareup.okhttp3:logging-interceptor:3.8.0" along with compile('com.github.eoinsha:JavaPhoenixChannels:0.2') {
exclude module: 'groovy-all'
}
to implement a socket connection in Android app. While launching, I get a build error of having multiple dex files (most probably its the conflicts between okhttp3 of Squareup and JavaPhoenixChannel). Is there any fix for this?

SocketTimeoutException

if I connect locally, it works fine, but, if I connect to the server on cloud, I get this error:

W/Socket: WebSocket connection error
java.net.SocketTimeoutException
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
at okio.Okio$2.read(Okio.java:139)
at okio.AsyncTimeout$2.read(AsyncTimeout.java:211)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:306)
at okio.RealBufferedSource.indexOf(RealBufferedSource.java:300)
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:196)
at com.squareup.okhttp.internal.http.Http1xStream.readResponse(Http1xStream.java:186)
at com.squareup.okhttp.internal.http.Http1xStream.readResponseHeaders(Http1xStream.java:127)
at com.squareup.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:737)
at com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:573)
at com.squareup.okhttp.Call.getResponse(Call.java:287)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:243)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:205)
at com.squareup.okhttp.Call.access$100(Call.java:35)
at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:171)
at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)

I am not using proxy or load balancer, why I get this error? how can debug this?

Improvements for Android

Hi, nice work on this library! I was able to confirm that it still works for the latest version of Phoenix. When I was trying it with a new Android project, I ran into the dex method limit. I ended up deleting SimpleCliTest.groovy and making the groovy dependency only for the tests and that got it to work. I can send a PR with the change if needed. Here is the Android demo project I created using this: https://github.com/bryanjos/AndroidPhoenixDemo

Also, since Phoenix is nearing 1.0, maybe putting together a release would be helpful? For the demo project above, I just used jitpack.io with the fork I created to get it working. Maybe making a tag here and doing the same would be sufficient for now?

Can not connect to localhost

I started a new android project using this library, but when I do socket.connect() I get htis error:

java.net.ConnectException: Failed to connect to localhost/127.0.0.1:4000

I can access the server at localhost:4000, but for some reason i can't connect to it using your library.

JavaPhoenixChannels not working on Phoenix 1.1.0

When we changed Phoenix 1.0.x to 1.1.0, JavaPhoenixChannels not working

after hooks have been replaced by a timeout option on push, and a receive("timeout", callback) hook.

// 1.0.x
channel.push("new_message", {body: "hi!"})
.receive("ok", resp => console.log(resp) )
.after(5000, () => console.log("times! up"))

channel.push("new_message", {body: "hi!"})
.receive("ok", resp => console.log(resp) )
.after(12000, () => console.log("times! up"))

// 1.1.0
// timeout default to 5000
channel.push("new_message", {body: "hi!"})
.receive("ok", resp => console.log(resp) )
.receive("timeout", () => console.log("times! up"))

This is message log
W/Socket: WebSocket connection error
java.io.EOFException
at okio.RealBufferedSource.require(RealBufferedSource.java:64)
at okio.RealBufferedSource.readByte(RealBufferedSource.java:77)
at com.squareup.okhttp.internal.ws.WebSocketReader.readHeader(WebSocketReader.java:108)
at com.squareup.okhttp.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:97)
at com.squareup.okhttp.internal.ws.RealWebSocket.readMessage(RealWebSocket.java:87)
at com.squareup.okhttp.ws.WebSocketCall$2.execute(WebSocketCall.java:187)
at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
at java.lang.Thread.run(Thread.java:856)
W/Socket: Failed to explicitly close following failure

Support for Phoenix Presence

It looks like there are some updates here needed to support presence. In particular in the JavaScript client, they have a Presence module with a couple of functions on it. The links below may help:

https://github.com/phoenixframework/phoenix/blob/f2e02d97ef79f825f6bbbdc2d7b69a1d005bff90/web/test/presence_test.js

https://github.com/phoenixframework/phoenix/blob/0cefe23a95628cd8ccb73db4e59644b699a544da/web/static/js/phoenix.js#L796

I think the change here would be to include a Presence class. I will also check to see if there are any further changes needed for the socket

Implement heartbeat

The connection to the channel dies if no activity is sent. Looking at the JavaScript Phoenix client, it sends a heartbeat message at some configurable interval to tell the server it's still alive.

Code from javascript:

  sendHeartbeat(){ if(!this.isConnected()){ return }
    this.push({topic: "phoenix", event: "heartbeat", payload: {}, ref: this.makeRef()})
  }

This functionality should be implemented here.

I'm going to try to drop a PR for this, but just wanted to make a note of it.

android.os.NetworkOnMainThreadException

When I use channel.push android throws this exception android.os.NetworkOnMainThreadException

channel.push("new_msg", "Hi")
                    .receive("ok", { _ ->
                       // message sent
                    })

I think that this library use another thread to call each method like push or connect

java.lang.NullPointerException:

Right now on master

GIVEN your endpoint is down/non existent
WHEN you try to connect
THEN you get a runtime exception instead of onError callback

10-13 12:51:49.810 18555-18617/limited.magnum.fireball E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
                                                                         Process: limited.magnum.fireball, PID: 18555
                                                                         java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.phoenixframework.channels.Envelope.getReason()' on a null object reference
                                                                             at org.phoenixframework.channels.Channel$5.onMessage(Channel.java:107)
                                                                             at org.phoenixframework.channels.Channel.trigger(Channel.java:155)
                                                                             at org.phoenixframework.channels.Socket.triggerChannelError(Socket.java:325)
                                                                             at org.phoenixframework.channels.Socket.access$1200(Socket.java:23)
                                                                             at org.phoenixframework.channels.Socket$PhoenixWSListener.onFailure(Socket.java:116)
                                                                             at com.squareup.okhttp.ws.WebSocketCall$1.onFailure(WebSocketCall.java:124)
                                                                             at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:177)
                                                                             at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
                                                                             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                             at java.lang.Thread.run(Thread.java:761)

not found: "com.github.eoinsha:JavaPhoenixChannels:0.2"

I downloaded the sample android app. When trying to build, I got the gradle error about artifact not found (see title).

I was able to fix this by changing the version to 0.1. Just wanted to note this in case someone else is seeing the same problems

    compile('com.github.eoinsha:JavaPhoenixChannels:0.1') {
        exclude module: 'groovy-all'
    }

Not triggers event signalling to all callbacks bound to the specified event.

channel.on(ChannelEvent.ERROR.getPhxEvent(), new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        System.out.println("ERROR: " + envelope.toString());
    }
});

This is the example of using channels in readme.

    /**
     * Triggers event signalling to all callbacks bound to the specified event.
     *
     * @param triggerEvent The event name
     * @param envelope     The message's envelope relating to the event or null if not relevant.
     */
    void trigger(final String triggerEvent, final Envelope envelope) {
        synchronized (bindings) {
            for (final Binding binding : bindings) {
                if (binding.getEvent().equals(triggerEvent)) {
                    // Channel Events get the full envelope
                    binding.getCallback().onMessage(envelope);
                    break;
                }
            }
        }
    }

The break statement inside if block, means that only first binding object will get the message. Is this ok? when I register an IMessageCallback for phx_error event, I will not called because this break statement.
And when I remove this block, all tasks will be failed.
I don't know, may we shouldn't code just like examples? :D

Auto reconnect keeps trying even after a disconnect

I'm writing an application interfacing with multiple phoenix servers and I encountered the following scenario:

  • Attempt to connect to an unreachable server
  • The socket keeps trying
  • Attempt to connect to another server, calling currentSocket.disconnect and initializing a new connection
  • The first socket keeps trying

This PR fix this by calling cancelReconnectTimer when disconnecting a socket

Token-authentification at socket creation/connection

Hello all,

In Socket.IO, it's super easy to get my token sent for authentification purposes during socket creation :

IO.Options opts = new IO.Options();
opts.forceNew = true;
opts.query = "auth_token=" + authToken;
Socket socket = IO.socket("http://localhost", opts);

How can I do the same thing with the Phoenix Socket ?
Thank you in advance,
Lucas

What dependency in build.gradle

Hi!

I am quite new to android so I still have to delve into gradle. Until now, if I wanted to use a third party component, all I had to do was to add a dependency to my build.gradle file ( compile "..").

I tried to do the same with JavaPhoenixChannels:
compile('org.phoenixframework.channels:JavaPhoenixChannels:0.1.0-SNAPSHOT')

This is what you do in the PhoenixChatAndroid example. But when I synchronize, it fails to resolve.

What dependency should I compile?

Thank you very much!

WebSocket connection error and SocketTimeoutException?

I followed a guide on how to get this completed . I'm able to receive messages but the socket keeps connecting and disconnecting, Or it'll crash if I have an onError method with an exception stating that envelope is null.

Ultimately the main issue is having socket timeout exception keeps occurring and I have no clear idea of what is going on. Here's is the stack trace with the .onError implementation.

01-21 15:15:22.392 29408-29821/com.app W/Socket: WebSocket connection error java.net.SocketTimeoutException at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488) at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:37) at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237) at okio.Okio$2.read(Okio.java:139) at okio.AsyncTimeout$2.read(AsyncTimeout.java:211) at okio.RealBufferedSource.request(RealBufferedSource.java:71) at okio.RealBufferedSource.require(RealBufferedSource.java:64) at okio.RealBufferedSource.readByte(RealBufferedSource.java:77) at com.squareup.okhttp.internal.ws.WebSocketReader.readHeader(WebSocketReader.java:110) at com.squareup.okhttp.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:99) at com.squareup.okhttp.internal.ws.RealWebSocket.readMessage(RealWebSocket.java:97) at com.squareup.okhttp.ws.WebSocketCall.createWebSocket(WebSocketCall.java:153) at com.squareup.okhttp.ws.WebSocketCall.access$000(WebSocketCall.java:40) at com.squareup.okhttp.ws.WebSocketCall$1.onResponse(WebSocketCall.java:98) at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:177) at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818) 01-21 15:15:22.393 29408-29821/com.app W/Socket: Failed to explicitly close following failure 01-21 15:15:22.393 29408-29821/com.app E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher Process: com.app, PID: 29408 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.phoenixframework.channels.Envelope.getReason()' on a null object reference at org.phoenixframework.channels.Channel$5.onMessage(Channel.java:108) at org.phoenixframework.channels.Channel.trigger(Channel.java:156) at org.phoenixframework.channels.Socket.triggerChannelError(Socket.java:365) at org.phoenixframework.channels.Socket.access$1300(Socket.java:24) at org.phoenixframework.channels.Socket$PhoenixWSListener.onFailure(Socket.java:122) at com.squareup.okhttp.internal.ws.RealWebSocket.readerErrorClose(RealWebSocket.java:217) at com.squareup.okhttp.internal.ws.RealWebSocket.readMessage(RealWebSocket.java:100) at com.squareup.okhttp.ws.WebSocketCall.createWebSocket(WebSocketCall.java:153) at com.squareup.okhttp.ws.WebSocketCall.access$000(WebSocketCall.java:40) at com.squareup.okhttp.ws.WebSocketCall$1.onResponse(WebSocketCall.java:98) at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:177) at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:818)

java.lang.NoClassDefFoundError: org.phoenixframework.channels.Socket$PhoenixWSListener

I don't if this is really an issue with the library or a mistake on my end so I post here anyway.

This is my build configuration:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "com.sandzar.paywand"
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/dependencies.txt'
        exclude 'META-INF/LGPL2.1'
    }
    lintOptions {
        disable 'InvalidPackage'
    }
    productFlavors {
        demo {
            applicationId "com.sandzar.paywand"
            buildConfigField "boolean", "IS_DEMO", "true"
        }
    }
}

repositories {
    mavenCentral()
    maven {
        url 'https://raw.github.com/iainconnor/ObjectCache/master/maven/'
    }
}

def dbflow_version = "4.0.5"
def sqlcipher_version = "3.5.7"

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    annotationProcessor "com.github.Raizlabs.DBFlow:dbflow-processor:${dbflow_version}"
    compile "com.github.Raizlabs.DBFlow:dbflow-core:${dbflow_version}"
    compile "com.github.Raizlabs.DBFlow:dbflow:${dbflow_version}"
    compile "com.github.Raizlabs.DBFlow:dbflow-sqlcipher:${dbflow_version}"
    compile "net.zetetic:android-database-sqlcipher:${sqlcipher_version}@aar"

    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support:cardview-v7:25.3.1'

    compile 'com.fasterxml.jackson.core:jackson-databind:2.8.3'

    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.okhttp3:okhttp:3.8.0'
    compile 'com.google.code.gson:gson:2.8.0'

    compile('com.github.eoinsha:JavaPhoenixChannels:0.2') {
        exclude module: 'groovy-all'
        exclude module: 'okhttp-ws'
        exclude module: 'jackson-databind'
    }
}

I get the following error as soon as any socket methods are invoked:

java.lang.NoClassDefFoundError: org.phoenixframework.channels.Socket$PhoenixWSListener E at org.phoenixframework.channels.Socket.<init>(Socket.java:167) E at org.phoenixframework.channels.Socket.<init>(Socket.java:170) E at com.sandzar.paywand.sockets.SocketService.initiateSocketConnection(SocketService.java:66) E at com.sandzar.paywand.sockets.SocketService.onStartCommand(SocketService.java:50) E at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3010) E at android.app.ActivityThread.access$2200(ActivityThread.java:150) E at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1442) E at android.os.Handler.dispatchMessage(Handler.java:102) E at android.os.Looper.loop(Looper.java:148) E at android.app.ActivityThread.main(ActivityThread.java:5417) E at java.lang.reflect.Method.invoke(Native Method) E at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:764) E at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) Process I Sending signal. PID: 4379 SIG: 9

The is the portion of code that causes the error:

private void initiateSocketConnection() {
    try {
        Log.e(DEBUG_TAG, "initiateSocketConnection") ;
        socket = new Socket(Constants.CHANNEL_URL);
        socket.onOpen(new ISocketOpenCallback() {
            @Override
            public void onOpen() {
                try {
                    final ObjectNode payload = objectMapper.createObjectNode();
                    payload.put("token", UserRepository.getInstance().getLoggedInUser().getAuthenticationToken()) ;
                    channel = socket.chan(getUserChannelTopic(), payload);
                    channel.join().receive("ok", new IMessageCallback() {
                        @Override
                        public void onMessage(final Envelope envelope) {
                            Log.e(DEBUG_TAG, "Joined channel successfully") ;
                        }
                    });
                    channel.on("payment:new", new IMessageCallback() {
                        @Override
                        public void onMessage(Envelope envelope) {

                        }
                    }) ;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        socket.onClose(new ISocketCloseCallback() {
            @Override
            public void onClose() {

            }
        });
        socket.onError(new IErrorCallback() {
            @Override
            public void onError(String s) {

            }
        });
    } catch(Exception e) {
        e.printStackTrace() ;
    }
}

Here is some extra output from the console:

Java7Support  W  Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added
 art  I  Rejecting re-init on previously-failed class java.lang.Class<org.phoenixframework.channels.Socket$PhoenixWSListener>
      I  Rejecting re-init on previously-failed class java.lang.Class<org.phoenixframework.channels.Socket$PhoenixWSListener>
      I  Rejecting re-init on previously-failed class java.lang.Class<org.phoenixframework.channels.Socket$PhoenixWSListener>
      I  Rejecting re-init on previously-failed class java.lang.Class<org.phoenixframework.channels.Socket$PhoenixWSListener>
      I  Rejecting re-init on previously-failed class java.lang.Class<org.phoenixframework.channels.Socket$PhoenixWSListener>
      I  Rejecting re-init on previously-failed class java.lang.Class<org.phoenixframework.channels.Socket$PhoenixWSListener>
      I  Rejecting re-init on previously-failed class java.lang.Class<org.phoenixframework.channels.Socket$PhoenixWSListener>
      I  Rejecting re-init on previously-failed class java.lang.Class<org.phoenixframework.channels.Socket$PhoenixWSListen

Background Thread or NetworkOnMainThreadException?

Do we need to use the channels in a background thread always?

Is there a plan to make its usage safe in activities using listeners and without worrying about NetworkOnMainThreadException?

I recently got NetworkOnMainThreadException when switching to SSL endpoint. I digged a bit and found it coming from okhttp. Pretty much same issue as here square/okhttp#2017

All exceptions thrown in background

The Java Phoenix Client library has crashed my android app a number of times because of exceptions thrown in the background. I temporarily fixed the crashing by catching all exceptions but that doesn't really fix the issue. While the app no longer crashed for users, I made it a point to log all the exceptions so that I can better identify the root cause.

I'm pasting the list of exceptions here in case anyone is interested. This is a list of all the exceptions after over a week on production (in order from highest frequency to least frequency):

  • java.net.SocketTimeoutException
    • connect timed out
    • timeout
    • Read timed out
    • connect timed out at
  • java.io.EOFException
  • javax.net.ssl.SSLException
    • Read error: ssl=0x7a36fd6c40: I/O error during system call, Software caused connection abort
    • Read error: ssl=0x55b9c933b0: I/O error during system call, Connection timed out
  • java.net.SocketException
    • Socket is closed
  • java.lang.IllegalStateException
    • closed
  • java.net.UnknownHostException
    • Unable to resolve host : No address associated with hostname
  • java.io.InterruptedIOException
    • thread interrupted
  • java.lang.IllegalStateException
    • Task already scheduled or cancelled
  • java.io.IOException
    • closed

Update bintray

I see something is being fixed in this plugin. I'm heavily using it in many applications and it has some quirks. Seeing that something is being fixed makes me very happy, however, could you release new versions to bintray? I'm making apps through Nativescript, but I don't know how to manually insert current version of this plugin from github in my projects. I am talking about this:
https://bintray.com/javaphoenixchannels/java-phoenix-channels/JavaPhoenixChannels

WebSocket connection error in Socket.java file under "onFailure" Method

We are using this library to get images from phoenix socket and showing these images in image view but Sometimes on slow internet connection, I got an exception:
Failed to read message payload and payload call the close method. This happens under "onMessage" method under Socket.java class. Following is the method:
} catch (IOException e) { LOG.log(Level.SEVERE, "Failed to read message payload", e); } finally { payload.close(); } }

After that "onFailure" method called and it goes to the following condition:
if (reconnectOnFailure) { scheduleReconnectTimer(); }

But after that phoenix Socket never gets connected and start a loop of above-mentioned exception. Can you please help me how to fix it or how can we notify our activity that exception occur and we dismiss our activity. Thanks

E/Socket: Failed to read message payload

Hi, I'm using the library for android client. While joining the channel and on every event I get the following error. The functionality works fine without any issues as the payload is getting delivered to the call backs.

Kindly advice how this exception can be handled.

E/Socket: Failed to read message payload
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "join_ref" (class org.phoenixframework.channels.Envelope), not marked as ignorable (4 known properties: "event", "ref", "payload", "topic"])
at [Source: buffer(okhttp3.internal.ws.WebSocketReader$FramedMessageSource@9999fee).inputStream(); line: 1, column: 86] (through reference chain: org.phoenixframework.channels.Envelope["join_ref"])
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:834)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1096)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1469)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1447)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:282)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2899)
at org.phoenixframework.channels.Socket$PhoenixWSListener.onMessage(Socket.java:80)
at okhttp3.internal.ws.RealWebSocket$1.onMessage(RealWebSocket.java:62)
at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:242)
at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:108)
at okhttp3.internal.ws.RealWebSocket.readMessage(RealWebSocket.java:97)
at okhttp3.ws.WebSocketCall.createWebSocket(WebSocketCall.java:152)
at okhttp3.ws.WebSocketCall.access$000(WebSocketCall.java:41)
at okhttp3.ws.WebSocketCall$1.onResponse(WebSocketCall.java:97)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:126)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)

Fatal Exception: java.lang.IllegalStateException: closed

I am using the Phoenix channel in my Android app and here is the code: https://github.com/evercam/evercam-play-android/blob/master/evercamPlay/src/main/java/io/evercam/androidapp/tasks/LiveViewRunnable.java

Crashlytics was integrated for tracking app crashes, and I'm keep getting this error:

Fatal Exception: java.lang.IllegalStateException: closed
       at com.squareup.okhttp.internal.ws.RealWebSocket.close(RealWebSocket.java:164)
       at org.phoenixframework.channels.Socket$PhoenixWSListener.onFailure(Socket.java:130)
       at com.squareup.okhttp.internal.ws.RealWebSocket.readerErrorClose(RealWebSocket.java:217)
       at com.squareup.okhttp.internal.ws.RealWebSocket.readMessage(RealWebSocket.java:100)
       at com.squareup.okhttp.ws.WebSocketCall.createWebSocket(WebSocketCall.java:153)
       at com.squareup.okhttp.ws.WebSocketCall.access$000(WebSocketCall.java:40)
       at com.squareup.okhttp.ws.WebSocketCall$1.onResponse(WebSocketCall.java:98)
       at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:177)
       at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
       at java.lang.Thread.run(Thread.java:841)

But I couldn't find a way to reproduce it in my app.

Any idea about the reason why it's happening? What's the suggested solution for handling errors like this?

Thanks,
Liuting

Invalid README or method definition

I'm not sure if this is more an issue with the README providing incorrect instructions, or a method incorrectly being marked as private, but some of the handler methods on a channel are no longer public. The README provides this snippet:

channel = socket.chan("rooms:lobby", null);
channel.join()
...
channel.onClose(new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        System.out.println("CLOSED: " + envelope.toString());
    }
});

channel.onError(new IErrorCallback() {
    @Override
    public void onError(String reason) {
        System.out.println("ERROR: " + reason);
    }
});

However the onClose and onError methods are private and thus this fails to compile.
I'm not sure whether it was meant to be made private (as they were public in a previous version) or if the README simply needs updating to show the usage of the on method instead.

Replace okhttp-ws with official okhttp websocket implementation

Now that a stable version of websockets is available in okhttp library I think this library should use it. In fact, I ended up pulling the source files into a local project and converting to use the latest version of okhttp and it's been working great so far.

I ended up using the source files in my project because I was having trouble building this library in Android Studio but I'll take another shot at it and see if I can't create a pull request with the official okhttp library.

https://medium.com/square-corner-blog/web-sockets-now-shipping-in-okhttp-3-5-463a9eec82d1#.e6cbixd8k

Using Gson instead of Jaxson

Hi,

This isn't an issue as it is a question. Have you thought about allowing any JSON serializer like Gson instead of Jaxson? I just noticed it referenced while quickly scanning the Socket.java class.

I'm asking b/c I already use Gson in my app - not because I have anything against Jaxson. It might be perfectly fine to use both - just wanted to ask since ideally I wouldn't need to use both.

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;

When try to connect again, channel would not push again

I tried to disconnect wifi connection, then, connecting again, the socket tried to connect successfully, however when try to push again on the channel I will get error on server as:

Ignoring unmatched topic "buses:1" in MyApp.Schools.SchoolSocket

If do not try to disconnect the wifi and keep the connection, the channel pushes normally and no error at server..

What we have done is to check if channel is not null, then leave it.

if (channel!= null)channel.leave();
channel= new channel ...etc

How to solve this?
You can share ideas at elixirforum thread here: https://elixirforum.com/t/why-i-get-warn-ignoring-unmatched-topic/5184/11

ConcurrentModificationException when leaving multiple channels

Leaving multiple channels at the same time seems to disagree with the current implementation !

The exception is always thrown from Socket.onMessage, and using the debugger I can observe calls made to remove(Channel) just "before" the exception.
I tried to secure every access to channels using synchronized() block, with no luck.

Eventually I ended up investigating threading issues and tried a lazy Java programmer solution: updating the type of channels to CopyOnWriteArrayList ; and it worked for me.

I can provide a PR with the related commit if needed

Unit test that connects to Socket works in debug mode, but not regular run.

Longshot, but here goes.

We are using this library successfully (so thanks so much for putting it out there!) in an app.

When trying to test some changes to the wss backend, we wrote a little .jar that connects to our server, waits for responses on a channel, etc. That works fine.

I tried moving it into a unit test to keep it a little closer to our app. I've had mixed results.

When I run it in debug mode and step through the breakpoints, it seems to connect to the socket fine, gets messages, etc. When I run it with the regular Run option, our socket connection doesn't seem to happen and the test then fails.

The test looks something like this (ignore terrible formatting please ๐Ÿ˜ธ ):

@Test
public void testWebsocketConnection() { 

  final Socket socket;
  Channel channel;
  final String SERVER =
                "wss://<some_server>/socket/websocket";

        try {
            socket = new Socket(SERVER);
            // Cert problems, so just ignoring
            TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() {
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] x509Certificates, String s)
                        throws java.security.cert.CertificateException {
                }

                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] x509Certificates, String s)
                        throws java.security.cert.CertificateException {

                }

                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[]{};
                }
            }
            };

            final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };

            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            socket.setSSLSocketFactory(sc.getSocketFactory());
            socket.setHostnameVerifier(DO_NOT_VERIFY);

            socket.connect();
            // This returns 'false'
            System.out.println("Connected? " + socket.isConnected());

            channel = socket.chan("searches:sample-events-uuid", null);

            channel.join()
                    .receive("ok", new IMessageCallback() {
                        @Override
                        public void onMessage(Envelope envelope) {
                            System.out.println("JOINED with: " + envelope.toString());
                        }
                    });
            channel.onError(new IErrorCallback() {
                @Override
                public void onError(String s) {
                    // I don't see this when test fails
                    System.out.println("fail! " + s);
                }
            });
        } catch (Exception e) {
            // This doesn't catch when test fails
            System.out.println("caught something " + e.getLocalizedMessage());
            e.printStackTrace();
        }
}

(Code modified in Github UI so may have left in a typo. But as mentioned, something similar passes and the jar runs when this is wrapped in a main and run separately).

Any ideas on what I'm missing? I tried messing with Run configurations in Android Studio 2.2 with no luck.

I realize this is a bad test - the point is just for us to be able to remove @ignore annotations on these tests and run them when we need to work with backend team to debug. Thanks for any thoughts!

Spurious retransmission of heartbeat

Hi..

While trying to debug my android application which stops responding on my local network after its been running for about a minute, I installed wireshark to see if I could find any more details about what might be blocking up transmission between client and server.

I noticed that the client (my Android box) was sending a spurious retransmission of the heartbeat.

I have attached my wireshark file to show what is happening... Is this normal? For example line 21084 shows numerous heartbeats being sent at one..

FYI:

192.168.16.30 is the server
192.168.16.43 is the android client.

Pings between each machine on the command line are less than 10ms so I don't think it is related to anything happening on my network. The android box is currently connected wirelessly, I might try wired to see if that helps.

My Android box is running Android 4.2.2 and uses the following board..

https://wholesaler.alibaba.com/product-detail/TISMART-A20-Android-Motherboard-for-Digital_60376215865.html

spurious_heartbeat.pcapng.zip

Phoenix 1.3 - UnrecognizedPropertyException: Unrecognized field "join_ref"

The join_ref field was added in Phoenix 1.3. Using a Phoenix 1.3 server with this library causes the following exception:

E/Socket: Failed to read message payload
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "join_ref" (class org.phoenixframework.channels.Envelope), not marked as ignorable (4 known properties: "event", "ref", "payload", "topic"])
                                                                      at [Source: buffer(okhttp3.internal.ws.WebSocketReader$FramedMessageSource@6881cef).inputStream(); line: 1, column: 85] (through reference chain: org.phoenixframework.channels.Envelope["join_ref"])
                                                                      at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:834)
                                                                      at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1096)
                                                                      at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1469)
                                                                      at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1447)
                                                                      at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:282)
                                                                      at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
                                                                      at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789)
                                                                      at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2899)
                                                                      at org.phoenixframework.channels.Socket$PhoenixWSListener.onMessage(Socket.java:80)
                                                                      at okhttp3.internal.ws.RealWebSocket$1.onMessage(RealWebSocket.java:62)
                                                                      at okhttp3.internal.ws.WebSocketReader.readMessageFrame(WebSocketReader.java:242)
                                                                      at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:108)
                                                                      at okhttp3.internal.ws.RealWebSocket.readMessage(RealWebSocket.java:97)
                                                                      at okhttp3.ws.WebSocketCall.createWebSocket(WebSocketCall.java:152)
                                                                      at okhttp3.ws.WebSocketCall.access$000(WebSocketCall.java:41)
                                                                      at okhttp3.ws.WebSocketCall$1.onResponse(WebSocketCall.java:97)
                                                                      at okhttp3.RealCall$AsyncCall.execute(RealCall.java:126)
                                                                      at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
                                                                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                      at java.lang.Thread.run(Thread.java:761)

Inconsistent callbacks (sometimes called, sometimes never called, sometimes empty callback sets, etc)

Considering the example chat App, I tried some network tests:

  • Start without any connection active, then connects later on
  • Start connected, wait the socket get connected and the channel joined, then disconnect
  • Start connected and while socket connection is ongoing, disconnect
  • Start connected, wait for the socket and channel to get connected, then shutdown the server
  • Start connected, but with the server offline
  • Have everything get connect, then put the application on background

In all cases I never got consistency from the error, close and open callbacks.

  • Sometimes any or all of the callback sets are empty when they are about to get called by the listener, even although I add them to the sets before connecting, seems like a threading issue
  • I never saw channel onError and onClose being called
  • Socket onOpen is called 1/2 of the times
  • Socket onClose is never called
  • Socket onError is never called

Example: on a java.net.SocketTimeoutException: timeout, that calls Socket.onFailure, the errorCallbacks was empty, even although I added listeners before connecting.

I'll try to work on a PR, but reporting here in case anyone faced the same issues / already have any fixes in mind.

Example code:

socket = new Socket("ws://..../socket/websocket");

socket.onOpen(new ISocketOpenCallback() {
    @Override
    public void onOpen() {
        Log.d("CHAT", "socket.onOpen");
    }
});

socket.onClose(new ISocketCloseCallback() {
    @Override
    public void onClose() {
        Log.d("CHAT", "socket.onClose");
    }
});

socket.onError(new IErrorCallback() {
    @Override
    public void onError(String reason) {
        Log.d("CHAT", "socket.onError");
    }
});

socket.connect();

channel = socket.chan("rooms:lobby", null);

channel.join()
        .receive("ignore", new IMessageCallback() {
            @Override
            public void onMessage(Envelope envelope) {
                Log.d(MainActivity.class.getName(), "auth error");
            }
        })
        .receive("ok", new IMessageCallback() {
            @Override
            public void onMessage(Envelope envelope) {
                Log.d(MainActivity.class.getName(), "join ok");
            }
        });

channel.on("new:msg", new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
    }
});

channel.onClose(new IMessageCallback() {
    @Override
    public void onMessage(Envelope envelope) {
        Log.d("CHAT", "channel.onClose");
    }
});

channel.onError(new IErrorCallback() {
    @Override
    public void onError(String reason) {
        Log.d("CHAT", "channel.onError");
    }
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.