RichardK
RichardK

Reputation: 3471

javax.tools.JavaCompiler how to catch compilation error

I want to compile Java class during runtime. Let's say that file looks like this:

public class TestClass
{
    public void foo()
    {
        //Made error for complpilation
        System.ouuuuut.println("Foo");
    }
}

This file TestClass.java is located in C:\

Now i have a class that compiles this file:

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

class CompilerError
{
    public static void main(String[] args)
    {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        compiler.run(null, null, null, "C:\\TestClass.java");
    }
}

TestClass.java has incorrect method name so it will not compile. In console it shows:

C:\TestClass.java:7: error: cannot find symbol
        System.ouuuuut.println("Foo");
              ^
  symbol:   variable ouuuuut
  location: class System
1 error

That's exactly what I need, but I need it as string. If I try to use try / catch block:

try
        {
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            compiler.run(null, null, null, "C:\\TestClass.java");
        } catch (Throwable e){
            e.printStackTrace(); //or get it as String
        }

This won't work, because JavaCompiler doesn't throw any exception. It prints error directly into console. Is it any way to get compile errors in String format ?

Upvotes: 2

Views: 893

Answers (1)

RichardK
RichardK

Reputation: 3471

The best solution is to use own OutputStream, which will be used instead of console:

 public static void main(String[] args) {

        /*
         * We create our own OutputStream, which simply writes error into String
         */

        OutputStream output = new OutputStream() {
            private StringBuilder sb = new StringBuilder();

            @Override
            public void write(int b) throws IOException {
                this.sb.append((char) b);
            }

            @Override
            public String toString() {
                return this.sb.toString();
            }
        };

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        /*
         * The third argument is OutputStream err, where we use our output object
         */
        compiler.run(null, null, output, "C:\\TestClass.java");

        String error = output.toString(); //Compile error get written into String
    }

Upvotes: 3

Related Questions