[webbeans-dev] Re: Java EE resource injection

Gavin King gavin at hibernate.org
Wed Jan 7 07:59:19 EST 2009


So this morning, Scott and I discussed the problem that EE resource
references are scoped to the EJB instead of to the EAR. Frankly, this
really messes things up for us. It means that, according to my Option
1 proposal, you could end up with the same type and binding types
resolving to a different object depending upon what EJB we are
injecting into.

To characterize this in the spec, one possibility would be to give
each enterprise web bean its own child Manager, say that EE resource
references belong to these child managers, and define that injection
into an EJB be done via the child manager for that EJB.  I suppose
that, additionally, the web application would have its own child
manager, with EE resource references that were defined in web.xml, and
Servlets and simple Web Beans would use that manager for resolving
their dependencies.

This definition would work, AFAICT, and is probably not that difficult
to specify. However, it certainly does make the spec more difficult to
understand.

Now, the more I think about this, the more I'm inclined to think that
the component-level scoping of resource references is basically
nonsense. I just don't buy that users really want to have

@Stateless
public class FooBean {

    @CustomerDatabase Datasource ds;

}

refer to one JDBC datasource in one EJB, and:

@Stateless
public class BarBean {

    @CustomerDatabase Datasource ds;

}

refer to a completely different JDBC datasource. That's just perverse!

So I'm now thinking that we should let this stuff to be declared in
web-beans.xml. We would simply allow a global JNDI name or "mapped
name" to be specified. There would be no double-declaration, since the
component-level resource declaration would not be required at all.

i.e:

  <Resource>
      <myapp:Foo>
          <myapp:Bar/>
      </myapp:Foo>
      <ResquestScoped/>
      <jndiName>foo/bar</jndiName>
  </Resource>

or:

  <Resource>
      <myapp:Foo>
          <myapp:Bar/>
      </myapp:Foo>
      <ResquestScoped/>
      <mappedName>foobar</mappedName>
  </Resource>

I now think this is a *much* better approach, and avoids all the
complexity of child managers, etc, and the inconsistency with all the
other kinds of injected things in JSR-299. Notice that it's also just
a very simple generalization of the approach we took with JMS Queues
and Topics.

Unless anyone objects, I would like to start writing up this approach,
so that I can circulate a concrete proposal next week. I now believe
it's the Right Thing.


