【问题标题】:Riak Java Client annotation not recognized in Scala case class?Scala案例类中无法识别Riak Java Client注释?
【发布时间】:2013-02-05 23:54:14
【问题描述】:

我正在使用案例类在我们的应用程序中定义不同的数据“模型”。原因是为了便于使用 Jerkson(Scala 接口到 Jackson)。为了将我的 User 转换为 Riak 中的域对象,我在我的 guid 上使用了 @RiakKey 注释。我有以下内容:

case class User(
  @RiakKey val guid: String,

  @RiakIndex(name = "email") val email: String,

  val salt: String,

  val passwordHash: String,

  val emailHash: String,

  val firstName: String,

  val lastName: String,

  val suspended: Boolean=false,

  val created: Timestamp=now

)

当我对案例类执行域转换时,@RiakKey 无法识别。它抛出一个NoKeySpecifedException。这是我的转换器:

class UserConverter(val bucket: String) extends Converter[User] {

  def fromDomain(domainObject: User, vclock: VClock) = {
    val key = getKey(domainObject)

    if(key == null) throw new NoKeySpecifedException(domainObject)

    val kryo = new Kryo()
    kryo.register(classOf[User])

    val ob = new ObjectBuffer(kryo)
    val value = ob.writeObject(domainObject)

    RiakObjectBuilder.newBuilder(bucket, key)
        .withValue(value)
        .withVClock(vclock)
        .withContentType(Constants.CTYPE_OCTET_STREAM)
        .build()
  }
}

这是 Scala 中带有 Java 注释的问题吗?有解决办法吗?

更新

这里是创建和存储用户对象的位置,以及引用转换器的位置:

1)

val user = parse[User](body) // jerkson parse, body is a string of JSON
User.store(user)

2)

object User {

  val bucketName = "accounts-users"
  val bucket = DB.client.createBucket(bucketName).execute()

  def fetch(id: String) = bucket.fetch(id).execute().getValueAsString()

  def store(o: User) = bucket.store( o ).withConverter(new UserConverter(bucketName)).execute()

}

轨迹追踪

com.basho.riak.client.convert.NoKeySpecifedException
        at com.basho.riak.client.bucket.DefaultBucket.store(DefaultBucket.java:455)
        at com.threetierlogic.AccountService.models.User$.store(User.scala:58)
        at com.threetierlogic.AccountService.controllers.Users$$anonfun$routes$3.apply(Users.scala:54)
        at com.threetierlogic.AccountService.controllers.Users$$anonfun$routes$3.apply(Users.scala:51)

【问题讨论】:

  • 从我读过的内容来看,它应该可以工作(我没有用 scala 写过任何东西)。我知道这是一个愚蠢的问题,但我只是想检查一下……您在传递给存储操作的User 对象中将guid 设置为null 以外的其他值,是吗?您是否也在使用自己的 Mutation 和 ConflictResolver?
  • 不使用我自己的Mutation and ConflictResolver,有必要吗? Guid 设置为字符串“0u0700fs984”。我发布了一些虚拟 JSON 并将其存储在 Riak 中,但 JSON 的解析检查正常。
  • Jackson 解析传入的 JSON 时注释是否会丢失?
  • 否 - 没有必要(只是想检查一下),如果没有提供默认值,基本上就是您所期望的(不支持兄弟姐妹,并且无论您传递给 store 调用的任何内容都会被存储)存在于Riak)。注解只是 Java/Scala 中的标记;它们不与对象数据一起存储(转换器中的toDomain() 使用它们来知道将检索到的数据放在哪里)。
  • 编辑:如果我注释掉 throw new NoKeySpecifed 行,看起来它实际上是在调用 store 方法时被抛出的。我想知道 RiakObjectBuilder 是否没有返回密钥。

标签: java scala riak


【解决方案1】:

(对于这个答案之前的长时间谈话,我深表歉意)

在了解了更多关于 scala 的知识后,我发现使用 case 类你必须做一些不同的事情。

http://piotrbuda.eu/2012/10/scala-case-classes-and-annotations-part-1.html

如果你这样做:

@(RiakKey@field) guid: String

它有效。

我在 scala 中编写了一个小型测试程序,并且能够使用 DefaultBucket 中使用的静态 getKey() 方法提取带注释的密钥,该方法返回 null 并导致引发异常。

import com.basho.riak.client.convert.KeyUtil.getKey;

object Main {

  def main(args: Array[String]): Unit = {
    val u = User("my_key")
    val k = getKey(u)
    System.out.println(k);

  }
}

用户.scala

/* scala 2.9.1 would be scala.annotation.target.field */
import scala.annotation.meta.field
import com.basho.riak.client.convert.RiakKey;

case class User (@(RiakKey@field) guid: String)

输出:

我的钥匙

(而且,如果您将注释改回原来的样子,它会按预期返回null

【讨论】:

  • 哇,我自己今天学到了一些新东西。看起来我也需要修复索引注释。非常感谢你张贴这个!到处都是 riak 的 scala 开发者会欢呼!
  • 很高兴我能帮上忙 :) 您也可以随时直接在 Riak-Users mailing list 上联系我们
  • 感谢您的链接。我还要注意 Scala 2.9.1 的导入是 import scala.annotation.target.field 看起来包结构在 2.10 中发生了变化
【解决方案2】:

这是我针对该问题提出的解决方法。我不依赖注解,而是直接使用DefaultBucket.store 方法并手动指定一个键。

我的用户伴随对象:

object User {

  val bucketName = "accounts-users"
  val bucket = DB.client.createBucket(bucketName).execute()

  def store(key: String, o: User) = bucket.store(key, o).withConverter(new UserConverter(bucketName)).execute()

}

并使用它:

val user = parse[User](body)
User.store(user.guid, user)

【讨论】:

  • 想通了。否则我会发疯的。抱歉,我缺乏 scala 知识,导致这比本来应该的更困难 :) 发布了答案。
猜你喜欢
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 2013-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多