尽管返回Flowable.error(...)或引发异常,但未调用RxJava doOnNext,为什么?

时间:2018-06-25 20:18:04

标签: scala spring-boot rx-java2

情况 我正在使用带有Scala和RxJava2的Spring Boot来编写一组服务。服务修改了RDBMS中的数据,因此我创建了一个事务处理方法,该方法采用一个块,然后执行它,然后调用以下之一:doOnError,doOnNext,doOnTerminate。这是这样的样子:

object JdbcTransaction {
  def transaction[T](executeInTransaction: => Flowable[T])(implicit 
  con:Connection):Flowable[T] = {

  con.setAutoCommit(false)
  executeInTransaction
  .doOnNext(next => {
    try {
      con.commit()
    } catch {
      case e:Exception => print(e)
    } finally {
      con.setAutoCommit(true)
      con.close()
    }
  }).doOnError(error => {
  try {
    con.rollback()
  } catch {
    case e:Exception => print(e)
  } finally {
    con.setAutoCommit(true)
    con.close()
  }
  }).doOnTerminate(() => {
  try {
    if (!con.getAutoCommit) {
      con.setAutoCommit(true)
    }

    if (!con.isClosed) {
      con.close()
    }
  } catch {
    case e:Exception => print(e)
  }
  })
 }
}

令人惊讶的是,在某些情况下该块会执行,但不会调用doOnError,doOnNext或doOnTerminate。这是下面的代码中返回 return error(ConflictException())时的这种情况的示例:

def handle(create: CreateCredential):Flowable[CreatedCredential] = {
  // if not valid crete request
  if (!isValidCreateRequest(create)) {
    return error(BadRequestException())
  }

  implicit val con:Connection = dataSource.getConnection

  //noinspection ConvertExpressionToSAM
  credentialRepository.getCredentialByUsername(create.username)
  .flatMap[CreatedCredential](new Function[Optional[Credential], Publisher[CreatedCredential]]() {
override def apply(t: Optional[Credential]): Publisher[CreatedCredential] = {
  transaction[CreatedCredential] ({
    // The credential exists
    if (t.isPresent) {
      // inform the requester that there's a conflict.
      return error(ConflictException())
    }

    import com.shapestone.authentication.v2.PasswordString._
    val date = new Date()
    val hashedPassword = create.password.encrypt(authenticationServiceData.getPasswordHashIterations)
    val confirmationCode = createConfirmationCode(create.username)

    val credential:Credential = toCredential(create, hashedPassword, date)
    val confirmation:Confirmation = toConfirmation(credential.credentialId, confirmationCode, date)
    val credentialEvent:Event = toEvent(create, credential, date)
    val confirmationEvent:Event = toEvent(create, confirmation, date)

    val newCredentialEvent:Flowable[Event] = eventRepository.save(credentialEvent)
    val newConfirmationEvent:Flowable[Event] = eventRepository.save(confirmationEvent)
    val newCredential:Flowable[Credential] = credentialRepository.save(credential)
    val newConfirmation:Flowable[Confirmation] = confirmationRepository.save(confirmation)

    val publishedValue:Flowable[CreatedCredential] = zip[Event, Event, Credential, Confirmation, CreatedCredential](
      newCredentialEvent, newConfirmationEvent, newCredential, newConfirmation,
      (cre:Event, cne:Event, cr: Credential, cf: Confirmation) => {
        CreatedCredential(cr, cf)
    }).flatMap[CreatedCredential](new Function[CreatedCredential, Publisher[CreatedCredential]]() {
      override def apply(t: CreatedCredential): Publisher[CreatedCredential] = {
        eventPublisher.publish(t).flatMap[CreatedCredential](new Function[String, Publisher[CreatedCredential]]() {
          override def apply(s: String): Publisher[CreatedCredential] = {
            if (!Option(s).exists(_.trim.nonEmpty)) {
              error(BadRequestException("Failed to send notification."))
            } else {
              just[CreatedCredential](t)
            }
          }
        })
      }
    })

    publishedValue
  })(con)
}
})
}

(注意:我也尝试过使用Single。但是,我想我会先询问RxJava 2代码。)

0 个答案:

没有答案