jOOQ / jOOR

jOOR - Fluent Reflection in Java jOOR is a very simple fluent API that gives access to your Java Class structures in a more intuitive way. The JDK's reflection APIs are hard and verbose to use. Other languages have much simpler constructs to access type meta information at runtime. Let us make Java reflection better.
http://www.jooq.org/products
Apache License 2.0
2.81k stars 376 forks source link

Dynamic runtime compilation with custom classes #73

Open joanbonilla opened 5 years ago

joanbonilla commented 5 years ago

Hi,

I have a spring boot application with some custom code and I've tried to compile that sample with a custom class inside.

Can I compile dynamic classes with my custom code?

Expected behavior and actual behavior:

Expected: show the "Hello World!" message

Actual:

I get the next error (classloader):

Compilation error: /com/sample/soc/RuntimeCompilerTest.java:1: error: package com.sample.spring does not exist\r\npackage com.sample.soc; import com.sample.spring.WebsitesBO; class RuntimeCompilerTest implements java.util.function.Supplier { public String get() { return \"Hello World!\"; } }\r\n ^\r\n1 error\r\n

Steps to reproduce the problem:

Create package com.sample.spring and create Java class in this package named WebsitesBO

Copy the next code and run it:

Supplier<String> supplier = Reflect.compile(
            "com.sample.soc.RuntimeCompilerTest",
            "package com.sample.soc; " +
                    "import com.sample.spring.WebsitesBO; " +
                    "class RuntimeCompilerTest implements java.util.function.Supplier<String> { " +
                    "public String get() { " +
                    "return \"Hello World!\"; } " +
                    "}"
    ).create().get();

Versions:

Thank you

lukaseder commented 5 years ago

Thanks for your report and for creating the issue :)

It should definitely work (see also some tests here: https://github.com/jOOQ/jOOR/blob/master/jOOR/src/test/java/org/joor/test/CompileTest.java), but is the com.sample.spring package visible to the code that invokes the compile method?

lukaseder commented 5 years ago

Can you create a test case to help reproduce this?

joanbonilla commented 5 years ago

You can reproduce it with this repo: https://github.com/joanbonilla/dynamic-compiler

Run it with mvn spring-boot:run

lukaseder commented 5 years ago

I see, thanks for the test case. Very interesting. When I run the class in Eclipse, it works. It doesn't work from whatever the spring-boot:run goal is doing. This seems to be some sort of a class loader issue.

lukaseder commented 5 years ago

Does this issue fix it? https://github.com/jOOQ/jOOR/issues/65

lukaseder commented 5 years ago

Tried it myself. #65 doesn't seem to fix it

joanbonilla commented 5 years ago

I solved the issue with some tips in your library about the classloader, I needed to use the current Classloader

joanbonilla commented 5 years ago

Do you want the code I just implemented in a new branch?

lukaseder commented 5 years ago

Do you want the code I just implemented in a new branch?

Is that it? https://github.com/joanbonilla/jOOR/commit/34f2379c775c2b5caa6bc4218e6d26e5edb1ca1d

The solution would be something similar, but the ClassLoader reference would go into the CompileOptions argument type. That's why it was added - because I don't want to overload new methods every time a new compile option is being considered.

joanbonilla commented 5 years ago

Are you using CompileOptions as context pattern object?

lukaseder commented 5 years ago

I don't know what a "context pattern object" is

joanbonilla commented 5 years ago

I did another branch:

https://github.com/joanbonilla/jOOR/commit/2d97d14108a23617221cdfed93471951cd3be9ab

lukaseder commented 5 years ago

Thanks. I've had a look at this when taking an attempt at implementing #72. Your code will affect the JDK 8 distribution, but what about JDK 9+? How can we define a class on an existing class loader when we're no longer allowed to "open up" the ClassLoader.defineClass() method through reflection? Lookup can be used, but it is much more difficult to get right...