Лучшая практика: ловли точек отказа в java.net.URL

Новый для JVM, работающий с Scala и Play 2.0

Я конвертирую устаревшее приложение в Play, которое требует обработки платежей через Authorize.net. Просматривая источник java.net.URL, существует множество потенциальных проблем с отказом. Учитывая интерфейс, который я написал ниже, где бы вы реализовали блоки try/catch? Мне нужно будет соответствующим образом адаптировать сигнатуры методов, возможно, возвращая Либо [Ошибка, Успех] для вызова кода клиента

import java.net.{URL, URLEncoder}
import java.io.{BufferedReader, DataOutputStream, InputStreamReader}
import javax.net.ssl._

trait Authnet {
  private val prodUrl = "https://secure.authorize.net/gateway/transact.dll"
  private val testUrl = "https://test.authorize.net/gateway/transact.dll"

  protected def authNetProcess(params: Map[String,String]) = {
    val(conn, urlParams) = connect(params)
    val request = new DataOutputStream( conn.getOutputStream )
    request.write(urlParams.getBytes)
    request.flush()
    request.close()
    val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
    val results = response.readLine().split("\\|")
    response.close()
    results.toList
  }  

  private def connect(params: Map[String,String]) = {
    val urlParams = (config ++ params) map { case(k,v) =>
        URLEncoder.encode(k, "UTF-8") + "=" + URLEncoder.encode(v, "UTF-8")
    } mkString("&")

    lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
    val conn = url.openConnection
    conn.setDoOutput(true)
    conn.setUseCaches(false)
    (conn, urlParams)
  }

  private val config = Map(
    'x_login        -> "...",
    'x_tran_key     -> "...",
    ...
  )
}

Ответ 1

ИЗМЕНИТЬ
Ну, если какая-либо часть процесса соединения/потока завершается с ошибкой, транзакция закрывается, поэтому глупо регистрировать ошибку при открытии соединения. Я просто обертываю всю транзакцию в блоке catching (operation) option и оставляю на ней; Я не слишком обеспокоен re: точная причина ошибки (независимо от того, что она регистрируется), поскольку она является временной, поэтому поймайте ее, попросите пользователя повторить попытку; если ошибка сохраняется, свяжитесь с нами...

ОРИГИНАЛ Хорошо, ну, учитывая вчерашние голоса и отсутствие комментариев, единственный вывод, который я могу сделать, -... никто здесь не знает, что они делают! хе-хе, шутит, -)

Несмотря на то, что я новичок в JVM, попробуйте/поймаем/окончательно раздувается быстро; через чудеса вывода типа Scala, я отвлек общую обработку ошибок на краткие реализации:
catching ( operation ) option
catching ( operation ) either

Если я не получаю обратную связь в противном случае, на данный момент я общаюсь, просто улавливая создание соединения (я считаю, в данном случае, наиболее вероятное условие ошибки). Здесь новая реализация:

protected def authNetProcess(params: Map[String,String]) = {
    connect() match {
      case Some(conn) =>
        val request = new DataOutputStream(conn.getOutputStream)
        request.write(getUrlParams(params).getBytes)
        request.flush()
        request.close()
        val response = new BufferedReader(new InputStreamReader(conn.getInputStream))
        val results = response.readLine().split("\\|")
        response.close()
        results.toList
      case None => List[String]()
    }
  }

  private def connect() = {
    lazy val url = if (isDev) new URL(testUrl) else new URL(prodUrl)
    catching ( url.openConnection ) option match {
      case Some(conn) =>
        conn.setDoOutput(true)
        conn.setUseCaches(false)
        //conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
        Some(conn)
      case None => None // connection failed
    }
  }

Я предполагаю, что более строгий подход состоял бы в том, чтобы извлечь все возможные условия ошибки в операции OperationWorked Option, а затем обернуть их все для понимания. Вероятно, это правильный/ответственный подход... но только так много часов в день, он будет снова просматривать этот

отзыв оценен!

Ответ 2

Придерживайтесь правила большого пальца:

Только поймайте исключение, если вы должны его обработать.

Нет четкого определения для "must handle", но это означает, что вы должны противостоять стремлению поймать исключение, потому что вы можете просто выбросить другое исключение.

"Обязательно обрабатывать" в основном определяется тем, как ваше приложение должно работать, или другими зависимостями.

Если приложение требует отображения ошибки пользователю вместо прерывания с исключением, то оно обязано.

В этом случае захват эксклюйта добавляет также значимую обработку.

Если API требует бросить другое исключение, тогда это необходимо, но определение API-интерфейсов, возможно, не звучит.

Я всегда задаю вопрос о добавленной стоимости замены исключения только с помощью другого исключения.

Применение этого к вашему примеру:

Будет ли добавлено какое-то значение для исключения исключения из connect() в authNetProcess()?

Нет! Невозможно обработать это исключение внутри connect(). Так что его нормально оставить это исключение для вызывающего пользователя authNetProcess. Там вы можете предоставить различную обработку, основанную на типе исключения.