lundi 16 octobre 2023

How to ensure Java has access to on-the-fly compilated classes?

Basically, I am generating files with Java Reflection. When using INtelliJ, everything works fine, everything is generated as it should. During the generation, I build some files I generated so I can use more Reflection on them. This is the code I use to do so :

private Class<?> compile(File sourceFile, String pack) throws ClassNotFoundException, IOException {
        File output = new File(Constants.BASE_TARGET_PATH);
        output.mkdirs();

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        StandardJavaFileManager standardJavaFileManager = compiler.getStandardFileManager(null, null, null);
        standardJavaFileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(output));
        Iterable<? extends JavaFileObject> compilationUnits = standardJavaFileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile));
        compiler.getTask(null, standardJavaFileManager, null, null, null, compilationUnits).call();
        standardJavaFileManager.close();


        URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] {output.toURI().toURL()});
        Class<?> dynamicClass = urlClassLoader.loadClass(pack + "." + sourceFile.getName().replaceFirst("[.][^.]+$", ""));

        return dynamicClass;
    }

When I try to package my generator in a .jar, this does not work because, even though some of my custom annotations have been generated correctly, Java can't find them so it can't import them when building. This is the error I get :

10:47:18.928 [main] INFO com.foo.codegeneration.generators.ControllerGenerator -- Generated ZoneController
compiling annotations
compiled IntermediateTableAttribute.java
compiling presentationals
src\main\java\com\foo\jpadataserverprototype\presentation\presentational\PresentationalCategory.java:3: error: package com.foo.jpadataserverprototype.presentation.presentational.annotations does not exist
import com.foo.jpadataserverprototype.presentation.presentational.annotations.*;
^
1 error
java.lang.ClassNotFoundException: com.foo.jpadataserverprototype.presentation.presentational.PresentationalCategory
        at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
        at java.base/java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:872)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
        at com.foo.codegeneration.GeneratedPresentationalRetriever.compile(GeneratedPresentationalRetriever.java:65)
        at com.foo.codegeneration.GeneratedPresentationalRetriever.retrieveEntities(GeneratedPresentationalRetriever.java:43)
        at com.foo.codegeneration.generators.MapperGenerator.<init>(MapperGenerator.java:31)
        at com.foo.codegeneration.CodeGenerator.main(CodeGenerator.java:93)
10:47:19.503 [main] INFO com.foo.codegeneration.generators.MapperGenerator -- Generating CategoryMapper...
Exception in thread "main" java.util.NoSuchElementException: No value present
        at java.base/java.util.Optional.get(Optional.java:143)
        at com.foo.codegeneration.GeneratedPresentationalRetriever.getEntityByName(GeneratedPresentationalRetriever.java:79)
        at com.foo.codegeneration.generators.MapperGenerator.generateEntityToDTOMapMethod(MapperGenerator.java:128)
        at com.foo.codegeneration.generators.MapperGenerator.generate(MapperGenerator.java:63)
        at com.foo.codegeneration.CodeGenerator.main(CodeGenerator.java:96)

I tried to change the Standard output class location, but I can't seem to find where to put the compiled classes. I also tried many other things not related to this problem when trying to understand what was the problem.





Aucun commentaire:

Enregistrer un commentaire