tigase / halcyon

Kotlin Multiplatform XMPP client library
GNU Affero General Public License v3.0
55 stars 9 forks source link

vCard error response is not passed back to application as an event #9

Open arthef opened 3 years ago

arthef commented 3 years ago

I am attempting to retrieve contact's vcard as described in the issue: https://github.com/tigase/halcyon/issues/6#issue-715152700

For some vcard request I am getting responses like this: Request:

<iq to="to@jid.com" id="JAiFXty3u8W0209Ro0EEDxvx" type="get">
  <vcard xmlns="urn:ietf:params:xml:ns:vcard-4.0"/>
</iq>

Response:

<iq to="my@jid.com" xmlns="jabber:client" from="to@jid.com" type="error" id="JAiFXty3u8W0209Ro0EEDxvx">
  <error type="cancel">
    <service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
  </error>
</iq>

In the library log I can see that the response was not correctly handler:

[EDT] 0:0:10,791 - Mon Oct 05 15:52:46 PDT 2020 [FINE] tigase.halcyon.core.connector.WebSocketConnector: Received: <iq to="my@jid.com" xmlns="jabber:client" from="to@jid.com" type="error" id="JAiFXty3u8W0209Ro0EEDxvx"><error type="cancel"><service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>
[EDT] 0:0:10,791 - Mon Oct 05 15:52:46 PDT 2020 [FINEST] tigase.halcyon.core.connector.WebSocketConnector: Received element <iq xmlns="jabber:client" from="to@jid.com" to="my@jid.com" id="JAiFXty3u8W0209Ro0EEDxvx" type="error"><error type="cancel"><service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq>
[EDT] 0:0:10,791 - Mon Oct 05 15:52:46 PDT 2020 [FINEST] tigase.halcyon.core.eventbus.EventBus: Firing event ReceivedXMLElementEvent(element=XMLElement[name='iq' hash='929711258']) with 3 handlers
[EDT] 0:0:10,791 - Mon Oct 05 15:52:46 PDT 2020 [WARNING] tigase.halcyon.core.requests.RequestsManager: Error on processing response
tigase.halcyon.core.xmpp.XMPPException

There is an event fired ReceivedXMLElementEvent but it is not really useful in the application space. It would be bette to receive an error event in response to the vcard IQRequest.

arthef commented 3 years ago

Also, on the WARNING level the information printed out in the log is very brief providing no information what is this related to or what is this error about:

[EDT] 0:0:10,791 - Mon Oct 05 15:52:46 PDT 2020 [WARNING] tigase.halcyon.core.requests.RequestsManager: Error on processing response
tigase.halcyon.core.xmpp.XMPPException

It would be useful here to have some more context with the error message.

bmalkow commented 3 years ago

I added few tests, and for me it works correctly. Every time error response is correctly handled. Also exception during mapping response is correctly converted to Response Failure. I improved logging a bit to show full stack trace if is provided.

arthef commented 3 years ago

Ok, in such a case how can I get the exact error from the response?

My code is like this:

vcardModule.retrieveVCard(jid).response { result ->
    result.onSuccess { vcard ->
        println("Received public vcard for $jid")
        handleVCardEvent(VCardUpdatedEvent(jid, vcard))
    }
    result.onFailure {
        println("Problem retrieving vCard for ${jid}, ${result.exceptionOrNull()}")
    }
}.send()

And all I get in the last println is this:

Problem retrieving vCard for name@domain.com, tigase.halcyon.core.requests.XMPPError

And the problem here is that this XMPPError does not say much. Whether the server no longer exists or something else. It would be useful to have more detailed information of why there was failure.

bmalkow commented 3 years ago

Obtaining error details is common in Halcyon, because kotlin.Result class is used to return request result. XMPPError is class containing all details of error response returned by server. In other cases, different exception will be provided:

vcardModule.retrieveVCard(jid).response { result ->
    result.onSuccess { vcard ->
        println("Received public vcard for $jid")
        handleVCardEvent(VCardUpdatedEvent(jid, vcard))
    }
    result.onFailure {
        when (it) {
            is tigase.halcyon.core.requests.XMPPError -> println("XMPP Error response: condition=${it.error}; text=${it.description}; responseStanza=${it.response}")
            else -> {
                println("Other error: $it")
                it.printStackTrace()
            }
        }
    }
}.send()