Call the Java Compiler from Processing

I’m currently writing a library for a few friends of mine who use Processing and it would be cool if I were to include a possibiity to compile and run Java-code.
I used a code I already used for another project. However when trying to include it in Processing I run in a few problems. Here ist the code I used:

import java.io.File;
import java.nio.file.Files;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
void settings() {
  File root = new File(sketchPath()+"/compiledPrograms");
  println(root.getAbsolutePath());
  try {
    String source = "public class CompiledProgram{public static void main(String[] args){System.out.println(\"Hello World\");  }}";
    // Save source in .java file. // On Windows running on C:\, this is C:\java.
    File sourceFile = new File(root, "CompiledProgram.java");
    sourceFile.getParentFile().mkdirs();
    Files.write(sourceFile.toPath(), source.getBytes(StandardCharsets.UTF_8));

    // Compile source file.
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    Class<?> cls = null ;

    //Here the error happens
    compiler.run(null, null, null, sourceFile.getPath());

    URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
    cls = Class.forName("CompiledProgram", true, classLoader);

    Object instance=cls.newInstance();
  }
  catch(Exception e) {
    e.printStackTrace();
  }
}

Here is the stack-trace:

java.lang.NullPointerException
at CompilerTest.settings(CompilerTest.java:55)
at processing.core.PApplet.handleSettings(PApplet.java:973)
at processing.core.PApplet.runSketch(PApplet.java:10751)
at processing.core.PApplet.main(PApplet.java:10476)

How can I prevent this from happening?

Edit: I removed an error.

hi NumericPrime,

just replace settings() by setup() and it will work
only few things can be done in settings as said here
otherwise it s interesting can you give a hint on when using this ‘inside’ compilation?

EDIT: oops i spoke too fast i think it doesn t do what you want, i had to replace settings to run it but still not doing more than writting the .java file

There is an error in this line should be
String source = "public class CompiledProgram{public static void main(String[] args){System.out.println(\"Hello World\"); }}";

without the parenthesises after the class name.

The source must have correct Java syntax otherwise it will fail to compile.

Well that is embaressing… Thank you!

Update: It still doesn’t work. Same exception.

I tried the code below in both Processing and Eclipse. It worked fine in Eclipse but was unable to create the compiler in Processing. I have no idea why

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

public void settings() {
  size(300, 300);
}

public void setup() {
  File root = new File(sketchPath()+"/compiledPrograms");
  println(root.getAbsolutePath());
  try {
    String source = "public class CompiledProgram{public static void main(String[] args){System.out.println(\"Hello World\");  }}";
    // Save source in .java file. // On Windows running on C:\, this is C:\java.
    File sourceFile = new File(root, "CompiledProgram.java");
    sourceFile.getParentFile().mkdirs();
    Files.write(sourceFile.toPath(), source.getBytes(StandardCharsets.UTF_8));

    // Compile source file.
    JavaCompiler compiler = (JavaCompiler) ToolProvider.getSystemJavaCompiler();
    if (compiler == null)
      println("No compiler");


    //Here the error happens beacuase compiler == null
    compiler.run(null, null, null, sourceFile.getPath());

    URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
    Class<?> cls = null ;
    cls = Class.forName("CompiledProgram", true, classLoader);
    if (cls == null)
      println("No class loader");

    Object instance=cls.newInstance();

    if (instance == null)
      println("No instance created");
  }
  catch(Exception e) {
    e.printStackTrace();
  }
}