views:

187

answers:

2

I'm learning Scala and trying to use javax.cache in Scala code and can't find how to solve this problem:

val cacheFactory = CacheManager.getInstance.getCacheFactory
val map = new HashMap
val cache = cacheFactory.createCache(map)

def rawSet(key:String, value:Array[Byte]) {
    cache.put(key, value)
}

and the compiler error is:

error: type mismatch
found: String
required: K
in cache.put(key, value)

Edit:
As Daniel said, I should have mentioned in the question that I'm over app engine since that seems to be highly relevant. In this case, the solution is to create a small class in Java to do this particular code, and call it from Scala.

+1  A: 

The problem seems to be one of providing the correct generic parameters for the HashMap. I presume you want something like:

val map = new HashMap[String, AnyRef]

Remember: Scala does not allow the use of raw types.

It's probably a good idea to use the REPL to see what type Scala has inferred your cache variable to be, or to provide the type information yourself to see whether it compiles OK:

val cache: Cache[String, AnyRef] = cacheFactory.getCache(map)
oxbow_lakes
Not solved, using: val cache: Cache[String, AnyRef] = cacheFactory.getCache(new HashMap[String, AnyRef])I get the same compiler error as before: found: String, required: K
Damian
It looks as though the `javax.cache` library (as documented here: http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules/jsr107/javax.cache.htm) badly misuses generics in *mixing parameterized and raw types*. To be honest, I'm not sure what scala would do with this (raw types are illegal in scala, as I've said). Perhaps this is out-of-date documentation?
oxbow_lakes
Can you attempt to use the **REPL** as requested? Just print out the results of `CacheManager.getInstance.getCacheFactory` - this should give you the type parameters of your cache instance
oxbow_lakes
I have no experience using scala interpreter, I'm trying javax.cache.CacheManager.getInstance.getCacheFactory but I get error "value cache is not a member of package javax"
Damian
@Damian - my guess is that you are not running the console with the right JAR files on the classpath. Daniel's suggestion below of using `cache.asInstanceOf[Map[String, AnyRef]]` is possibly what you need to do
oxbow_lakes
+1  A: 

Try:

val cache: Cache[_, AnyRef] = cacheFactory.getCache(new HashMap[String, AnyRef])

Or even Cache[_, _]. You may have to use something like this to put the values:

cache.asInstanceOf[HashMap[String,AnyRef]].put(key, value)

I'm pretty sure there is a way to do it without asInstanceOf, using the full existential syntax (Cache[T, AnyRef] forSome { type T }), but I can't recall how (or find the site that explains it :).

Daniel
No luck, I cant use asInstanceOf, I get this at runtime:java.lang.ClassCastException: com.google.appengine.api.memcache.stdimpl.GCache cannot be cast to java.util.HashMap(I'm over app engine)
Damian
If you are over app engine, you should have mentioned that in the question, as that is highly relevant. In that case, you should create a small class in Java to do this particular code, and call it from Scala.
Daniel
Well, thanks a lot, I thought that app engine implementation of jcache was totally compatible. I also thought that *any* java code could be used from scala.
Damian
Any Java code can be used from Scala. It is App Engine who is having trouble with the code produced by Scala (specifically, asInstanceOf).
Daniel