As I move through the metamodel code, I try to keep an eye on things we
want to do eventually and where/how they might fit in the new mapping
processing and binding code.
One of the changes we are going through is the move to Jandex. Mainly we
are using Jandex for its "annotation indexing" capabilities. But Jandex
also has some limited ability to query class relationships, mainly in terms
of hierarchies. For example, Jandex lets you ask for all classes that are
extensions of a given class or for all classes that are implementations of
a given interface.
This last part combined in my head with a previous discussion we have had
with regard to "dynamic models". The idea was to support generic contracts
on the Hibernate Session interface. The main difficulty there being in how
@Proxy is handled internally versus on the API. Given an entity like:
@Entity
@Proxy(proxyClass=Employee.class)
class EmployeeImpl implements Employee {
...
}
the problem is the attempt to type the return of, e.g., Session#get based
on the Class parameter passed in because atm you'd have to pass in
EmployeeImpl.. but the result would not necessarily be castable to
EmployeeImpl.
The "simple" solution for this is to allow some form of call where the
Employee interface is passed in rather than the EmployeeImpl class.
Internally this most likely means a cross reference from Employee
->Persister just like we already do for EmployeeImpl->Persister. We'd want
to be VERY sure there is only one impl per interface in this model. Jandex
can help there. Not sure how to best handle "persistent inheritance" and
especially middle types. I think the difference
between org.jboss.jandex.IndexView#getKnownDirectImplementors
and org.jboss.jandex.IndexView#getAllKnownImplementors can be leveraged
here.
Then we had expanded the previous discussion to look at the more general
case... interface based models. Imo, the best way to map the above model
would be:
@Entity
interface Employee {
...
}
Yes, this deviates from JPA which explicitly says that only classes can be
annotated. The question is whether we think its worthy of a "vendor
extension".
This mapping could be interpreted in one of 2 ways:
1) We assume that there is a class that implements this interface
(EmployeeImpl) and use that as the concrete class. A lot of the discussion
previously was how to "bind" the interface and the concrete class. Again,
Jandex can help us there by telling us about "known implementors". More
than one would be an error I guess.
2) We'd dynamically generate a class to back this. This generated class
can contain many of the performance tweaks we've been developing via
bytecode extensions (inline dirty-checking, "entity entry" info, etc).
Note that many of the "Jandex can help us" statements make an assumption
that Jandex knows about all the classes we are interested in. In the
WildFly/Jipijapa deployment case that is not a problem. In other scenarios
it is something to be mindful of since we'd need to properly feed the
indexer (which is a concern anyway outside of this discussion).