On Aug 13, 2007, at 5:04 PM, David Blevins wrote:

One of the remaining issues for the 3.0 release is the JNDI name strategy we're going to use. I had totally thought this was all straightened out when I added the TemplatedStrategy (documented here: http://openejb.apache.org/jndi-names.html), but it turns out we are still using the LegacyAddedSuffixStrategy by default so the documentation in that page also isn't right by default :)

More on the jndi name issue as it relates to proxies.

You may recall our discussions[1][2][3] on what do to about all-in- one proxies and the fact that some spec compliant beans may have business interfaces that conflict[4] and therefore can't be all-in- one proxies requiring us to also support a one-proxy-per-interface approach.

What we ended up with is for each bean we create an all-in-one proxy and bind it into jndi, then for each of that bean's business interfaces we create a proxy with just that interface in it (the one- proxy-per-interface approach) and bind each proxy into jndi as well. So a bean with four remote business interfaces, for example, gets 1 all-in-one "business remote" proxy and 4 single-interface proxies, one for each remote business interface. The same algorithm would apply to local business interfaces. We still do not support an all- in-one proxy that implements both local business interfaces and remote business interfaces.

This is the part that has changed. *Now* we no longer have two separate approaches (all-in-one-proxy vs single-interface-proxy) we have a sort of hybrid approach. In the new approach we still create one proxy per each business interface, but we *also* include all the other business interfaces implemented by the bean class provided none of them conflict. So a bean with four business interfaces gets 4 proxies, each possibly containing all four business interfaces.

Recap: each proxy has all the business interfaces your bean implements (provided no conflicts are found), plus the interface the proxy is dedicated to (regardless if the bean implemented it). We create one such proxy for each business interface you have.

So what are these conflicts? Business interfaces extending java.rmi.Remote. If you do not have any business interfaces extending java.rmi.Remote *and* you implemented all your business interfaces in your bean class, you are good to go and do not need to be concerned; all your proxies will be guaranteed to be 'all in one' proxies you can cast it to any of the other business interfaces of the same type (type=local vs remote) that bean implements.

What's the deal with java.rmi.Remote? The specific issue with java.rmi.Remote interfaces is that per spec rules many runtime exceptions (container or connection related) are thrown to clients as java.rmi.RemoteException which is not a runtime exception and must be throwable via the proxy.

For example it's legal for a bean to implement two conflicting methods such as these:
      InterfaceA: void doIt() throws Foo;
      InterfaceB: void doIt() throws RemoteException;

by leaving out exceptions from the throws clause that aren't declared in both interfaces methods.
      Implementation:  void doIt(){}

This is fine for a bean class as it isn't going to need to throw RemoteException. However if we create a proxy from these two interfaces it will also wind up with a 'doIt(){}' method that cannot throw RemoteException. This is very bad as the container does need to throw RemoteException per spec rules to any business interfaces extending java.rmi.Remote. If the container attempts to throw a RemoteException from the proxies 'doIt(){}' method, it will result in an UndeclaredThrowableException thrown by the VM. The only way to guarantee the proxy has the 'doIt() throws RemoteException {}' method of InterfaceB is to cut out InterfaceA when we create the proxy dedicated to InterfaceB. When we create the proxy dedicated to InterfaceA, InterfaceB is cut out.

Hope this helps describe how we deal with proxies and the strange edge case that may occur.

The important thing to remember is that if you implement all your business interfaces and do not use java.rmi.Remote, your life is super easy.

The only real issue in all of this java.rmi.Remote business is if you decide to use an openejb.jndiname.format[5] that results in you getting one proxy per bean (format="{deploymentId}" for example) or one "business remote" proxy per bean (format="{deploymentId} {interfaceType}", my preference) instead of one proxy per each interface of a bean (format={deploymentId}/ {interfaceClass.simpleName}, the default).



Wow, that took a lot to describe.... I'm not so sure if it came out clearly. We definitely want to make sure we nail this chunk of documentation and that we all understand how things work.

Is it coming out clear?

-David

[1] http://marc.info/?l=openejb-development&m=117636072115360&w=2
[2] http://marc.info/?l=openejb-user&m=117636204916491&w=2
[3] http://marc.info/?l=openejb-development&m=117661592616633&w=2
[4] http://openejb.apache.org/multiple-business-interface-hazzards.html
[5] http://openejb.apache.org/jndi-names.html

Reply via email to