我在Scala/Play中使用Cassandra作为数据库的Web应用程序。我在测试潜在的错误时遇到以下问题。了解play/scala错误处理
下面是我的项目
Application.scala的组件 - >基本控制器
Model.scala - >承装 业务逻辑
CassandraClient.scala - >逻辑连接到 cassandra并运行查询cassandra
CassandraClient.scala看起来像下面
object CassandraClient {
private val cluster = Cluster.builder()
.withLoadBalancingPolicy(
new WhiteListPolicy(new RoundRobinPolicy(), nodes))
.withSocketOptions(socketOptions)
.addContactPointsWithPorts(nodes)
.withCredentials(CASSANDRA_USERNAME, CASSANDRA_PWD).build()
}
private val session = cluster.connect()
def getValueFromCassandraTable(token:String) = {
var query = QueryBuilder.select.all()...
seesion.execute(query)
}
卡桑德拉连接时,我打电话getValueFromCassandraTable在第一时间首先建立。由于CassandraClient是一个对象,连接到Cassandra的逻辑只被调用一次。
Model.Scala有一些代码可以处理将来由session.execute返回的代码。
例如:请看Model.scala下面的示例代码。
def getTitles(titles: String)(implicit ctxt: ExecutionContext): Future[List[<Sometype>]] = {
try{
CassandraClient.getValueFromCassandraTable(token).toScalaFuture.map { rows =>
rows.map(row => row("value").toList
}.recover { case e: Exception =>List()}
}
} catch{case e:Exception =>
Logger.info("THIS DOES NOT EXECUTE??")
Future{List()}}
}
现在当上面的示例代码第一次执行时,会执行session.execute()。然后执行getValueFromCassandraTable。 所以我想执行的流程是 代码段以上Models.scala - > session.execute() - > getValueFromCassandraTable()
所以,如果session.execute失败,我应该能够捕捉到它的尝试捕获异常块。但令我惊讶的是,当session.execute失败时catch块没有执行。相反,玩框架会抛出异常。有人可以解释这种行为。
异常堆栈
Caused by: java.lang.RuntimeException: java.lang.ExceptionInInitializerError
at play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:498) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) ~[play_2.10-2.4.2.jar:2.4.2]
at play.utils.Threads$.withContextClassLoader(Threads.scala:21) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:104) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:103) ~[play_2.10-2.4.2.jar:2.4.2]
at scala.Option.map(Option.scala:145) ~[scala-library-2.10.5.jar:na]
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:103) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:96) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.libs.iteratee.DoneIteratee$$anonfun$mapM$2.apply(Iteratee.scala:741) ~[play-iteratees_2.10-2.4.2.jar:2.4.2]
Caused by: java.lang.ExceptionInInitializerError: null
at models.Model$.getTitles(Model.scala:121) ~[classes/:na]
at models.Model$.getMatchingTitles(Model.scala:48) ~[classes/:na]
at models.Model$.getMatchingTitles(Model.scala:56) ~[classes/:na]
at controllers.Application$$anonfun$searchTitle$1.apply(Application.scala:15) ~[classes/:na]
at controllers.Application$$anonfun$searchTitle$1.apply(Application.scala:15) ~[classes/:na]
at play.api.mvc.ActionBuilder$$anonfun$async$1.apply(Action.scala:456) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.mvc.ActionBuilder$$anonfun$async$1.apply(Action.scala:456) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.mvc.Action$.invokeBlock(Action.scala:533) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.mvc.Action$.invokeBlock(Action.scala:530) ~[play_2.10-2.4.2.jar:2.4.2]
at play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:493) ~[play_2.10-2.4.2.jar:2.4.2]
Caused by: com.datastax.driver.core.exceptions.AuthenticationException: Authentication error on host /10.65.5.44:9042: Username and/or password are incorrect
at com.datastax.driver.core.Connection$8.apply(Connection.java:368) ~[cassandra-driver-core-2.1.6.jar:na]
at com.datastax.driver.core.Connection$8.apply(Connection.java:338) ~[cassandra-driver-core-2.1.6.jar:na]
at com.google.common.util.concurrent.Futures$ChainingListenableFuture.run(Futures.java:861) ~[guava-16.0.1.jar:na]
at com.google.common.util.concurrent.MoreExecutors$SameThreadExecutorService.execute(MoreExecutors.java:297) ~[guava-16.0.1.jar:na]
at com.google.common.util.concurrent.ExecutionList.executeListener(ExecutionList.java:156) ~[guava-16.0.1.jar:na]
at com.google.common.util.concurrent.ExecutionList.execute(ExecutionList.java:145) ~[guava-16.0.1.jar:na]
at com.google.common.util.concurrent.AbstractFuture.set(AbstractFuture.java:185) ~[guava-16.0.1.jar:na]
at com.datastax.driver.core.Connection$Future.onSet(Connection.java:1170) ~[cassandra-driver-core-2.1.6.jar:na]
at com.datastax.driver.core.Connection$Dispatcher.channelRead0(Connection.java:1000) ~[cassandra-driver-core-2.1.6.jar:na]
at com.datastax.driver.core.Connection$Dispatcher.channelRead0(Connection.java:922) ~[cassandra-driver-core-2.1.6.jar:na]
林#121 Modle.scala是调用CassandrClient.getValueFromCassandraTable之一。 我通过传递连接到cassandra的错误密码来模仿异常,因此获得AuthroizationException。我希望这个异常能够在Try catch中被捕获。但它没有被捕获。
(注意,这是没有任何关系与未来,当发生异常session.executAysnc甚至没有叫。所以期货尚未开始发挥作用。)
- 编辑 -
看起来像播放吞咽异常并抛出一个错误对象。不知道为什么会这样。
这个问题似乎纯粹是关于对Scala期货的理解。 –
好吧,我不确定。 session.execute()引发异常,这不是异步调用。我不明白的是为什么我的try catch块没有捕获session.execute抛出的异常。 – konquestor
如果使用'recover {case _ => Future(List())}',它会被抓到吗? –