androidscalareflectionscala-reflectsbt-android

sbt-android: unable to use scala-reflect on android: java.rmi.Remote not found


I'm trying to use the scala-reflect package for android development. I have added the scala-reflect dependency in my build.sbt:

libraryDependencies += "org.scala-lang" % "scala-reflect" % "2.11.8"

but I get an exception:

java.lang.NoClassDefFoundError: Failed resolution of: Ljava/rmi/Remote;
                                at scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass$lzycompute(Definitions.scala:370)
                                at scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass(Definitions.scala:370)
                                at scala.reflect.runtime.JavaUniverseForce$class.force(JavaUniverseForce.scala:255)
                                at scala.reflect.runtime.JavaUniverse.force(JavaUniverse.scala:16)
                                at scala.reflect.runtime.JavaUniverse.init(JavaUniverse.scala:147)
                                at scala.reflect.runtime.JavaUniverse.<init>(JavaUniverse.scala:78)
                                at scala.reflect.runtime.package$.universe$lzycompute(package.scala:17)
                                at scala.reflect.runtime.package$.universe(package.scala:17)

I have tried to add the java source of java.rmi.Remote and java.rmi.RemoteException and built the project with android:package --core-library (because sbt has not found the dexCoreLibrary option) , it builded successfully, but I got the runtime error.

So, is it possible to add the java.rmi dependency otherwise, that scala.reflect can use it?

I'm using the scala.reflect library in the context of an implementation of a method Option.orDefault:

class RichOption[+A : TypeTag](val delegate: Option[A]) {

  def orDefault : A = delegate.getOrElse {
    delegate match {
      case t if typeOf[A] <:< typeOf[Int] => 0.asInstanceOf
      case _ => throw new IllegalAccessException("there is no default value for this type.")
    }
  }


}

If you know a better implementation for Option.orDefault (possibly without scala.reflect), please let me know.


Solution

  • Much better:

    case class Default[A](value: A)
    object Default {
      implicit val intDefault: Default[Int] = Default(0)
      // other Default implementations
    }
    
    class RichOption[+A](val delegate: Option[A])(implicit d: Default[A]) {
      def orDefault : A = delegate.getOrElse(d.value)
    }
    

    You get a compilation error instead of a runtime error if used with a type which doesn't have a defined default value, no complex matching, no need for a large dependency, etc.