0
votes

UPDATE:

I have somewhat resolved the issue. Just in case if anyone runs in the same problem, here is the simplest solution: Looking at the MTApplcation source code, I have discovered that the initialize() method can be overloaded, taking a String parameter for the name of the class to instantiate. So if I create a separate class that extends MTApplication and pass it's name there, everything works correctly.

END OF UPDATE

I have a situation in Scala while trying to use a java library (MT4j, which is based on Processing). The library wants to instantiate the main class of the app (the caller-class):

  Class<?> c = Thread.currentThread().getContextClassLoader().loadClass(name);
  applet = (PApplet) c.newInstance();

So as to refer it later in it's works.

However, it fails because, I guess, the main Scala class is not a class, but an object and due to library structure, it is necessary to call a static method initialize() of the main library class MTApplication. In Java static fields are located in classes, but in Scala - in objects. So it is impossible to instantiate an object and the library fails. In contrast to MT4j, Processing itself makes no calls to static methods on startup and successfully passes that phase.

If I just create a companion class, everything works fine except that the companion class does not get its fields initialized because the static initialize() method is called in companion object, the class instance just gets dead-born and the library becomes unusable.

At least that is how I understand this problem.

I get this error:

Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalAccessException: Class processing.core.PApplet can not access a member of class main.Main$ with modifiers "private"
    at processing.core.PApplet.runSketch(PApplet.java:9103)
    at processing.core.PApplet.main(PApplet.java:9292)
    at org.mt4j.MTApplication.initialize(MTApplication.java:311)
    at org.mt4j.MTApplication.initialize(MTApplication.java:263)
    at org.mt4j.MTApplication.initialize(MTApplication.java:254)
    at main.Main$.main(Main.scala:26)
    at main.Main.main(Main.scala)

It is hard for me to explain also because I do not fully understand what is going on here. But anyone who has these libs can reproduce the situation in a couple of minutes, trying to launch the main class.

The abstract startUp() method which should be implemented to start the app, makes everything look even more sad. It initializes the object, but what the library tries to work with is an instance of the companion class which does not get initialized because in Scala the method belongs to the object.

My code:

object Main extends MTApplication {

    def main(args: Array[String]) {
        MTApplication.initialize()
        new Main().startUp()
    }

    //this method is abstarct so it MUST be implemented,
    override def startUp(){ 
    }

}

class Main extends MTApplication {

    override def startUp(){
       //startup here
    }
}

I am sorry if my explanations are vague, I just do not get it all completely. Probably to understand it is easier to repeat the experiment with MT4j library with Processing source code instead of the pre-linked 'core.jar' there to see what is happening inside. Doeas anyone have ideas on any workaround here?

1

1 Answers

-1
votes

Problem solved. Here is the solution:

object Main {

    var current: MainC = _

    def main(args: Array[String]) {
        MTApplication.initialize("org.mttablescreen.main.MainC")
    }

}

class MainC extends MTApplication {

    //cons
    Main.current = this

    //cons ends

    override def startUp(){
        prepare
    }

    def prepare () {...}
}