Hi Eduardo,
Se my commends inline:
On Apr 1, 2013, at 12:47 PM, Eduardo Martins <emartins(a)redhat.com> wrote:
Hi all, I have been looking at whole code of service based naming
stores, and we have several more issues (beyond the injection without lookup), some which
may motivate deep changes on the logic:
1. Subcontext created not stored
InitialContext context = new InitialContext();
context.createSubcontext("a");
Context a = (Context) context.lookup("a");
The lookup above fails, and this due to not creating sub contexts on the store. I
discussed this briefly with David last week, seems a bug, but it could also be done this
way as a feature. As it is now implemented, a context only exists if there a child entry.
It was certainly a design choice. Keep in mind that the EE contexts are read-only, so
supporting this kind of thing wasn't required (although it would be better if we threw
exceptions or something like that to say you can't do this). The one exception is of
course the writable areas that we allowed as an additional feature (where we let users
call bind).
In the case of a writable bind area, at the time it was decided to allow users to place
dependancies on things they bind. That way you could have something like an @Resource
pointing to something that a user manually creates. We should validate whether or not that
is still important. If it's not important, we could switch the writable areas to a
non-service based JNDI mechanism.
If we do keep the service backing approach we could just fix the bug by having
createSubcontext return a temporary Context (this is exactly what we do if you pull a
context that does have leafs).
Obviously by not having sub contexts we also fail on managing sub
contexts environments, it is always null, when it should start as the parent context's
one, and store changes on its own.
I don't follow this point, can you explain in more detail?
Note that this implementation choice was clearly made on purpose, there is no
destroyContext() impl at all (other than name validation and check for writable store
type).
This implementation choice saves the storing of a few msc services, but that also means
no dependencies to contexts will exist
Right all service based injectable components are not contexts, they are leaf nodes.
Maintaining branch nodes means additional locking and memory usage.
2. (Re)Bind without parent context
Context a = null;
InitialContext context = new InitialContext();
try {
a = (Context) context.lookup("a");
} catch (NameNotFoundException e) {
context.bind("a/b",new Object());
}
The bind above will succeed, i.e. we allow binds without parent context, but according to
Context javadocs bind or rebind require that the parent context exists.
Right this is a "feature" side effect when you don't have branches. I
don't think its a big deal.
3. Linkrefs madness
Currently the lookup logic, wrt links is more or less: lookup a msc service with the
provided name, and if nothing found look for a parent msc service, which if exists and is
a link then we try again with link value + remaining name. Then on bind we do not follow
links, we bind directly to the provided name, so:
InitialContext context = new InitialContext();
context.bind("a1",new LinkRef("a2"));
context.bind(new CompositeName("a2","b"),new Object());
context.bind(new CompositeName("a1","b"),new Object());
context.lookup(new CompositeName("a1","b"));
context.lookup(new CompositeName("a2","b"));
This will bind 2 values to the same "logic" name, and both lookups will work,
yet return the different values. To fix this on bind we should first lookup the parent
context, which if follows links correctly, would have failed context.bind(new
CompositeName("a1","b"),new Object())
There are also obvious link related issues on msc deps: if something is bound using a
name that contains a link, lookup deps will only work if use the name used in bind. Fixing
this part may be scary, msc would need to know that when a link is bound, deps to both
linksource/x and linktarget/y may become satisfied. Still on msc topic, rebind support is
also a problem.
This is another "feature" of not having contexts and having names reflect
services. There is no way to fix it without introducing branches and fat locks. This I
think goes back to the question of whether user directed bind() is service based and has
dependencies or if it's not and is just a locked tree.
4. Other issues
There are other issues, for instance rebind does unbind+bind, and this would mean that
any state (such as env on the old entry) is lost, msc deps get screwed, etc. but I did not
check these with testing yet, and we can probably target these later.
5. So, how do we fix all of this?
Well, for a start should we fix it? I know some people may want to avoid these kind of
changes, but naming is not quite something that is going away any soon, and imho our
naming is broken at so many ways…
Well first of all, we can't make changes like this in EAP 6.x due to all of the
compatibility implications. Second of all the primary purpose of service-backed naming is
not to be a fully complete writable JNDI implementation. That is of lesser concern because
the primary purpose is to support dependency wiring concurrently with decent CPU and
memory efficiency. As mentioned above though I'm open to using a different
implementation for bindable contexts (which would not allow for dependencies expressed
against them).
--
Jason T. Greene
JBoss AS Lead / EAP Platform Architect
JBoss, a division of Red Hat