Scala: Mis-using traits, gives runtime error - scala

Sorry for the broad topic; I'm just not quite sure what I'm doing wrong.
I have a class structure
trait BaseType {
val property: String
}
trait MiddleTrait extends BaseType {
val myProperty = property.length.toString
def userProperty() = {
myProperty
}
}
object Top extends MiddleTrait {
val property = "value given here"
}
Which compiles; but hits a run time error - java.lang.RuntimeException: java.lang.NoClassDefFoundError: Could not initialize class controllers.test.Top$
Updating MiddleTrait to def myProperty = property.length.toString it will run fine.
I looking to understand the theory behind this better so I could predict the error without seeing it fail at run time first
Thanks

When I paste your code into a Scala 2.11.6 REPL I don't get any errors at first. Trying to access myProperty will result in a NullPointerException
scala> Top.myProperty
java.lang.NullPointerException
at MiddleTrait$class.$init$(<console>:12)
... 35 elided
The NullPointerException is thrown because MiddleTrait gets initialized before Top at which point property is still null (see spec on template evaluation). If you turn myProperty into a function, the error goes away because the function is called on the fully initialized Top.
The error you quoted comes up for me when I try to access myProperty again, after the NullPointerException
scala> Top.myProperty
java.lang.NoClassDefFoundError: Could not initialize class Top$
... 33 elided

Related

Scala StackOverflow error while creating the object of the class inside class

I defined my scala class as follows:
scala> class test2(private var a:Int) {
| var t1 = new test2(10)
| println(t1.a)
| }
defined class test2
Now when i try to create the object of this class i am getting stackoverflow error (see below).
scala> var t2 = new test2(5)
java.lang.StackOverflowError
... 1024 elided
Can anyone explain why is this error coming ?
It is not a duplicate. The problem posted in the link is related to java. My problem is related to scala.
You are creating a new object inside constructor which is recursively creating new object and it continues. So stack overflow error occurred

Type mismatch runtime error on ClassTag (Scala)

I am a C++ programmer and is trying to learn Scala. I want to achieve something similar to the following code using C++ template
template<typename T>
class Foo {
public:
T* bar;
/////////////////Other Code Omitted//////////////////////////
};
Its counter-part in Scala will not compile due to type erasure
class Foo[E](){
val bar = new E() //Will not compile
}
I have been searching the whole night for a workaround, this seems to be one of them
package test
import scala.reflect._
object Type {
def newInstance[T: ClassTag](init_args: AnyRef*): T = {
classTag[T].runtimeClass.getConstructors.head.newInstance(init_args: _*).asInstanceOf[T]
}
}
class Foo[T1:ClassTag](init_args: AnyRef*){
val bar = Type.newInstance[T1](init_args)
}
class TestClass(val arg:String){
val data = arg
}
However, when I try to instantiate one (val test = new Foo[Test]("test")) in the scala console, it gives the following error
java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at ParActor.Type$.newInstance(ParActor.scala:32)
at ParActor.Foo.<init>(ParActor.scala:37)
... 35 elided
I am not exactly sure what causes the problem and how to fix this. Other work around is also welcomed.
You should turn
Type.newInstance[T1](init_args)
into
Type.newInstance[T1](init_args: _*)
What : _* does is turn a list or sequence into a varargs argument. A varargs parameter AnyRef* is actually an IndexedSeq[AnyRef], more specifically a WrappedArray[AnyRef]. So when you pass init_args as an argument to newInstance without telling the compiler to interpret it as a varargs argument you are actually passing in WrappedArray(WrappedArray("test")).

Dynamically classloading Scala types

