#2039 Sys.homeDir in the jar

zapletnev Mon 1 Oct 2012

Hi all,

I have fantom pod that packed in the jar with help of JarDist. And when I have tried to use CompilerInput it throws an NPE. The cause of it that Env.cur.workDir is null. In pod this variable successfully resolved via "FAN_HOME" enviroment variable.

Thanks, Igor

brian Mon 1 Oct 2012

Could you provide some more details by what you mean when you say CompilerInput throws NPE? Are you trying to use the compiler API in your jar? Or Env.compileScript? Did you include the entire compiler pod in your Jar?

zapletnev Mon 1 Oct 2012

Variable Env.cur.workDir is null when I build my pod in the jar. So I think it is the main issue because NPE throws on the next line of the code in the CompilerInput:91 File outDir := Env.cur.workDir + lib/fan/ on the plus method of the Uri object.

Here is more details: I am using Compiler api in the my jar and here is buildJar:

@Target { help = "" }
Void distFansh()
{
  dist := JarDist(this)
  dist.outFile = `./mypod.jar`.toFile.normalize
  dist.podNames = Str["mypod", "compiler"]
  dist.mainMethod = "fmaven::Main.main"
  dist.run
}

zapletnev Tue 2 Oct 2012

Looks like I make a mistake and the main issue is http://fantom.org/sidewalk/topic/2040#c13421

brian Tue 2 Oct 2012

Could you clarify if you think there is a bug? If so I'm not sure what it is, something do with Uris in the build script or in Java runtime?

zapletnev Tue 2 Oct 2012

class TestClass
{
  Uri[] uri := [`testUri`]
  Uri[] uriFromStr := [Uri.fromStr("testUri")]
}

Fantom:Main:

class Main
{
  static Void main() 
  { 
    TestClass clazz := TestClass()
    echo(clazz.uri)
    echo(clazz.uriFromStr)
  }
}

Output:

[testUri]
[testUri]

Java:Main

import fan.testPod.TestClass;

public class Main {

    /**
     * @param args
     */
    public static void main(final String[] args) {
        final fan.testPod.TestClass testClass = TestClass.make();
        System.out.println(testClass.uri);
        System.out.println(testClass.uriFromStr);
    }
}

Output:

[null]
[testUri]

brian Tue 2 Oct 2012

Promoted to ticket #2039 and assigned to brian

Okay perfect, just what I needed

brian Mon 15 Oct 2012

Ticket cancelled

This isn't actually a bug, I think it is just because you are using the JarDist jar file as a library file but not actually booting up Fantom and initializing the constant pool. When you create JarDist it creates a special bit of code in its main that initializes Fantom for the VM:

System.getProperties().put("fan.jardist", "true");
System.getProperties().put("fan.home",    ".");
Sys.boot();
Env.cur().loadPodClass(Pod.find("sys"));
Env.cur().loadPodClass(Pod.find("concurrent"));
Env.cur().loadPodClass(Pod.find("util"));

That last bit is important because it loads the constant pool for each pod including constant URIs (which is why yours are null).

So if using Fantom jar as a library someone has to kick off the initialization. To make this a bit easier, I've separated the init code in the Main generated by JarDist so that you can just do this:

fanjardist.Main.boot();

zapletnev Fri 26 Oct 2012

Hi Brian,

Thanks for your response. But during investigation I have found one more issue. Everything works properly when I am using jar that were builded via JarDist (and call main procedure), all constants initialized. But when I am using this jar as external library in the another jar all constastans still null.

Here is my fantom code:

class Main
{
  static Void main() { 
    test := ConstTest()
    echo("My constant is " + test.test)
  }
}

class ConstTest
{
  Uri test := `test_uri`
}

Here is output for jar that builded via JarDist:

>java -jar myjar.jar
>My_constant is test_uri

My java code:

package test.project;

import fan.mypod.Main;

public class Main {

    /**
     * @param args
     */
    public static void main(final String[] args) {
        Main.main();
    }
}

Output:

>java -jar my_java.jar
>My_constant is null

brian Fri 26 Oct 2012

It doesn't look like your Main.main calls out to initialize the Fantom runtime though? I think you just need to add the call to boot Fantom in your main:

static Void main() {

fanjardist.Main.boot();
test := ConstTest();
}

That requires using the latest build.pod code though - if you can't build from bootstrap, I'll be happy to email it to you. Just send me an email

Login or Signup to reply.