ラベル Play Framework の投稿を表示しています。 すべての投稿を表示
ラベル Play Framework の投稿を表示しています。 すべての投稿を表示

2014年12月7日日曜日

Play Framework でデシリアライズ時に ClassNotFoundException

Play Framework ではセッションデータは Cookie に保存されるため、大きなデータは保存できない。
なので、Cookie には ID のみを保存して実際のデータはシリアリアズして DB に保存するように、
変更したところ嵌った・・・

Map や List など標準クラスでは問題ないのだが、独自クラスを保存すると ClassNotFoundException が発生する・・・

using(new ObjectInputStream(new ByteArrayInputStream(bytes))) { r =>
    r.readObject().asInstanceOf[HashMap[String, java.io.Serializable]]
  }
}
java.lang.ClassNotFoundException: com.example.MyClass
  at java.net.URLClassLoader$1.run(URLClassLoader.java:372) ~[na:1.8.0_20]
  at java.net.URLClassLoader$1.run(URLClassLoader.java:361) ~[na:1.8.0_20]
  at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_20]
  at java.net.URLClassLoader.findClass(URLClassLoader.java:360) ~[na:1.8.0_20]
  at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_20]
  at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_20]
  at java.lang.Class.forName0(Native Method) ~[na:1.8.0_20]
  at java.lang.Class.forName(Class.java:340) ~[na:1.8.0_20]
  at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:626) ~[na:1.8.0_20]
  at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1613) ~[na:1.8.0_20]
  at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) ~[na:1.8.0_20]
  at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) ~[na:1.8.0_20]
  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) ~[na:1.8.0_20]
  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) ~[na:1.8.0_20]
どうもクラスローダが違うようだ。

調べてみたところ、似たような質問が上がっていて、 解決策が出ていた。
class LocalInputStream(in: InputStream) extends ObjectInputStream(in) {
  override protected def resolveClass(desc: ObjectStreamClass): Class[_] =
    Class.forName(desc.getName, false, this.getClass.getClassLoader)
}
using(new LocalInputStream(new ByteArrayInputStream(bytes))) { r =>
    r.readObject().asInstanceOf[HashMap[String, java.io.Serializable]]
  }
}
これでデシリアライズできるようになった。