2014-01-09 7 views
3

내 Scala/Scalatra 프로젝트에서 Salat을 사용하여 MongoDB 개체를 직렬화합니다. 이것은 내가 만든 데이터베이스에서 복잡한 MongoDB 객체를 가져 와서 다른 해시와 배열을 포함하는 일반적인 질문입니다. 필자는 필드별로 주석을 달고 사례 클래스에서 무엇이 고장 났는지 알아낼 수는 있지만이를 디버깅하는 것은 터무니없는 방법 일뿐입니다. 나는 시작 필드에 의해 코멘트 밖으로 필드에 의해이 디버깅을 시작Salat : 예외를 일으키는 case 클래스의 필드를 알기 위해 스택 추적을 디버깅하는 방법

case class MLBPlayByPlay(datetime: DateTime, gamedate: DateTime, game_id: Int, home_team_id: Int, away_team_id: Int, 
          home_team_score: Int, away_team_score: Int, sport: String, season_year: Int, season_type: String, location: String, status: String, 
          home_team_abbr: String, away_team_abbr: String, hp_umpire: String, fb_umpire: String, sb_umpire: String, tb_umpire: String, 
          play_by_play_seqs: Seq[MLBPlayByPlaySeq], created_at: Option[Date] = None, updated_at: Date) 

case class MLBPlayByPlaySeq(batter: Option[MLBBatter] = None, next_batter: Option[MLBBatter] = None, pitchers: Option[Seq[MLBPitcher]] = None, pitches: Option[Seq[MLBPitches]] = None, fielders: Option[Seq[MLBFielder]] = None, 
          seq_id: Int, inning: Option[Int] = None, outs: Option[Int] = None, no_play: Option[Int] = None, home_team_score: Int, away_team_score: Int) 

case class MLBBatter(batter_id: Int, team_id: Int, first_name: String, last_name: String, action: Option[String] = None, out: Option[Int] = None, adv: Option[Int] = None, 
        to_base: Option[Int] = None, scored: Option[Int] = None, bats: Option[String] = None, appear: Option[Int] = None, pos: Option[String] = None, 
        pitcher_id: Option[Int] = None, pthrows: Option[String] = None, error_ids: Option[String] = None, location: Option[String] = None, traj: Option[String] = None, 
        field: Option[String] = None, coords: Option[String] = None, ab: Option[Int] = None, gndout: Option[Int] = None) 

case class MLBPitcher(pitcher_id: Int, team_id: Int, first_name: String, last_name: String, inning: Int, outs: Int, throws: String, bbats: String, ab: Int, bf: Int) 
case class MLBFielder(fielder_id: Int, team_id: Int, first_name: String, last_name: String, pos: String, assist: Int, put_out: Int) 
case class MLBPitches(count: Int, total_pitches: Int, balls: Int, strikes: Int, value: String, batter_id: Int, pitcher_id: Int, runner_1_id: Int, runner_2_id: Int, 
         runner_3_id: Int, final_pitch: String) 

: 다음과 같은

