And Oracle has a lot of relevant experience as well, since the shared
loader mechanism I created for our AS stack ("shared libraries")
supports only the import-by-name model. We have *lots* of
shared-libraries (I've seen 100+ running simultaneously), used by many
different components in the stack, in addition to customer applications.
It is a tremendous pain when refactoring or even simple renaming has to
be done (I hope to shift this implementation onto 277 to solve this
problem, rather than inventing an interim approach). And this kind of
change happens far more frequently than you probably expect.
I don't want to repeat the same mistake here. Nor do I think that
leaving a long trail of extraneous "view" modules behind for
compatibility is a good solution.
Worse still, if the 277 APIs don't support import-by-package, then the
compiler won't support it either. If the compiler doesn't support it,
then we've lost a golden opportunity to move to a better world, one in
which packaging is irrelevant.
We're supposed to be eliminating "jar-hell" here. Let's not simply
replace it with "module-hell".
In this context, the question is really about what
it would take to make #4 possible if we want to support it, and so far
there are two different approaches we have discussed:
a. Treat import-by-package separately from import-by-module in the
reflective APIs and make the module layer fully aware of the
import-by-package concept.
b. Expose exported-package using the ModuleDefinition abstraction, and
provide necessary hooks (e.g. consistency checking) for the module
system to resolve this kind of dependency appropriately. The module
layer is not aware of the import-by-package concept at all. New import
dependency granularity could also be introduced in a similar manner in
the future without requiring significant changes in the module layer.
As Richard and I discussed in previous emails, it seems to make the most
sense for JSR 277 to define the minimal set of features possible in the
module layer to accomplish what needs to be accomplished to provide core
modularity support in the Java platform. I think (b) follows this
principle nicely while (a) does not. If we decide to support #3 and #4,
then how we want to address #4 would impact our overall design
significantly.
Is there anyone in the EG provide good reasons why #3 and #4 are
important to be supported? If so, is there anyone in the EG think (b) is
not feasible at all and we should do (a) instead to support #4? Can you
explain your rationale?
Yes, and yes. See above for rationale (ease-of-refactoring and compiler
support).
> RESOLUTION MODELS
>
> The current design requires that each ModuleSystem provide its own
> resolution logic, and that each definition will be resolved by its
> owning ModuleSystem. This model appears to provide flexibility for
> significant differences in implementation, but we really don't know
> enough at this point. Perhaps only an actual second implementation
will
> tell us if this provides useful flexibility.
In the existing module systems we are aware, e.g. OSGi and NetBeans, we
already know their resolution logics are different from each other. Even
if they are migrated/re-based to JSR 277 in the future, I think we
should expect their resolution logic would remain the same to maintain
backward compatibility with their existing modules/bundles. In other
words, their resolution logic would still be different from each other.
And this is very likely to be the source of subtle but very painful
interop issues. Which is why I also suggested that we should consider
moving to a canonical, though evolvable, resolution mechanism.
A phased approach would be particularly beneficial if the initial phase
could be delivered as part of Java 7 and subsequent phases implemented
strictly on top of Java 7. But getting the API right up front might be
tricky unless we can spot some really good abstractions or prototype
the
later phases sufficiently well. Is that the kind of phasing you had in
mind?
Once an API is put into the SE platform, it will stick around almost
forever. I think if we go with the phased approach on interoperability
support (I believe this is what Bryan suggested), it would be much
better to simply left out those features/APIs which do not have
implementations to back them up from JDK 7, rather than putting the
half-baked features/APIs into the release and regret later. ;) We can
always add new APIs in subsequence releases if we decide to offer better
degree of interoperability in the future.
I couldn't agree more that we don't want to put half-baked APIs into SE!
If we cannot expect significant validation of our interoperation model
(whatever we settle on) from NetBeans and OSGi, then we shouldn't expose
these APIs at all. Period.
But this doesn't just apply to import-by-package. We haven't even
defined how class and resource sharing will occur. I won't be a bit
surprised if we want one or more new types here.
And, last thoughts for the day...
Even if you are adamantly opposed to import-by-package, please take a
good look at the other ideas buried in my message from yesterday,
particularly the ModuleContext proposal.
It is completely independent of import-by-package, and seems to me at
least to be a concise, flexible model for caching/isolating/finding
Module instances. (The idea of exposing a resolve() method on it also
makes a clean API, even if it delegates to ModuleSystem instead of a new
resolver type.)
There are other potentially interesting tidbits there as well
(PlatformBinding exposure on definition, Query support for current
platform, ImportDependency *as* Query).
I'd hate for the baby to be thrown out with the bath water :^)
// Bryan
- Stanley