#1412 Literal Uri Syntax throws NPE on jardist

kaushik Tue 15 Feb 2011

A line like this is throwing NPE when you build a jar and execute it from a java environment

Uri uri := `http://www.google.com`

while this works

Uri uri := "http://www.google.com".toUri

brian Tue 15 Feb 2011

I can't reproduce this? In fact in the examples code I build testSys and run thru all the tests including UriTest.

If you can narrow this down, can you email me directly?

kaushik Tue 15 Feb 2011

Here are the steps I did to reproduce it now Create a pod with just one fan file that looks like this

class Main{
    Uri uri := `http://www.google.com`
    Uri anotherUri := "http://www.google.com".toUri

    static Void main(){
        echo(Main().uri)
        echo(Main().anotherUri)
    }
}

build the pod "testjar". Do a JarDist with just this pod to generate testjar.jar. Create a java class, include this jar in the classpath that looks like this

public class Main {
    public static void main(String[] args){
        System.setProperty("fan.home", "/files/fantom-1.0.57/");
        fan.testjar.Main.main(); 
    }
}

prints

null
http://www.google.com/

would it help if i send the jar to you in an email?

brian Tue 15 Feb 2011

Okay, the problem is that you can't just boot the Fantom environment by setting that one system property. The real steps you need to handle are written by the jardist into an explicit main class for the jar: http://fantom.org/doc/build/JarDist_src.html#mainMethod

Summarized, they would be something like this:

System.getProperties().put("fan.jardist", "true");
System.getProperties().put("fan.home",    ".");
Sys.boot();
Sys.bootEnv.setArgs(args);
Env.cur().loadPodClass(Pod.find("sys"));
Env.cur().loadPodClass(Pod.find("testjar"));
fan.testjar.Main.main();

vkuzkokov Tue 15 Feb 2011

Literals in Java runtime of Fantom are stored in static fields of $Pod class for each pod. These fields are usually initialized in FanClassLoader. You may want to look into source code of build::JarDist.main which generates boilerplate needed to manually start Fantom runtime from Java.

Also you aren't likely to need /files/fantom-1.0.57/ as JarDist generates jar, that already contains everything from sys.jar.

So your code should look like:

public class Main {
    public static void main(String[] args){
        System.getProperties().put("fan.jardist", "true");
        System.getProperties().put("fan.home",    ".");
        Sys.boot(); // this one does nothing except static initialization
        Sys.bootEnv.setArgs(args); // in case you will use args
        Env.cur().loadPodClass(Pod.find("testjar")); // here happens the loading
        fan.testjar.Main.main();
    }
}

kaushik Tue 15 Feb 2011

Ah okay, thanks. Fixed fanzy.net too.

vkuzkokov Tue 15 Feb 2011

Still, I don't get why this works for strings (And I bet everything else but Duration and Uri).

Maybe it's possible to trigger loading to $Pod.<clinit>?

brian Tue 15 Feb 2011

It works for Bools, Ints, Floats, and Strs because we can directly use Java constants in the bytecode via the LDC opcode. For Types, Duration, Uri, Slots, etc we have to reference an instance (which as you identified are stored in $Pod class)

Login or Signup to reply.