DefaultArg.safeValue$lzycompute(Grater.scala:406) 
com.novus.salat.DefaultArg.safeValue(Grater.scala:402) 
com.novus.salat.ConcreteGrater.safeDefault(Grater.scala:363) 
com.novus.salat.ConcreteGrater$$anonfun$5$$anonfun$apply$3.apply(Grater.scala:262) 
com.novus.salat.ConcreteGrater$$anonfun$5$$anonfun$apply$3.apply(Grater.scala:262) 
scala.Option.orElse(Option.scala:257) 
com.novus.salat.ConcreteGrater$$anonfun$5.apply(Grater.scala:262) 
com.novus.salat.ConcreteGrater$$anonfun$5.apply(Grater.scala:247) 
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) 
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) 
scala.collection.immutable.List.foreach(List.scala:318) 
scala.collection.TraversableLike$class.map(TraversableLike.scala:244) 
scala.collection.AbstractTraversable.map(Traversable.scala:105) 
com.novus.salat.ConcreteGrater.asObject(Grater.scala:247) 
com.novus.salat.transformers.in.DBObjectToInContext$class.transform0(Injectors.scala:333) 
com.novus.salat.transformers.in.DBObjectToInContext$class.transform(Injectors.scala:339) 
com.novus.salat.transformers.in.package$$anon$1.transform(Injectors.scala:66) 
com.novus.salat.transformers.Transformer$$anonfun$1.apply(Transformer.scala:85) 
com.novus.salat.transformers.Transformer$$anonfun$1.apply(Transformer.scala:85) 
scala.Option.flatMap(Option.scala:170) 
com.novus.salat.transformers.Transformer.transform_$bang(Transformer.scala:85) 
com.novus.salat.Field.in_$bang(Field.scala:64) 
com.novus.salat.ConcreteGrater$$anonfun$5$$anonfun$apply$2.apply(Grater.scala:262) 
com.novus.salat.ConcreteGrater$$anonfun$5$$anonfun$apply$2.apply(Grater.scala:262) 
scala.Option.flatMap(Option.scala:170) 
com.novus.salat.ConcreteGrater$$anonfun$5.apply(Grater.scala:262) 
com.novus.salat.ConcreteGrater$$anonfun$5.apply(Grater.scala:247) 
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) 
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) 
scala.collection.immutable.List.foreach(List.scala:318) 
scala.collection.TraversableLike$class.map(TraversableLike.scala:244) 
scala.collection.AbstractTraversable.map(Traversable.scala:105) 
com.novus.salat.ConcreteGrater.asObject(Grater.scala:247) 
com.novus.salat.transformers.in.DBObjectToInContext$class.transform0(Injectors.scala:333) 
com.novus.salat.transformers.in.DBObjectToInContext$class.transform(Injectors.scala:338) 
com.novus.salat.transformers.in.package$$anon$2.com$novus$salat$transformers$in$TraversableInjector$$super$transform(Injectors.scala:123) 
com.novus.salat.transformers.in.TraversableInjector$class.transformElement(Injectors.scala:370) 
com.novus.salat.transformers.in.package$$anon$2.transformElement(Injectors.scala:123) 
com.novus.salat.transformers.in.TraversableInjector$$anonfun$after$1.apply(Injectors.scala:385) 
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) 
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) 
scala.collection.immutable.List.foreach(List.scala:318) 
scala.collection.TraversableLike$class.map(TraversableLike.scala:244) 
scala.collection.AbstractTraversable.map(Traversable.scala:105) 
com.novus.salat.transformers.in.TraversableInjector$class.after(Injectors.scala:385) 
com.novus.salat.transformers.in.package$$anon$2.after(Injectors.scala:123) 
com.novus.salat.transformers.Transformer$$anonfun$1.apply(Transformer.scala:85) 
com.novus.salat.transformers.Transformer$$anonfun$1.apply(Transformer.scala:85) 
scala.Option.flatMap(Option.scala:170) 
com.novus.salat.transformers.Transformer.transform_$bang(Transformer.scala:85) 
com.novus.salat.Field.in_$bang(Field.scala:64) 
com.novus.salat.ConcreteGrater$$anonfun$5$$anonfun$apply$2.apply(Grater.scala:262) 
com.novus.salat.ConcreteGrater$$anonfun$5$$anonfun$apply$2.apply(Grater.scala:262) 
scala.Option.flatMap(Option.scala:170) 
com.novus.salat.ConcreteGrater$$anonfun$5.apply(Grater.scala:262) 
com.novus.salat.ConcreteGrater$$anonfun$5.apply(Grater.scala:247) 
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) 
scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244) 
scala.collection.immutable.List.foreach(List.scala:318) 
scala.collection.TraversableLike$class.map(TraversableLike.scala:244) 
scala.collection.AbstractTraversable.map(Traversable.scala:105) 
com.novus.salat.ConcreteGrater.asObject(Grater.scala:247) 
com.sportsnetwork.api.models.MLBPlayByPlay$$anonfun$findByGameId$1.apply(MLBPlayByPlay.scala:38) 
com.sportsnetwork.api.models.MLBPlayByPlay$$anonfun$findByGameId$1.apply(MLBPlayByPlay.scala:38) 
scala.Option.map(Option.scala:145) 
com.sportsnetwork.api.models.MLBPlayByPlay$.findByGameId(MLBPlayByPlay.scala:38) 
com.sportsnetwork.api.MLBController$$anonfun$3.apply(MLBController.scala:49) 
org.scalatra.ScalatraBase$class.org$scalatra$ScalatraBase$$liftAction(ScalatraBase.scala:250) 
org.scalatra.ScalatraBase$$anonfun$invoke$1.apply(ScalatraBase.scala:245) 
org.scalatra.ScalatraBase$$anonfun$invoke$1.apply(ScalatraBase.scala:245) 
org.scalatra.ApiFormats$class.withRouteMultiParams(ApiFormats.scala:175) 
com.sportsnetwork.api.MLBController.withRouteMultiParams(MLBController.scala:20) 
org.scalatra.ScalatraBase$class.invoke(ScalatraBase.scala:244) 
com.sportsnetwork.api.MLBController.org$scalatra$json$JsonSupport$$super$invoke(MLBController.scala:20) 
org.scalatra.json.JsonSupport$$anonfun$invoke$1.apply(JsonSupport.scala:65) 
org.scalatra.json.JsonSupport$$anonfun$invoke$1.apply(JsonSupport.scala:57) 
org.scalatra.ApiFormats$class.withRouteMultiParams(ApiFormats.scala:175) 
com.sportsnetwork.api.MLBController.withRouteMultiParams(MLBController.scala:20) 
org.scalatra.json.JsonSupport$class.invoke(JsonSupport.scala:57) 
com.sportsnetwork.api.MLBController.invoke(MLBController.scala:20) 
org.scalatra.ScalatraBase$$anonfun$runRoutes$1$$anonfun$apply$7.apply(ScalatraBase.scala:220) 
org.scalatra.ScalatraBase$$anonfun$runRoutes$1$$anonfun$apply$7.apply(ScalatraBase.scala:218) 
scala.Option.flatMap(Option.scala:170) 
org.scalatra.ScalatraBase$$anonfun$runRoutes$1.apply(ScalatraBase.scala:218) 
org.scalatra.ScalatraBase$$anonfun$runRoutes$1.apply(ScalatraBase.scala:217) 
scala.collection.immutable.Stream.flatMap(Stream.scala:442) 
org.scalatra.ScalatraBase$class.runRoutes(ScalatraBase.scala:217) 
org.scalatra.ScalatraServlet.runRoutes(ScalatraServlet.scala:49) 
org.scalatra.ScalatraBase$class.runActions$1(ScalatraBase.scala:163) 
org.scalatra.ScalatraBase$$anonfun$executeRoutes$1.apply$mcV$sp(ScalatraBase.scala:175) 
org.scalatra.ScalatraBase$$anonfun$executeRoutes$1.apply(ScalatraBase.scala:175) 
org.scalatra.ScalatraBase$$anonfun$executeRoutes$1.apply(ScalatraBase.scala:175) 
org.scalatra.ScalatraBase$class.org$scalatra$ScalatraBase$$cradleHalt(ScalatraBase.scala:190) 
org.scalatra.ScalatraBase$class.executeRoutes(ScalatraBase.scala:175) 
org.scalatra.ScalatraServlet.executeRoutes(ScalatraServlet.scala:49) 
org.scalatra.ScalatraBase$$anonfun$handle$1.apply$mcV$sp(ScalatraBase.scala:113) 
org.scalatra.ScalatraBase$$anonfun$handle$1.apply(ScalatraBase.scala:113) 
org.scalatra.ScalatraBase$$anonfun$handle$1.apply(ScalatraBase.scala:113) 
scala.util.DynamicVariable.withValue(DynamicVariable.scala:57) 
org.scalatra.DynamicScope$class.withResponse(DynamicScope.scala:80) 
org.scalatra.ScalatraServlet.withResponse(ScalatraServlet.scala:49) 
org.scalatra.DynamicScope$$anonfun$withRequestResponse$1.apply(DynamicScope.scala:60) 
scala.util.DynamicVariable.withValue(DynamicVariable.scala:57) 
org.scalatra.DynamicScope$class.withRequest(DynamicScope.scala:71) 
org.scalatra.ScalatraServlet.withRequest(ScalatraServlet.scala:49) 
org.scalatra.DynamicScope$class.withRequestResponse(DynamicScope.scala:59) 
org.scalatra.ScalatraServlet.withRequestResponse(ScalatraServlet.scala:49) 
org.scalatra.ScalatraBase$class.handle(ScalatraBase.scala:111) 
org.scalatra.ScalatraServlet.org$scalatra$servlet$ServletBase$$super$handle(ScalatraServlet.scala:49) 
org.scalatra.servlet.ServletBase$class.handle(ServletBase.scala:43) 
com.sportsnetwork.api.MLBController.org$scalatra$scalate$ScalateSupport$$super$handle(MLBController.scala:20) 
org.scalatra.scalate.ScalateSupport$class.handle(ScalateSupport.scala:122) 
com.sportsnetwork.api.MLBController.org$scalatra$CorsSupport$$super$handle(MLBController.scala:20) 
org.scalatra.CorsSupport$$anonfun$handle$1.apply$mcV$sp(CORSSupport.scala:202) 
org.scalatra.CorsSupport$$anonfun$handle$1.apply(CORSSupport.scala:190) 
org.scalatra.CorsSupport$$anonfun$handle$1.apply(CORSSupport.scala:190) 
scala.util.DynamicVariable.withValue(DynamicVariable.scala:57) 
org.scalatra.DynamicScope$class.withResponse(DynamicScope.scala:80) 
org.scalatra.ScalatraServlet.withResponse(ScalatraServlet.scala:49) 
org.scalatra.DynamicScope$$anonfun$withRequestResponse$1.apply(DynamicScope.scala:60) 
scala.util.DynamicVariable.withValue(DynamicVariable.scala:57) 
org.scalatra.DynamicScope$class.withRequest(DynamicScope.scala:71) 
org.scalatra.ScalatraServlet.withRequest(ScalatraServlet.scala:49) 
org.scalatra.DynamicScope$class.withRequestResponse(DynamicScope.scala:59) 
org.scalatra.ScalatraServlet.withRequestResponse(ScalatraServlet.scala:49) 
org.scalatra.CorsSupport$class.handle(CORSSupport.scala:188) 
com.sportsnetwork.api.MLBController.handle(MLBController.scala:20) 
org.scalatra.ScalatraServlet.service(ScalatraServlet.scala:54) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:848) 
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669) 
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:455) 
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137) 
org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:560) 
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231) 
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1072) 
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:382) 
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193) 
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1006) 
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135) 
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:255) 
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116) 
org.eclipse.jetty.server.Server.handle(Server.java:361) 
org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:485) 
org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:926) 
org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:988) 
org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:635) 
org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235) 
org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82) 
org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628) 
org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52) 
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608) 
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543) 
java.lang.Thread.run(Thread.java:701) 

