The Scala class Programmer (Listing-1) has a field named skillMap whose type is scalca.collection.mutable.Map. The map is used to record the programmer's skills and respective skill levels.
Listing-1
package tutorial.db4o class Programmer (val name: String, var phone: String) { private val skillMap = scala.collection.mutable.Map[String, Int]() def skills = skillMap.keySet def hasSkill(skill : String) = skills.contains(skill) def skillLevel(skill: String) : Option[Int] = { if (hasSkill(skill)) Some(skillMap(skill)) else None } def addSkill(skill: String, level: Int) {skillMap(skill) = level} }
In the program in Listing-2, we create an instance of the Programmer class and store it in the db4o database. In the program in Listin-3, we retrieve the object stored in db4o, and print out the programer's name, phone number, skills and corresponding levels. However, the execution runs into an exception.
Listing-2 - A Program to store an object into db4o
package tutorial.db4o import com.db4o.Db4oEmbedded import Adapter._ object AddProgrammers extends App { // a connection to the tutorial (db4o) database val connection = Db4oEmbedded.openFile("tutorial.db4o") // create a Programmer instance and store it in the database val steve = new Programmer("Steve", "513-206-3276") steve.addSkill("Java", 6) steve.addSkill("Perl", 3) connection.store(steve) connection.commit() connection.close() }
Listing-3 - A Program to retrieve an object from db4o
package tutorial.db4o import com.db4o.Db4oEmbedded import Adapter._ import com.db4o.query.Predicate object ReadProgrammers extends App { // a connection to the tutorial (db4o) database val connection = Db4oEmbedded.openFile("tutorial.db4o") // Retrieve programmers with the name Steve from the database val rs = connection.query{programmer: Programmer => programmer.name == "Steve"} // Print out each programmer's name, phone number, and skills rs.foreach{programmer => println("Programmer name: %s, phone number: %s, skills:".format(programmer.name, programmer.phone)) programmer.skills.foreach{skill => println(" %s at level %d".format(skill, programmer.skillLevel(skill).get))} } connection.close() }
Output of execution of the program in Listing-3:
Programmer name: Steve, phone number: 513-206-3276, skills:
Exception in thread "main" java.lang.NullPointerException
at scala.collection.mutable.HashTable$$anon$1.(HashTable.scala:159)
at scala.collection.mutable.HashTable$class.entriesIterator(HashTable.scala:157)
at scala.collection.mutable.HashMap.entriesIterator(HashMap.scala:45)
at scala.collection.mutable.HashTable$class.foreachEntry(HashTable.scala:190)
at scala.collection.mutable.HashMap.foreachEntry(HashMap.scala:45)
at scala.collection.mutable.HashMap$$anon$1.foreach(HashMap.scala:99)
at tutorial.db4o.ReadProgrammers$$anonfun$2.apply(ReadProgrammers.scala:17)
at tutorial.db4o.ReadProgrammers$$anonfun$2.apply(ReadProgrammers.scala:15)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:76)
at tutorial.db4o.ReadProgrammers$delayedInit$body.apply(ReadProgrammers.scala:15)
at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
at scala.App$$anonfun$main$1.apply(App.scala:60)
at scala.App$$anonfun$main$1.apply(App.scala:60)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:76)
at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:30)
at scala.App$class.main(App.scala:60)
at tutorial.db4o.ReadProgrammers$.main(ReadProgrammers.scala:7)
at tutorial.db4o.ReadProgrammers.main(ReadProgrammers.scala)
Clearly, the Programmer object was not stored correctly in db4o. If we replace the Scala Map by a Java Map (e.g. java.util.HashMap), the programs will work correctly. It is however a awkward work-around to use Java map instead of Scala map in a Scala program.
No comments:
Post a Comment