1

I am trying to implement a simple usecase using Guava caching but facing some issues as shown below:

case class Person(x:Int, y:String)
val db = Map(1 -> Person(1,"A"), 2 -> Person(2,"B"), 3 -> Person(3,"C"))

val loader:CacheLoader[Int,Person] = new CacheLoader[Int,Person](){
    def load(key: Int): Person = {
      db(key)
    }
}

lazy val someData = CacheBuilder.newBuilder().expireAfterWrite(60, MINUTES).maximumSize(10).build(loader)

 someData.get(3)

The error I am getting is related to types which I am not able figure out

scala> someData.get(3)
<console>:24: error: type mismatch;
    found   : Int(3)
    required: Int
             someData.get(3)     

Can someone advice on what can be the issue.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
Jayadeep Jayaraman
  • 2,747
  • 3
  • 15
  • 26

1 Answers1

2

That's a common issue with Java's use-site covariance annotations.

This here works with scala 2.12.4 and guava 24.1:

import com.google.common.cache._
import java.util.concurrent.TimeUnit._

object GuavaCacheBuilderTypeProblem {
    case class Person(x:Int, y:String)
    val db = Map(1 -> Person(1,"A"), 2 -> Person(2,"B"), 3 -> Person(3,"C"))

    val loader: CacheLoader[java.lang.Integer, Person] = 
      new CacheLoader[java.lang.Integer, Person](){
        def load(key: java.lang.Integer): Person = {
          db(key)
        }
      }

    lazy val someData = CacheBuilder
      .newBuilder()
      .expireAfterWrite(60, MINUTES)
      .maximumSize(10)
      .build[java.lang.Integer, Person](loader)

    someData.get(3)
}

Answers with similar errors:

  1. compiler error when using Google guava from scala code
Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • Thank you. Can you please explain what do you mean by "Java's use-site covariance annotations." – Jayadeep Jayaraman Apr 10 '18 at 16:52
  • @jjayadeep I mean these types ` Cache` in the [declaration of build() method](https://google.github.io/guava/releases/19.0/api/docs/com/google/common/cache/CacheBuilder.html). These java-types translate to existential types in scala, and the compiler infers total nonsense. Look at [this related question](https://stackoverflow.com/a/48893292/2707792) for a discussion why it infers nonsense like `Int with AnyRef`. – Andrey Tyukin Apr 10 '18 at 16:56
  • Yes I read the link and now understand. For some reason this link didn't come up with in my search...! – Jayadeep Jayaraman Apr 10 '18 at 16:57
  • @jjayadeep no problem, similar answers are sometimes difficult to find. It was relatively fresh in my memory, that's why I remembered it. I've added links in both directions, maybe it helps with the search next time. – Andrey Tyukin Apr 10 '18 at 17:03
  • I had one more question. I am trying to use the getAll method which expects java.lang.Iterable[_ <: String] and I am trying to do the below val keys:Iterable[String]=Seq("AAA") keys.toIterable.asJava but getting error that ` asJava is not a member of Iterable[String]` but I see that there is an implicit converter which adds asJava method to Iterable[K] scala-lang.org/api/2.9.2/scala/collection/JavaConverters$.html. Where am I going wrong? – Jayadeep Jayaraman Apr 10 '18 at 17:26
  • @jjayadeep First, check the docs for the version that you actually use: [2.11.8](https://www.scala-lang.org/api/2.11.8/index.html#scala.collection.JavaConverters$). I'm not sure what the problem is there, maybe something went wrong in the imports. Hard to tell, comments are not good format for that. Looks like an unrelated question anyway, so consider asking a new question, providing all the imports. – Andrey Tyukin Apr 10 '18 at 17:44