On Jul 1, 2012, at 5:11 PM, exabrial wrote:

> Hey sorry to wake a dead thread...

Preferred actually.  Saves the time of having to dig for the old thread.

> but I just thought of something: Does
> OpenEJB has a jndi-link feature?
> 
> I don't think it does, but I know GlassFish and Resin can do it....
> http://www.caucho.com/resin-3.0/config/env.xtp#jndi-link
> 
> Would writing a custom ObjectFactory be the correct way to do this?
> 
> In my frontend JSF application, in a servlet, say I had:
> 
> @EJB
> MyService myService;
> 
> If I wanted to link that EJB to an external context, I would put something
> in TomEE.xml like this:
> 
>       <JndiProvider id="shoe" type="javax.naming.InitialContext">
>               java.naming.provider.url = ejbd://localhost:3201
>               java.naming.factory.initial =
> org.apache.openejb.client.RemoteInitialContextFactory
>       </JndiProvider>
> 
>       <Resource id="MyService"
> type="org.apache.openejb.xxx.OpenEJBExternalJndiLink">
>               externalContext = "shoe"
>               externalName="MyDeploymentId/MyService.Remote"
>       </JndiProvider>

Ignoring the <Resource> part for a moment, the best fit would likely be 
something that allows you to describe the external EJB.

The trick is when you use `@EJB` like shown above, the matching EJB is resolved 
by type.  The pseudo <Resource> declaration doesn't have the type `MyService` 
in it anywhere and therefore wouldn't work.  You'd be stuck matching by string 
(id) and then what I mention before about needing to change all your `@EJB` 
references to use `name` as in `@EJB(name="MyService")` would still apply.

So something that allows you to say, "I have an EJB of type X that you can 
lookup via Y jndi name using Z <JndiProvider>" would be the most terse and 
common-case solution.

Being able to optionally specify the "ejb-name" so you could also match with 
`@EJB(beanName="fooService")` would be nice.  The `beanName` attribute is used 
as a tie-breaker when there is more than one bean that could satisfy an `@EJB` 
ref by type (e.g. say you have two beans that implement the same @Remote 
interface, `@EJB` will no longer work unless you specify `beanName`.

Theoretically that could look something like:

  <ExternalEjb>
    <interface>org.superbiz.MyService</interface>
    <interface>org.superbiz.Foo</interface>
    <bean-name>fooService</bean-name>
    <jndi-name>FooService.Remote</jndi-name>
    <jndi-provider>shoe</jndi-provider>
  </ExternalEjb>

Not crazy about the ExternalEjb element name, but that's the basic idea.  To 
recap:

  - @EJB is resolved by either `type` or `beanName`
  - if we can provide a way to tie either a type or a bean-name to an external 
ejb, we're good.

So what we'd do is take these ExternalEjb refs and add them into the mix when 
we run our "find the matching EJB for this @EJB ref" logic.

Since we allow you to declare the actual server info in <JndiProvider>, you 
could potentially do all this in code if we were to create an equivalent 
annotation.  Maybe something like:

    public @interface ExternalEjb {
        Class[] interfaces() default {};
        String beanName() default "";
        String jndiName() default "";
        String jndiProvider() default "";
    }

We could maybe allow you to specify that on a class or something.  Or perhaps 
even more clever:

    @ExternalEjb(jndiName = "FooService.Remote", jndiProvider = "shoe")
    public abstract class FooService implements MyService, Foo {}

At this point you have far less XML to maintain and having 1 to 100+ of these 
external ejbs would be pretty easy as you'd only need to keep a single 
`<JndiProvider id="shoe">` entry up-to-date.

Thoughts?


-David

Reply via email to