dlite922
dlite922

Reputation: 1994

How To Convert Scala Case Class to Java HashMap

I'm using Mule ESB (Java Based) and I have some scala components that modify and create data. My Data is represented in Case Classes. I'm trying to convert them to Java, however Just getting them to convert to Scala types is a challenge. Here's a simplified example of what I'm trying to do:

package com.echostar.ese.experiment


import scala.collection.JavaConverters

case class Resource(guid: String, filename: String)
case class Blackboard(name: String, guid:String, resource: Resource)

object CCC extends App {
    val res = Resource("4alskckd", "test.file")
    val bb = Blackboard("Test", "123asdfs", res)

    val myMap = getCCParams(bb)
    val result = new java.util.HashMap[String,Object](myMap)
    println("Result:"+result)

    def getCCParams(cc: AnyRef) =
        (Map[String, Any]() /: cc.getClass.getDeclaredFields) {(a, f) =>
            f.setAccessible(true)
            val value = f.get(cc) match {
                //  this covers tuples as well as case classes, so there may be a more specific way
                case caseClassInstance: Product => getCCParams(caseClassInstance): Map[String, Any]
                case x => x
            }
            a + (f.getName -> value)
        }
}

Current Error: Recursive method needs return type.

My Scala Foo isn't very strong. I grabbed this method from another answer here and basically know what it's doing, but not enough to change this to java.util.HashMap and java.util.List

Expected Output:

Result:{"name"="Test", "guid"="123asdfs", "resource"= {"guid"="4alskckd", "filename"="test.file"}}

UPDATE1: 1. Added getCCParams(caseClassInstance): Map[String, Any] to line 22 Above per @cem-catikkas. IDE syntax error still says "recursive method ... needs result type" and "overloaded method java.util.HashMap cannot be applied to scala.collection.immutable.Map". 2. Changed java.util.HashMap[String, Object]

Upvotes: 0

Views: 2517

Answers (3)

Claudius
Claudius

Reputation: 156

Answering this in case anyone else going through the issue ends up here (as happened to me).

I believe the error you were getting had to do with the fact that the return type was being declared at method invocation (line 22), however the compiler was expecting it at the method's declaration (in your case, line 17). The below seems to have worked:

def getCCParams(cc: AnyRef): Map[String, Any] = ...

Regarding the conversion from Scala Map to Java HashMap, by adding the ._ wildcard to the JavaConverters import statement, you manage to import all the methods of the object as single identifiers, which is a requirement for implicit conversions. This will include the asJava method which can then be used to convert the Scala Map to a Java one, and then this can be passed to the java.util.HashMap(Map<? extends K,? extends V> m) constructor to instantiate a HashMap:

import scala.collection.JavaConverters._
import java.util.{HashMap => JHashMap}

...

val myMap = getCCParams(bb)
val r = myMap.asJava    // converting to java.util.Map[String, Any]
val result: JHashMap[String,Any] = new JHashMap(r)

Upvotes: 2

Ryan
Ryan

Reputation: 11

I wonder if you've considered going at it the other way around, by implementing the java.util.Map interface in your case class? Then you wouldn't have to convert back and forth, but any consumers downstream that are using a Map interface will just work (for example if you're using Groovy's field dot-notation).

Upvotes: 1

Cem Catikkas
Cem Catikkas

Reputation: 7174

You should follow what the error tells you. Since getCCParams is a recursive method you need to declare its return type.

def getCCParams(cc: AnyRef): Map[String, Any]

Upvotes: 2

Related Questions