[hibernate-dev] Scanner contract

Steve Ebersole steve at hibernate.org
Mon Mar 18 11:40:35 EDT 2013

On Mon 18 Mar 2013 09:10:40 AM CDT, Emmanuel Bernard wrote:
> That was the point of the Scanning API in the first place: not to depend
> on specific APIs like the VirtualFile. That and the fact that JBoss AS
> had Jandex and we did not were the reason for Ales and me to have this
> interface.
Ok, but the decision to ask the Scanner these questions for each jar is 
inadvertently requiring Hibernate to be sensitive to these protocols.  
In fact the current standard Scanner impl has explicit handling for VFS 
protocol schemes.  And for OSGi, it would require that the single root 
URL (because again thats all we get) actually encompasses the root jar 
*and* any other specified jars.  Aka, `if ( "bundle".equals( urlProtocol 
) ) { doSomethingDrasticallyDifferent(); }...`.

So take the EE case, which I know is true of JBoss.  JBoss is the one 
handing us the PersistenceUnitInfo (which is the thing that backs the  
PersistenceUnitDescriptor we pass back to it in this Scanner proposal).  
I don't think it is unreasonable that JBoss understands the difference 
between PersistenceUnitInfo#getPersistenceUnitRootUrl and 
PersistenceUnitInfo#getJarFileUrls intrinsically (after all, it is the 
one that gave us the PUI).  By intrinsically I mean that it already 
understands that there is a difference/distinction between the root and 
any non-roots.  So from there the question really is whether expecting 
the Scanner to apply different scanning rules to root versus not-root 
URLs constitutes "deep JPA knowledge".  And maybe that is different for 
each type of thing for which we scan.

For classes e.g. nothing stops us from saying the the Scanner just 
returns us everything it finds and that we then filter or weed through 
it.  For example, if it returns us descriptors for all the classes it 
finds, we can apply the "only use that class if it (a) came from a 
specified jar or (b) came from the root and #excludeUnlistedClasses 
allows us to use them" logic ourselves. Thats a trivial matter of us 
defining the ClassDescriptor contract to tell us whether the class was 
found in the root or not:

interface ClassDescriptor {
     public String getClassName();
     public NamedInputStream getNamedInputStream();
     public boolean foundInRoot();

But again, I dont think that the Scanner applying that simple logic is 
really "deep JPA knowledge".  But if everyone else agrees it is, we can 
easily alleviate that via the above pattern.

As for resources (orm.xml and hbm.xml files), I'd have to look a little 
closer maybe.  To be honest that is some of the code that uses the "Map 
as an API" approach that makes me want to rip out my hair, gouge out my 
eyes and leap off the nearest bridge :)  It is code like this code that 
has made me want to re-write what was EJB3Configuration from scratch 
ever since I first started looking at it.  That and the fact that any 
time I ask anyone that had a hand in writing that code anything about 
that code they simply throw up their hands and say they don't know ;)

Maybe it is more complicated than I am making it out to be.  But I don't 
think the way this is then presented to the rest of the code needs to be 
complex.  At the end of the day, there should be a scan and the results 
of that scan should be a nice easy-to-understand contract.

> The previous implementation of Scanner was returning the resource
> streams so you had to take PUI.getMappingFileNames() into account. I got
> confused.

Still not following.  The proposed Scanner contract is returning 
NamedInputStreams, which is exactly what the current Scanner returns for 

> No that's what the JPA spec says (or intended), additional jars are to 
> be scanned to
> find the entity classes. Otherwise the additional jar feature becomes
> very limited or even useless. You would only need it otherwise to
> retrieve the XML DD which was considered a second class citizen on JPA 
> 1.0.

Ok, but is that "deep JPA knowledge" beyond what a typical JPA container 
developer would generally know?

>>> - look for META-INF/orm.xml in the root JAr (only) and exclude it if it
>>> is already listed explicitly in the getMappingFileNames to not process
>>> it twice.
>> Not sure how this is classified as "deep JPA knowledge".
> Understanding and implementing all these rules took me a while :)
Ok, don't include duplicates.. check.  ;)  Not saying the rules are 
simplistic.  Just questioning whether they are only known to those with 
"deep JPA knowledge".  Not so sure that is true.

> I gave you my opinion, if you think that implementing Scanner will
> remain simple enough then most of my remarks are moot.

Considering I will implement the 3 main Scanner impls... ;)  But 
seriously, I don't think delegating to Scanner just once per persistence 
unit puts undue difficulty on the Scanner impl.

More information about the hibernate-dev mailing list