On Wed, Jan 7, 2009 at 3:43 PM, Scott Ferguson <ferg at caucho.com> wrote:
>
> On Jan 6, 2009, at 9:54 AM, Michael Keith wrote:
>
>> I would like to see all of the EE injection be in the same spec, meaning
>> that existing
>> EE resource injection would transition from its definition in the EE
>> document to being in this
>> one (if injection is to be a primary service defined and offered by this
>> spec). All injection
>> should be consistently defined, explained and implemented.
>
> If it helps, we've run into related issues because we've implemented @EJB,
> @Resource, etc. on top of an underlying WebBeans repository.  So, in our
> case, Java EE injection is a facade over WebBeans.  Theoretically, Java EE
> injection could be officially defined in a similar way.
>
> When a user configures a DataSource, we register it with the appropriate
> WebBeans Manager (using a special Bean wrapper implementation), and give it
> an internal binding name like @Name("foo").  A user could theoretically
> inject the resource directly using a pure webbeans-only injection.
>
> So, @EJB, @PersistenceUnit, @Resource, etc. find the resource using normal
> WebBeans rules, inject it if necessary, and bind to JNDI if necessary.
>  (We're still working out some of the details for the internal binding, but
> it's essentially in place.  If necessary, for things like *-link, we can
> define a link Bean similar to Gavin's JNDI bean.)
>
> I believe it would be possible to specify Java EE injection entirely in
> terms of an underlying WebBeans registry without too much difficulty.  The
> other way around would be a bit of a mess.
>
> For the issue of component scoping for EJBs, we have a separate WebBeans
> Manager associated with each EJB scope, web-app and ear arranged in a tree.
>  This lets us have scope-specific definitions and links.  For example, an
> <env-entry> defined in a session bean is stored in its scoped Manager, not
> the global Manager.  A child scope might entirely consist of links to
> resources defined in the parent scope.  (Hierarchy scope rules apply, so a
> lookup that fails in the client the tries the parent Manager.)
>
> (I'm a bit behind in reading the latest EJB 3.1 draft, so there are still
> probably details that aren't quite right, but the basic model shouldn't
> change.)
>
> Option 1, then, would work like a rebinding from the internal configured
> resource, as a LinkBean which would be registered using the new <binding> in
> the component's scope.  (And published in JNDI using the public JNDI name.)
>  Pretty straightforward.
>
> Options 2. hmmm.  The scoping of the resources in the EJB's web-beans.xml is
> a bit of a problem.  IIRC, EJB doesn't create a foo.jar scope, only
> bean-specific scopes, so I assume the <ResourceRef> would be published in
> the application scope.  But that means that option 2 doesn't really capture
> the concept of an <ejb-ref> defined in a session bean's scope.  I think.
>
> BTW, I didn't want to bring up the idea of a Manager hierarchy because it
> seemed beyond the spec's scope, but it's handy in order to properly model
> the Java-EE, ear, web-app, EJB scopes and references in terms of WebBeans
> capabilities.
>
> -- Scott
>>
>>
>> -Mike
>>
>>> -----Original Message-----
>>> From: Gavin King [mailto:gavin at hibernate.org]
>>> Sent: Monday, January 05, 2009 9:11 PM
>>> To: Java Community Process JSR #299 Expert List; Michael Keith; Scott
>>> Ferguson; Matt Drees; WebBeans
>>> Subject: Java EE resource injection
>>>
>>>
>>> Folks, it's time to address the problem of generalized Java EE
>>> resource injection.
>>>
>>> Web Beans needs to support injection of the following kinds of things:
>>>
>>> * EE resources (e.g. JDBC datasources, etc)
>>> * remote EJB references
>>> * web service references
>>>
>>> I believe we can treat all three as essentially the same kind of thing
>>> in the spec. Let's call it a "EE resource reference", or whatever.
>>> It's a new "kind" of Web Bean in Chapter 3. This functionality should
>>> not impact any other part of the specification.
>>>
>>> (An additional complication is that we need to unify the current
>>> notion of a "JMS endpoint" with this functionality. I don't believe
>>> that this is a difficult problem, we just need to make it a special
>>> case of a "EE resource reference", that supports additional
>>> semantics.)
>>>
>>> I see two possible paths we could go down here:
>>>
>>> Option 1:
>>> =======
>>>
>>> The spec could simply say that for every "EE resource reference"
>>> defined in web.xml or ejb-jar.xml, that a Web Bean exists with
>>> deployment type @Production and no name. The scope and binding types
>>> of this Web Bean have the usual defaults (@Depenent, @Current), but
>>> these may be specified explicitly in web.xml or ejb-jar.xml:
>>>
>>> <ejb-ref>
>>>   <ejb-ref-name>foo</ejb-ref-name>
>>>   <remote>org.myapp.FooRemote</remote>
>>>   <binding>org.myapp.Bar</binding>
>>>   <scope>javax.webbeans.Conversation</scope>
>>> </ejb-ref>
>>>
>>> <resource-ref>
>>>    <res-ref-name>jdbc/DefaultDS</res-ref-name>
>>>    <res-type>javax.sql.DataSource</res-type>
>>>    <res-auth>Container</res-auth>
>>>    <binding>org.myapp.Default</binding>
>>> </resource-ref>
>>>
>>> <service-ref>
>>>   <service-ref-name>service/FooService</service-ref-name>
>>>   <service-interface>org.myapp.Foo</service-interface>
>>>   <wsdl-file>META-INF/wsdl/FooService.wsdl</wsdl-file>
>>>
>>> <jaxrpc-mapping-file>META-INF/foo-mapping.xml</jaxrpc-mapping-file>
>>>   <binding>org.myapp.Bar</binding>
>>>   <scope>javax.webbeans.Request</scope>
>>> </service-ref>
>>>
>>> The lifecycle of this Web Bean would be super-simple:
>>>
>>> * Bean.create() would be equivalent to a JNDI lookup for the resource
>>> * Bean.destroy() would simply discard the reference
>>>
>>> There is just one problem with this approach: EE resource references
>>> are by nature scoped to a particular EE module, whereas this is not
>>> naturally the case for Web Beans (which are naturally EAR scoped). I
>>> don't believe this is a really big problem but we would need to
>>> institute an additional layer of validation to ensure that injection
>>> points that refer to an EE resource are in the same module as the
>>> resource ref declaration. This would be a new section in the spec, but
>>> I don't believe it is difficult to write.
>>>
>>> Option 2:
>>> =======
>>>
>>> The second option would be to require explicit declaration of the
>>> resource in web-beans.xml, thus making them an EAR-global declaration.
>>>
>>> <ResourceRef jndiName=".....">
>>>   <myapp:Foo>
>>>       <myapp:Bar/>
>>>   </myapp:Foo>
>>>   <ResquestScoped/>
>>> </ResourceRef>
>>>
>>> There are a couple of major problems with this:
>>>
>>> * resources must be declared twice, in different places
>>> * the two declarations are correlated via a global JNDI name, which:
>>>  - is still not really a well-defined construct in the EE spec
>>>  - cannot be properly validated at development time
>>>
>>> Therefore I strongly prefer Option 1.
>>>
>>> WDYT?
>>>
>>> --
>>> Gavin King
>>> gavin.king at gmail.com
>>> http://in.relation.to/Bloggers/Gavin
>>> http://hibernate.org
>>> http://seamframework.org
>>>
>>
>>
>
> _______________________________________________
> webbeans-dev mailing list
> webbeans-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/webbeans-dev
>



-- 
Gavin King
gavin.king at gmail.com
http://in.relation.to/Bloggers/Gavin
http://hibernate.org
http://seamframework.org



More information about the weld-dev mailing list