Module isolation
Stanley M. Ho
Stanley.Ho at sun.com
Wed Jun 20 12:54:35 PDT 2007
Hi Bryan,
Sorry, I was sidetracked in the last two days, will follow up other
threads soon.
Bryan Atsatt wrote:
> This use case seems to presume that the IDE can/will ensure that there
> is only *one* consumer of the module: itself. What if a different plugin
> has a dependency on it, and has already been resolved? Is the intention
> that the IDE will be wired into the module system deeply enough to
> manage this correctly?
It won't affect existing plugins that has also been initialized with the
dependency. My assumption is that the IDE should know what it's doing
when using the APIs.
> An application server, for example, will need to keep one application
> from accessing the modules of another. And it must *know* that there is
> no sharing, so that the application lifecycles can remain independent.
>
> So we need some notion of a context. A purely private repository
> instance is one (probably good) possibility. Another is the wrapper
> Repository approach, but this requires definition copies (and management
> of sharing content, lifecycle, etc).
The way I see it is that the repository is the context that you want to
use for isolation. The APIs allow developers only to walk up the parent
repository instance from a child repository instance, but not vice
versa. If the repository instance is only used in a specific domain
(e.g. webapp) and the repository instance is hidden from other
applications (e.g. other webapps), this would effectively hide the
modules in that repository and the repository could be considered
private. Whether such repository is constructed using the wrapper
approach or reusing existing ModuleDefinitionContent is an
implementation detail. Do you agree?
> Regardless of what approach we take, the releaseModule() idea is too
> simplistic. Having originally created the detach() method, thinking
> along similar lines as you are with the plugin case, I do understand the
> idea; I just no longer think it is sufficient :^).
>
> The only "safe" time to release a module is when there are *zero*
> importers, and, even then, you must hide/release atomically, ensuring
> that no new imports spring up during the operation.
Releasing a module simply means that its reference is released from the
module system's cache; it does not affect any existing importer. Also,
hide and release does not need to happen atomically - I think hiding it
first would be sufficient to prevent new imports to be resolved, but
I'll need to double check it with the RI.
Note that I'm not arguing the releaseModule() approach is perfect, but I
do think this is a use case that we can ignore; I would welcome better
suggestion to handle this.
> Other than Module instances, what other "runtime information" is there
> to keep track of? Caches of exported packages?
The Module instances that have been initialized, the ModuleDefinitions
that are being instantiated and the corresponding Module instances that
are being initialized (could be triggered simultaneously from multiple
threads), and the ModuleDefinitions that have been disabled (e.g. the
repository has been shutdown and no new Module instance should be created).
> For example, if we were to eliminate the releaseModule() method (in
> favor of some more complete mechanism), then there really is always a
> 1:1 for Module:ModuleDefinition, and the model is simple and obvious.
> (And therefore a field cache *could* be used).
To keep this discussion focus, I think we could assume
Module:ModuleDefinition is 1:1 for now. releaseModule() is just a
special case. That said, even if the relationship is 1:1, it still
doesn't mean we *should* put the state in ModuleDefinition, see above. ;-)
> So, in effect, we have 100% *private repository* instances.
>
> I've been thinking that we need an intermediate somewhere between a
> shared/public repo instance and an entirely private one, but... that now
> strikes me as too fuzzy, and I can't see a real use case :^)
>
> So an application server would have to create, say, a private
> LocalRepository instance to hold the modules of a single application.
> And it would have to ensure that no other application could get it's
> grubby paws on that repository instance.
>
> Ok. That works for me. And it eliminates the need for cloning AND for
> releaseModule():
>
> 1. Any given Repository instance is either 100% shared or 100% private,
> with *no* in-between.
>
> 2. The lifecycle of a shared repository instance is that of the process.
>
> 3. The lifecycle of a private repository instance is entirely up to the
> creator of that instance.
I agreed that distinguishing the repository instances for sharing or
private usages is more easy to understand, but the notion of shared and
private really depends on the usage context, and it's not an attribute
of the repository itself. Suppose there is a repository with two child
repositories; this repository would be considered "shared" from the
perspective of the modules in the child repositories, but this
repository might still be considered private from the other applications
in the same JVM.
I think your first three points can be combined as follows:
1. Any given Repository instance could be used for sharing or private
purpose.
2. The lifetime of a repository instance is managed by its creator.
> 4. The lifecycle of a ModuleDefinition/Module is at most that of the
> enclosing Repository instance, and at least is bounded by
> install/uninstall (no finer granularity).
Yes.
> It does leave open the issue of dependencies *within* a private
> repository. The simple model would be to treat the entire repository as
> atomic, with any change requiring a new Repository instance. This is
> probably too simplistic, however.
>
> In an EE app, web-modules are supposed to be isolated from each other
> and from other parts of the app (ejb, connectors, etc.). So this
> requires either a further partitioning of the app into multiple
> repositories, or some form of access control.
The web-modules should probably be in its own repository if isolation is
needed. There is no access control for ModuleDefinitions - accessibility
of a ModuleDefinition is the same as visibility of ModuleDefinition;
this is also a very different issue. I think we should focus our
discussion on using repository instance for isolation unless we find
this approach insufficient.
> Further, it is possible to re-start or re-deploy/re-start only a single
> web-module, *without* restarting the rest of the app. The re-start case
> could use releaseModule(), though a "real" stop method would be
> preferable. But this is a very special case in which the specs
> essentially dictate the possible dependencies between modules. In the
> general case where the dependencies are not dictated, releaseModule() is
> problematic.
> The re-deploy case would use uninstall/install (but would still like
> stop!).
Whether the solution is stop() or releaseModule(), it still shows that
we need to support the use case of long-lived repository with
short-lived modules. Do you agree?
> If you *really* want the releaseModule() functionality, I would suggest
> that we introduce a PrivateRepository type, and support release *only*
> on that type.
The notion of private or shared depends on the usage context of the
repository instance, so it won't be appropriate to surface the concept
at the API level.
Bryan, there are many topics in this thread, but I think what you really
want is to discuss the notion of module isolation. As we discussed so
far, I think we all agreed that repository is the appropriate context to
make module isolation possible. Could you summarize any outstanding
design concern you have with this approach in a paragraph or two?
Thanks,
- Stanley
More information about the jsr277-eg-observer
mailing list