ronif
ronif

Reputation: 815

Using JavaCompiler API in a Spring Boot app - unable to properly set the compilation classpath

We have an app that's been migrated from a traditional WAR Spring web application to what we had hoped would be a modern Spring Boot executable Jar.

One of the app modules uses the JavaCompiler API to generate Java code and compile it in runtime.
The generated code requires dependencies that reside in the web app classpath, and so we had roughly the following code:

StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);

List<String> optionList = new ArrayList<String>();

    // set compiler's classpath to be same as the runtime's
    String classpathString = System.getProperty("java.class.path");
    optionList.addAll(Arrays.asList("-nowarn",
                                    "-classpath",
                                    classpathString,
                                    "-g",
                                    "-source",
                                    javaVersion,
                                    "-target",
                                    javaVersion));

    Collection classpathFiles = getClasspathJars(classpathString);
    addPreviousCompiledClassesToClasspathFiles(rootClassPath, classpathFiles);

    try {
        File file = new File(getTargetRoot(tempClassPath));
        file.mkdirs();
        standardFileManager.setLocation(StandardLocation.CLASS_OUTPUT, Lists.newArrayList(file));
        standardFileManager.setLocation(StandardLocation.CLASS_PATH, classpathFiles);

        // adding current dir to the source path, to find the compiled DV
        if (generateSeparateJarsForEachDecision.equals(NO_JAR)) {
            standardFileManager.setLocation(StandardLocation.SOURCE_PATH, Lists.newArrayList(file));
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }


        List<CharSequenceJavaFileObject> compilationUnits = Lists
                .newArrayList(new CharSequenceJavaFileObject(   StringUtils.capitalize(filename),
                                                                toString(javaCode)));
        JavaCompiler.CompilationTask task = compiler
                .getTask(writer, standardFileManager, listener, optionList, null, compilationUnits);
        status = task.call();

```

However, that doesn't work with Boot. The classpath only contains my-app.jar, and I can't add any of the nested jars to the -cp of the task - it just won't those nested jars. I've also attempted to manually add the to the -cp parameter them like so: {absolute-path}/my-app.jar!/BOOT-INF/lib/my-dep.jar {absolute-path}/my-app.jar!/BOOT-INF/lib/*.jar

None of those worked. Thought about using the <requiresUnpack> tag on build too, but that didn't seem to help because I couldn't get a hold of the expanded dir in order to add it to the classpath.

Upvotes: 8

Views: 920

Answers (1)

sgokul55
sgokul55

Reputation: 3

Faced similar issue.

Looks like a limitation with spring boot.

So created a standalone application with Jersey and Tomcat embedded.

Now jar contains all libraries and able to set it as class path to Java Compiler

Upvotes: 0

Related Questions