Библиотека Android выдает исключение внутри блока try, который улавливает все Throwable

Мы написали библиотеку Kotlin для обработки сетевой логики. Сама библиотека содержит AsyncTask, который использует возможности HttpURLConnection в java.net.*.

private inner class ClickstreamTask(
                                    headers: HashMap<String, String>,
                                    params: Request,
                                    success: (() -> Unit)? = null,
                                    failure: ((statusCode: Int?, json: 
HashMap<String, String>?) -> Unit)? = null) : AsyncTask<Void, Unit, Unit>() {

    private var headers: HashMap<String, String> = headers
    private var paramaters: Request = params
    private var success: (() -> Unit)? = success
    private var failure: ((statusCode: Int?, json: HashMap<String, String>?) -> Unit)? = failure

    override fun doInBackground(vararg params: Void){

        val url = try {
            URL(getURLString() + path)
        } catch (e: Exception) {
            failure?.invoke(null, hashMapOf("error" to "Invalid URL."))
            return Unit
        }

        var request = try{
            url.openConnection() as HttpURLConnection
        } catch (e: Exception){
            failure?.invoke(null, hashMapOf("error" to "Unable to establish connection"))
            return Unit
        }

        request.doInput = false
        request.doOutput = true
        val mapper = jacksonObjectMapper()

        request.requestMethod = "POST"
        val httpBody = try {
            mapper.writeValueAsBytes(paramaters)
        } catch (e: Exception) {
            failure?.invoke(null, hashMapOf("error" to "Invalid params."))
            return Unit
        }

        for ((key, value) in headers) {
            request.setRequestProperty(key, value)
        }

        try{
            request.outputStream.write(httpBody)
        }catch (e: Throwable){
            request.outputStream.close()
            failure?.invoke(null, hashMapOf("error" to "Issue writing to URL"))
            return Unit
        }
        request.outputStream.close()


        if (request.responseCode != 200){
            failure?.invoke(request.responseCode, hashMapOf("Failed request" to request.responseMessage))
            return Unit
        }

        success?.invoke()
        return Unit
    }
}

Когда мы используем приложение Android, которое использует библиотеку в режиме полета, приложение вылетает из-за неперехваченного исключения UnknownHostException:

Caused by: java.net.UnknownHostException: Unable to resolve host "ste03lbclkapp00.iteclientsys.local": No address associated with hostname at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:141) at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90) at java.net.InetAddress.getAllByName(InetAddress.java:787) at com.android.okhttp.Dns$1.lookup(Dns.java:39) at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:175) at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:141) at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:83) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:174) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:258) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(Unknown Source:0) at com.tdameritrade.amerivest.clickstreamshared.Network.NetworkManager$ClickstreamTask.doInBackground(NetworkManager.kt:87) at com.tdameritrade.amerivest.clickstreamshared.Network.NetworkManager$ClickstreamTask.doInBackground(NetworkManager.kt:43) at android.os.AsyncTask$2.call(AsyncTask.java:333) at java.util.concurrent.FutureTask.run(FutureTask.java:266) ... 4 more Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname) at libcore.io.Linux.android_getaddrinfo(Native Method) at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:59) at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:122) ... 24 more

Строка, вызывающая исключение, - request.outputStream.write(httpBody). Однако мы оборачиваем эту строку в try / catch, который обрабатывает Throwable.

Как doOnBackground() строка 87 выдает исключение, когда оно заключено в catch?

Хотя ловить Throwable - очень плохая идея.

Zoe 23.04.2018 17:28

Это был Exception, и я поменял его на Throwable, просто чтобы проверить

It's Your App LLC 23.04.2018 17:35

Затем в своем блоке исключения, который можно выбросить, вы пытаетесь получить доступ к request.outputstream.close, который, как я предполагаю, затем генерирует исключение, которое находится вне улова.

Andy 23.04.2018 17:42
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
729
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Этот код:

    try{
        request.outputStream.write(httpBody)
    }catch (e: Throwable){
        request.outputStream.close()
        failure?.invoke(null, hashMapOf("error" to "Issue writing to URL"))
        return Unit
    }

попытается выполнить операцию в блоке catch, который также может вызвать исключение:

        request.outputStream.close()

Это не обнаружено, но также кажется нецелесообразным, учитывая, что вы обрабатываете ошибку некоторый при доступе к выходному потоку.

Трассировка исключения указывает на другие причины, и я предполагаю, что если копать дальше, вы исправите это.

Я удалил ручей рядом с уловом и никаких изменений в поведении

It's Your App LLC 23.04.2018 18:04

Опубликуйте полную трассировку стека ... и еще кое-что - полезные вещи обычно находятся внизу цепочки вызванных. Окружите весь код doinbackground исключениями try / catch и log-исключениями.

Andy 23.04.2018 18:08

К., когда вернусь с обеда, попробую. Спасибо

It's Your App LLC 23.04.2018 18:12

Другие вопросы по теме