spring-projects / spring-modulith

Modular applications with Spring Boot
https://spring.io/projects/spring-modulith
Apache License 2.0
813 stars 140 forks source link

Support JPMS #837

Closed xenoterracide closed 1 month ago

xenoterracide commented 1 month ago

So I want to use my JPMS modules as modulith modules. I looked at writing my own ApplicationModuleDetectionStrategy but it seems to hide the real class and thus I can't actually ask for the ask the module-info if it's got an annotation, with which to make determinations.

I'm certain I can figure out another way, but it'd be nice if this was somehow supported directly. Even if the support is limited to a custom strategy if you could make JavaPackage and JavaClass expose some kind of getModule that'd be great. Alternatively even exposing the real Class would get me there easier.

odrotbohm commented 1 month ago

ApplicationModuleDetectionStrategy works based on packages because they'll be in place with JPMS included or not. You could certainly try something around accessing the classes contained in the package, call reflect() on those and finally traverse into getModule(). But as there's no direct relationship between a Java package and a JPMS module on the reflection API level, we cannot expose the module corresponding to a package.

So I want to use my JPMS modules as modulith modules.

If we resort only to satisfy that goal, you should be fine by laying out the package structure as expected or annotating the Java Module's base package with @ApplicationModule (or jMolecules' @Module) and using the explicitly annotated detection strategy.

xenoterracide commented 1 month ago

Java Module's base package

This isn't actually required to exist according to JPMS. You could do this if you wanted, leaving no root package. Obviously not a great idea though, and certainly wouldn't agree with either of our principals.

export org.example
export com.foo

JPMS also doesn't see hierarchy, so org.example.foo is not a subpackage of org.example. Both are just unique keys (similar to S3 where some people name keys according to a file hierarchy). Technically when I say JPMS, I mean java. JPMS or not, the JVM doesn't see a hierarchy. JPMS just enforces unique keys and makes this more obviou.

ApplicationModuleDetectionStrategy works based on packages because they'll be in place with JPMS included or not. You could certainly try something around accessing the classes contained in the package, call reflect() on those and finally traverse into getModule(). But as there's no direct relationship between a Java package and a JPMS module on the reflection API level, we cannot expose the module corresponding to a package.

It does all essentially start at the "application" class right? You look at that to get the root package.

In JPMS a given package can only exist within a single module. A class is declared unique with its package. So any given class may only exist within a single module. So on and so forth, you could explose a JavaModule class on a JavaPackage or JavaClass because JPMS enforces that uniqueness. Even if you only exposed getModule on JavaClass that would also make it easier, and there is a relationship there in Java's model.

or jMolecules' @Module

I opened a ticket to discuss allowing this on a JPMS module before even opening this ticket.

I believe though that what we're talking about has also lead to #838

odrotbohm commented 1 month ago

I honestly don't know what the intention of the discussion is. Given the amount of time this (and a lot of the other tickets are draining) I'm gonna close this, as all I would do is continue to reiterate on things I already stated.