deepstreamio / deepstream.io-client-java Goto Github PK
View Code? Open in Web Editor NEWThe Java/Android Client for deepstream.io
License: Other
The Java/Android Client for deepstream.io
License: Other
Hi!
For many reasons i cant and wont use firebase. Therefore I try to figure out what i can do with deepstream. Now I'm researching offline capabilities. As you can imagine I have some questions:
Is there some kind of built in cache or local storage?
What happens to messages send while reconnecting or offline
Thanks for your help.
Classes
Do we need the following classes publicly?
DeepstreamError's are used for things like snapshot errors and record retrieval errors. DeepstreamExceptions are thrown for other reasons like message parse error
The following classes don't have any docs:
The following classes need renaming
The following methods need renaming
AnonymousRecord::delete__ ( rename delete so only function has the name )
DeepstreamClient::initWithNSString:withJavaUtilMap: ( needs object c rename )
DeepstreamClient::addConnectionChangeListenerWithConnectionStateListener: ( needs object c rename )
DeepstreamClient::loginWithJsonElement::( needs object c rename )
DeepstreamClient::removeConnectionChangeListenerWithConnectionStateListener : ( needs object c rename )
EventHandler::emitWithNSString: ( needs object c rename )
EventHandler::emitWithNSString:withId: ( needs object c rename )
EventHandler::listenWithNSString:withListenListener: ( needs object c rename )
EventHandler::subscribeWithNSString:withEventListener: ( needs object c rename )
EventHandler::unlistenWithNSString: ( needs object c rename )
EventHandler::unsubscribeWithNSString:withEventListener: ( needs object c rename )
List::subscribeWithListEntryChangedListener:( needs object c rename )
List::unsubscribeWithListEntryChangedListener:( needs object c rename )
List::version__ ( needs object c rename )
PresenceHandler::subscribeWithPresenceEventListener: ( needs object c rename )
PresenceHandler::unsubscribeWithPresenceEventListener:( needs object c rename )
Record::delete__ ( needs object c rename )
Record::setMergeStrategyWithRecordMergeStrategy: ( needs object c rename )
Record::setWithAckWithId ( needs object c rename )
Record::setWithAckWithNSString:withId:: ( needs object c rename )
Record::version__: ( needs object c rename )
Record::getWithIOSClass:: private
RecordHandler_RecordHandlerListeners::initWithRecordHandler: private
RecordHandler_RecordHandlerListeners::onDestroyPendingWithNSString: private
Interfaces/Protocol
Rename Interface
Rename Methods
Constants
We want to implement event listening so that we can do the following:
public DeepstreamClient listen( String regex, ListenCallback listenCallback ) {
...
return this;
}
public DeepstreamClient unlisten( String regex, ListenCallback listenCallback ) {
...
return this;
}
// This API will change going on, but only a little
public class ListenCallback() {
public void onListen( recordName, isSubscribed ) {
}
}
Be good to use a ported version of:
https://github.com/deepstreamIO/deepstream.io-client-js/blob/master/src/utils/listener.js
Hi,
in a perfect world I want to subscribe to a record that does not exist, and have a data provider listening and go and create the record, (ie I want the record to be readonly to the client). Unfortunately this functionality does not exist, it is logged as a potential feature
https://github.com/deepstreamIO/deepstream.io/issues/684#issuecomment-304118122
The suggestion I got was to give a user create and read access but not write and delete access. An example permission would look like this, (the server user is what the active data provider will use to set the record).
record:
"readonlyrec":
create: "user.id === 'todd'"
write: "user.id === 'server'"
read: true
delete: "user.id === 'server'"
listen: true
I used the following code to test, the java client hangs at the setwithack and does not get any error back. So it looks like a bug in the java client ?
import io.deepstream.DeepstreamClient;
import io.deepstream.Record;
import java.net.URISyntaxException;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.Gson;
class mytest {
public static void main(String[] args) throws URISyntaxException {
System.out.println("About to run"); // Display the string.
try{
new mytest().run();
} catch(Exception e) {
System.out.println("Error:" + e.getMessage()); // Display the string.
}
}
public void run() throws URISyntaxException {
System.out.println("creating client");
DeepstreamClient client = new DeepstreamClient("localhost:6020");
System.out.println("closing client");
JsonObject e = new JsonObject();
e.add("username", new JsonPrimitive("chris"));
e.add("password", new JsonPrimitive("test"));
client.login(e);
System.out.println("logged in");
JsonObject params = new JsonObject();
params.addProperty("name", "test");
params.addProperty("age", "23");
System.out.println("setting record");
SetRecord(client, "readonlyrec" ,params);
System.out.println("record set");
client.close();
}
public void SetRecord(DeepstreamClient client, String recordname , JsonObject val)
{
Record rec;
System.out.println("getting record");
rec = client.record.getRecord(recordname);
System.out.println("set with ack");
// hangs here, does not get an error back
String r = rec.setWithAck(val).getResult();
System.out.println(String.format("Has result: %s", r));
}
}
Does this client updated to support the WS in 2.x (Since 2.x removed tcp and going all with Websocket)? If so, any examples/docs?
I have done setup of deepstream on my local mac machine. its working fine
used js client for creating master to emit event whenever device gets connected to deepstream with listen and its working fine
const DeepstreamClient = require( '../src/client' )
const ds = DeepstreamClient( 'localhost:6021' )
ds.login()
ds.event.listen('57fb28b9ef70ca0d6238df2d/commands', function (eventName, isSubscribed, response) {
console.log('eventName:',eventName, ' , isSubscribed:', isSubscribed, ' ,response:', response)
if (isSubscribed) {
ds.event.emit('57fb28b9ef70ca0d6238df2d/commands', '#Command1')
}
else {
}
})
ds.event.subscribe("57fb28b9ef70ca0d6238df2d/loggedIn", function (deviceId){
console.log("device loggedIn : ", deviceId)
})
And below is what i have used in java to connect with deepstream
try {
dp = new DeepstreamClient("192.168.1.134:6021", new DeepstreamRuntimeErrorHandler() {
@Override
public void onException(Topic topic, Event event, String errorMessage) {
System.out.println("exception : " + errorMessage);
}
});
dp.login();
dp.event.emit("57fb28b9ef70ca0d6238df2d/loggedIn", "oneplus2");
dp.event.subscribe("57fb28b9ef70ca0d6238df2d/commands", new EventListener() {
@Override
public void onEvent(String eventName, Object... args) {
System.out.println("event called : " + eventName);
}
});
} catch (Exception e) {
e.printStackTrace();
}
Its able to connect to deep-stream, as i can see logs coming over deep-stream terminal for Incoming connection
But master which is working already is not able to listen to above android incoming device also emitting manual event is not reaching to device.
Whereas, trying same stuff from another terminal window of my mac machine its working fine.
const DeepstreamClient = require( '../src/client' )
const ds = DeepstreamClient( 'localhost:6021' )
ds.login()
ds.event.emit("57fb28b9ef70ca0d6238df2d/loggedIn", "terminal");
ds.event.subscribe("57fb28b9ef70ca0d6238df2d/commands", function (data){
console.log("command received : ", data)
})
console.log("subscribed to 57fb28b9ef70ca0d6238df2d/commands")
Need help on why android device is not able to listen to any event happening from master.
Anything i am missing.
Acks are an important part in making sure subscriptions occurred correctly. However there are some very important things to take into account ( that isn't yet in the JS client ):
This can be done within a port of the AckTimeoutRegistry that is aware of conneciton state.
Hi
What is the best practice in using deepstream in ever connected android apps like messengers?
Using android services or ...when to login, keep session between activities, ...
If it is possible give me detailed info.
Can you provide installation instructions in the Readme?
The install instructions here: https://deepstream.io/install/java/ tell me to add this to my pom.xml file.
<dependency>
<groupId>io.deepstream</groupId>
<artifactId>deepstream.io-client-java</artifactId>
<version>0.8</version>
<type>pom</type>
</dependency>
result in
[WARNING] The POM for io.deepstream:deepstream.io-client-java:pom:0.8 is missing, no dependency information available
I assume because I don't have a bintray resolver? But after searching for a while I thought I would ask here.
Sorry, but I a new to java/scala programming.
(Bonus points if you know how to do this in a build.sbt
too)
Thanks.
RPC's sometime take longer time to execute, making rpc's async solves this issue.
Should be able to do record.unsubscribeAll()
and record.unsubscribeAll(String path)
earlier i was doing work on mac , and everything was working fine, if i m running same code over windows then its not getting connect to deepstream, i am talikng about android client , getting this error
io.deepstream.DeepstreamException: CONNECTION_ERROR: failed to connect to /192.168.0.5 (port 6020): connect failed: ETIMEDOUT (Connection timed out)
Map config = new HashMap<String, Object>();
config.put(ConfigOptions.SUBSCRIPTION_TIMEOUT.toString(), 500);
config.put(ConfigOptions.RECORD_READ_ACK_TIMEOUT.toString(), 500);
config.put(ConfigOptions.RECORD_READ_TIMEOUT.toString(), 500);
client = new DeepstreamClient("localhost:6020", config);
[6:40]
i have tried with this code and also with this
Map config = new HashMap<String, Object>();
config.put(ConfigOptions.SUBSCRIPTION_TIMEOUT.toString(), 500);
config.put(ConfigOptions.RECORD_READ_ACK_TIMEOUT.toString(), 500);
config.put(ConfigOptions.RECORD_READ_TIMEOUT.toString(), 500);
client = new DeepstreamClient("192.168.0.5:6020/deepstream", config);
Hi all,
I am using java deepstreeam client 2.2.1, in a desktop environment (not Android).
When performing any rpc call, the app won't exit because some threads (used by deepstream) in the executor pool are still waiting for tasks.
Perhaps I am missing something, but I guess the ds.close() call should trigger a complete shutdown of the pool ?
Here is the minimal code to reproduce this issue:
public static void main(String[] pArgs) {
try {
DeepstreamClient ds = new DeepstreamClient("myhost");
JsonObject auth = new JsonObject();
auth.add("username", new JsonPrimitive("myuser"));
auth.add("password", new JsonPrimitive("mypassword"));
ds.login(auth);
ds.rpc.make("anything", "data");
ds.close();
System.out.println("Main Thread END");
} catch (Exception e) {
e.printStackTrace();
}
}
BTW, thanks again for this great project !
Hi, my company is testing DP technology. We have build a game server (in java) that use DP as gateway beetwen js client (built with react) and the backend (java server). Actually it work well with DP 1.1.1 (on ubuntu 16) using java client 1.0-SNAPSHOT (installed in local mvn some weeks ago) and js library 1.1.1.
Now setting up a new ubuntu server we have seen that apt get, install a new version 2.0 of DP with this new versione the old java client doesn't work. We have tried to download and compile the actual java client (master branch) present on git but DP get some errors about auth request (AREQ).
So it seems that the actual version on git for java client is not yet compatible with DP 2.0, my question then is when it's planned the official release of the related java client?
Thanks in advance for any reply.
Regards, Giovanni
how to search or query by using android sdk, i can able to get the records based on key value but not with List query parameter.
String temp = "{\"table\":\"Lctr\",\"query\":[\"personId\",\"eq\",\"1234\"]}";
io.deepstream.List list = client.record.getList("search?" + temp);
i tried with jsonObject too below is code
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("table", "Locator");
JSONArray jsonArray = new JSONArray();
JSONArray first = new JSONArray();
first.put("personId");
first.put("eq");
first.put(1234);
jsonArray.put(first);
jsonObject.put("query", jsonArray);
} catch (JSONException e) {
e.printStackTrace();
}
io.deepstream.List list = client.record.getList("search?" + jsonObject.toString());
for (String id : list.getEntries()) {
Log.d("entries_id", "" + id);
}
list.subscribe(new ListChangedListener() {
@Override
public void onListChanged(String s, String[] strings) {
for (String recordEntry : strings) {
Log.d("data", "" + recordEntry);
}
}
});
rethinkdb connector is also installed but still i am not getting from the server even though db has matching data.
I'm running a Jersey/Spring based API on Tomcat 8 that uses the deepstream Java client to connect to deepstream and then send various RPC requests. I've been developing and testing on Windows and everything has been fine.
Now I'm moving it into production on AWS (latest Linux on a t2.small). If I stop the deepstream server, the CPU immediately goes to 100% for the Tomcat process. When I restart deepstream and the API logs back in to deepstream but the CPU still remains at 100%. Only a Tomcat restart fixes it.
I'm also using the client in Android and it has the same issue. Though CPU goes from 5% to 60%
Hello,
Is their any possibility in deepstream with caching of events being emitted from one end. So that whom so ever subscribed to that channel/topic gets information if they are not currently connected to it.
I'm running into the following error
Caused by: java.lang.NullPointerException:
Attempt to invoke interface method 'void io.deepstream.Endpoint.send(java.lang.String)' on a null object reference
at io.deepstream.Connection.send(Connection.java:114)
at io.deepstream.EventHandler.unsubscribe(EventHandler.java:68)
when I'm trying to unsubscribe
in onDestroy()
as
deepstreamClient.event.unsubscribe(channel, mChatEventListener);
the deepstreamClient
was initialized as deepstreamClient = new DeepstreamClient(url);
Any idea?
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean io.deepstream.Event.equals(java.lang.Object)' on a null object reference at io.deepstream.DeepstreamClientAbstract.onError(DeepstreamClientAbstract.java:48)
Exception java.lang.NullPointerException: Attempt to invoke interface method 'com.google.gson.JsonElement io.deepstream.RecordMergeStrategy.merge(io.deepstream.Record, com.google.gson.JsonElement, int)' on a null object reference
io.deepstream.Record.recoverRecord (Record.java:629)
io.deepstream.Record.applyUpdate (Record.java:589)
io.deepstream.Record.onMessage (Record.java:520)
io.deepstream.RecordHandler.handle (RecordHandler.java:297)
io.deepstream.Connection$4.run (Connection.java:218)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1133)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:607)
java.lang.Thread.run (Thread.java:761)
** its happen when changing from 4/3G to wifi and vice versa **
I am using below code to login to deepstream
private static void loginToDeepStream() {
try {
client = new DeepstreamClient(Const.CONST_CHAT_HOST);
client.setRuntimeErrorHandler(new DeepstreamRuntimeErrorHandler() {
@Override
public void onException(Topic topic, Event event, String s) {
log("Error : via callback" + s);
client.close();
}
});
LoginResult result = client.login();
if (result.loggedIn()) {
log("realtime server ready");
} else log("realtime server not ready");
} catch (DeepstreamException ex) {
log("error : " + ex.getStackTrace());
} catch (URISyntaxException ex) {
log("error : " + ex.getStackTrace());
}
}
I tried to call this function from main thread and from background thread both, but whenever network goes offline, it calls setRuntimeErrorHandler and shows black screen on device (android). Seems it tries to reconnect again.
How can I force deepstream to make connections on background instead of main thread. Currently even I am calling this method from doInBackground method of AsyncTask class, it blocks UI when setRuntimeErrorHandler gets call .
Please assist me better way if any to perform login and reconnection code without blocking UI thread
Hi,
How can i delete a field in a record ?
{
fieldToClean: {
fieldA: '..',
fieldB: '..',
fieldC: '..'
}
}
How can i with java client delete fieldB
(not setting null)
This is occurring in Android when a RPC request to the app times out (easy to simulate with a breakpoint)
java.lang.ArrayIndexOutOfBoundsException: length=2; index=2
at io.deepstream.RpcHandler.handle(RpcHandler.java:159)
at io.deepstream.Connection$3.run(Connection.java:223)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
The handler receives this message:
P¬E¬INVALID_RPC_CORRELATION_ID¬ unexpected state for rpc..
This causes an app crash which can't be caught.
If the conneciton drops and comes back up, all subscriptions must be resent to deepstream.
Looks like this is same as deepstreamIO/deepstream.io#534 where the provider is sending RESPONSE_TIMEOUT even after setting the rpcTimeout while creating the DeepstreamClient.
Properties clientConfig = new Properties(); clientConfig.put("rpcTimeout", "400000"); clientConfig.put("rpcAckTimeout", "400000"); DeepstreamClient agent = new DeepstreamClient("ip:port",clientConfig);
client.record.getList("")
shouldn't send a request to the server. Can lead to confusing situations
In my initial Activity I set up Deepstreem as shown below:
DeepstreamFactory factory = DeepstreamFactory.getInstance();
try {
deepstreamClient = factory.getClient("wss://...");
JsonElement auth = new JsonParser().parse("{username: Safinn}");
deepstreamClient.login(auth);
} catch (URISyntaxException uriSyntaxException) {
// Deal with error
}
In another activity I try and use Deepstream:
DeepstreamFactory deepstreamFactory = DeepstreamFactory.getInstance();
deepstreamClient = deepstreamFactory.getClient();
new Thread(new Runnable() {
@Override
public void run() {
Record userRecord = deepstreamClient.record.getRecord("user");
userRecord.set("room", "topic");
userRecord.discard();
}
}).start();
My problem is that it never seems to get past the getRecord() line and the data does not show up in Deepstream hub. It just seems to hang on that line. @AlexBHarley
SSL cert was installed using the instructions from deepstream tutorials
Everything works fine but when the cert expired and client tries to connect.
I get a BufferOverflowException
without any other error/information and not any indication what the error was.
Exception in thread "Thread-10" java.nio.BufferOverflowException
at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:363)
at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:342)
at sun.nio.ch.IOUtil.write(IOUtil.java:60)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
at org.java_websocket.SSLSocketChannel2.close(SSLSocketChannel2.java:270)
at org.java_websocket.WebSocketImpl.closeConnection(WebSocketImpl.java:453)
at org.java_websocket.WebSocketImpl.closeConnection(WebSocketImpl.java:472)
at org.java_websocket.WebSocketImpl.eot(WebSocketImpl.java:509)
at org.java_websocket.client.WebSocketClient.interruptableRun(WebSocketClient.java:249)
at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:188)
at java.lang.Thread.run(Thread.java:745)
There's a possibly related issue on TooTallNate/Java-WebSocket#380
When I try to connect to the server from java client, application hangs and the following exception gets printed in the console:
Exception in thread "Thread-15" java.nio.BufferOverflowException
at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:363)
at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:342)
at sun.nio.ch.IOUtil.write(IOUtil.java:60)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
at org.java_websocket.SSLSocketChannel2.close(SSLSocketChannel2.java:270)
at org.java_websocket.WebSocketImpl.closeConnection(WebSocketImpl.java:453)
at org.java_websocket.WebSocketImpl.closeConnection(WebSocketImpl.java:472)
at org.java_websocket.WebSocketImpl.eot(WebSocketImpl.java:509)
at org.java_websocket.client.WebSocketClient.interruptableRun(WebSocketClient.java:249)
at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:188)
at java.lang.Thread.run(Thread.java:745)
Looks like it keeps on waiting for the countdown latch in this line but it never gets decremented. It does not matter if I remove authorization data from the login request, it still occurs.
What is weird is when I connect to the very same server with JavaScript client, everything works as expected.
When WSS is disabled the client connects just fine but since JS client connects without any problem(with WSS enabled) I rule out the possibility that the WSS is poorly configured.
Did anyone else encounter this behavior?
Below is the code I use to setup a connection:
val ds = DeepstreamClient(deepstreamEndpoint) // "wss://myaddress:63200"
val loginReq = Gson().toJsonTree(LoginData(basicId, basicSecret))
val result = ds.login(loginReq) // << in my code it hangs here
if (result.loggedIn()) {
logger.info("Deepstream: Log in success!")
} else {
logger.info("Deepstream: Log in error!")
}
Using java client with version 2.0.4 and Linux Deepstream server 2.1.3.
We are looking to incorporate deepstream into our applications. The scenario is that we have a REST API that acts as 'publisher' and a number of connected javascript/mobile based clients.
Our API has an authentication endpoint that expects either a cookie or header as an authentication token. This end point is configured into the deepstream server as the authentication mechanism.
Each browser client authenticates with our API and receives a JWT token that is passed back to the browser as a cookie. This cookie is then forwarded with the javascript request to login to deepstream. All good so far..
We now need to authenticate from within the API itself (on the java side of the house). In order to do this I was thinking that the 'publisher' code in the API generates a JWT token for itself and then this token be attached as a header and/or cookie along with the call to DeepStreamClient.login();
The idea being that the deepstream server will pass this token back into the API via the http authentication mechanism.
But I cannot see a way to supply a header value or cookie to the login from the java client.
Can you please help?
Dev Note: this was discovered while testing with the java-client the two following and related deepstream.io server (master/v2.2.0) issues:
I have submitted FIXes for the above server-side json-path resolver issues. See comments and attachments in issue#651 deepstreamIO/deepstream.io#651.
Description of this java-client issue:
There is still a corner case with Java client (v2.0.8) see below (w redis cache plugin configured, all components running localhost/Mac osx, all latest versions):
e.g.
JsonObject newTixTextObj = new JsonObject();
newTixTextObj.addProperty("1","tt-1");
newTixTextObj.addProperty("2","tt-2");
newTixTextObj.addProperty("3","tt-3");
newTixTextObj.addProperty("4","tt-4");
newTixTextObj.addProperty("5","tt-5");
newTixTextObj.addProperty("6","tt-6");
Record rec_setPathNum = dsClient.record.getRecord("test/rec_setPathNum");
rec_setPathNum.set("a.b.4", newTixTextObj);
rec_setPathNum.set("aaa[1].333.bbb[0].222", newTixTextObj);
rec_setPathNum.set("a.b.0.2.xxx[4].a", newTixTextObj);
//rec_setPathNum.set("aaa[0].b.1.ccc[1].1", newTixTextObj);
JsonElement val = rec_setPathNum.get("aaa[0]");
rec_setPathNum.set("aaa[0].b", newTixTextObj);
val = rec_setPathNum.get("aaa[0]");
JsonElement rec_setPathNum_elem = rec_setPathNum.get();
System.out.println(">> rec_setPathNum.get() = " + rec_setPathNum_elem.toString());
rec_setPathNum.discard();
SnapshotResult rec_setPathNum_snap = dsClient.record.snapshot("test/rec_setPathNum");
System.out.println(">> rec_setPathNum SNAP = " + rec_setPathNum_snap.getData().toString());
rec_setPathNum = dsClient.record.getRecord("test/rec_setPathNum");
System.out.println(">> rec_setPathNum = " + rec_setPathNum_elem.toString());
rec_setPathNum.set("aaa[0].b") does not apply update on client-side BUT does update server-side with no errs logged.
I’ve tested and VERIFIED that the JAVA client corner case I sighted above ( rec_setPathNum.set(“aaa[0].b”, newTixTextObj); ) IS AN ISSUE with the JAVA-client somewhere. I haven’t traced the java-client side issue yet, but I did verify that the back-end/server/redis value is written correctly AND the above JAVA client SNAPSHOT call returns the correct data as well, but the java record that the “.set” is called on above does NOT reflect the correct updated server-side value. The client-side and server-side are NOT SYNC’D anymore in this use case.
Friends, has anyone an idea why the marker method crashes ??????
List recordList = client.record.getList("driver/users");
Log.d("Deepstream", Arrays.toString(recordList.getEntries()));
for (String recordName : recordList.getEntries())
{
Record record = client.record.getRecord(recordName);
record.subscribe(new RecordChangedCallback()
{
@Override
public void onRecordChanged(String recordName, JsonElement data)
{
Gson gson = new Gson();
JsonObject jsonData = (JsonObject) gson.toJsonTree(data);
double latitude = jsonData.get("lat").getAsDouble();
double longitude = jsonData.get("lng").getAsDouble();
Marker marker = map.addMarker(new MarkerOptions()
.position(new LatLng(latitude, longitude))
.title("San Francisco")
.snippet("Population: 776733"));
System.out.println(String.format("Record '%s' changed, data is now: %s", recordName, data));
}
});
}
Process: com.app, PID: 17957
com.google.maps.api.android.lib6.common.apiexception.c: Not on the main thread
at com.google.maps.api.android.lib6.common.k.b(:com.google.android.gms.DynamiteModulesB@11518448:11)
at com.google.maps.api.android.lib6.common.p.a(:com.google.android.gms.DynamiteModulesB@11518448:5)
at com.google.maps.api.android.lib6.impl.ba.a(:com.google.android.gms.DynamiteModulesB@11518448:483)
at com.google.android.gms.maps.internal.k.onTransact(:com.google.android.gms.DynamiteModulesB@11518448:94)
at android.os.Binder.transact(Binder.java:499)
at com.google.android.gms.internal.zzeb.zza(Unknown Source)
at com.google.android.gms.maps.internal.zzg.addMarker(Unknown Source)
at com.google.android.gms.maps.GoogleMap.addMarker(Unknown Source)
at com.appMapActivity.updatePoll(MapActivity.java:408)
at com.app.MapActivity.access$200(MapActivity.java:63)
at com.app.MapActivity$7.onRecordChanged(MapActivity.java:324)
at io.deepstream.Record.completeChange(Record.java:708)
at io.deepstream.Record.applyUpdate(Record.java:619)
at io.deepstream.Record.onMessage(Record.java:527)
at io.deepstream.RecordHandler.handle(RecordHandler.java:476)
at io.deepstream.Connection$4.run(Connection.java:230)
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:776)
We're seeing the below Fatal Exception occur in the Deepstream library consistently when have valid OPEN connection after login via WiFi and then WiFi connectivity drops on our device.
Using deepstream.io-client-java v2.0.7.
04-20 13:38:02.870 6357-20138/com.testapp.debug E/AndroidRuntime: FATAL EXCEPTION: Timer-0
Process: com.testapp.debug, PID: 6357
io.deepstream.DeepstreamException: CONNECTION_ERROR: null
at io.deepstream.DeepstreamClientAbstract.onError(DeepstreamClientAbstract.java:59)
at io.deepstream.Connection$1.run(Connection.java:194)
at java.util.Timer$TimerImpl.run(Timer.java:284)
Hello,
Currently i use undertow ws client to connect to various endpoints. Is it possible to reuse undertow for connection to deepstream(reusing some part of your lib for creating messages)?
Thanks
The records
, lists
, and listeners
HashMaps of RecordHandler
are accessed and modified in non-thread safe ways. There is an attempt in some places to make it thread safe with the following double checked pattern:
Record record = records.get( name );
if( record == null ) {
synchronized (this) {
record = records.get( name );
if (record == null) {
record = new Record(name, new HashMap(), connection, deepstreamConfig, client);
records.put(name, record);
...
But that allows HashMap.get
to happen simultaneously with HashMap.put
. The HashMap
javadocs are very clear on this:
If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally.
04-19 19:31:04.766: E/AndroidRuntime(9840): FATAL EXCEPTION: pool-2-thread-1
04-19 19:31:04.766: E/AndroidRuntime(9840): Process: com.Company.test, PID: 9840
04-19 19:31:04.766: E/AndroidRuntime(9840): java.lang.Error: FATAL EXCEPTION [pool-2-thread-1]
04-19 19:31:04.766: E/AndroidRuntime(9840): Unity version : 5.3.3f1
04-19 19:31:04.766: E/AndroidRuntime(9840): Device model : HTC HTC Desire 820s dual sim
04-19 19:31:04.766: E/AndroidRuntime(9840): Device fingerprint: xxx
04-19 19:31:04.766: E/AndroidRuntime(9840): Caused by: java.util.ConcurrentModificationException
04-19 19:31:04.766: E/AndroidRuntime(9840): at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
04-19 19:31:04.766: E/AndroidRuntime(9840): at io.deepstream.List.afterChange(List.java:360)
04-19 19:31:04.766: E/AndroidRuntime(9840): at io.deepstream.List.access$200(List.java:15)
04-19 19:31:04.766: E/AndroidRuntime(9840): at io.deepstream.List$RecordListeners.afterRecordUpdate(List.java:440)
04-19 19:31:04.766: E/AndroidRuntime(9840): at io.deepstream.Record.applyUpdate(Record.java:615)
04-19 19:31:04.766: E/AndroidRuntime(9840): at io.deepstream.Record.onMessage(Record.java:520)
04-19 19:31:04.766: E/AndroidRuntime(9840): at io.deepstream.RecordHandler.handle(RecordHandler.java:297)
04-19 19:31:04.766: E/AndroidRuntime(9840): at io.deepstream.Connection$4.run(Connection.java:218)
04-19 19:31:04.766: E/AndroidRuntime(9840): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
04-19 19:31:04.766: E/AndroidRuntime(9840): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
04-19 19:31:04.766: E/AndroidRuntime(9840): at java.lang.Thread.run(Thread.java:848)
Following on to issue #109, I figured I should look to see if these same thread safety issues were in other parts of this library. Sure enough, the first two classes I looked at, UtilEmitter
and UtilAckTimeoutRegistry
, both have these same kinds of thread safety issues. They do use Concurrent*
collections in a lot of places, but that alone does not make them thread safe. For example, this seems to be common:
Concurrent* foo;
obj = foo.get()
if (obj == null) {
foo.put(...);
}
This is not thread safe. One thread could preempt after the obj == null
and then a second thread could come through and do the put. The first thread would then resume and also do the put.
It appears this library needs to be gone through class by class to address thread safety. This is a serious issue that needs to be addressed ASAP if this library is to be used for projects that are highly concurrent. Trading apps come to mind (lots and lots of quotes coming in).
I get the clientData successfully on javascript. But now when I try to get it on Android, it's coming emptry. Shouldn't LoginResult.getData()
work?
Hello @yasserf
As i have been using and testing deepstream 2.0.0 rc1 release and its working fine with node client. But with java client when i use it in android it gets frequent disconnects on its own.
Also i have below logs which shows behaviour of dis-connectivity.
12-02 14:22:47.787 com.test : GCM2 connectStateChange : AUTHENTICATING , AUTHENTICATING
12-02 14:22:47.798 com.test : GCM2 connectStateChange : AWAITING_CONNECTION , AWAITING_CONNECTION
12-02 14:22:47.802 com.test : GCM2 connectStateChange : CHALLENGING , CHALLENGING
12-02 14:22:48.564 com.test : GCM2 connectStateChange : AWAITING_AUTHENTICATION , AWAITING_AUTHENTICATION
12-02 14:22:48.568 com.test : GCM2 connectStateChange : AUTHENTICATING , AUTHENTICATING
12-02 14:22:49.149 com.test : GCM2 connectStateChange : OPEN , OPEN
12-02 14:22:49.151 com.test : GCM2 login success :
12-02 14:23:02.602 com.test : GCM2 message : tryReconnect
12-02 14:23:02.645 com.test : GCM2 message : tryReconnect time : 1000 , 1
12-02 14:23:02.646 com.test : GCM2 connectStateChange : RECONNECTING , RECONNECTING
12-02 14:23:05.531 com.test : GCM2 connectStateChange : AUTHENTICATING , AUTHENTICATING
12-02 14:23:05.556 com.test : GCM2 connectStateChange : AWAITING_CONNECTION , AWAITING_CONNECTION
12-02 14:23:05.558 com.test : GCM2 connectStateChange : CHALLENGING , CHALLENGING
12-02 14:23:07.035 com.test : GCM2 connectStateChange : AWAITING_AUTHENTICATION , AWAITING_AUTHENTICATION
12-02 14:23:07.036 com.test : GCM2 connectStateChange : AUTHENTICATING , AUTHENTICATING
12-02 14:23:07.898 com.test : GCM2 connectStateChange : OPEN , OPEN
12-02 14:23:08.813 com.test : GCM2 exception : E�A�S�584002b971722b1820d4b5bf/commands , event : UNSOLICITED_MESSAGE
12-05 10:23:19.815 com.test : GCM2 message : tryReconnect
12-05 10:23:19.816 com.test : GCM2 message : tryReconnect time : 2000 , 2
12-05 10:23:19.816 com.test : GCM2 connectStateChange : RECONNECTING , RECONNECTING
12-05 10:23:23.591 com.test : GCM2 connectStateChange : AUTHENTICATING , AUTHENTICATING
12-05 10:23:23.603 com.test : GCM2 connectStateChange : AWAITING_CONNECTION , AWAITING_CONNECTION
12-05 10:23:23.605 com.test : GCM2 connectStateChange : CHALLENGING , CHALLENGING
12-05 10:23:24.929 com.test : GCM2 connectStateChange : AWAITING_AUTHENTICATION , AWAITING_AUTHENTICATION
12-05 10:23:24.930 com.test : GCM2 connectStateChange : AUTHENTICATING , AUTHENTICATING
12-05 10:23:25.596 com.test : GCM2 connectStateChange : OPEN , OPEN
12-05 10:23:26.320 com.test : GCM2 exception : E�A�S�584002b971722b1820d4b5bf/commands , event : UNSOLICITED_MESSAGE
12-05 10:23:53.710 com.test : GCM2 message : onClose : false , false , p.appice.io:6020/deepstream , p.appice.io:6020/deepstream
12-05 10:23:53.720 com.test : GCM2 message : tryReconnect
12-05 10:23:53.727 com.test : GCM2 message : onClose : false , false , p.appice.io:6020/deepstream , p.appice.io:6020/deepstream
12-05 10:23:53.729 com.test : GCM2 message : tryReconnect
12-05 10:23:53.730 com.test : GCM2 message : tryReconnect time : 4000 , 3
12-05 10:23:53.731 com.test : GCM2 connectStateChange : RECONNECTING , RECONNECTING
12-05 10:23:58.890 com.test : GCM2 connectStateChange : AUTHENTICATING , AUTHENTICATING
12-05 10:23:58.902 com.test : GCM2 connectStateChange : AWAITING_CONNECTION , AWAITING_CONNECTION
12-05 10:23:58.905 com.test : GCM2 connectStateChange : CHALLENGING , CHALLENGING
12-05 10:24:00.119 com.test : GCM2 connectStateChange : AWAITING_AUTHENTICATION , AWAITING_AUTHENTICATION
12-05 10:24:00.124 com.test : GCM2 connectStateChange : AUTHENTICATING , AUTHENTICATING
12-05 10:24:00.733 com.test : GCM2 connectStateChange : OPEN , OPEN
12-05 10:24:01.051 com.test : GCM2 exception : E�A�S�584002b971722b1820d4b5bf/commands , event : UNSOLICITED_MESSAGE
12-05 10:24:53.884 com.test : GCM2 message : onClose : false , false , p.appice.io:6020/deepstream , p.appice.io:6020/deepstream
12-05 10:24:53.886 com.test : GCM2 message : tryReconnect
Also their is just retry of max 5 times. So i have update code in Connection.java class under below function to just reconnects again to server if its not connected currently. And added a broadcast receiver to intercept internet re-connectivity to reconnect to server back again.
public void tryReconnect() {
this.client.onMessage("tryReconnect");
if (this.reconnectTimeout != null) {
return;
}
// int maxReconnectAttempts = options.getMaxReconnectAttempts();
// int reconnectIntervalIncrement = options.getReconnectIntervalIncrement();
// int maxReconnectInterval = options.getMaxReconnectInterval();
// if (this.reconnectionAttempt < maxReconnectAttempts) {
// this.setState(ConnectionState.RECONNECTING);
// this.reconnectTimeout = new Timer();
// this.reconnectTimeout.schedule(new TimerTask() {
// public void run() {
// tryOpen();
// }
// }, Math.min(
// reconnectIntervalIncrement * this.reconnectionAttempt,
// maxReconnectInterval
// ));
// this.reconnectionAttempt++;
//
// } else {
// this.clearReconnect();
// this.close();
// }
//
long tryTime = 0;
if (this.reconnectionAttempt == 0 || this.reconnectionAttempt >= 7) {
tryTime = 1000;
this.reconnectionAttempt = 1;
} else {
tryTime = ((int) Math.pow(2, this.reconnectionAttempt)) * 1000;
this.reconnectionAttempt++;
}
this.client.onMessage("tryReconnect time : " + tryTime + " , " + this.reconnectionAttempt);
this.setState(ConnectionState.RECONNECTING);
this.reconnectTimeout = new Timer();
this.reconnectTimeout.schedule(new TimerTask() {
public void run() {
tryOpen();
}
}, tryTime);
}
chinmay [6:55 PM]
FATAL EXCEPTION: Timer-0Process: com.vikilabs.hombot.app, PID: 6756
io.deepstream.DeepstreamException: CONNECTION_ERROR: MESSAGE_PARSE_ERROR: UNKNOWN_TYPE (U)
at io.deepstream.DeepstreamClientAbstract.onError(DeepstreamClientAbstract.java:56)
at io.deepstream.Connection$1.run(Connection.java:180)
at java.util.Timer$TimerImpl.run(Timer.java:284)
E/AbstractTracker: Can't create handler inside thread that has not called Looper.prepare()
Hi guys, I am using your lib in Android for testing deepstream.io server especially and stuck with some kind of issue. When I emitted event to more then one subscriber's client eventListener was going to stuck in infinitely loop.
Publisher emit:
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss a");
String time = format.format(new Date());
client.event.emit("event/a", time);
Subscriber 1 & Subscriber N:
client.event.subscribe("event/a", new EventListener() {
@Override
public void onEvent(String eventName, Object... args) {
String parameter = (String) args[0];
System.out.println(String.format("Event '%s' occurred with: %s ", eventName, parameter));
}
Ps; If I do the same with javascript everything works fine, but when I just add at least 2 subscribers from java client side - callback return infinitely data.
What I did wrong? Could you please provide me with right solution. Thanks
https://github.com/deepstreamIO/deepstream.io-client-specs
This requires a mock TCP server to be created that matches:
https://github.com/deepstreamIO/deepstream.io-client-specs/blob/master/step-definitions-server/tcp-server.js
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.