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