On 09/15/2011 05:50 AM, David M. Lloyd wrote:
Okay so after a bunch of discussion with various personages, it
looks
like we have some remote EJB client design shaken out. Please read
through a couple times to make sure you have gotten a clear
understanding to avoid questions that are already answered here.
Client API
----------
We'll introduce a concept of an "EJB invocation receiver" or "EJB
receiver" for short. The job of this fellow is to receive invocations
on behalf of a connection to a peer or a cluster or locally. So for the
Remoting transport, there is a 1:1 correspondence between connections
and EJB receivers.
Multiple EJB receivers can be collected up into a single "EJB client
context", each with a "preference" level. Same-VM receivers will
typically have a higher preference than remote receivers.
The scheduling of these contexts must take care not to starve the lower
preferred levels.
An EJB remote proxy (and by extension, its Handle) identify their EJB
by
the combination of application name, module name, "distinct" name, and
bean name. All of the equals()-type operations that are specified by
EJB are implemented in terms of this basic level of equivalence (though
some types have additional criteria, like SFSB using session ID as
well). There is no notion of a specific server address or URI in a
proxy or handle.
Definitely not a server address (or anything like that). An URI might
have a different meaning, see below.
The "distinct" name is an _optional_ name which can be
associated with a
deployment (by deployment descriptor, and possibly also by
configuration) in the event that two different deployments which are
visible from one client have the same application and module name.
(Yes, I know you can't have two deployments with the same app+module
name in one server; however, a client can "see" more than one server at
once and may need to distinguish, especially if the user does not
control the name of the deployment.)
An EJB client can at any point start communication with another server.
That other server can have the same set of EJBs. So having an "distinct"
name is not optional and needs to be in the proxy. It identifies the
client context to use over which the invocation needs take place. The
identification of the client context could be an URI (I don't see why not).
Each EJB receiver has an obligation to keep the EJB client context
updated with the list of module identities that it can access. When a
proxy is invoked upon, the EJB client context uses this table to select
the destination. This means that for the Remoting protocol for example,
the server sends back messages informing the client of changes in
deployment status (which should be relatively infrequent) as well as
sending an initial summary of what modules are available.
This doesn't scale up. If there are 10K EJBs deployed a client is rarely
interested in more than 5%, just the EJBs it invokes upon. Nor do we
want to send an update of 1K+ EJBs to every client connected on each
status change.
Most client interceptors are associated with both an EJB client
context
and a receiver type. This is because things like transactions,
security, etc. will vary in their implementation based upon the protocol
in use.
We _may_ support protocol-independent interceptors, however we'll have
to evaluate use cases first. If we do then most likely they'd work with
a protocol-dependent counterpart; for example, a general security
interceptor might attach additional principal information to the
invocation in a standard spot, which the protocol-specific interceptor
might then publish to the server (or not).
Maybe it is possible to use Externalizable as the protocol-independent
contract?
The only requirement here is backwards compatibility, not?
JBossPrincipal -> Principal10 -> bits -> Principal10 -> JBossPrincipal
Where the JBossPrincipal -> Principal10 transformation is done by a
specific interceptor.
An invocation on a remote proxy will use whatever EJB client context
is
current for the calling thread. Thus remote proxies and handles can be
passed from one context to another (directly or via cloning or
serialization) without any special action being taken. If no EJB client
context is available, remote invocation will fail immediately.
Remote Async Invocation
-----------------------
Any Session Bean remote interface method which returns a Future will
always be treated as asynchronous by the client. Methods which return
void but are visibly (to the client) marked with the appropriate
annotation will be treated as asynchronous. Other methods which return
void will not be automatically treated as asynchronous, though the
server protocol allows for a message to come back to inform the client
that the invocation will proceed asynchronously.
A method is only asynchronous if designated as such. (EJB 3.1 FR 4.5.1)
This is independent of the return type.
If the client knows that a method is asynchronous or wants to call a
void method asynchronously, it may use a static API method to acquire an
asynchronous "view" of that interface so that all calls to void methods
proceed asynchronously:
myProxy.theVoidMethod(); // called sync unless the server unblocks
EJB.async(myProxy).theVoidMethod(); // called async always
This cannot be solved any other way as the client might not have access
to the EJB metadata which specifies whether the method is asynchronous.
The underlying protocol is asynchronous regardless of any method
metadata. So the client is more or less always faced with a decision to
process async or sync. Or so you want to add a pre-result packet?
You also need the divine methods (see
http://java.net/jira/browse/EJB_SPEC-11).
Client JNDI
-----------
Client JNDI is just a simple in-memory JNDI implementation. We will not
automatically bind anything to it at all, except in two possible cases:
1. A simple configuration file which describes what to bind, or 2. A
configuration instructing a binding list to be fetched from somewhere.
Clients running in an AS7 instance or in an AS7 application client
container will be using our server JNDI implementation which supports
injection, not the client JNDI implementation, which is reserved for
truly standalone clients.
Server Implementation
---------------------
The EE subsystem already contains most of the required APIs for handling
remote invocations. Any remotely accessible ComponentView will be
registered with the remote invocation service along with its
app/module/distinctName identification.
A special in-VM EJB receiver will also exist and will be similarly
updated with the current available component views and their modules.
Management configurations will be introduced for the purpose of
establishing and maintaining Remoting connections to remote servers.
EJB client contexts should be created for each deployment, and a
deployment descriptor should be made available to any EE deployment for
the purpose of associating Remoting connections (and probably clusters
etc.) with the EJB client context for that EE module. This allows each
deployment to specify what remote servers it can "see", while still
keeping the network configuration business in the central management model.
All deployments on the server which have an EE client context will have
the in-VM receiver added to it automatically, so that it can access all
EJBs in the server via remote interface locally.
This does not scale up. Especially with large deployments and/or many
small ones.
Summary
-------
Okay I think that's it for the first draft. Please give feedback on
anything that I might have missed or anything that's just outright wrong
and needs to be changed. In particular I'm currently assuming that IIOP
exists in a world outside of other invocation forms, but that might not
actually be desirable.
IIOP invocations should come in via the same facility as the EJB
receivers invoke. Binding and interceptors are in this case very
protocol specific. So IIOP can be left out of scope.
Carlo