JBoss Modules has a redirection mechanism for JAXP that allows us to
override the default provider with one from a module, while still
allowing TCCL-based selection to occur. Since Java 9, our
implementation violates the stricter reflection rules that are now in
place, meaning that JBoss Modules will probably stop working in a
future version. We had hoped that Java 9 would have some useful way
to establish the default implementation of various JAXP factories, but
that never happened. So I want to take the opportunity to review a
few mitigation options and get some feedback.
Option 1: Fix the redirection facility in Java 9
Java 9 offers a "newDefaultFactory()" method on most (maybe all) of
the JAXP factory classes, which always simply instantiates the system
provider of the given function. Using this method should allow us to
bypass the now-disallowed reflection by switching all of the cached
Constructor<? extends T> fields with cached Supplier<T> fields, whose
implementation would either be a call to the appropriate
newDefaultFactory() or a service loader-style public Constructor call.
Pros:
• Less change
• We can still override the default JAXP implementation
Cons:
• Continue carrying around the baggage of the __redirected code
until/unless the JAXP spec is modified to allow setting the default
factories
Option 2: Stop using redirection in Java 9, "cold turkey"
We could delete these classes completely. Instead of setting the
default JAXP implementation, we ensure that any modules using JAXP
have a services dependency on the implementation(s) corresponding to
those APIs, carefully monitoring TCCL setup and usage or ensuring that
the newFactory(xxx, getClass().getClassLoader()) form is always used,
depending on the situation.
Pros:
• No more dealing with redirection ever again
• While deployments generally use the newFactory() form, but
deployments also have TCCL set so that's not a problem
• One less source of bugs
Cons:
• It may be hard to be sure that we've done this 100% correctly in all
cases outside of deployments; the results could be weird mixed
implementations
Option 3: Use a dependency strategy
We could cause JBoss Modules to always include a "hidden" last
dependency on our chosen default JAXP implementation, which in turn
could be set up by a service loader configuration in the boot module.
Pros:
• Simpler than redirection
Cons:
• Due to the way JAXP works, we have to pollute the target module's
namespace with the implementation classes (though with redirection
we've already done that via __redirected classes)
So far Option 1 is (unfortunately) still looking the best to me,
overall. Does anyone have any differing opinions on this?
--
- DML