Suggestions for persisting a set/list of class objects? #16

Open
jpc001 opened this Issue Sep 17, 2010 · 1 comment

Projects

None yet

2 participants

@jpc001

Hi Debasish

Firstly, I'd like to thank you for sharing scouchdb and sjson, they make working with Scala and CouchDB much easier!

I'm trying to use scouchdb (cloned from github a few days ago along with sjson 0.7 using Scala 2.8.0 final) to persist objects that contain a list of classes. The basic idea is that I want to represent something like a 'folder' that is only allowed to contain certain types of objects. For example, I may want one folder to contain only JPG, PNG or TIFF files, but another folder to contain only PDF files. Each of the file types is defined as a different class, so I create subclasses of my generic 'folder', e.g. ImageFolder (which sets the acceptable classes to JPG, PNG and TIFF) and PdfFolder (which sets the acceptable classes to PDF). This makes it easy to test if someone is adding an acceptable object to a folder. I hope this is clear!

However, trying to persist an object with a list of class objects results in an error:

java.lang.UnsupportedOperationException: Class class $Proxy3 not supported for conversion

I can sort of work around this by changing the code to use canonical class names (i.e. List[String]), but then I'm starting to change my core classes to suite the persistence model, which is less than ideal. It also means I need to manage the marshalling of the classes into class names and vice-versa when unmarshalling.

Here some simplified code that illustrates the issue:

import java.lang.Class
import scala.reflect._
import scala.annotation.target._
import scouch.db._
import dispatch._
import dispatch.json._
import dispatch.json.JsHttp._
import sjson.json._

class SampleScouchdbClass(@BeanProperty val name: String) {

@BeanProperty
@(JSONTypeHint @field)(value = classOf[Class[_]])
val classes: List[Class[_ <: SampleScouchdbClass]] = List(classOf[SampleScouchdbClass])

}

object SampleScouchdbClass {

def main(args: Array[String]): Unit = {

        val http = new Http
    val sampleDb = Db(Couch(), "rms")

    var sample = new SampleScouchdbClass("Sample 1")

    val doc = Doc(sampleDb, sample.name)
    http(doc add sample)
}

}

The full error stack is:

Exception in thread "main" java.lang.UnsupportedOperationException: Class class $Proxy3 not supported for conversion
at sjson.json.JsBean$class.toJSON(JsBean.scala:256)
at sjson.json.JsBean$.toJSON(JsBean.scala:311)
at sjson.json.JsBean$$anonfun$toJSON$2.apply(JsBean.scala:234)
at sjson.json.JsBean$$anonfun$toJSON$2.apply(JsBean.scala:234)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:206)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:206)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:34)
at scala.collection.mutable.ArrayOps.foreach(ArrayOps.scala:34)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:206)
at scala.collection.mutable.ArrayOps.map(ArrayOps.scala:34)
at sjson.json.JsBean$class.toJSON(JsBean.scala:234)
at sjson.json.JsBean$.toJSON(JsBean.scala:311)
at sjson.json.JsBean$$anonfun$5.apply(JsBean.scala:280)
at sjson.json.JsBean$$anonfun$5.apply(JsBean.scala:261)
at scala.collection.TraversableLike$WithFilter$$anonfun$map$2.apply(TraversableLike.scala:787)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:34)
at scala.collection.mutable.ArrayOps.foreach(ArrayOps.scala:34)
at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:786)
at sjson.json.JsBean$class.toJSON(JsBean.scala:261)
at sjson.json.JsBean$.toJSON(JsBean.scala:311)
at sjson.json.JsBean$$anonfun$toJSON$1.apply(JsBean.scala:231)
at sjson.json.JsBean$$anonfun$toJSON$1.apply(JsBean.scala:231)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:206)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:206)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:61)
at scala.collection.immutable.List.foreach(List.scala:45)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:206)
at scala.collection.immutable.List.map(List.scala:45)
at sjson.json.JsBean$class.toJSON(JsBean.scala:231)
at sjson.json.JsBean$.toJSON(JsBean.scala:311)
at sjson.json.JsBean$$anonfun$5.apply(JsBean.scala:280)
at sjson.json.JsBean$$anonfun$5.apply(JsBean.scala:261)
at scala.collection.TraversableLike$WithFilter$$anonfun$map$2.apply(TraversableLike.scala:787)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:34)
at scala.collection.mutable.ArrayOps.foreach(ArrayOps.scala:34)
at scala.collection.TraversableLike$WithFilter.map(TraversableLike.scala:786)
at sjson.json.JsBean$class.toJSON(JsBean.scala:261)
at sjson.json.JsBean$.toJSON(JsBean.scala:311)
at scouch.db.Doc.add(Database.scala:263)
at com.x.persistence.SampleScouchdbClass$.main(SampleScouchdbClass.scala:31)
at com.x.persistence.SampleScouchdbClass.main(SampleScouchdbClass.scala)

Any suggestions/ideas on how to approach this problem would be much appreciated! I'm new to Scala and CouchDb, so my apologies in advance if I'm doing this in an unusual way.

Regards
Ben

@debasishg
Owner

I will look into the problem ASAP. But on first look, my hunch is that JSON serialization of Class objects is failing. I am not sure if Class[] is JSON serializable at all or not. I think for the time being you need to use List[String] with the class names till I come up with a better suggestion.

Very soon I will be updating scouchdb with type class serialization that I introduced into sjson recently. Then I think I would be able to suggest u a better alternative. For the time being, please bear with the List[String] based solution :) ..

Thanks for using scouchdb & sjson.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment