How to store child objects on GAE using JDO from Scala - scala

I'm have a parent-child relation between 2 classes, but the child objects are never stored. I do get an warning:
"org.datanucleus.store.appengine.MetaDataValidator checkForIllegalChildField: Unable to validate relation net.vermaas.kivanotify.model.UserCriteria.internalCriteria"
but it is unclear to me why this occurs. Already tried several alternatives without luck.
The parent class is "UserCriteria" which has a List of "Criteria" as children.
The classes are defined as follows (Scala):
class UserCriteria(tu: String, crit: Map[String, String]) extends LogHelper {
#PrimaryKey
#Persistent{val valueStrategy = IdGeneratorStrategy.IDENTITY}
var id = KeyFactory.createKey("UserCriteria", System.nanoTime)
#Persistent
var twitterUser = tu
#Persistent
var internalCriteria: java.util.List[Criteria] = flatten(crit)
def flatten(crits: Map[String, String]) : java.util.List[Criteria] = {
val list = new java.util.ArrayList[Criteria]
for (key <- crits.keySet) {
list.add(new Criteria(this, key, crits(key)))
}
list
}
def criteria: Map[String, String] = {
val crits = mutable.Map.empty[String, String]
for (i <- 0 to internalCriteria.size-1) {
crits(internalCriteria.get(i).name) = internalCriteria.get(i).value
}
Map.empty ++ crits
}
// Stripped the equals, canEquals, hashCode, toString code to keep the code snippet short...
}
#PersistenceCapable
#EmbeddedOnly
class Criteria(uc: UserCriteria, nm: String, vl: String) {
#Persistent
var userCriteria = uc
#Persistent
var name = nm
#Persistent
var value = vl
override def toString = {
"Criteria name: " + name + " value: " + value
}
}
Any ideas why the childs are not stored? Or why I get the error message?
Thanks,
Gero

It looks to me like you are trying to implement an owned one-to-many relationship. Also you seem to have forgotten the #Embedded annotation for the UserCriteria's internalCriteria field, though I think, that it might still not work since the field contains a list and not the embedded class itself.

Related

how to make the following scala immutable

Suppose I have the following code:
BroadcastMessage gets a list of groups of students in the form of iterators that can only be traversed once
On call to sendMessage it will send message to all students in the groups.
class BroadcastMessage(message:String,groups:List[Iterator[Student]]) {
def sendMessage:Unit = {
groups.foreach(group=>group.foreach(sendeMessage))
}
private def sendMessage(student:Student): Unit ={
EmailClient.sendMessage(student.email,message)
}
}
case class Student(id: String,email:String)
Say that student can exist in several groups and we don't want to send him more than one email.
The mutable solution would be to add mutable set and to add the id of the student to the set and only send the message if the id exists in the set.
class BroadcastMessage(message:String,groups:List[Iterator[Student]]) {
// evil mutable set
private var set:scala.collection.mutable.Set[String] = Set()
def sendMessage:Unit = {
groups.foreach(group=>group.foreach(sendeMessage))
}
private def sendMessage(student:Student): Unit ={
if (set.add(student.id)) {
EmailClient.sendMessage(student.email, message)
}
}
}
How do I implement it in immutable way?
Well, I think that you are making two different mutable things in your example, while you only really need one.
You either need a private val set : mutable.Set[Student] = mutable.Set.empty[Student] or a private var set : Set[Student] = Set.empty[Student]. That is, you either need to mutate the set itself or just the reference to it that your class holds. I would personally go for the latter, ending up with something like:
case class Student(id: String,email:String)
class BroadcastMessage(message:String,groups:List[Iterator[Student]]) {
private var set : Set[Student] = Set.empty // <- no mutable Set, just a mutable reference to several immutable Sets
def sendMessage:Unit = {
groups.foreach(group=>group.foreach(sendMessage))
}
private def sendMessage(student:Student): Unit = {
if (!set(student)) {
set = set + student
EmailClient.sendMessage(student.email, message)
}
}
}
Finally, you could even get rid of the sendMessage(student : Student) method all together:
case class Student(id: String,email:String)
class BroadcastMessage(message:String,groups:List[Iterator[Student]]) {
private var set : Set[Student] = Set.empty
def sendMessage:Unit = {
val students = (for{
group <- groups
student <- group
} yield student).toSet
val toBeNotified = (students -- set)
toBeNotified.foreach(student => EmailClient.sendMessage(student.email, message))
set = set ++ toBeNotified
}
}
I guess it depends on style then...
I managed to do do this. I think I lost some readability but it is mutable:
class BroadcastMessage(message: String, groups: List[Iterator[Student]]) {
def sendMessage(): Unit = {
groups.foldLeft[Set[String]](Set.empty)(sendMessage)
}
private def sendMessage(sent: Set[String], group: Iterator[Student]):Set[String] = {
group.foldLeft[Set[String]](sent)(sendMessage)
}
private def sendMessage(sent: Set[String], student: Student): Set[String] = {
if (!sent.contains(student.id)) {
EmailClient.sendMessage(student.email, message)
return sent + student.id
}
sent
}
}
If you have no memory restrictions, you can just do this:
def sendMessage:Unit = {
groups.flatten.distinct.foreach(sendMessage)
}
It looks like what you are looking for is all unique Students in the nested collection.
A very simple way to do this is by flattening the collection and converting it to a Set; here is an example with Ints:
scala> val groups = List(Iterator(1,2,3), Iterator(3,4,5))
groups: List[Iterator[Int]] = List(non-empty iterator, non-empty iterator)
scala> val unique: Set[Int] = groups.flatten.toSet
unique: Set[Int] = Set(5, 1, 2, 3, 4)
A problem here is that the toSet methods actually copies your list. To avoid this, you can use this little trick (you can read more about collection.breakOut and CanBuildFrom here):
scala> val unique: Set[Int] = groups.flatMap(identity)(collection.breakOut)
unique: Set[Int] = Set(5, 1, 2, 3, 4)
However, the source of mutability here is the usage of an Iterator which will be consumed anyway, there mutating and breaking referential transparency.
You can do it with a one-liner:
def sendMessage: Unit =
groups.reduce(_ ++ _).toStream.distinct.foreach(sendMessage)
Expanded version for learning purpose:
val students: Iterator[Student] = groups.reduce(_ ++ _)
val sStudents: Stream[Student] = students.toStream
val dStudents: Stream[Student] = sStudents.distinct
def sendMessage: Unit = sStudents.foreach(sendMessage)

Map key not found error despite using option classes

I'm new to the concept of using the Option type but I've tried to use it multiple places in this class to avoid these errors.
The following class is used to store data.
class InTags(val tag35: Option[String], val tag11: Option[String], val tag_109: Option[String], val tag_58: Option[String])
This following code takes a string and converts it into a Int -> String map by seperating on an equals sign.
val message= FIXMessage("8=FIX.4.29=25435=D49=REDACTED56=REDACTED115=REDACTED::::::::::CENTRAL34=296952=20151112-17:11:1111=Order7203109=CENTRAL1=TestAccount63=021=155=CSCO48=CSCO.O22=5207=OQ54=160=20151112-17:11:1338=5000040=244=2815=USD59=047=A13201=CSCO.O13202=510=127
")
val tag58 = message.fields(Some(58)).getOrElse("???")
val in_messages= new InTags(message.fields(Some(35)), message.fields(Some(11)), message.fields(Some(109)), Some(tag58))
println(in_messages.tag_109.getOrElse("???"))
where the FIXMessage object is defined as follows:
class FIXMessage (flds: Map[Option[Int], Option[String]]) {
val fields = flds
def this(fixString: String) = this(FIXMessage.parseFixString(Some(fixString)))
override def toString: String = {
fields.toString
}
}
object FIXMessage{
def apply(flds: Map[Option[Int], Option[String]]) = {
new FIXMessage(flds)
}
def apply(flds: String) = {
new FIXMessage(flds)
}
def parseFixString(fixString: Option[String]): Map[Option[Int], Option[String]] = {
val str = fixString.getOrElse("str=???")
val parts = str.split(1.toChar)
(for {
part <- parts
p = part.split('=')
} yield Some(p(0).toInt) -> Some(p(1))).toMap
}
}
The error I'm getting is ERROR key not found: Some(58) but doesnt the option class handle this? Which basically means that the string passed into the FIXMessage object doesnt contain a substring of the format 58=something(which is true) What is the best way to proceed?
You are using the apply method in Map, which returns the value or throw NoSuchElementException if key is not present.
Instead you could use getOrElse like
message.fields.getOrElse(Some(58), Some("str"))

Neo4j OGM example with Scala

I tried the example mentioned in Luanne's article The essence of Spring Data Neo4j 4 in Scala. The code can be found in the neo4j-ogm-scala repository.
package neo4j.ogm.scala.domain
import org.neo4j.ogm.annotation.GraphId;
import scala.beans.BeanProperty
import org.neo4j.ogm.annotation.NodeEntity
import org.neo4j.ogm.annotation.Relationship
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
abstract class Entity {
#GraphId
#BeanProperty
var id: Long = _
override def equals(o: Any): Boolean = o match {
case other: Entity => other.id.equals(this.id)
case _ => false
}
override def hashCode: Int = id.hashCode()
}
#NodeEntity
class Category extends Entity {
var name: String = _
def this(name: String) {
this()
this.name = name
}
}
#NodeEntity
class Ingredient extends Entity {
var name: String = _
#Relationship(`type` = "HAS_CATEGORY", direction = "OUTGOING")
var category: Category = _
#Relationship(`type` = "PAIRS_WITH", direction = "UNDIRECTED")
var pairings: Set[Pairing] = Set()
def addPairing(pairing: Pairing): Unit = {
pairing.first.pairings +(pairing)
pairing.second.pairings +(pairing)
}
def this(name: String, category: Category) {
this()
this.name = name
this.category = category
}
}
#RelationshipEntity(`type` = "PAIRS_WITH")
class Pairing extends Entity {
#StartNode
var first: Ingredient = _
#EndNode
var second: Ingredient = _
def this(first: Ingredient, second: Ingredient) {
this()
this.first = first
this.second = second
}
}
object Neo4jSessionFactory {
val sessionFactory = new SessionFactory("neo4j.ogm.scala.domain")
def getNeo4jSession(): Session = {
System.setProperty("username", "neo4j")
System.setProperty("password", "neo4j")
sessionFactory.openSession("http://localhost:7474")
}
}
object Main extends App {
val spices = new Category("Spices")
val turmeric = new Ingredient("Turmeric", spices)
val cumin = new Ingredient("Cumin", spices)
val pairing = new Pairing(turmeric, cumin)
cumin.addPairing(pairing)
val session = Neo4jSessionFactory.getNeo4jSession()
val tx: Transaction = session.beginTransaction()
try {
session.save(spices)
session.save(turmeric)
session.save(cumin)
session.save(pairing)
tx.commit()
} catch {
case e: Exception => // tx.rollback()
} finally {
// tx.commit()
}
}
The problem is that nothing gets saved to Neo4j. Can you please point out the problem in my code?
Thanks,
Manoj.
Scala’s Long is an instance of a Value class. Value classes were explicitly introduced to avoid allocating runtime objects. At the JVM level therefore Scala's Long is equivalent to Java’s primitive long which is why it has the primitive type signature J. It cannot be therefore be null, and should not be used as a graphId. Although Scala mostly will do auto-boxing between its own Long and Java’s Long class, this doesn’t apply to declarations, only to operations on those objects.
The #GraphId isn't being picked up on your entities. I have zero knowledge of Scala but it looks like the scala long isn't liked much by the OGM; var id: java.lang.Long = _ works fine.

type mismatch; found : Int required: String when trying to persist the form data in play framework

I have a model as follows:
case class User(username: String, email: String) {
var id:Int = User.nextId
}
object User {
protected var currentId = 0
def nextId: Int = {
currentId += 1
currentId
}
}
And my Controller looks like this:
object Users extends Controller {
val users: scala.collection.mutable.Map[String, User] = new HashMap
val form = Form(
mapping(
"username" -> text,
"email" -> text
)(User.apply)(User.unapply))
def add = Action {
Ok(views.html.users.add(form))
}
def save = Action{
implicit request =>
val user = form.bindFromRequest.get
users.put(user.id, user)
Ok("contact saved")
}
}
But when I compile the code my browser throws an error telling there is a miss match in the type that is accepted by the users.put(user.id, user).
The error message looks as follows:
When I change the type of the id as string then it will work but I want to keep my id as integer and not string.
Is there any way I can achieve this. I am using play framework 2.11.1.
What is that I am missing. Any help would be greatly appreciated since I am new to play framework.
users is a map from String to User.
val users: scala.collection.mutable.Map[String, User] = new HashMap
The put method expects a key of type String and a value of type User, but you tried to use it with a key of type Int.
You need to change your map to the type
scala.collection.mutable.Map[Int, User]
or instead you could use a value of type String as key.

Class A cannot be cast to Class A after dynamic loading

Let's say I have:
object GLOBAL_OBJECT{
var str = ""
}
class A(_str: String){
GLOBAL_OBJECT.str = _str
}
and I would like to create 2 copies of GLOBAL_OBJECT (for tests), so I am using different classloader to create obj2:
val obj1 = new A("1")
val class_loader = new CustomClassLoader()
val clazz = class_loader.loadClass("my.packagename.A")
val obj2 = clazz.getDeclaredConstructor(classOf[String]).newInstance("2")
println("obj1.getSecret() == " + obj1.getSecret()) // Expected: 1
println("obj2.getSecret() == " + obj2.asInstanceOf[A].getSecret()) // Expected: 2
which results following error:
my.packagename.A cannot be cast to my.packagename.A.
IntelliJ Idea seems to do it correctly, I can run obj2.asInstanceOf[A].getSecret() in "expression" window during debug process without errors.
PS. I have seen similar questions, but I could not find any not regarding loading class from .jarfile.
You're not going to be able to get around Java's class casting, which requires strict typing, within the same ClassLoader. Same with traits/interfaces.
However, Scala comes to the rescue with structural typing (a.k.a. Duck Typing, as in "it quacks like a duck.") Instead of casting it to type A, cast it such that it has the method you want.
Here's an example of a function which uses structural typing:
def printSecret(name : String, secretive : { def getSecret : String } ) {
println(name+".getSecret = "+secretive.getSecret)
}
And here's sample usage:
printSecret("obj1", obj1) // Expected: 1
printSecret("obj2", obj2.asInstanceOf[ {def getSecret : String} ]) // Expected: 2
You could, of course, just call
println("secret: "+ obj2.asInstanceOf[ {def getSecret : String} ].getSecret
Here's full sample code that I wrote and tested.
Main code:
object TestBootstrap {
def createClassLoader() = new URLClassLoader(Array(new URL("file:///tmp/theTestCode.jar")))
}
trait TestRunner {
def runTest()
}
object RunTest extends App {
val testRunner = TestBootstrap.createClassLoader()
.loadClass("my.sample.TestCodeNotInMainClassLoader")
.newInstance()
.asInstanceOf[TestRunner]
testRunner.runTest()
}
In the separate JAR file:
object GLOBAL_OBJECT {
var str = ""
}
class A(_str: String) {
println("A classloader: "+getClass.getClassLoader)
println("GLOBAL classloader: "+GLOBAL_OBJECT.getClass.getClassLoader)
GLOBAL_OBJECT.str = _str
def getSecret : String = GLOBAL_OBJECT.str
}
class TestCodeNotInMainClassLoader extends TestRunner {
def runTest() {
println("Classloader for runTest: " + this.getClass.getClassLoader)
val obj1 = new A("1")
val classLoader1 = TestBootstrap.createClassLoader()
val clazz = classLoader1.loadClass("com.vocalabs.A")
val obj2 = clazz.getDeclaredConstructor(classOf[String]).newInstance("2")
def printSecret(name : String, secretive : { def getSecret : String } ) {
println(name+".getSecret = "+secretive.getSecret)
}
printSecret("obj1", obj1) // Expected: 1
printSecret("obj2", obj2.asInstanceOf[ {def getSecret : String} ]) // Expected: 2
}
}
Structural typing can be used for more than one method, the methods are separated with semicolons. So essentially you create an interface for A with all the methods you intend to test. For example:
type UnderTest = { def getSecret : String ; def myOtherMethod() : Unit }
One workaround to actually run some method from dynamically delivered object instead of casting it is to use reflection in order to extract particular method, from new class and then invoke it on our new object instance:
val m2: Method = obj2.getClass.getMethod("getSecret")
m2.invoke(obj2)
The class file that contains obj2.asInstanceOf[A].getSecret() should be reloaded by CustomClassLoader, too.
And you must not use any class that references to A unless you reload the class by the same class loader that reloads A.