I have the following Scala class hierarchy:
abstract class BaseModule(val appConf : AppConfig) {
// ...
}
class SimpleModule(appConf : AppConfig) extends BaseModule(appConf) {
// ...
}
class FairlyComplexModule(appConf : AppConfig) extends BaseModule(appConf) {
// ...
}
// dozens of other BaseModule subclasses...
At runtime, my app will accept a String input argument for the fully-qualified class name of a BaseModule subclass to instantiate, but the code won't know which concrete subclass it will be. So I have:
val moduleFQCN = loadFromInputArgs() // ex: "com.example.myapp.SimpleModule"
val moduleClass = Class.forName(moduleFQCN)
println(s"Found ${moduleFQCN} on the runtime classpath.")
val module = Class.forName(moduleFQCN).getConstructor(classOf[AppConfig]).newInstance(appConf).asInstanceOf[BaseModule]
So this way, the input specifies which BaseModule subclass to look for on the classpath, and then subsequently, to instantiate. The first three lines above execute just fine, and I see the println fire. However the last line above throws an exception:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
<rest of stacktrace omitted for brevity>
So clearly I'm doing something wrong when trying to create an instance of the SimpleModule subclass, just can't figure out what it is. Any ideas?
You're probably failing because you call newInstance() without any arguments, but no default constructor is found therefore the instantiation fails.
try this:
Class.forName(moduleFQCN).getConstructor(classOf[AppConfig])
.newInstance(appConf).asInstanceOf[BaseModule]
Where appConf is an instance of AppConfig and is the parameter to instantiate BaseModule with.

Why is the Scala compiler giving me an error when passing a Kotlin sealed class into a constructor?

I have a sealed class, written in Kotlin:
sealed class Schema {
class RecordSchema(val fields: List<Field>): Schema()
class ArraySchema(val elementSchema: Schema): Schema()
...
}
And another class that takes RecordSchema as a parameter:
class Enrichment(config: Config, val schema: RecordSchema) { ... }
In Scala I have a class that, among other things, get an instance of the RecordSchema and then create an instance of the Enrichment.
object Job {
def main(args: Array[String]): Unit = {
/// some initializing of resources... and then...
val recordSchema = schemas.getSchema(id) // type is Schema.RecordSchema
val enrichment = Enrichment(config, recordSchema) // this is where scalac errors out
}
}
The scala compiler ends up printing this error message:
Error:(52, 62) type mismatch;
found : com.companyname.enricher.schemas.com.companyname.enricher.schemas.com.companyname.enricher.schemas.
required: com.companyname.enricher.schemas.(some other)com.companyname.enricher.schemas.com.companyname.enricher.schemas.
val enrichment = new Enrichment(config, recordSchema)
If I cast recordSchema using asInstanceOf I get another, not so useful, error:
Error:(52, 62) type mismatch;
found : com.companyname.enricher.schemas.Schema.RecordSchema
required: com.companyname.enricher.schemas.com.companyname.enricher.schemas.
val enrichment = new Enrichment(config, recordSchema.asInstanceOf[RecordSchema])
Overall, I have no idea why this is happening. If I make the constructor take the parent class as a parameter rather than nested class, it compiles just fine (which is my workaround for now). If I do the same type of thing, except having written the sourcecode in Java rather than Kotlin, this error does not happen. I am using Java 1.8, Kotlin 1.0.4, Scala 2.11.8.
UPDATE:
demonstrated bug here:
https://github.com/mjburghoffer/scala-kotlin-innerclass-bug/tree/master
Looks like Kotlin generates different number of classes for this case. I compiled Java and Kotlin sources and found that Java has additional file ParentSealedJava$1.class. Bytecode of Parent and Sealed classes in Java and Kotlin pretty the same (i inspect bytecode using javap -c), so i think Scala compiler relies somehow on this missing file in Kotlin.

Create instance of a Class type using newInstance()

So I'm trying to create an instance of a class using following statements (simplified):
class A
classOf[A].newInstance()
The call throws:
java.lang.InstantiationException: A$A426$A$A426$A
Caused by: java.lang.NoSuchMethodException: A$A426$A$A426$A.<init>()
I did try defining init() method with different variations with no success. What am I missing?
Thanks in advance.
Related, didn't work for me:
No such method exception Hadoop <init>
This answer
I suspect your problem is that A is being declared inside anther class. See this example:
import org.specs2.mutable.Specification
class StackoverflowSpec extends Specification {
class B
"A" should {
"be instantiatable" in {
classOf[A].newInstance() must not(beNull)
}
}
"B" should {
"throw an instantiation exception" in {
classOf[B].newInstance must throwAn[InstantiationException]
}
}
}
class A
I think that what's happening is that in the jvm, your classes are A and StackoverflowSpec$B, and that StackoverflowSpec$B requires a StackoverflowSpec to be passed in to it's constructor, because it's an inner class.
Thanks for suggestion about inner class but actually it has to do with IntelliJ IDEA 'scala worksheet' -- scala sandbox file with interactive evaluation. For some reason, instantiation described above throws only in a worksheet, it does work in a regular Scala REPL.