Open puryagh opened 4 years ago
Hello, could you please provide a bit more information: 1) Version of centrifuge-java 2) Version of server 3) Does stale disconnect reproduces reliably? 4) Do you have any proxy between client and server? Or you just run server locally?
hi 1 - java client library version is 0.0.5 2 - server version is 2.7.2 3 - after 3 days and testing for near 2000 time, my android app couldn't connect to centrifugo server even 1 time, but ios and web version worked fine 4 - i tested it with both instance, behind Nginx and locally instance and just android not worked
OOOps!!! i find reason of problem my android project is based on KOTLIN when i create a new android JAVA project, library worked fine but i don't know why when use library in kotlin project, it couldn't work
i trace library code
in Client.java at line 617 progress of code stoped and next block not run
Protocol.ConnectRequest req = Protocol.ConnectRequest.newBuilder() .setToken(this.token) .build();
Hmm, that's strange. Thanks for finding this. Since I never used Kotlin personally will appreciate any help in investigating why this happens.
Just tried to create basic Kotlin project and it works for me.
I started with Basic Activity template, selected Kotlin language. Code inside MainActivity
:
package com.example.myfirstapp
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.snackbar.Snackbar
import io.github.centrifugal.centrifuge.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
val listener: EventListener = object : EventListener() {
@SuppressLint("SetTextI18n")
override fun onConnect(client: Client?, event: ConnectEvent) {
println("connect")
}
@SuppressLint("SetTextI18n")
override fun onDisconnect(client: Client?, event: DisconnectEvent) {
println("disconnect")
}
}
val client = Client(
"ws://192.168.1.34:8000/connection/websocket?format=protobuf",
Options(),
listener
)
client.setToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0c3VpdGVfand0In0.hPmHsVqvtY88PvK4EmJlcdwNuKFuy3BGaF7dMaKdPlw")
client.connect()
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
return when (item.itemId) {
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
}
Set internet permission inside AndroidManifest.xml
:
<uses-permission android:name="android.permission.INTERNET" />
After running application I see successful connect in Centrifugo logs:
2020-11-10 02:12:03 [DBG] client connection established client=5967b2de-a6b4-41c9-aa79-ee085cb77b53 transport=websocket
2020-11-10 02:12:04 [DBG] client authenticated client=5967b2de-a6b4-41c9-aa79-ee085cb77b53 user=testsuite_jwt
yes, it worked in empty android project but in my case
I have GRPC backend service and in prohect gradle already implemented
com.google.protobuf:protobuf-java
now that add centrifuge-java dependency to gradle, protobuf-java must be excluded on it
implementation('io.github.centrifugal:centrifuge-java:0.0.5') { exclude group: 'com.google.protobuf', module: 'protobuf-java' }
if i exclude protobuf-java centrifuge not work 😩 and if don't exclude it duplicated package error occurred
Maybe GRPC depends on protobuf-javalite package?
Could you try an opposite and exclude javalite package from GRPC instead? I found similar problem in Centrifugo Telegram chat history:
Solution as text:
Fixed this by adding next lines:
implementation ("com.google.firebase:firebase-perf:19.0.5", {
exclude group: 'com.google.protobuf', module: 'protobuf-javalite'
exclude group: 'com.google.protobuf', module: 'protobuf-lite'
})
So the same problem happened with Firebase. I suppose this should work for GRPC too.
By the way there is a pr that migrates centrifuge-java to protobuf-javalite
– https://github.com/centrifugal/centrifuge-java/pull/8
hi sorry for too long to response thank you for your help
i try this solution before, but it does not worked
finally i use centrifuge-mobile library , its worked perfect
Looks like I need to test it out myself at some point in the future then. I believe that finding a root cause of this issue is not too hard having a reproducing example (especially since similar stale case already solved by excluding javalite). Personally, I'd go with a native approach instead of centrifuge-mobile especially since you already using centrifuge-swift.
If you can provide a minimal reproducing example this could help a lot
Greetings I encountered the same issue as puryagh & solved it. It has nothing to do with protobuf.
His code was failing because he is missing dependencies. The solution is for him to either include lines 29 & 30 from here https://github.com/centrifugal/centrifuge-java/blob/master/centrifuge/build.gradle#L30 into his project or for you to change implementation
to api
for those lines, so they are also included for any user of your library.
I also suggest updating this file https://github.com/centrifugal/centrifuge-java/blob/master/README.md
When someone new looks at the file it is not clear AT ALL that sections Generate proto
& after are in fact documentation for yourself & not for the user of the library. Protobuf-gen of classes is totally irrelevant to the user of the library & is in fact leading him in the wrong direction in solving this issue. There is no need to regenerate classes with protobuf if the protocol has not changed. Hint: separate instructions for yourself
into a different file.
i trace library code
in Client.java at line 617 progress of code stoped and next block not run
Protocol.ConnectRequest req = Protocol.ConnectRequest.newBuilder() .setToken(this.token) .build();
This is happening because he was getting exceptions like this due to the missing libraries I mentioned in my previous comment.
Method threw 'java.lang.NoSuchMethodError' exception. Cannot evaluate io.github.centrifugal.centrifuge.internal.protocol.Protocol$ConnectRequest$Builder.toString()
It might be a good idea to introduce some try-catch wrapping & logging in the Runnable's you are passing to your executor, like here - https://github.com/centrifugal/centrifuge-java/blob/master/centrifuge/src/main/java/io/github/centrifugal/centrifuge/Client.java#L185
Library erroring out & swallowing & disappearing all of the crashes is super aggravating 🤬... Yes I had an enjoyable time getting to these solutions /s
@sqrt1764 hello, thanks, do you have time maybe to send pr with fixes you suggest? Since I am not a Java dev at all I could write absolutely non-idiomatic code here.
When someone new looks at the file it is not clear AT ALL that sections Generate proto & after are in fact documentation for yourself & not for the user of the library. Protobuf-gen of classes is totally irrelevant to the user of the library & is in fact leading him in the wrong direction in solving this issue. There is no need to regenerate classes with protobuf if the protocol has not changed.
Made this more clear in 6871e7b1be85566962da850dc2962f50ba779096
I've made a new release 0.0.6 where library migrated to protobuf-javalite and exception in Connect now printed - this may help to detect a dependency issue much faster. Though I still not really understand the root cause here.
Guys, can someone who experienced this issue try version 0.0.7?
I have faced with this issue on Android with 0.0.8 lib version. We use JWT token and I encountered error with parsing the token and some fields there were not found. I found that my issue was that Android shrinker removed some generated protobuf classes in Release builds. It seems that the proguard rule should fix it:
-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
<fields>;
}
@agent10 thanks, could you elaborate more where this rule should be placed and why this happens?
I'm getting event:
onDisconnect, = stale, reconnect = false
And in the log I see(it's partly obfuscated):
System.err: java.lang.RuntimeException: Field token_ for com.apppackagename.d04 not found. Known fields are [public com.apppackagename.iw3 com.apppackagename.d04.e, public static final com.apppackagename.d04 com.apppackagename.d04.f, public static volatile ccom.apppackagename.rw3 com.apppackagename.d04.g]
I'm not sure where it comes from.
This rule should be added to the proguard-rules.pro(or any other appropriate names) file inside Android project. But I'm not sure that is possible to add somewhere inside this library.
More information about Android shrinker can be found here
Basically it happens because shrinker removes unused classes from the code. But as I know protobuf generated classes are used with reflection and that's why shrinker will remove them as well without explicit rule to keep them in the code. Probably, it also might be the problem that shrinker also obfuscates(and changes the names) fields and these fields just can't be found(with reflection)
Original issue: https://github.com/protocolbuffers/protobuf/issues/6463
So it looks like Protobuf Javalite uses reflection in releases after 3.11.4
and the official answer there: add proguard rule into a project.
@agent10 have you already had a chance to try a rule you posted above - does it fix a problem?
Right, it fixes the problem for me.
Unfortunate thing, just documented this in README - I suppose there is nothing else we can do here.
In my App ,this problem happened too,can you help me ,thank you . when i use your demo ,the error message is connection error
This is what your project's module's dependencies should look like when using this library.
implementation "io.github.centrifugal:centrifuge-java:0.0.5"
// `centrifuge-java` dependency is silently crashing when the following is missing
implementation "net.sourceforge.streamsupport:streamsupport-cfuture:1.7.1"
implementation "com.google.protobuf:protobuf-java:3.15.8"
Centrifuge library could solve this in an alternate way by modifying the dependencies of their own.
They are also including these same extra dependencies; if they were to include them using api
instead of implementation
, you would not have to do it manually in your project.
Thank you for answer my question. I use dependencies same with you,but build error like this :
A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable Duplicate class com.google.protobuf.AbstractMessageLite found in modules jetified-protobuf-java-3.15.8 (com.google.protobuf:protobuf-java:3.15.8) and jetified-protobuf-javalite-3.11.4 (com.google.protobuf:protobuf-javalite:3.11.4) Duplicate class com.google.protobuf.AbstractMessageLite$Builder found in modules jetified-protobuf-java-3.15.8 (com.google.protobuf:protobuf-java:3.15.8) and jetified-protobuf-javalite-3.11.4 (com.google.protobuf:protobuf-javalite:3.11.4) Duplicate class com.google.protobuf.AbstractMessageLite$Builder$LimitedInputStream found in modules jetified-protobuf-java-3.15.8 (com.google.protobuf:protobuf-java:3.15.8) and jetified-protobuf-javalite-3.11.4 (com.google.protobuf:protobuf-javalite:3.11.4) Duplicate class com.google.protobuf.AbstractMessageLite$InternalOneOfEnum found in modules jetified-protobuf-java-3.15.8 (com.google.protobuf:protobuf-java:3.15.8) and jetified-protobuf-javalite-3.11.4 (com.google.protobuf:protobuf-javalite:3.11.4) Duplicate class com.google.protobuf.AbstractParser found in modules jetified-protobuf-java-3.15.8 (com.google.protobuf:protobuf-java:3.15.8) and jetified-protobuf-javalite-3.11.4 (com.google.protobuf:protobuf-javalite:3.11.4) Duplicate class com.google.protobuf.AbstractProtobufList found in modules jetified-protobuf-java-3.15.8 (com.google.protobuf:protobuf-java:3.15.8) and jetified-protobuf-javalite-3.11.4 (com.google.protobuf:protobuf-javalite:3.11.4) Duplicate class com.google.protobuf.AllocatedBuffer found in modules jetified-protobuf-java-3.15.8 (com.google.protobuf:protobuf-java:3.15.8) and jetified-protobuf-javalite-3.11.4 (com.google.protobuf:protobuf-javalite:3.11.4) Duplicate class com.google.protobuf.AllocatedBuffer$1 found in modules jetified-protobuf-java-3.15.8 (com.google.protobuf:protobuf-java:3.15.8) and jetified-protobuf-javalite-3.11.4 (com.google.protobuf:protobuf-javalite:3.11.4) Duplicate class com.google.protobuf.AllocatedBuffer$2 found in modules jetified-protobuf-java-3.15.8 (com.google.protobuf:protobuf-java:3.15.8) and jetified-protobuf-javalite-3.11.4 (com.google.protobuf:protobuf-javalite:3.11.4) ......
and then ,i change dependencies like this:
api("io.github.centrifugal:centrifuge-java:0.1.0") { exclude group: "com.google.protobuf", module: "protobuf-java" exclude group: "net.sourceforge.streamsupport", module: "streamsupport-cfuture" }
// centrifuge-java
dependency is silently crashing when the following is missing
implementation "net.sourceforge.streamsupport:streamsupport-cfuture:1.7.1"
implementation "com.google.protobuf:protobuf-java:3.15.8"
but ,still build with same error
last,i only dependencies api "io.github.centrifugal:centrifuge-java:0.1.0" this method can build success,but connect error: {"reason":"bad request","reconnect":false}
Sorry ,I find the question .It's my error , I have not add "?format=protobuf" to my connect url . Thank you very much.
Had the same issue with Stale connection on Android.
I was already using protobuf Gradle plugin in my app. There is definitely some problem with how different versions and flavours of protobuf are working with each other. Particularly in my case, there was NoSuchMethodError somewhere in the Protocol
class of centrifuge java client (generated with protobuf).
I updated my protobuf to latest version and also switched from protoc-gen-javalite
plugin, to a 'lite' built-in. (javalite is now built into protoc
). It seems to be working now.
Here is some info about the built-in: https://stackoverflow.com/a/60856398
Here is the new configuration that works:
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.20.1"
}
generateProtoTasks {
all().configureEach {
builtins {
register("java") {
option("lite")
}
}
}
}
}
dependencies {
implementation("com.google.protobuf:protobuf-javalite:3.20.1")
}
Here is what I had before the change:
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.12.3"
}
plugins {
id("javalite") {
artifact = "com.google.protobuf:protoc-gen-javalite:3.0.0"
}
}
generateProtoTasks {
all().forEach { task ->
task.plugins {
id("javalite")
}
}
}
}
dependencies {
implementation("com.google.protobuf:protobuf-lite:3.0.1")
}
I don't think anything should be changed in centrifuge-java. Just the projects that use protobuf might have some trouble integrating and will have to update their protobuf setup.
hi dear
i use your java library on android with kotlin implemention but when i try to connect with JWT token, returns disconnected stale, reconnect false error but on iOS(swift) and Web version every thing is ok
this is my code
`
val cfListener = object : EventListener() { override fun onConnect(client: Client?, event: ConnectEvent?) { Log.d("CENTRIFUGE", "connected") }