kumuluz / kumuluzee

Lightweight open-source framework for developing microservices using standard Java EE technologies and migrating Java EE to cloud-native architecture.
https://ee.kumuluz.com
MIT License
291 stars 71 forks source link

Not possible to introspect the uberJar classpath by resource partial name #148

Open ikonkere opened 5 years ago

ikonkere commented 5 years ago

It's not currently possible to look for classes on the classpath that reside in the uberJar itself using only their partial names (i.e. name of a package) because of this line in EeClassLoader: https://github.com/kumuluz/kumuluzee/blob/62f1ea9e6824b67c7b66391a62da165f944bf000/tools/loader/src/main/java/com/kumuluz/ee/loader/EeClassLoader.java#L297. The introspection works for classes in jars, so a quick solution might be just to move the classes from inside the uberJar to a separate lib jar, but it's an inconvenience; the runtime should not impose such limitations on the project structure.

I wonder if this behaviour is intentional, and if so - what was the intention, and whether the line 297 can be patched with something like if (fileInfo.getSimpleName().startsWith(name)) {?

ikonkere commented 5 years ago

PS. Now that i was approved full access to github from office, i can implement a necessary fix, but i'm not ready to commit to core without discussing with you guys first.

urbim commented 5 years ago

I don't think ClassLoader's getResource is supposed to work this way (see: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ClassLoader.html#getResource(java.lang.String)).

Package scanning is not really supported by ClassLoaders. Classes are loaded dynamically and thus ClassLoader doesn't have to know what packages it provides.

I recommend you use something like https://github.com/classgraph/classgraph instead. There are some specifics concerning Uberjars but we have successfully used the library here: https://github.com/kumuluz/kumuluzee-openapi-mp/blob/a7e3d4b077a4ce9f2aa2590a61f652bc5ae1ebc8/core/src/main/java/com/kumuluz/ee/openapi/mp/OpenApiMpExtension.java#L103.

ikonkere commented 5 years ago

I saw you using classgraph in there, ok i'll give it a try.

ikonkere commented 5 years ago

ClassLoader's getResource is supposed to work this way

Actually it does work sort of this way. I just debugged BuiltinClassLoader from JDK 12, which is the superclass for all classloaders by default, and when #getResources(String) would be called with something like "com/kumuluz/ee" it will return a URL for this directory, while EeClassLoader would return nothing.

I think it must behave at least the same way, otherwise it breaks alot of stuff relying on this behaviour. I suggest the issue be reopened.

urbim commented 5 years ago

I mean this is questionable at best. The fix would require a lot of work and testing and may have an impact on performance of KumuluzEE. I don't see enough benefits from this functionality. If you really need this behaviour I suggest you run the application as exploded.

ikonkere commented 5 years ago

I don't see enough benefits from this functionality

So the fact that by not having this functionality (because you chose to interpret the specification the way that suits you) you break the expected classloader behaviour doesn't bother you at the slightest?

urbim commented 5 years ago

How a classloader is supposed to behave is defined in the javadocs and not by observing behaviour of a JDK classloader of your choice.

I haven't seen anything that relies on the behaviour you describe or heard of any use-case where this would be desirable.

EeClassLoader is a core class for the KumuluzEE implementation and we don't take changes to it lightly. What I'm saying is that we are not prepared to allocate resources to implement this feature or even potentially review a PR proposing an implementation.

ikonkere commented 5 years ago

How a classloader is supposed to behave is defined in the javadocs

A directory is a resource and so if i wanted to get a reference to a directory relative to the classpath root (which in no way contradics the spec), then the desired behaviour is definitely not present.

haven't seen anything that relies on the behaviour you describe

Spring Framework depends on this very behaviour since 2003.

a JDK classloader of your choice.

Well, if how OpenJDK (which is literally the RI of the JDK spec) behaves is just something you find inconsequential, then there's nothing else i can say.

ikonkere commented 5 years ago

Oh yes, did i forget to mention that getResources breaks even what you suggest it does and behaves inconsistently depending on whether the directory is in a jar, or not? In the former case you seem to have no issues with interpreting the spec in a certain way and return a directory URL within a jar.

Do you think that such inconsistent behaviour is also according to the JDK spec?

urbim commented 5 years ago

Ok, we will take a look at it.