내 경우 클래스의 예 무언가 : 내가 얻을 스택 추적은 다음과 같습니다 MLBPlayByPlay 케이스 클래스와 잘 응답 API를 받고 있었다. 결국 내가 주석을 제거했을 때 play_by_play_seqs: Seq[MLBPlayByPlaySeq] 모든 것이 폭발했습니다. 이제 MLBPlayByPlaySeq 케이스 클래스에 들어가야합니다.이 클래스는 자체 클래스 클래스 유형을 포함하고 거기에서 하나씩 주석을 달기 시작합니다. 확실히 Salat를 디버그하는 쉬운 방법이 있습니까? 이것은 내가 강판을 사용하고 있습니다 방법은 다음과 같습니다

val res = MLBPlayByPlayDAO.findByGameId(gameId) 
res.map(grater[MLBPlayByPlay].asObject(_)) 

실제 예외 : 나는 필드에서 Option[Seq[T]]을 제거 직후

k.api.MLBController - exception occured: com.novus.salat.DefaultArg.safeValue$lzycompute(Grater.scala:406) 

스레드를 업데이트합니다.

는 ** UPDATE 2 **

내 경우 클래스의 모든 Option[Seq[T]]를 제거한 후, 나는 next_batterMLBPlayByPlaySeqs 경우 클래스 내 데이터베이스에서 빈 해시 인 경우로 문제를 좁혀. 나는 next_batter: Option[MLBBatter] = None (이것은 빈 해시에서 폭발 할 수 있음)에서 next_batter: Map[String, Any] = Map.empty으로 변경되었으며 작동합니다.

  • 내가지도
  • 나는 더 이상 손 내 직렬화 된 JSON 출력에 표시하려는 속성을 무엇을 선택할 수를 사용하여 유형의 안전을 분실 : 여기에 문제가 있다는 것입니다. JSON에서 임베디드 해시에 대한 created_at 및 updated_at와 같은 것들이 있으며 케이스 클래스에서 명시 적으로 제외시킨 것들은 next_batter을 대문자와 사례 클래스로 변경하여 수행 할 수 없습니다.

답변

2

여기 Salat 작성자 - 스택 추적에서 실제 예외를 공유 할 수 있습니까?

Salat은 컬렉션이 포함 된 옵션을 지원하지 않습니다. MLBPlayByPlaySeq에있는 몇 가지 참조하십시오. 기본값을 Seq.empty으로 설정하고 Seq으로 바꿔보고 문제가 해결되는지 확인하십시오.

실제 예외가 게시되면 다시 보겠습니다.

+0

안녕하세요. @prasinous, 답장을 보내 주셔서 감사합니다. 위의 내 스레드에 실제 예외를 게시했습니다. 이제 컬렉션을 포함하는 옵션을 제거하는 코드를 작업하고 있습니다. 곧 다시보고 할 것입니다. – randombits

+0

나는 문제를 다음과 같이 좁혔다 고 생각한다 : next_batter : Option [MLBBatter] = None. MLBPlayByPlaySeq 정의에 있습니다. next_batter가 데이터베이스의 빈 해시 인 경우 Salat가 폭발합니다. – randombits