[hibernate-dev] Using Hibernate ORM as automatic JPMS modules
Gunnar Morling
gunnar at hibernate.org
Tue Jan 2 16:12:09 EST 2018
2017-12-28 18:07 GMT+01:00 Steve Ebersole <steve at hibernate.org>:
> Gunnar, back to the original discussion...
>
> I asked you about this specifically in Paris and you responded "no" - but
> reading info I have found online seems to indicate that it is indeed
> perfectly valid to build with Java 9 and include a module-info.class into
> the jar and be able to load that into Java 8 (module-info is simply
> ignored). Are the resources I have read just wrong?
>
I think it's feasible to do this (assuming of course that the class files
other than module-info.class are compiled to Java 8 byte code level). The
module-info.class file should be ignored, although there are some
exceptions, e.g. Jandex used to stumble upon the module-info.class file
until recently (as it's doing its own scanning of JARs). This one has been
fixed, but other libraries doing their own scanning may have similar
problems.
What's definitely not recommended is to publish a modularized JAR with
dependences to non-stable module names (i.e. dependences to any JARs which
neither have an Automatic-Module-Name header nor a proper module-info.class
descriptor, see
http://blog.joda.org/2017/05/java-se-9-jpms-automatic-modules.html).
Besides that I'd expect a few more changes to be required in order to make
ORM a modularized JAR. One specific issue is related to retrieval of XSDs
(or more generally any resources loaded from ORM's own module). Currently
this is done via ClassLoader#getResource() (see
PersistenceXmlParser.resolveLocalSchema() and ClassLoaderServiceImpl),
which will return null for resources in named modules unless that module is
opened (see
https://docs.oracle.com/javase/9/docs/api/java/lang/ClassLoader.html#getResource-java.lang.String-),
which of course isn't desirable for the ORM module. The recommended way to
load resources from your own module is to use Class#getResources() (or an
equivalent on Module, which would tie this code to Java 9, though) as per
Mark Reinhold (see
https://stackoverflow.com/questions/45166757/loading-classes-and-resources-in-java-9/45173837
).
I've pushed an update to the "orm-modularized" branch in my exploration
repo (
https://github.com/gunnarmorling/hibernate-orm-on-java9-modules/tree/orm-modularized),
which makes ORM a named module and runs the same test as before. By making
it an open module, the issue described above is circumvented, but I
wouldn't be surprised if there were more issues of that kind when doing
some more advanced tests for other ORM functionality.
>
>
> On Thu, Dec 28, 2017 at 9:06 AM Steve Ebersole <steve at hibernate.org>
> wrote:
>
> > After tweaking this, here is what I have...
> >
> > Manifest-Version: 1.0
> > Created-By: 1.8.0_121 (Oracle Corporation)
> > Main-Class: org.hibernate.Version
> >
> > Specification-Title: hibernate-core
> > Specification-Version: 5.3
> > Specification-Vendor: Hibernate.org
> >
> > Implementation-Title: hibernate-core
> > Implementation-Version: 5.3.0.SNAPSHOT
> > Implementation-Vendor-Id: org.hibernate
> > Implementation-Vendor: Hibernate.org
> > Implementation-Url: http://hibernate.org
> >
> > Automatic-Module-Name: org.hibernate.orm.core
> >
> > Bundle-ManifestVersion: 2
> > Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
> > Tool: Bnd-3.4.0.201707252008
> >
> > Bundle-SymbolicName: org.hibernate.orm.core
> > Bundle-Version: 5.3.0.SNAPSHOT
> > Bundle-Name: hibernate-core
> > Bundle-Description: A module of the Hibernate O/RM project
> > Bundle-Vendor: Hibernate.org
> > Bundle-DocURL: http://www.hibernate.org/orm/5.3
> > Bnd-LastModified: 1513615321000
> >
> > Import-Package: ...
> > Export-Package: ...
> >
> >
> > Which looks great to me...
> >
> > On Wed, Dec 27, 2017 at 3:39 PM Steve Ebersole <steve at hibernate.org>
> > wrote:
> >
> >> I had intended this for 5.3 which hasn't even gone Beta yet (we wont
> have
> >> an Alpha).
> >>
> >> On Wed, Dec 27, 2017 at 3:38 PM Brett Meyer <brett at hibernate.org>
> wrote:
> >>
> >>> +1 from me on making them consistent. In practice, Bundle-SymbolicName
> >>> isn't used for much, other than a guaranteed unique identifier. One of
> >>> the Karaf guys pointed out that Bundle-SymbolicName is used to link a
> >>> fragment bundle to its host bundle, but we've been able to avoid
> >>> fragments like the plague on purpose.
> >>>
> >>> In practice, most users should be pulling in and interacting with our
> >>> bundles purely through Maven artifacts or our features.xml, so a change
> >>> would largely be unnoticed.
> >>>
> >>> We still might consider holding off doing that until at least a minor
> >>> version change, since there is a potential issue for any tooling that
> >>> might be relying on that (logging/auditing, etc.)...
> >>>
> >>>
> >>> On 12/23/17 11:38 PM, Steve Ebersole wrote:
> >>> > Another thing I was noticing was an annoying minor difference between
> >>> the
> >>> > OSGi bundle name and the Java 9 module name:
> >>> >
> >>> > Automatic-Module-Name: org.hibernate.orm.core
> >>> > Bundle-SymbolicName: org.hibernate.core
> >>> >
> >>> > Does it make sense to adjust the OSGi bundle name to follow the
> module
> >>> > naming?
> >>> >
> >>> > On Sat, Dec 23, 2017 at 8:47 AM Steve Ebersole <steve at hibernate.org>
> >>> wrote:
> >>> >
> >>> >> I already did a PR for the `Automatic-Module-Name` yesterday and
> >>> added you
> >>> >> as a reviewer. when you get a chance...
> >>> >>
> >>> >>
> >>> >>
> >>> >> On Sat, Dec 23, 2017 at 8:36 AM Gunnar Morling <
> gunnar at hibernate.org>
> >>> >> wrote:
> >>> >>
> >>> >>> 2017-12-22 23:07 GMT+01:00 Steve Ebersole <steve at hibernate.org>:
> >>> >>>
> >>> >>>> I created a Jira to track this:
> >>> >>>> https://hibernate.atlassian.net/browse/HHH-12188
> >>> >>>>
> >>> >>>> On Fri, Dec 22, 2017 at 5:33 AM Steve Ebersole <
> steve at hibernate.org
> >>> >
> >>> >>>> wrote:
> >>> >>>>
> >>> >>>>> Thanks for investigating this Gunnar.
> >>> >>>>>
> >>> >>>>> Some thoughts inline...
> >>> >>>>>
> >>> >>>>> On Wed, Dec 20, 2017 at 3:54 PM Gunnar Morling <
> >>> gunnar at hibernate.org>
> >>> >>>>> wrote:
> >>> >>>>>
> >>> >>>>>
> >>> >>>>>> * JDK 9 comes with an incomplete JTA module (java.transaction),
> >>> so a
> >>> >>>>>> complete one must be provided via --upgrade-module-path (I'm
> >>> using the
> >>> >>>>>> 2.0.0.Alpha1 version Tomaz Cerar has created for that purpose)
> >>> >>>>>>
> >>> >>>>> Do you know if there is a plan to fix this in Java 9? Seems
> >>> bizarre
> >>> >>>>> that Java 9 expects all kinds of strict modularity from libraries
> >>> and
> >>> >>>>> applications when the JDK itself can't follow that..
> >>> >>>>>
> >>> >>> The "java.transaction" module of the JDK is marked with
> >>> >>> @Deprecated(forRemoval=true) as of Java 9, but I don't know when
> the
> >>> >>> removal will happen. There's JEP 320 for this (
> >>> >>> http://openjdk.java.net/jeps/320), which also describes why the
> >>> module
> >>> >>> exists in its current form. It's not scheduled for Java 10
> >>> currently, and
> >>> >>> given the latter is in rampdown already, I wouldn't expect this
> >>> removal to
> >>> >>> happen before Java 11.
> >>> >>>
> >>> >>>
> >>> >>>>>> * hibernate-jpa-2.1-api-1.0.0.Final.jar can't be used as an
> >>> automatic
> >>> >>>>>> module, as the automatic naming algorithm stumples upon the
> >>> numbers
> >>> >>>>>> (2.1)
> >>> >>>>>> within the module name it derives; I'm therefore using my
> ModiTect
> >>> >>>>>> tooling (
> >>> >>>>>> https://github.com/moditect/moditect/) to convert the JPA API
> JAR
> >>> >>>>>> into an
> >>> >>>>>> explicit module on the fly
> >>> >>>>>>
> >>> >>>>> We actually no longer use that artifact as a dependency. Since
> JPA
> >>> >>>>> 2.2, the EG publishes a "blessed" API jar which is what we use
> as a
> >>> >>>>> dependency.
> >>> >>>>>
> >>> >>> Ah, yes, very nice. That one already defines an explicit module
> name
> >>> >>> ("java.persistence") via the Automatic-Module-Name manifest entry.
> >>> >>>
> >>> >>>>>> * When using ByteBuddy as the byte code provider, a reads
> >>> relationship
> >>> >>>>>> must
> >>> >>>>>> be added from the user's module towards hibernate.core
> ("requires
> >>> >>>>>> hibernate.core"). This is due to the usage of
> >>> >>>>>> org.hibernate.proxy.ProxyConfiguration within the generated
> proxy
> >>> >>>>>> classes.
> >>> >>>>>> Ideally no dependence to the JPA provider should be needed when
> >>> solely
> >>> >>>>>> working with the JPA API (as this demo does), but I'm not sure
> >>> whether
> >>> >>>>>> this
> >>> >>>>>> can be avoided when using proxies (or could we construct proxies
> >>> in a
> >>> >>>>>> way
> >>> >>>>>> not requiring this dependence?).
> >>> >>>>>>
> >>> >>>>> I'm not sure what a decent solution would be here. Ultimately
> the
> >>> >>>>> runtime needs to be able to communicate with the generated
> proxies
> >>> - how
> >>> >>>>> else would you suggest this happen?
> >>> >>>>>
> >>> >>> Not sure either. Maybe we could generate a dedicated interface into
> >>> the
> >>> >>> user's module and then inject a generated implementation -- living
> >>> within
> >>> >>> the ORM module -- of that interface into the entities. Worth some
> >>> tinkering
> >>> >>> I reckon.
> >>> >>>
> >>> >>>>> * When using ByteBuddy as the byte code provider, I still needed
> >>> to have
> >>> >>>>>> Javassist around, as it's used in ClassFileArchiveEntryHandler.
> I
> >>> >>>>>> understand that eventually this should be using Jandex, but I'm
> >>> >>>>>> wondering
> >>> >>>>>> whether we could (temporarily) change it to use ASM instead of
> >>> >>>>>> Javassist
> >>> >>>>>> (at least when using ByteBuddy as byte code provider, which is
> >>> based on
> >>> >>>>>> ASM), so people don't need to have Javassist *and* ByteBuddy
> when
> >>> >>>>>> using the
> >>> >>>>>> latter as byte code provider? This seems desirable esp. once we
> >>> move to
> >>> >>>>>> ByteBuddy by default.
> >>> >>>>>>
> >>> >>>>> Yes, Sanne brought this up in Paris and it is something I will
> >>> look at
> >>> >>>>> prior to a 5.3.0.Final
> >>> >>>>>
> >>> >>> Excellent.
> >>> >>>
> >>> >>>>> * Multiple methods in ReflectHelper call setAccessible() without
> >>> >>>>>> checking
> >>> >>>>>> whether the method/field/constructor already is accessible. If
> we
> >>> >>>>>> changed
> >>> >>>>>> that to only call setAccessible() if actually needed, people
> would
> >>> >>>>>> have to
> >>> >>>>>> be a little bit less permissive in their module descriptor. It'd
> >>> >>>>>> suffice
> >>> >>>>>> for them to declare "exports com.example.entities to
> >>> hibernate.core"
> >>> >>>>>> instead of "opens com.example.entities to hibernate.core",
> unless
> >>> they
> >>> >>>>>> mandate (private) field access for their entities.
> >>> >>>>>>
> >>> >>>>> Can you open a Jira for that?
> >>> >>>>>
> >>> >>> Done: https://hibernate.atlassian.net/browse/HHH-12189.
> >>> >>>
> >>> >>>
> >>> >>>>>> The demo is very simple (insert and load of an entity with a
> lazy
> >>> >>>>>> association). If there's anything else you'd like to try out
> when
> >>> >>>>>> using ORM
> >>> >>>>>> as JPMS modules, let me know or just fork the demo and try it
> out
> >>> >>>>>> yourself
> >>> >>>>>>
> >>> >>>>> IIUC for jars targeting both Java 8 and Java 9 we cannot include
> a
> >>> >>>>> module-info file. But we need to set the module names - you
> >>> mentioned
> >>> >>>>> there was a "hinting" process. From what I could glean from
> >>> searching
> >>> >>>>> (which was oddly not many hits), this is achieved by adding a
> >>> >>>>> `Automatic-Module-Name` entry in the JAR's MANIFEST.MF. Correct?
> >>> >>>>>
> >>> >>> Yes, exactly that's the mechanism. Jason Greene is working on a
> >>> document
> >>> >>> with recommendations around naming patterns, I hope it'll be
> >>> published soon.
> >>> >>>
> >>> >>>
> >>> >>>>> Also, IIRC we agreed with `org.hibernate.orm` as the base for all
> >>> ORM
> >>> >>>>> module names, so we'd have:
> >>> >>>>>
> >>> >>>>> - org.hibernate.orm.c3p0
> >>> >>>>> - org.hibernate.orm.core
> >>> >>>>> - ...
> >>> >>>>>
> >>> >>>>>
> >>> >>>>>
> >>> >>>>>
> >>> >>>>>
> >>> > _______________________________________________
> >>> > hibernate-dev mailing list
> >>> > hibernate-dev at lists.jboss.org
> >>> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
> >>>
> >>>
> >>> _______________________________________________
> >>> hibernate-dev mailing list
> >>> hibernate-dev at lists.jboss.org
> >>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
> >>
> >>
> _______________________________________________
> hibernate-dev mailing list
> hibernate-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
More information about the hibernate-dev
mailing list