[wildfly-dev] New JNDI-based remote service API (for EJB etc.)

David M. Lloyd david.lloyd at redhat.com
Mon Jan 20 23:19:20 EST 2014


We've been having some discussions around improving the way that the EJB 
invocation API looks, feels, and behaves to produce smaller, simpler, 
and perhaps more "expected" code for more common cases.  I'm going to 
outline some of the design points here so that everyone knows what's 
coming and has a chance to ask questions.

Part 1: JNDI API
----------------
Right now connection management is accomplished via a mishmash of APIs 
from different client libraries.  In most cases the connections are 
automatically "managed", but in different ways, and such that each 
client really cannot interact with each other.

 From the user's perspective, this is really not desirable.  Most users 
are, for better or worse, expecting to use an API like JNDI to establish 
and maintain their connection to the remote system.  So the first idea 
here is to encapsulate all common Remoting-based services into a single 
JNDI context.  The user should be able to do something like this:

    Hashtable env = new Hashtable();
    env.put(Context.PROVIDER_URL, "remote+http://myserver.com:8080");
    ...couple other properties here...
    InitialContext c = new InitialContext(env);

Now 'c' is a useful server connection that can be used for various 
services.  These services would include remote transaction control:

    UserTransaction ut = (UserTransaction) c.lookup("UserTransaction");

Remote authentication/authorization:

    SomeLoginContextLike lc = (...) c.lookup("AuthenticationService");
    lc.login(subject, ...);
    subject.doAs(...{
        ...do stuff...
    });

Remote JNDI:

    Context rc = (Context) c.lookup("RemoteNaming");

And of course EJBs:

    MyEJBRemote rem = (MyEJBRemote) 
c.lookup("EJB/MyApp/MyModule/MyEJB!com.mycom.MyEJB");

Please note that none of these JNDI names or APIs are final, just examples.

Once these services use a common infrastructure, a couple of things 
become possible:

1) The services shared among a connection can work together more 
effectively; for example, a UserTransaction can encapsulate all services 
running over that connection, rather than just EJBs.  Likewise for the 
upcoming authentication service.

2) This API can be expanded to cover transport protocols other than 
Remoting-based protocols for use cases in which a single persistent 
connection is not the best option.

Part 2: Connection Management
-----------------------------
By using a URI as the connection destination, we can have one unified 
configuration infrastructure for connection establishment.  We can also 
potentially cache and reuse connections with the same URI.  In this 
case, the user would not need to close the initial context; it could be 
maintained indefinitely or closed after a configurable "idle" interval.

Configuration could be set up in a properties file for simple clients. 
However there will also (often) be cases where the user simply wants to 
establish a connection programmatically in the InitialContext 
environment.  To support this use case, a context will also be able to 
be configured in this way (though there is still a little bit of 
figuring out to do to work out a way that won't result in weird behavior 
if this method is used when there is also an external configuration).

Part 3: Connection Authentication
---------------------------------
In order for connection reuse to work in the presence of multiple 
identities (and make various other things nicer, as an aside), we need 
to create a separate concept of connection authentication, to avoid the 
situation where we ask for a connection as user A and get user B's 
connection instead, or a situation where a user feels they must make one 
connection per identity.  Thus we need a separate client authentication 
context and configuration method to determine the client authentication 
method and credentials to use for the connection itself.

Once a connection is established, the authentication service on that 
connection can be used to switch between authenticated identities.  The 
connection itself need only authenticate to an identity which has 
adequate authorization to switch to, or authenticate as, those 
identities.  On the other hand, for simple cases, the client might only 
need one identity: in this case the authentication service need not be 
used; instead the client authentication context would be set up to 
authenticate the desired user from the outset, and no other identity 
would be established during its usage.

To switch identities, the user would have to acquire some type of 
JAAS-like login context and authenticate a JAAS-like subject with it. 
Then the user would use a typical "doAs"-style construct to perform some 
body of work as that identity.  This will be the subject (!) of a 
different email.

Again, there will be cases where an external configuration for this 
purpose will be too heavy-handed for the specific use case; in this case 
we should allow an environment-based configuration mode.

Part 4: EJB Proxy Behavior
--------------------------
An EJB proxy which was acquired from this sort of connection can attain 
an association to the remote system by URI.  The identifying 
characteristic of the proxy would then be: view type, URI, application 
name, module name, EJB name.  The 'distinct name' concept will no longer 
be necessary and could possibly be deprecated if there is no remaining 
use case for it.

The URI is significant primarily when the proxy is realized in a new 
context.  When the proxy is invoked upon for the first time, it must be 
associated with a connection to the target system.  The information in 
the URI must therefore be sufficient to establish such a connection and 
register it with the connection cache in order to allow such proxies to 
be useful.

This is simple in the case of a URL; if a proxy is deserialized in an 
unknown context, the URL plus any environment security settings may be 
used to establish a new connection to allow the proxy to be invoked upon 
again automatically (without compromising security in any way).

However on the negative side, if a URL is used for the URI, the URL may 
not be valid after deserialization across certain types of NAT 
configuration.  This is a very real problem in some environments.  In 
order to mitigate this problem, a discovery mechanism is introduced.

Part 5: Discovery
-----------------
It will be possible for more advanced environments to utilize a URN 
instead of a URL for connection establishment.  The benefit of doing 
this is that the URN given can be resolved in a location-specific 
manner.  A proxy with a URN of, say, "node:usa-1" might use a discovery 
protocol to locate a node named "usa-1", find a URL that can be used to 
connect, and establish and maintain the connection automatically.  An 
EJB proxy associated with this URN may be serialized and deserialized in 
a completely different network environment, and the URN may still be 
used (but resolved in a different manner) allowing the proxy (and its 
connection) to continue to function.

The discovery mechanism should be pluggable to allow support for cloud 
environments and potentially the Service Location Protocol (SLP, RFC 
2608) for data center environments.  Other schemes may be introduced 
which do simple name-to-DNS-name mappings or other such simple schemes.

Part 6: Compatibility
---------------------
EJB Proxies acquired using the existing AS 7/WildFly 8 EJB API should 
map the EJB locator information to a locator which is compatible with 
the URI scheme given here, and vice versa, so that there is a seamless 
migration path between old and new location schemes.

The wire protocol should also be made compatible so that old clients 
will continue to function against new servers (and the reverse as well, 
if possible).

-- 
- DML


More information about the wildfly-dev mailing list